diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-02-14 19:27:17 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-02-14 19:27:17 +0000 |
commit | 6de8cb0481bd793706e38dead271f9233a57b7e5 (patch) | |
tree | 7ff9ff6922a48636469d3b019d912ee0b7894c00 | |
parent | 627e15b4811e5758670f68174f71540e63fb4040 (diff) |
236 files changed, 79946 insertions, 0 deletions
diff --git a/gnu/usr.bin/gcc/config/a29k/udi.h b/gnu/usr.bin/gcc/config/a29k/udi.h new file mode 100644 index 00000000000..400ffbbe985 --- /dev/null +++ b/gnu/usr.bin/gcc/config/a29k/udi.h @@ -0,0 +1,94 @@ +/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU + running over UDI using COFF. + Copyright (C) 1994, 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Support the ctors and dtors sections for g++. */ + +#define CTORS_SECTION_ASM_OP "\t.use .ctors" +#define DTORS_SECTION_ASM_OP "\t.use .dtors" + +/* A list of other sections which the compiler might be "in" at any + given time. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS readonly_data, in_ctors, in_dtors + +/* A list of extra section function definitions. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + READONLY_DATA_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#define READONLY_DATA_FUNCTION \ +void \ +literal_section () \ +{ \ + if (in_section != readonly_data) \ + { \ + fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \ + in_section = readonly_data; \ + } \ +} \ + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +#define INT_ASM_OP ".word" + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) diff --git a/gnu/usr.bin/gcc/config/alpha/elf.h b/gnu/usr.bin/gcc/config/alpha/elf.h new file mode 100644 index 00000000000..8a7f06a928b --- /dev/null +++ b/gnu/usr.bin/gcc/config/alpha/elf.h @@ -0,0 +1,506 @@ +/* Definitions of target machine for GNU compiler, for DEC Alpha w/ELF. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@tamu.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. */ + +/* This is used on Alpha platforms that use the ELF format. + Currently only GNU/Linux uses this. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux with ELF)"); + +#undef OBJECT_FORMAT_COFF +#undef EXTENDED_COFF +#define OBJECT_FORMAT_ELF + +#define SDB_DEBUGGING_INFO + +#undef ASM_FINAL_SPEC + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "\ +-D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \ +-Asystem(linux) -Acpu(alpha) -Amachine(alpha) -D__ELF__" + +#undef LINK_SPEC +#ifdef USE_GNULIBC_1 +#define LINK_SPEC "-m elf64alpha -G 8 %{O*:-O3} %{!O*:-O1} \ + %{shared:-shared} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \ + %{static:-static}}" +#else +#define LINK_SPEC "-m elf64alpha -G 8 %{O*:-O3} %{!O*:-O1} \ + %{shared:-shared} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ + %{static:-static}}" +#endif + +/* Output at beginning of assembler file. */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +{ \ + alpha_write_verstamp (FILE); \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + fprintf (FILE, "\t.set noat\n"); \ +} + +#define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \ + alpha_output_lineno (STREAM, LINE) +extern void alpha_output_lineno (); + +extern void output_file_directive (); + +/* Attach a special .ident directive to the end of the file to identify + the version of GCC which compiled this code. The format of the + .ident string is patterned after the ones produced by native svr4 + C compilers. */ + +#define IDENT_ASM_OP ".ident" + +#ifdef IDENTIFY_WITH_IDENT +#define ASM_IDENTIFY_GCC(FILE) /* nothing */ +#define ASM_IDENTIFY_LANGUAGE(FILE) \ + fprintf(FILE, "\t%s \"GCC (%s) %s\"\n", IDENT_ASM_OP, \ + lang_identify(), version_string) +#else +#define ASM_FILE_END(FILE) \ +do { \ + fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ + } while (0) +#endif + +/* Allow #sccs in preprocessor. */ + +#define SCCS_DIRECTIVE + +/* Output #ident as a .ident. */ + +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +/* This is how to allocate empty space in some section. The .zero + pseudo-op is used for this on most svr4 assemblers. */ + +#define SKIP_ASM_OP ".zero" + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE)) + +/* Output the label which precedes a jumptable. Note that for all svr4 + systems where we actually generate jumptables (which is to say every + svr4 target except i386, where we use casesi instead) we put the jump- + tables into the .rodata section and since other stuff could have been + put into the .rodata section prior to any given jumptable, we have to + make sure that the location counter for the .rodata section gets pro- + perly re-aligned prior to the actual beginning of the jump table. */ + +#define ALIGN_ASM_OP ".align" + +#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL +#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + ASM_OUTPUT_ALIGN ((FILE), 2); +#endif + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ + do { \ + ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ + } while (0) + +/* The standard SVR4 assembler seems to require that certain builtin + library routines (e.g. .udiv) be explicitly declared as .globl + in each assembly file where they are referenced. */ + +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) + +/* This says how to output assembler code to declare an + uninitialized external linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#define COMMON_ASM_OP ".comm" + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ +} while (0) + +/* This says how to output assembler code to declare an + uninitialized internal linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#define LOCAL_ASM_OP ".local" + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +/* This is the pseudo-op used to generate a 64-bit word of data with a + specific value in some section. */ + +#define INT_ASM_OP ".quad" + +/* This is the pseudo-op used to generate a contiguous sequence of byte + values from a double-quoted string WITHOUT HAVING A TERMINATING NUL + AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */ + +#undef ASCII_DATA_ASM_OP +#define ASCII_DATA_ASM_OP ".ascii" + +/* Support const sections and the ctors and dtors sections for g++. + Note that there appears to be two different ways to support const + sections at the moment. You can either #define the symbol + READONLY_DATA_SECTION (giving it some code which switches to the + readonly data section) or else you can #define the symbols + EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and + SELECT_RTX_SECTION. We do both here just to be on the safe side. */ + +#define USE_CONST_SECTION 1 + +#define CONST_SECTION_ASM_OP ".section\t.rodata" + +/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. + + Note that we want to give these sections the SHF_WRITE attribute + because these sections will actually contain data (i.e. tables of + addresses of functions in the current root executable or shared library + file) and, in the case of a shared library, the relocatable addresses + will have to be properly resolved/relocated (and then written into) by + the dynamic linker when it actually attaches the given shared library + to the executing process. (Note that on SVR4, you may wish to use the + `-z text' option to the ELF linker, when building a shared library, as + an additional check that you are doing everything right. But if you do + use the `-z text' option when building a shared library, you will get + errors unless the .ctors and .dtors sections are marked as writable + via the SHF_WRITE attribute.) */ + +#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" +#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" + +/* On svr4, we *do* have support for the .init and .fini sections, and we + can put stuff in there to be executed before and after `main'. We let + crtstuff.c and other files know this by defining the following symbols. + The definitions say how to change sections to the .init and .fini + sections. This is the same for all known svr4 assemblers. */ + +#define INIT_SECTION_ASM_OP ".section\t.init" +#define FINI_SECTION_ASM_OP ".section\t.fini" + +/* A default list of other sections which we might be "in" at any given + time. For targets that use additional sections (e.g. .tdesc) you + should override this definition in the target-specific file which + includes this file. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_ctors, in_dtors + +/* A default list of extra section function definitions. For targets + that use additional sections (e.g. .tdesc) you should override this + definition in the target-specific file which includes this file. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#undef READONLY_DATA_SECTION +#define READONLY_DATA_SECTION() const_section () + +extern void text_section (); + +#define CONST_SECTION_FUNCTION \ +void \ +const_section () \ +{ \ + if (!USE_CONST_SECTION) \ + text_section(); \ + else if (in_section != in_const) \ + { \ + fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ + in_section = in_const; \ + } \ +} + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +/* Switch into a generic section. + This is currently only used to support section attributes. + + 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. */ +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") + + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } 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. */ + +#define SELECT_SECTION(DECL,RELOC) \ +{ \ + if (TREE_CODE (DECL) == STRING_CST) \ + { \ + if (! flag_writable_strings) \ + const_section (); \ + else \ + data_section (); \ + } \ + else if (TREE_CODE (DECL) == VAR_DECL) \ + { \ + if ((flag_pic && RELOC) \ + || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ + || !DECL_INITIAL (DECL) \ + || (DECL_INITIAL (DECL) != error_mark_node \ + && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else \ + const_section (); \ +} + +/* A C statement or statements to switch to the appropriate + section for output of RTX in mode MODE. RTX is some kind + of constant in RTL. The argument MODE is redundant except + in the case of a `const_int' rtx. Currently, these always + go into the const section. */ + +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) const_section() + +/* Define the strings used for the special svr4 .type and .size directives. + These strings generally do not vary from one system running svr4 to + another, but if a given system (e.g. m88k running svr) needs to use + different pseudo-op names for these, they may be overridden in the + file which includes this one. */ + +#define TYPE_ASM_OP ".type" +#define SIZE_ASM_OP ".size" + +/* This is how we tell the assembler that a symbol is weak. */ + +#define ASM_WEAKEN_LABEL(FILE,NAME) \ + do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); } while (0) + +/* This is how we tell the assembler that two symbols have the same value. */ + +#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \ + do { assemble_name(FILE, NAME1); \ + fputs(" = ", FILE); \ + assemble_name(FILE, NAME2); \ + fputc('\n', FILE); } while (0) + +/* The following macro defines the format used to output the second + operand of the .type assembler directive. Different svr4 assemblers + expect various different forms for this operand. The one given here + is just a default. You may need to override it in your machine- + specific tm.h file (depending upon the particulars of your assembler). */ + +#define TYPE_OPERAND_FMT "@%s" + +/* Write the extra assembler code needed to declare a function's result. + Most svr4 assemblers don't require any special declaration of the + result value, but there are exceptions. */ + +#ifndef ASM_DECLARE_RESULT +#define ASM_DECLARE_RESULT(FILE, RESULT) +#endif + +/* 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 an object properly. */ + +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ + putc ('\n', FILE); \ + size_directive_output = 0; \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } while (0) + +/* Output the size directive for a decl in rest_of_decl_compilation + in the case where we did not do so before the initializer. + Once we find the error_mark_node, we know that the value of + size_directive_output was set + by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ + +#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ +do { \ + char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ + && ! AT_END && TOP_LEVEL \ + && DECL_INITIAL (DECL) == error_mark_node \ + && !size_directive_output) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, name); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + } while (0) + +/* A table of bytes codes used by the ASM_OUTPUT_ASCII and + ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table + corresponds to a particular byte value [0..255]. For any + given byte value, if the value in the corresponding table + position is zero, the given character can be output directly. + If the table value is 1, the byte must be output as a \ooo + octal escape. If the tables value is anything else, then the + byte value should be output as a \ followed by the value + in the table. Note that we can use standard UN*X escape + sequences for many control characters, but we don't use + \a to represent BEL because some svr4 assemblers (e.g. on + the i386) don't know about that. Also, we don't use \v + since some versions of gas, such as 2.2 did not accept it. */ + +#define ESCAPES \ +"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" + +/* Some svr4 assemblers have a limit on the number of characters which + can appear in the operand of a .string directive. If your assembler + has such a limitation, you should define STRING_LIMIT to reflect that + limit. Note that at least some svr4 assemblers have a limit on the + actual number of bytes in the double-quoted string, and that they + count each character in an escape sequence as one byte. Thus, an + escape sequence like \377 would count as four bytes. + + If your target assembler doesn't support the .string directive, you + should define this to zero. +*/ + +#define STRING_LIMIT ((unsigned) 256) + +#define STRING_ASM_OP ".string" + +/* + * We always use gas here, so we don't worry about ECOFF assembler problems. + */ +#undef TARGET_GAS +#define TARGET_GAS (1) + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux 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:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on + the GNU/Linux 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 + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" diff --git a/gnu/usr.bin/gcc/config/alpha/osf2or3.h b/gnu/usr.bin/gcc/config/alpha/osf2or3.h new file mode 100644 index 00000000000..03bc58a61e3 --- /dev/null +++ b/gnu/usr.bin/gcc/config/alpha/osf2or3.h @@ -0,0 +1,24 @@ +/* Definitions of target machine for GNU compiler, for DEC Alpha, osf[23]. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* In OSF 2 or 3, linking with -lprof1 doesn't require -lpdf. */ + +#undef LIB_SPEC +#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} %{a:-lprof2} -lc" diff --git a/gnu/usr.bin/gcc/config/alpha/t-vms b/gnu/usr.bin/gcc/config/alpha/t-vms new file mode 100644 index 00000000000..12ac24098ce --- /dev/null +++ b/gnu/usr.bin/gcc/config/alpha/t-vms @@ -0,0 +1,6 @@ +# Do not build libgcc1. +LIBGCC1 = +CROSS_LIBGCC1 = + +LIB2FUNCS_EXTRA = tramp.s + diff --git a/gnu/usr.bin/gcc/config/alpha/vms-tramp.asm b/gnu/usr.bin/gcc/config/alpha/vms-tramp.asm new file mode 100644 index 00000000000..fce9ec539ca --- /dev/null +++ b/gnu/usr.bin/gcc/config/alpha/vms-tramp.asm @@ -0,0 +1,22 @@ +;# New Alpha OpenVMS trampoline +;# + .set noreorder + .set volatile + .set noat + .file 1 "tramp.s" +.text + .align 3 + .globl __tramp + .ent __tramp +__tramp..en: + +.link + .align 3 +__tramp: + .pdesc __tramp..en,null +.text + ldq $1,24($27) + ldq $27,16($27) + ldq $28,8($27) + jmp $31,($28),0 + .end __tramp diff --git a/gnu/usr.bin/gcc/config/alpha/vms.h b/gnu/usr.bin/gcc/config/alpha/vms.h new file mode 100644 index 00000000000..8e4fd6dc858 --- /dev/null +++ b/gnu/usr.bin/gcc/config/alpha/vms.h @@ -0,0 +1,461 @@ +/* Output variables, constants and external declarations, for GNU compiler. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define OPEN_VMS 1 + +/* This enables certain macros in alpha.h, which will make an indirect + reference to an external symbol an invalid address. This needs to be + defined before we include alpha.h, since it determines which macros + are used for GO_IF_*. */ + +#define NO_EXTERNAL_INDIRECT_ADDRESS + +#include "alpha/alpha.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ +"-Dalpha -D__ALPHA -Dvms -DVMS -D__alpha__ -D__alpha -D__vms__ -D__VMS__\ + -Asystem(vms) -Acpu(alpha) -Amachine(alpha)" + +#undef CPP_SPEC +#define CPP_SPEC "\ +%{mfloat-ieee:-D__IEEE_FLOAT} \ +%{mfloat-vax:-D__G_FLOAT} \ +%{!mfloat-vax:-D__IEEE_FLOAT} \ +%{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \ +%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ +%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \ +%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \ +%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \ +%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C}" + +/* We allow $'s in identifiers unless -ansi is used .. */ + +#define DOLLARS_IN_IDENTIFIERS 2 + +/* These match the definitions used in DECCRTL, the VMS C run-time library + +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +*/ + +/* Use memcpy for structure copying, and so forth. */ +#define TARGET_MEM_FUNCTIONS + +/* By default, allow $ to be part of an identifier. */ +#define DOLLARS_IN_IDENTIFIERS 2 + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_FP|MASK_FPREGS|MASK_GAS|MASK_OPEN_VMS) +#undef TARGET_NAME +#define TARGET_NAME "OpenVMS/Alpha" +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME); + +/* The structure return address arrives as an "argument" on VMS. */ +#undef STRUCT_VALUE_REGNUM +#define STRUCT_VALUE 0 +#undef PCC_STATIC_STRUCT_RETURN + +/* no floating emulation. */ +#undef REAL_ARITHMETIC + +/* "long" is 32 bits. */ +#undef LONG_TYPE_SIZE +#define LONG_TYPE_SIZE 32 + +/* Pointer is 32 bits but the hardware has 64-bit addresses, sign extended. */ +#undef POINTER_SIZE +#define POINTER_SIZE 32 +#define POINTERS_EXTEND_UNSIGNED 0 + +#define MAX_OFILE_ALIGNMENT 524288 /* 8 x 2^16 by DEC Ada Test CD40VRA */ + +#undef FIXED_REGISTERS +#define FIXED_REGISTERS \ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } + +#undef CALL_USED_REGISTERS +#define CALL_USED_REGISTERS \ + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } + +#undef HARD_FRAME_POINTER_REGNUM +#define HARD_FRAME_POINTER_REGNUM 29 + +#undef CAN_ELIMINATE +#define CAN_ELIMINATE(FROM, TO) \ +((TO) != STACK_POINTER_REGNUM || ! alpha_using_fp ()) + +#undef INITIAL_ELIMINATION_OFFSET +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ +{ if ((FROM) == FRAME_POINTER_REGNUM) \ + (OFFSET) = alpha_sa_size () + alpha_pv_save_size (); \ + else if ((FROM) == ARG_POINTER_REGNUM) \ + (OFFSET) = (ALPHA_ROUND (alpha_sa_size () + alpha_pv_save_size () \ + + get_frame_size () \ + + current_function_pretend_args_size) \ + - current_function_pretend_args_size); \ + if ((TO) == STACK_POINTER_REGNUM) \ + (OFFSET) += ALPHA_ROUND (current_function_outgoing_args_size); \ +} + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. + + On Alpha/VMS, this is a structure that contains the number of + arguments and, for each argument, the datatype of that argument. + + The number of arguments is a number of words of arguments scanned so far. + Thus 6 or more means all following args should go on the stack. */ + +enum avms_arg_type {I64, FF, FD, FG, FS, FT}; +typedef struct {char num_args; enum avms_arg_type atypes[6];} avms_arg_info; + +#undef CUMULATIVE_ARGS +#define CUMULATIVE_ARGS avms_arg_info + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +#undef INIT_CUMULATIVE_ARGS +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ + (CUM).num_args = 0; \ + (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64; \ + (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64; + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + +extern enum avms_arg_type alpha_arg_type (); + +/* Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode (or VOIDmode for no more args). + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). + + On Alpha the first 6 words of args are normally in registers + and the rest are pushed. */ + +extern struct rtx_def *alpha_arg_info_reg_val (); +#undef FUNCTION_ARG +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +((MODE) == VOIDmode ? alpha_arg_info_reg_val (CUM) \ + : ((CUM.num_args) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ + ? gen_rtx(REG, (MODE), \ + ((CUM).num_args + 16 \ + + ((TARGET_FPREGS \ + && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ + || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ + * 32))) \ + : 0)) + +#undef FUNCTION_ARG_ADVANCE +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + if (MUST_PASS_IN_STACK (MODE, TYPE)) \ + (CUM).num_args += 6; \ + else \ + { \ + if ((CUM).num_args < 6) \ + (CUM).atypes[(CUM).num_args] = alpha_arg_type (MODE); \ + \ + (CUM).num_args += ALPHA_ARG_SIZE (MODE, TYPE, NAMED); \ + } + +/* For an arg passed partly in registers and partly in memory, + this is the number of registers used. + For args passed entirely in registers or entirely in memory, zero. */ + +#undef FUNCTION_ARG_PARTIAL_NREGS +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ +((CUM).num_args < 6 && 6 < (CUM).num_args \ + + ALPHA_ARG_SIZE (MODE, TYPE, NAMED) \ + ? 6 - (CUM).num_args : 0) + +/* Perform any needed actions needed for a function that is receiving a + variable number of arguments. + + CUM is as for INIT_CUMULATIVE_ARGS. + + MODE and TYPE are the mode and type of the current parameter. + + PRETEND_SIZE is a variable that should be set to the amount of stack + that must be pushed by the prolog to pretend that our caller pushed + it. + + Normally, this macro will push all remaining incoming registers on the + stack and set PRETEND_SIZE to the length of the registers pushed. + + For VMS, we allocate space for all 6 arg registers plus a count. + + However, if NO registers need to be saved, don't allocate any space. + This is not only because we won't need the space, but because AP includes + the current_pretend_args_size and we don't want to mess up any + ap-relative addresses already made. */ + +#undef SETUP_INCOMING_VARARGS +#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ +{ if ((CUM).num_args < 6) \ + { \ + if (! (NO_RTL)) \ + { \ + emit_move_insn (gen_rtx (REG, DImode, 1), \ + virtual_incoming_args_rtx); \ + emit_insn (gen_arg_home ()); \ + } \ + \ + PRETEND_SIZE = 7 * UNITS_PER_WORD; \ + } \ +} + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +{ \ + alpha_write_verstamp (FILE); \ + fprintf (FILE, "\t.set noreorder\n"); \ + fprintf (FILE, "\t.set volatile\n"); \ + ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ +} + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.%c_floating %s\n", (TARGET_FLOAT_VAX)?'f':'s', str); \ + } \ + } + +#define LINK_SECTION_ASM_OP ".link" +#define READONLY_SECTION_ASM_OP ".rdata" +#define LITERALS_SECTION_ASM_OP ".literals" + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_link, in_rdata, in_literals + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ +void \ +readonly_section () \ +{ \ + if (in_section != in_rdata) \ + { \ + fprintf (asm_out_file, "%s\n", READONLY_SECTION_ASM_OP); \ + in_section = in_rdata; \ + } \ +} \ +void \ +link_section () \ +{ \ + if (in_section != in_link) \ + { \ + fprintf (asm_out_file, "%s\n", LINK_SECTION_ASM_OP); \ + in_section = in_link; \ + } \ +} \ +void \ +literals_section () \ +{ \ + if (in_section != in_literals) \ + { \ + fprintf (asm_out_file, "%s\n", LITERALS_SECTION_ASM_OP); \ + in_section = in_literals; \ + } \ +} + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort () + +#undef ASM_OUTPUT_ADDR_VEC_ELT +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\t.quad $%d\n", (VALUE) + 32) + +#undef READONLY_DATA_SECTION +#define READONLY_DATA_SECTION readonly_section + +#define ASM_FILE_END(FILE) alpha_write_linkage (FILE); + +#undef CASE_VECTOR_MODE +#define CASE_VECTOR_MODE DImode +#undef CASE_VECTOR_PC_RELATIVE + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \ +{ ASM_OUTPUT_ALIGN (FILE, 3); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); } + +#define NO_MD_PROTOTYPES + +/* Output assembler code for a block containing the constant parts + of a trampoline, leaving space for the variable parts. + + The trampoline should set the static chain pointer to value placed + into the trampoline and should branch to the specified routine. + Note that $27 has been set to the address of the trampoline, so we can + use it for addressability of the two data items. Trampolines are always + aligned to FUNCTION_BOUNDARY, which is 64 bits. */ + +#undef TRAMPOLINE_TEMPLATE +#define TRAMPOLINE_TEMPLATE(FILE) \ +{ \ + fprintf (FILE, "\t.quad 0\n"); \ + fprintf (FILE, "\t.linkage __tramp\n"); \ + fprintf (FILE, "\t.quad 0\n"); \ +} + +/* Length in units of the trampoline for entering a nested function. */ + +#undef TRAMPOLINE_SIZE +#define TRAMPOLINE_SIZE 32 + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ + +#undef INITIALIZE_TRAMPOLINE +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +{ \ + emit_move_insn (gen_rtx (MEM, Pmode, \ + memory_address (Pmode, \ + plus_constant ((TRAMP), 16))), \ + (FNADDR)); \ + emit_move_insn (gen_rtx (MEM, Pmode, \ + memory_address (Pmode, \ + plus_constant ((TRAMP), 24))), \ + (CXT)); \ +} + +#undef TRANSFER_FROM_TRAMPOLINE + +#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, NAME, ARGS) \ + (vms_valid_decl_attribute_p (DECL, ATTRIBUTES, NAME, ARGS)) +extern int vms_valid_decl_attribute_p (); + +#undef SDB_DEBUGGING_INFO +#undef MIPS_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO + +#define DWARF2_DEBUGGING_INFO + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + fprintf (FILE, "\t.align %d\n", LOG); + +#define UNALIGNED_SHORT_ASM_OP ".word" +#define UNALIGNED_INT_ASM_OP ".long" +#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad" + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t.comm\t"); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ +} while (0) + +#define ASM_OUTPUT_SECTION(FILE,SECTION) \ + (strcmp (SECTION, ".text") == 0) \ + ? text_section () \ + : named_section (NULL_TREE, SECTION, 0), \ + ASM_OUTPUT_ALIGN (FILE, 0) \ + +#define ASM_OUTPUT_SECTION_NAME(FILE,DECL,NAME,RELOC) \ + do \ + { \ + char *flags; \ + int ovr = 0; \ + if (DECL && DECL_MACHINE_ATTRIBUTES (DECL) \ + && lookup_attribute \ + ("overlaid", DECL_MACHINE_ATTRIBUTES (DECL))) \ + flags = ",OVR", ovr = 1; \ + else if (strncmp (NAME,".debug", 6) == 0) \ + flags = ",NOWRT"; \ + else \ + flags = ""; \ + fputc ('\n', (FILE)); \ + fprintf (FILE, ".section\t%s%s\n", NAME, flags); \ + if (ovr) \ + (NAME) = ""; \ + } while (0) + +#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \ + do { literals_section(); \ + fprintf ((FILE), "\t"); \ + assemble_name (FILE, LABEL1); \ + fprintf (FILE, " = "); \ + assemble_name (FILE, LABEL2); \ + fprintf (FILE, "\n"); \ + } while (0) + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +#undef ASM_FORMAT_PRIVATE_NAME +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \ + sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) + +#undef ASM_SPEC +#undef ASM_FINAL_SPEC +#undef LINK_SPEC +#undef STARTFILE_SPEC +#define ASM_SPEC "-nocpp %{pg}" +#define LINK_SPEC "%{g3:-g3} %{g0:-g0} %{shared:-shared} %{v:-v}" + +/* Define the names of the division and modulus functions. */ +#define DIVSI3_LIBCALL "ots$div_i" +#define DIVDI3_LIBCALL "ots$div_l" +#define UDIVSI3_LIBCALL "ots$div_ui" +#define UDIVDI3_LIBCALL "ots$div_ul" +#define MODSI3_LIBCALL "ots$rem_i" +#define MODDI3_LIBCALL "ots$rem_l" +#define UMODSI3_LIBCALL "ots$rem_ui" +#define UMODDI3_LIBCALL "ots$rem_ul" diff --git a/gnu/usr.bin/gcc/config/alpha/xm-vms.h b/gnu/usr.bin/gcc/config/alpha/xm-vms.h new file mode 100644 index 00000000000..6b7dad578f1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/alpha/xm-vms.h @@ -0,0 +1,82 @@ +/* Configuration for GNU C-compiler for openVMS/Alpha. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Klaus Kaempf (kkaempf@progis.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. */ + +/* If compiling with DECC, need to fix problem with <stdio.h> + which defines a macro called FILE_TYPE that breaks "tree.h". + Fortunately it uses #ifndef to suppress multiple inclusions. + Three possible cases: + 1) <stdio.h> has already been included -- ours will be no-op; + 2) <stdio.h> will be included after us -- "theirs" will be no-op; + 3) <stdio.h> isn't needed -- including it here shouldn't hurt. + In all three cases, the problem macro will be removed here. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef __DECC +#undef FILE_TYPE +#endif + +#undef HOST_BITS_PER_LONG +#define HOST_BITS_PER_LONG 32 + +#define HOST_WIDE_INT long long +#define HOST_BITS_PER_WIDE_INT 64 + +#undef SUCCESS_EXIT_CODE +#define SUCCESS_EXIT_CODE 1 +#undef FATAL_EXIT_CODE +#define FATAL_EXIT_CODE (44 | 0x10000000) /* Abort, and no DCL message. */ + +/* A couple of conditionals for execution machine are controlled here. */ +#ifndef VMS +#define VMS +#endif + +/* Define a local equivalent (sort of) for unlink */ +#define unlink remove + +#define NEED_ATEXIT +#define HAVE_VPRINTF +#define HAVE_PUTENV +#define HAVE_STRERROR + +#define NO_SYS_PARAMS_H /* Don't have <sys/params.h> */ +#define NO_STAB_H /* Don't have <stab.h> */ +#define USE_C_ALLOCA /* Using alloca.c */ + +#define HAVE_FCNTL_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_STRING_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_TIME_H 1 +#define STDC_HEADERS 1 + +#if __STDC__ +extern void *alloca (size_t); +#else +extern char *alloca (unsigned int); +#endif + +#define OBJECT_SUFFIX ".obj" +#define EXECUTABLE_SUFFIX ".exe" diff --git a/gnu/usr.bin/gcc/config/arc/arc.c b/gnu/usr.bin/gcc/config/arc/arc.c new file mode 100644 index 00000000000..7272cc927c8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/arc.c @@ -0,0 +1,2212 @@ +/* Subroutines used for code generation on the Argonaut ARC cpu. + Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* ??? This is an old port, and is undoubtedly suffering from bit rot. */ + +#include <stdio.h> +#include "config.h" +#include "tree.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "expr.h" +#include "recog.h" + +/* Which cpu we're compiling for (NULL(=base), ???). */ +char *arc_cpu_string; +int arc_cpu_type; + +/* Name of mangle string to add to symbols to separate code compiled for each + cpu (or NULL). */ +char *arc_mangle_cpu; + +/* Save the operands last given to a compare for use when we + generate a scc or bcc insn. */ +rtx arc_compare_op0, arc_compare_op1; + +/* Name of text, data, and rodata sections, as specified on command line. + Selected by -m{text,data,rodata} flags. */ +char *arc_text_string = ARC_DEFAULT_TEXT_SECTION; +char *arc_data_string = ARC_DEFAULT_DATA_SECTION; +char *arc_rodata_string = ARC_DEFAULT_RODATA_SECTION; + +/* Name of text, data, and rodata sections used in varasm.c. */ +char *arc_text_section; +char *arc_data_section; +char *arc_rodata_section; + +/* Array of valid operand punctuation characters. */ +char arc_punct_chars[256]; + +/* Variables used by arc_final_prescan_insn to implement conditional + execution. */ +static int arc_ccfsm_state; +static int arc_ccfsm_current_cc; +static rtx arc_ccfsm_target_insn; +static int arc_ccfsm_target_label; + +/* The maximum number of insns skipped which will be conditionalised if + possible. */ +#define MAX_INSNS_SKIPPED 3 + +/* A nop is needed between a 4 byte insn that sets the condition codes and + a branch that uses them (the same isn't true for an 8 byte insn that sets + the condition codes). Set by arc_final_prescan_insn. Used by + arc_print_operand. */ +static int last_insn_set_cc_p; +static int current_insn_set_cc_p; +static void record_cc_ref (); + +void arc_init_reg_tables (); + +/* Called by OVERRIDE_OPTIONS to initialize various things. */ + +void +arc_init (void) +{ + if (arc_cpu_string == 0 + || !strcmp (arc_cpu_string, "base")) + { + /* Ensure we have a printable value for the .cpu pseudo-op. */ + arc_cpu_string = "base"; + arc_cpu_type = 0; + arc_mangle_cpu = NULL; + } + else if (ARC_EXTENSION_CPU (arc_cpu_string)) + ; /* nothing to do */ + else + { + error ("bad value (%s) for -mcpu switch", arc_cpu_string); + arc_cpu_string = "base"; + arc_cpu_type = 0; + arc_mangle_cpu = NULL; + } + + /* Set the pseudo-ops for the various standard sections. */ + arc_text_section = xmalloc (strlen (arc_text_string) + sizeof (ARC_SECTION_FORMAT) + 1); + sprintf (arc_text_section, ARC_SECTION_FORMAT, arc_text_string); + arc_data_section = xmalloc (strlen (arc_data_string) + sizeof (ARC_SECTION_FORMAT) + 1); + sprintf (arc_data_section, ARC_SECTION_FORMAT, arc_data_string); + arc_rodata_section = xmalloc (strlen (arc_rodata_string) + sizeof (ARC_SECTION_FORMAT) + 1); + sprintf (arc_rodata_section, ARC_SECTION_FORMAT, arc_rodata_string); + + arc_init_reg_tables (); + + /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */ + memset (arc_punct_chars, 0, sizeof (arc_punct_chars)); + arc_punct_chars['#'] = 1; + arc_punct_chars['*'] = 1; + arc_punct_chars['?'] = 1; + arc_punct_chars['!'] = 1; + arc_punct_chars['~'] = 1; +} + +/* The condition codes of the ARC, and the inverse function. */ +static char *arc_condition_codes[] = +{ + "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv", + "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0 +}; + +#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1) + +/* Returns the index of the ARC condition code string in + `arc_condition_codes'. COMPARISON should be an rtx like + `(eq (...) (...))'. */ + +static int +get_arc_condition_code (comparison) + rtx comparison; +{ + switch (GET_CODE (comparison)) + { + case EQ : return 2; + case NE : return 3; + case GT : return 10; + case LE : return 11; + case GE : return 12; + case LT : return 13; + case GTU : return 14; + case LEU : return 15; + case LTU : return 6; + case GEU : return 7; + default : abort (); + } + /*NOTREACHED*/ + return (42); +} + +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, + return the mode to be used for the comparison. */ + +enum machine_mode +arc_select_cc_mode (op, x, y) + enum rtx_code op; + rtx x, y; +{ + switch (op) + { + case EQ : + case NE : + return CCZNmode; + default : + switch (GET_CODE (x)) + { + case AND : + case IOR : + case XOR : + case SIGN_EXTEND : + case ZERO_EXTEND : + return CCZNmode; + case ASHIFT : + case ASHIFTRT : + case LSHIFTRT : + return CCZNCmode; + } + } + return CCmode; +} + +/* Vectors to keep interesting information about registers where it can easily + be got. We use to use the actual mode value as the bit number, but there + is (or may be) more than 32 modes now. Instead we use two tables: one + indexed by hard register number, and one indexed by mode. */ + +/* The purpose of arc_mode_class is to shrink the range of modes so that + they all fit (as bit numbers) in a 32 bit word (again). Each real mode is + mapped into one arc_mode_class mode. */ + +enum arc_mode_class { + C_MODE, + S_MODE, D_MODE, T_MODE, O_MODE, + SF_MODE, DF_MODE, TF_MODE, OF_MODE +}; + +/* Modes for condition codes. */ +#define C_MODES (1 << (int) C_MODE) + +/* Modes for single-word and smaller quantities. */ +#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE)) + +/* Modes for double-word and smaller quantities. */ +#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE)) + +/* Modes for quad-word and smaller quantities. */ +#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE)) + +/* Value is 1 if register/mode pair is acceptable on arc. */ + +unsigned int arc_hard_regno_mode_ok[] = { + T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, + T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, + T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES, + D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, + + /* ??? Leave these as S_MODES for now. */ + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, + S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES +}; + +unsigned int arc_mode_class [NUM_MACHINE_MODES]; + +enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER]; + +void +arc_init_reg_tables () +{ + int i; + + for (i = 0; i < NUM_MACHINE_MODES; i++) + { + switch (GET_MODE_CLASS (i)) + { + case MODE_INT: + case MODE_PARTIAL_INT: + case MODE_COMPLEX_INT: + if (GET_MODE_SIZE (i) <= 4) + arc_mode_class[i] = 1 << (int) S_MODE; + else if (GET_MODE_SIZE (i) == 8) + arc_mode_class[i] = 1 << (int) D_MODE; + else if (GET_MODE_SIZE (i) == 16) + arc_mode_class[i] = 1 << (int) T_MODE; + else if (GET_MODE_SIZE (i) == 32) + arc_mode_class[i] = 1 << (int) O_MODE; + else + arc_mode_class[i] = 0; + break; + case MODE_FLOAT: + case MODE_COMPLEX_FLOAT: + if (GET_MODE_SIZE (i) <= 4) + arc_mode_class[i] = 1 << (int) SF_MODE; + else if (GET_MODE_SIZE (i) == 8) + arc_mode_class[i] = 1 << (int) DF_MODE; + else if (GET_MODE_SIZE (i) == 16) + arc_mode_class[i] = 1 << (int) TF_MODE; + else if (GET_MODE_SIZE (i) == 32) + arc_mode_class[i] = 1 << (int) OF_MODE; + else + arc_mode_class[i] = 0; + break; + case MODE_CC: + default: + /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so + we must explicitly check for them here. */ + if (i == (int) CCmode || i == (int) CCZNmode || i == (int) CCZNCmode) + arc_mode_class[i] = 1 << (int) C_MODE; + else + arc_mode_class[i] = 0; + break; + } + } + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (i < 60) + arc_regno_reg_class[i] = GENERAL_REGS; + else if (i == 60) + arc_regno_reg_class[i] = LPCOUNT_REG; + else if (i == 61) + arc_regno_reg_class[i] = NO_REGS /* CC_REG: must be NO_REGS */; + else + arc_regno_reg_class[i] = NO_REGS; + } +} + +/* ARC specific attribute support. + + The ARC has these attributes: + interrupt - for interrupt functions +*/ + +/* Return nonzero if IDENTIFIER is a valid decl attribute. */ + +int +arc_valid_machine_decl_attribute (type, attributes, identifier, args) + tree type; + tree attributes; + tree identifier; + tree args; +{ + if (identifier == get_identifier ("__interrupt__") + && list_length (args) == 1 + && TREE_CODE (TREE_VALUE (args)) == STRING_CST) + { + tree value = TREE_VALUE (args); + + if (!strcmp (TREE_STRING_POINTER (value), "ilink1") + || !strcmp (TREE_STRING_POINTER (value), "ilink2")) + return 1; + } + return 0; +} + +/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible, + and two if they are nearly compatible (which causes a warning to be + generated). */ + +int +arc_comp_type_attributes (type1, type2) + tree type1, type2; +{ + return 1; +} + +/* Set the default attributes for TYPE. */ + +void +arc_set_default_type_attributes (type) + tree type; +{ +} + +/* Acceptable arguments to the call insn. */ + +int +call_address_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (symbolic_operand (op, mode) + || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op)) + || (GET_CODE (op) == REG)); +} + +int +call_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM) + return 0; + op = XEXP (op, 0); + return call_address_operand (op, mode); +} + +/* Returns 1 if OP is a symbol reference. */ + +int +symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + case CONST : + return 1; + default: + return 0; + } +} + +/* Return truth value of statement that OP is a symbolic memory + operand of mode MODE. */ + +int +symbolic_memory_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + if (GET_CODE (op) != MEM) + return 0; + op = XEXP (op, 0); + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST + || GET_CODE (op) == LABEL_REF); +} + +/* Return true if OP is a short immediate (shimm) value. */ + +int +short_immediate_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return SMALL_INT (INTVAL (op)); +} + +/* Return true if OP will require a long immediate (limm) value. + This is currently only used when calculating length attributes. */ + +int +long_immediate_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF : + case LABEL_REF : + case CONST : + return 1; + case CONST_INT : + return !SMALL_INT (INTVAL (op)); + case CONST_DOUBLE : + /* These can happen because large unsigned 32 bit constants are + represented this way (the multiplication patterns can cause these + to be generated). They also occur for SFmode values. */ + return 1; + } + return 0; +} + +/* Return true if OP is a MEM that when used as a load or store address will + require an 8 byte insn. + Load and store instructions don't allow the same possibilities but they're + similar enough that this one function will do. + This is currently only used when calculating length attributes. */ + +int +long_immediate_loadstore_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM) + return 0; + + op = XEXP (op, 0); + switch (GET_CODE (op)) + { + case SYMBOL_REF : + case LABEL_REF : + case CONST : + return 1; + case CONST_INT : + /* This must be handled as "st c,[limm]". Ditto for load. + Technically, the assembler could translate some possibilities to + "st c,[limm/2 + limm/2]" if limm/2 will fit in a shimm, but we don't + assume that it does. */ + return 1; + case CONST_DOUBLE : + /* These can happen because large unsigned 32 bit constants are + represented this way (the multiplication patterns can cause these + to be generated). They also occur for SFmode values. */ + return 1; + case REG : + return 0; + case PLUS : + if (GET_CODE (XEXP (op, 1)) == CONST_INT + && !SMALL_INT (INTVAL (XEXP (op, 1)))) + return 1; + return 0; + } + return 0; +} + +/* Return true if OP is an acceptable argument for a single word + move source. */ + +int +move_src_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF : + case LABEL_REF : + case CONST : + return 1; + case CONST_INT : + return (LARGE_INT (INTVAL (op))); + case CONST_DOUBLE : + /* We can handle DImode integer constants in SImode if the value + (signed or unsigned) will fit in 32 bits. This is needed because + large unsigned 32 bit constants are represented as CONST_DOUBLEs. */ + if (mode == SImode) + return arc_double_limm_p (op); + /* We can handle 32 bit floating point constants. */ + if (mode == SFmode) + return GET_MODE (op) == SFmode; + return 0; + case REG : + return register_operand (op, mode); + case SUBREG : + /* (subreg (mem ...) ...) can occur here if the inner part was once a + pseudo-reg and is now a stack slot. */ + if (GET_CODE (SUBREG_REG (op)) == MEM) + return address_operand (XEXP (SUBREG_REG (op), 0), mode); + else + return register_operand (op, mode); + case MEM : + return address_operand (XEXP (op, 0), mode); + default : + return 0; + } +} + +/* Return true if OP is an acceptable argument for a double word + move source. */ + +int +move_double_src_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case REG : + return register_operand (op, mode); + case SUBREG : + /* (subreg (mem ...) ...) can occur here if the inner part was once a + pseudo-reg and is now a stack slot. */ + if (GET_CODE (SUBREG_REG (op)) == MEM) + return move_double_src_operand (SUBREG_REG (op), mode); + else + return register_operand (op, mode); + case MEM : + /* Disallow auto inc/dec for now. */ + if (GET_CODE (XEXP (op, 0)) == PRE_DEC + || GET_CODE (XEXP (op, 0)) == PRE_INC) + return 0; + return address_operand (XEXP (op, 0), mode); + case CONST_INT : + case CONST_DOUBLE : + return 1; + default : + return 0; + } +} + +/* Return true if OP is an acceptable argument for a move destination. */ + +int +move_dest_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case REG : + return register_operand (op, mode); + case SUBREG : + /* (subreg (mem ...) ...) can occur here if the inner part was once a + pseudo-reg and is now a stack slot. */ + if (GET_CODE (SUBREG_REG (op)) == MEM) + return address_operand (XEXP (SUBREG_REG (op), 0), mode); + else + return register_operand (op, mode); + case MEM : + return address_operand (XEXP (op, 0), mode); + default : + return 0; + } +} + +/* Return true if OP is valid load with update operand. */ + +int +load_update_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM + || GET_MODE (op) != mode) + return 0; + op = XEXP (op, 0); + if (GET_CODE (op) != PLUS + || GET_MODE (op) != Pmode + || !register_operand (XEXP (op, 0), Pmode) + || !nonmemory_operand (XEXP (op, 1), Pmode)) + return 0; + return 1; +} + +/* Return true if OP is valid store with update operand. */ + +int +store_update_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM + || GET_MODE (op) != mode) + return 0; + op = XEXP (op, 0); + if (GET_CODE (op) != PLUS + || GET_MODE (op) != Pmode + || !register_operand (XEXP (op, 0), Pmode) + || !(GET_CODE (XEXP (op, 1)) == CONST_INT + && SMALL_INT (INTVAL (XEXP (op, 1))))) + return 0; + return 1; +} + +/* Return true if OP is a non-volatile non-immediate operand. + Volatile memory refs require a special "cache-bypass" instruction + and only the standard movXX patterns are set up to handle them. */ + +int +nonvol_nonimm_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op)) + return 0; + return nonimmediate_operand (op, mode); +} + +/* Accept integer operands in the range -0x80000000..0x7fffffff. We have + to check the range carefully since this predicate is used in DImode + contexts. */ + +int +const_sint32_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + /* All allowed constants will fit a CONST_INT. */ + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff)); +} + +/* Accept integer operands in the range 0..0xffffffff. We have to check the + range carefully since this predicate is used in DImode contexts. Also, we + need some extra crud to make it work when hosted on 64-bit machines. */ + +int +const_uint32_operand (op, mode) + rtx op; + enum machine_mode mode; +{ +#if HOST_BITS_PER_WIDE_INT > 32 + /* All allowed constants will fit a CONST_INT. */ + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL)); +#else + return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0) + || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0)); +#endif +} + +/* Return 1 if OP is a comparison operator valid for the mode of CC. + This allows the use of MATCH_OPERATOR to recognize all the branch insns. + + Some insns only set a few bits in the condition code. So only allow those + comparisons that use the bits that are valid. */ + +int +proper_comparison_operator (op, mode) + rtx op; + enum machine_mode mode; +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != '<') + return 0; + + if (GET_MODE (XEXP (op, 0)) == CCZNmode) + return (code == EQ || code == NE); + if (GET_MODE (XEXP (op, 0)) == CCZNCmode) + return (code == EQ || code == NE + || code == LTU || code == GEU || code == GTU || code == LEU); + return 1; +} + +/* Misc. utilities. */ + +/* X and Y are two things to compare using CODE. Emit the compare insn and + return the rtx for the cc reg in the proper mode. */ + +rtx +gen_compare_reg (code, x, y) + enum rtx_code code; + rtx x, y; +{ + enum machine_mode mode = SELECT_CC_MODE (code, x, y); + rtx cc_reg; + + cc_reg = gen_rtx (REG, mode, 61); + + emit_insn (gen_rtx (SET, VOIDmode, cc_reg, + gen_rtx (COMPARE, mode, x, y))); + + return cc_reg; +} + +/* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number). + We assume the value can be either signed or unsigned. */ + +int +arc_double_limm_p (value) + rtx value; +{ + HOST_WIDE_INT low, high; + + if (GET_CODE (value) != CONST_DOUBLE) + abort (); + + low = CONST_DOUBLE_LOW (value); + high = CONST_DOUBLE_HIGH (value); + + if (low & 0x80000000) + { + return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0) + || (((low & - (unsigned HOST_WIDE_INT) 0x80000000) + == - (unsigned HOST_WIDE_INT) 0x80000000) + && high == -1)); + } + else + { + return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0; + } +} + +/* Do any needed setup for a variadic function. For the ARC, we must + create a register parameter block, and then copy any anonymous arguments + in registers to memory. + + CUM has not been updated for the last named argument which has type TYPE + and mode MODE, and we rely on this fact. + + We do things a little weird here. We're supposed to only allocate space + for the anonymous arguments. However we need to keep the stack eight byte + aligned. So we round the space up if necessary, and leave it to va-arc.h + to compensate. */ + +void +arc_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int *pretend_size; + int no_rtl; +{ + int first_anon_arg; + + /* All BLKmode values are passed by reference. */ + if (mode == BLKmode) + abort (); + + /* We must treat `__builtin_va_alist' as an anonymous arg. */ + if (current_function_varargs) + first_anon_arg = *cum; + else + first_anon_arg = *cum + ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) + / UNITS_PER_WORD); + + if (first_anon_arg < MAX_ARC_PARM_REGS && !no_rtl) + { + /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */ + int first_reg_offset = first_anon_arg; + /* Size in words to "pretend" allocate. */ + int size = MAX_ARC_PARM_REGS - first_reg_offset; + /* Extra slop to keep stack eight byte aligned. */ + int align_slop = size & 1; + rtx regblock; + + regblock = gen_rtx (MEM, BLKmode, + plus_constant (arg_pointer_rtx, + FIRST_PARM_OFFSET (0) + + align_slop * UNITS_PER_WORD)); + move_block_from_reg (first_reg_offset, regblock, + MAX_ARC_PARM_REGS - first_reg_offset, + ((MAX_ARC_PARM_REGS - first_reg_offset) + * UNITS_PER_WORD)); + + *pretend_size = ((MAX_ARC_PARM_REGS - first_reg_offset + align_slop) + * UNITS_PER_WORD); + } +} + +/* Cost functions. */ + +/* Provide the costs of an addressing mode that contains ADDR. + If ADDR is not a valid address, its cost is irrelevant. */ + +int +arc_address_cost (addr) + rtx addr; +{ + switch (GET_CODE (addr)) + { + case REG : + /* This is handled in the macro that calls us. + It's here for documentation. */ + return 1; + + case LABEL_REF : + case SYMBOL_REF : + case CONST : + return 2; + + case PLUS : + { + register rtx plus0 = XEXP (addr, 0); + register rtx plus1 = XEXP (addr, 1); + + if (GET_CODE (plus0) != REG) + break; + + switch (GET_CODE (plus1)) + { + case CONST_INT : + return SMALL_INT (plus1) ? 1 : 2; + case CONST : + case SYMBOL_REF : + case LABEL_REF : + return 2; + default: + break; + } + break; + } + } + + return 4; +} + +/* Function prologue/epilogue handlers. */ + +/* ARC stack frames look like: + + Before call After call + +-----------------------+ +-----------------------+ + | | | | + high | local variables, | | local variables, | + mem | reg save area, etc. | | reg save area, etc. | + | | | | + +-----------------------+ +-----------------------+ + | | | | + | arguments on stack. | | arguments on stack. | + | | | | + SP+16->+-----------------------+FP+48->+-----------------------+ + | 4 word save area for | | reg parm save area, | + | return addr, prev %fp | | only created for | + SP+0->+-----------------------+ | variable argument | + | functions | + FP+16->+-----------------------+ + | 4 word save area for | + | return addr, prev %fp | + FP+0->+-----------------------+ + | | + | local variables | + | | + +-----------------------+ + | | + | register save area | + | | + +-----------------------+ + | | + | alloca allocations | + | | + +-----------------------+ + | | + | arguments on stack | + | | + SP+16->+-----------------------+ + low | 4 word save area for | + memory | return addr, prev %fp | + SP+0->+-----------------------+ + +Notes: +1) The "reg parm save area" does not exist for non variable argument fns. + The "reg parm save area" can be eliminated completely if we created our + own va-arc.h, but that has tradeoffs as well (so it's not done). */ + +/* Structure to be filled in by arc_compute_frame_size with register + save masks, and offsets for the current function. */ +struct arc_frame_info +{ + unsigned int total_size; /* # bytes that the entire frame takes up. */ + unsigned int extra_size; /* # bytes of extra stuff. */ + unsigned int pretend_size; /* # bytes we push and pretend caller did. */ + unsigned int args_size; /* # bytes that outgoing arguments take up. */ + unsigned int reg_size; /* # bytes needed to store regs. */ + unsigned int var_size; /* # bytes that variables take up. */ + unsigned int reg_offset; /* Offset from new sp to store regs. */ + unsigned int gmask; /* Mask of saved gp registers. */ + int initialized; /* Nonzero if frame size already calculated. */ +}; + +/* Current frame information calculated by arc_compute_frame_size. */ +static struct arc_frame_info current_frame_info; + +/* Zero structure to initialize current_frame_info. */ +static struct arc_frame_info zero_frame_info; + +/* Type of function DECL. + + The result is cached. To reset the cache at the end of a function, + call with DECL = NULL_TREE. */ + +enum arc_function_type +arc_compute_function_type (decl) + tree decl; +{ + tree a; + /* Cached value. */ + static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN; + /* Last function we were called for. */ + static tree last_fn = NULL_TREE; + + /* Resetting the cached value? */ + if (decl == NULL_TREE) + { + fn_type = ARC_FUNCTION_UNKNOWN; + last_fn = NULL_TREE; + return fn_type; + } + + if (decl == last_fn && fn_type != ARC_FUNCTION_UNKNOWN) + return fn_type; + + /* Assume we have a normal function (not an interrupt handler). */ + fn_type = ARC_FUNCTION_NORMAL; + + /* Now see if this is an interrupt handler. */ + for (a = DECL_MACHINE_ATTRIBUTES (current_function_decl); + a; + a = TREE_CHAIN (a)) + { + tree name = TREE_PURPOSE (a), args = TREE_VALUE (a); + + if (name == get_identifier ("__interrupt__") + && list_length (args) == 1 + && TREE_CODE (TREE_VALUE (args)) == STRING_CST) + { + tree value = TREE_VALUE (args); + + if (!strcmp (TREE_STRING_POINTER (value), "ilink1")) + fn_type = ARC_FUNCTION_ILINK1; + else if (!strcmp (TREE_STRING_POINTER (value), "ilink2")) + fn_type = ARC_FUNCTION_ILINK2; + else + abort (); + break; + } + } + + last_fn = decl; + return fn_type; +} + +#define ILINK1_REGNUM 29 +#define ILINK2_REGNUM 30 +#define RETURN_ADDR_REGNUM 31 +#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) +#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) + +/* Tell prologue and epilogue if register REGNO should be saved / restored. + The return address and frame pointer are treated separately. + Don't consider them here. */ +#define MUST_SAVE_REGISTER(regno, interrupt_p) \ +((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \ + && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p))) + +#define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM]) + +/* Return the bytes needed to compute the frame pointer from the current + stack pointer. + + SIZE is the size needed for local variables. */ + +unsigned int +arc_compute_frame_size (size) + int size; /* # of var. bytes allocated. */ +{ + int regno; + unsigned int total_size, var_size, args_size, pretend_size, extra_size; + unsigned int reg_size, reg_offset; + unsigned int gmask; + enum arc_function_type fn_type; + int interrupt_p; + + var_size = size; + args_size = current_function_outgoing_args_size; + pretend_size = current_function_pretend_args_size; + extra_size = FIRST_PARM_OFFSET (0); + total_size = extra_size + pretend_size + args_size + var_size; + reg_offset = FIRST_PARM_OFFSET(0) + current_function_outgoing_args_size; + reg_size = 0; + gmask = 0; + + /* See if this is an interrupt handler. Call used registers must be saved + for them too. */ + fn_type = arc_compute_function_type (current_function_decl); + interrupt_p = ARC_INTERRUPT_P (fn_type); + + /* Calculate space needed for registers. + ??? We ignore the extension registers for now. */ + + for (regno = 0; regno <= 31; regno++) + { + if (MUST_SAVE_REGISTER (regno, interrupt_p)) + { + reg_size += UNITS_PER_WORD; + gmask |= 1 << regno; + } + } + + total_size += reg_size; + + /* If the only space to allocate is the fp/blink save area this is an + empty frame. However, if we'll be making a function call we need to + allocate a stack frame for our callee's fp/blink save area. */ + if (total_size == extra_size + && !MUST_SAVE_RETURN_ADDR) + total_size = extra_size = 0; + + total_size = ARC_STACK_ALIGN (total_size); + + /* Save computed information. */ + current_frame_info.total_size = total_size; + current_frame_info.extra_size = extra_size; + current_frame_info.pretend_size = pretend_size; + current_frame_info.var_size = var_size; + current_frame_info.args_size = args_size; + current_frame_info.reg_size = reg_size; + current_frame_info.reg_offset = reg_offset; + current_frame_info.gmask = gmask; + current_frame_info.initialized = reload_completed; + + /* Ok, we're done. */ + return total_size; +} + +/* Common code to save/restore registers. */ + +void +arc_save_restore (file, base_reg, offset, gmask, op) + FILE *file; + char *base_reg; + unsigned int offset; + unsigned int gmask; + char *op; +{ + int regno; + + if (gmask == 0) + return; + + for (regno = 0; regno <= 31; regno++) + { + if ((gmask & (1L << regno)) != 0) + { + fprintf (file, "\t%s %s,[%s,%d]\n", + op, reg_names[regno], base_reg, offset); + offset += UNITS_PER_WORD; + } + } +} + +/* Set up the stack and frame pointer (if desired) for the function. */ + +void +arc_output_function_prologue (file, size) + FILE *file; + int size; +{ + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + char *fp_str = reg_names[FRAME_POINTER_REGNUM]; + unsigned int gmask = current_frame_info.gmask; + enum arc_function_type fn_type = arc_compute_function_type (current_function_decl); + + /* If this is an interrupt handler, set up our stack frame. + ??? Optimize later. */ + if (ARC_INTERRUPT_P (fn_type)) + { + fprintf (file, "\t%s interrupt handler\n", + ASM_COMMENT_START); + fprintf (file, "\tsub %s,%s,16\n", sp_str, sp_str); + } + + /* This is only for the human reader. */ + fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n", + ASM_COMMENT_START, ASM_COMMENT_START, + current_frame_info.var_size, + current_frame_info.reg_size / 4, + current_frame_info.args_size, + current_frame_info.extra_size); + + size = ARC_STACK_ALIGN (size); + size = (! current_frame_info.initialized + ? arc_compute_frame_size (size) + : current_frame_info.total_size); + + /* These cases shouldn't happen. Catch them now. */ + if (size == 0 && gmask) + abort (); + + /* Allocate space for register arguments if this is a variadic function. */ + if (current_frame_info.pretend_size != 0) + fprintf (file, "\tsub %s,%s,%d\n", + sp_str, sp_str, current_frame_info.pretend_size); + + /* The home-grown ABI says link register is saved first. */ + if (MUST_SAVE_RETURN_ADDR) + fprintf (file, "\tst %s,[%s,%d]\n", + reg_names[RETURN_ADDR_REGNUM], sp_str, UNITS_PER_WORD); + + /* Set up the previous frame pointer next (if we need to). */ + if (frame_pointer_needed) + { + fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str); + fprintf (file, "\tmov %s,%s\n", fp_str, sp_str); + } + + /* ??? We don't handle the case where the saved regs are more than 252 + bytes away from sp. This can be handled by decrementing sp once, saving + the regs, and then decrementing it again. The epilogue doesn't have this + problem as the `ld' insn takes reg+limm values (though it would be more + efficient to avoid reg+limm). */ + + /* Allocate the stack frame. */ + if (size - current_frame_info.pretend_size > 0) + fprintf (file, "\tsub %s,%s,%d\n", + sp_str, sp_str, size - current_frame_info.pretend_size); + + /* Save any needed call-saved regs (and call-used if this is an + interrupt handler). */ + arc_save_restore (file, sp_str, current_frame_info.reg_offset, + /* The zeroing of these two bits is unnecessary, + but leave this in for clarity. */ + gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), + "st"); + + fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START); +} + +/* Do any necessary cleanup after a function to restore stack, frame, + and regs. */ + +void +arc_output_function_epilogue (file, size) + FILE *file; + int size; +{ + rtx epilogue_delay = current_function_epilogue_delay_list; + int noepilogue = FALSE; + enum arc_function_type fn_type = arc_compute_function_type (current_function_decl); + + /* This is only for the human reader. */ + fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START); + + size = ARC_STACK_ALIGN (size); + size = (!current_frame_info.initialized + ? arc_compute_frame_size (size) + : current_frame_info.total_size); + + if (size == 0 && epilogue_delay == 0) + { + rtx insn = get_last_insn (); + + /* If the last insn was a BARRIER, we don't have to write any code + because a jump (aka return) was put there. */ + if (GET_CODE (insn) == NOTE) + insn = prev_nonnote_insn (insn); + if (insn && GET_CODE (insn) == BARRIER) + noepilogue = TRUE; + } + + if (!noepilogue) + { + unsigned int pretend_size = current_frame_info.pretend_size; + unsigned int frame_size = size - pretend_size; + int restored, fp_restored_p; + int can_trust_sp_p = !current_function_calls_alloca; + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + char *fp_str = reg_names[FRAME_POINTER_REGNUM]; + + /* ??? There are lots of optimizations that can be done here. + EG: Use fp to restore regs if it's closer. + Maybe in time we'll do them all. For now, always restore regs from + sp, but don't restore sp if we don't have to. */ + + if (!can_trust_sp_p) + { + if (!frame_pointer_needed) + abort (); + fprintf (file,"\tsub %s,%s,%d\t\t%s sp not trusted here\n", + sp_str, fp_str, frame_size, ASM_COMMENT_START); + } + + /* Restore any saved registers. */ + arc_save_restore (file, sp_str, current_frame_info.reg_offset, + /* The zeroing of these two bits is unnecessary, + but leave this in for clarity. */ + current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), + "ld"); + + if (MUST_SAVE_RETURN_ADDR) + fprintf (file, "\tld %s,[%s,%d]\n", + reg_names[RETURN_ADDR_REGNUM], + frame_pointer_needed ? fp_str : sp_str, + UNITS_PER_WORD + (frame_pointer_needed ? 0 : frame_size)); + + /* Keep track of how much of the stack pointer we've restored. + It makes the following a lot more readable. */ + restored = 0; + fp_restored_p = 0; + + /* We try to emit the epilogue delay slot insn right after the load + of the return address register so that it can execute with the + stack intact. Secondly, loads are delayed. */ + /* ??? If stack intactness is important, always emit now. */ + if (MUST_SAVE_RETURN_ADDR && epilogue_delay != NULL_RTX) + { + final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); + epilogue_delay = NULL_RTX; + } + + if (frame_pointer_needed) + { + /* Try to restore the frame pointer in the delay slot. We can't, + however, if any of these is true. */ + if (epilogue_delay != NULL_RTX + || !SMALL_INT (frame_size) + || pretend_size + || ARC_INTERRUPT_P (fn_type)) + { + /* Note that we restore fp and sp here! */ + fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size); + restored += frame_size; + fp_restored_p = 1; + } + } + else if (!SMALL_INT (size /* frame_size + pretend_size */) + || ARC_INTERRUPT_P (fn_type)) + { + fprintf (file, "\tadd %s,%s,%d\n", sp_str, sp_str, frame_size); + restored += frame_size; + } + + /* These must be done before the return insn because the delay slot + does the final stack restore. */ + if (ARC_INTERRUPT_P (fn_type)) + { + if (epilogue_delay) + { + final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); + } + } + + /* Emit the return instruction. */ + { + static int regs[4] = { + 0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM + }; + fprintf (file, "\tj.d %s\n", reg_names[regs[fn_type]]); + } + + /* If the only register saved is the return address, we need a + nop, unless we have an instruction to put into it. Otherwise + we don't since reloading multiple registers doesn't reference + the register being loaded. */ + + if (ARC_INTERRUPT_P (fn_type)) + fprintf (file, "\tadd %s,%s,16\n", sp_str, sp_str); + else if (epilogue_delay != NULL_RTX) + { + if (frame_pointer_needed && !fp_restored_p) + abort (); + if (restored < size) + abort (); + final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); + } + else if (frame_pointer_needed && !fp_restored_p) + { + if (!SMALL_INT (frame_size)) + abort (); + /* Note that we restore fp and sp here! */ + fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size); + } + else if (restored < size) + { + if (!SMALL_INT (size - restored)) + abort (); + fprintf (file, "\tadd %s,%s,%d\n", + sp_str, sp_str, size - restored); + } + else + fprintf (file, "\tnop\n"); + } + + /* Reset state info for each function. */ + current_frame_info = zero_frame_info; + arc_compute_function_type (NULL_TREE); +} + +/* Define the number of delay slots needed for the function epilogue. + + Interrupt handlers can't have any epilogue delay slots (it's always needed + for something else, I think). For normal functions, we have to worry about + using call-saved regs as they'll be restored before the delay slot insn. + Functions with non-empty frames already have enough choices for the epilogue + delay slot so for now we only consider functions with empty frames. */ + +int +arc_delay_slots_for_epilogue () +{ + if (arc_compute_function_type (current_function_decl) != ARC_FUNCTION_NORMAL) + return 0; + if (!current_frame_info.initialized) + (void) arc_compute_frame_size (get_frame_size ()); + if (current_frame_info.total_size == 0) + return 1; + return 0; +} + +/* Return true if TRIAL is a valid insn for the epilogue delay slot. + Any single length instruction which doesn't reference the stack or frame + pointer or any call-saved register is OK. SLOT will always be 0. */ + +int +arc_eligible_for_epilogue_delay (trial, slot) + rtx trial; + int slot; +{ + if (slot != 0) + abort (); + + if (get_attr_length (trial) == 1 + /* If registers where saved, presumably there's more than enough + possibilities for the delay slot. The alternative is something + more complicated (of course, if we expanded the epilogue as rtl + this problem would go away). */ + /* ??? Note that this will always be true since only functions with + empty frames have epilogue delay slots. See + arc_delay_slots_for_epilogue. */ + && current_frame_info.gmask == 0 + && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial)) + && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial))) + return 1; + return 0; +} + +/* PIC */ + +/* Set up PIC-specific rtl. This should not cause any insns + to be emitted. */ + +void +arc_initialize_pic () +{ + /* nothing to do */ +} + +/* Emit special PIC prologues and epilogues. */ + +void +arc_finalize_pic () +{ + /* nothing to do */ +} + +/* Return true if OP is a shift operator. */ + +int +shift_operator (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case ASHIFTRT: + case LSHIFTRT: + case ASHIFT: + return 1; + default: + return 0; + } +} + +/* Output the assembler code for doing a shift. + We go to a bit of trouble to generate efficient code as the ARC only has + single bit shifts. This is taken from the h8300 port. We only have one + mode of shifting and can't access individual bytes like the h8300 can, so + this is greatly simplified (at the expense of not generating hyper- + efficient code). + + This function is not used if the variable shift insns are present. */ + +/* ??? We assume the output operand is the same as operand 1. + This can be optimized (deleted) in the case of 1 bit shifts. */ +/* ??? We use the loop register here. We don't use it elsewhere (yet) and + using it here will give us a chance to play with it. */ + +char * +output_shift (operands) + rtx *operands; +{ + static int loopend_lab; + rtx shift = operands[3]; + enum machine_mode mode = GET_MODE (shift); + enum rtx_code code = GET_CODE (shift); + char *shift_one; + + if (mode != SImode) + abort (); + + switch (code) + { + case ASHIFT: shift_one = "asl %0,%0"; break; + case ASHIFTRT: shift_one = "asr %0,%0"; break; + case LSHIFTRT: shift_one = "lsr %0,%0"; break; + default: abort (); + } + + if (GET_CODE (operands[2]) != CONST_INT) + { + if (optimize) + output_asm_insn ("mov lp_count,%2", operands); + else + output_asm_insn ("mov %4,%2", operands); + goto shiftloop; + } + else + { + int n = INTVAL (operands[2]); + + /* If the count is negative, make it 0. */ + if (n < 0) + n = 0; + /* If the count is too big, truncate it. + ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to + do the intuitive thing. */ + else if (n > GET_MODE_BITSIZE (mode)) + n = GET_MODE_BITSIZE (mode); + + /* First see if we can do them inline. */ + if (n <= 8) + { + while (--n >= 0) + output_asm_insn (shift_one, operands); + } + /* See if we can use a rotate/and. */ + else if (n == BITS_PER_WORD - 1) + { + switch (code) + { + case ASHIFT : + output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands); + break; + case ASHIFTRT : + /* The ARC doesn't have a rol insn. Use something else. */ + output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands); + break; + case LSHIFTRT : + /* The ARC doesn't have a rol insn. Use something else. */ + output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands); + break; + } + } + /* Must loop. */ + else + { + char buf[100]; + + if (optimize) + output_asm_insn ("mov lp_count,%c2", operands); + else + output_asm_insn ("mov %4,%c2", operands); + shiftloop: + if (optimize) + { + if (flag_pic) + sprintf ("lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start", + ASM_COMMENT_START); + else + sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2", + ASM_COMMENT_START); + output_asm_insn (buf, operands); + output_asm_insn ("sr %4,[lp_start]", operands); + output_asm_insn ("add %4,%4,1", operands); + output_asm_insn ("sr %4,[lp_end]", operands); + output_asm_insn ("nop\n\tnop", operands); + if (flag_pic) + asm_fprintf (asm_out_file, "\t%s single insn loop\n", + ASM_COMMENT_START); + else + asm_fprintf (asm_out_file, "1:\t%s single insn loop\n", + ASM_COMMENT_START); + output_asm_insn (shift_one, operands); + } + else + { + asm_fprintf (asm_out_file, "1:\t%s begin shift loop\n", + ASM_COMMENT_START); + output_asm_insn ("sub.f %4,%4,1", operands); + output_asm_insn ("nop", operands); + output_asm_insn ("bn.nd 2f", operands); + output_asm_insn (shift_one, operands); + output_asm_insn ("b.nd 1b", operands); + asm_fprintf (asm_out_file, "2:\t%s end shift loop\n", + ASM_COMMENT_START); + } + } + } + + return ""; +} + +/* Nested function support. */ + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ + +void +arc_initialize_trampoline (tramp, fnaddr, cxt) + rtx tramp, fnaddr, cxt; +{ +} + +/* Set the cpu type and print out other fancy things, + at the top of the file. */ + +void +arc_asm_file_start (file) + FILE *file; +{ + fprintf (file, "\t.cpu %s\n", arc_cpu_string); +} + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ + +void +arc_print_operand (file, x, code) + FILE *file; + rtx x; + int code; +{ + switch (code) + { + case '#' : + /* Conditional branches. For now these are equivalent. */ + case '*' : + /* Unconditional branches. Output the appropriate delay slot suffix. */ + if (!final_sequence || XVECLEN (final_sequence, 0) == 1) + { + /* There's nothing in the delay slot. */ + fputs (".nd", file); + } + else + { + rtx jump = XVECEXP (final_sequence, 0, 0); + rtx delay = XVECEXP (final_sequence, 0, 1); + if (INSN_ANNULLED_BRANCH_P (jump)) + fputs (INSN_FROM_TARGET_P (delay) ? ".jd" : ".nd", file); + else + fputs (".d", file); + } + return; + case '?' : /* with leading "." */ + case '!' : /* without leading "." */ + /* This insn can be conditionally executed. See if the ccfsm machinery + says it should be conditionalized. */ + if (arc_ccfsm_state == 3 || arc_ccfsm_state == 4) + { + /* Is this insn in a delay slot? */ + if (final_sequence && XVECLEN (final_sequence, 0) == 2) + { + rtx insn = XVECEXP (final_sequence, 0, 1); + + /* If the insn is annulled and is from the target path, we need + to inverse the condition test. */ + if (INSN_ANNULLED_BRANCH_P (insn)) + { + if (INSN_FROM_TARGET_P (insn)) + fprintf (file, "%s%s", + code == '?' ? "." : "", + arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc)]); + else + fprintf (file, "%s%s", + code == '?' ? "." : "", + arc_condition_codes[arc_ccfsm_current_cc]); + } + else + /* This insn is executed for either path, so don't + conditionalize it at all. */ + ; /* nothing to do */ + } + else + { + /* This insn isn't in a delay slot. */ + fprintf (file, "%s%s", + code == '?' ? "." : "", + arc_condition_codes[arc_ccfsm_current_cc]); + } + } + return; + case '~' : + /* Output a nop if we're between a set of the condition codes, + and a conditional branch. */ + if (last_insn_set_cc_p) + fputs ("nop\n\t", file); + return; + case 'd' : + fputs (arc_condition_codes[get_arc_condition_code (x)], file); + return; + case 'D' : + fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE + (get_arc_condition_code (x))], + file); + return; + case 'R' : + /* Write second word of DImode or DFmode reference, + register or memory. */ + if (GET_CODE (x) == REG) + fputs (reg_names[REGNO (x)+1], file); + else if (GET_CODE (x) == MEM) + { + fputc ('[', file); + /* Handle possible auto-increment. Since it is pre-increment and + we have already done it, we can just use an offset of four. */ + /* ??? This is taken from rs6000.c I think. I don't think it is + currently necessary, but keep it around. */ + if (GET_CODE (XEXP (x, 0)) == PRE_INC + || GET_CODE (XEXP (x, 0)) == PRE_DEC) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4)); + else + output_address (plus_constant (XEXP (x, 0), 4)); + fputc (']', file); + } + else + output_operand_lossage ("invalid operand to %R code"); + return; + case 'S' : + if ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x)) + || GET_CODE (x) == LABEL_REF) + { + fprintf (file, "%%st("); + output_addr_const (file, x); + fprintf (file, ")"); + return; + } + break; + case 'H' : + case 'L' : + if (GET_CODE (x) == REG) + { + /* L = least significant word, H = most significant word */ + if ((TARGET_BIG_ENDIAN != 0) ^ (code == 'L')) + fputs (reg_names[REGNO (x)], file); + else + fputs (reg_names[REGNO (x)+1], file); + } + else if (GET_CODE (x) == CONST_INT + || GET_CODE (x) == CONST_DOUBLE) + { + rtx first, second; + + split_double (x, &first, &second); + fprintf (file, "0x%08lx", + code == 'L' ? INTVAL (first) : INTVAL (second)); + } + else + output_operand_lossage ("invalid operand to %H/%L code"); + return; + case 'A' : + { + REAL_VALUE_TYPE d; + char str[30]; + + if (GET_CODE (x) != CONST_DOUBLE + || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT) + abort (); + REAL_VALUE_FROM_CONST_DOUBLE (d, x); + REAL_VALUE_TO_DECIMAL (d, "%.20e", str); + fprintf (file, "%s", str); + return; + } + case 'U' : + /* Output a load/store with update indicator if appropriate. */ + if (GET_CODE (x) == MEM) + { + if (GET_CODE (XEXP (x, 0)) == PRE_INC + || GET_CODE (XEXP (x, 0)) == PRE_DEC) + fputs (".a", file); + } + else + output_operand_lossage ("invalid operand to %U code"); + return; + case 'V' : + /* Output cache bypass indicator for a load/store insn. Volatile memory + refs are defined to use the cache bypass mechanism. */ + if (GET_CODE (x) == MEM) + { + if (MEM_VOLATILE_P (x)) + fputs (".di", file); + } + else + output_operand_lossage ("invalid operand to %V code"); + return; + case 0 : + /* Do nothing special. */ + break; + default : + /* Unknown flag. */ + output_operand_lossage ("invalid operand output code"); + } + + switch (GET_CODE (x)) + { + case REG : + fputs (reg_names[REGNO (x)], file); + break; + case MEM : + fputc ('[', file); + if (GET_CODE (XEXP (x, 0)) == PRE_INC) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), + GET_MODE_SIZE (GET_MODE (x)))); + else if (GET_CODE (XEXP (x, 0)) == PRE_DEC) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), + - GET_MODE_SIZE (GET_MODE (x)))); + else + output_address (XEXP (x, 0)); + fputc (']', file); + break; + case CONST_DOUBLE : + /* We handle SFmode constants here as output_addr_const doesn't. */ + if (GET_MODE (x) == SFmode) + { + REAL_VALUE_TYPE d; + long l; + + REAL_VALUE_FROM_CONST_DOUBLE (d, x); + REAL_VALUE_TO_TARGET_SINGLE (d, l); + fprintf (file, "0x%08lx", l); + break; + } + /* Fall through. Let output_addr_const deal with it. */ + default : + output_addr_const (file, x); + break; + } +} + +/* Print a memory address as an operand to reference that memory location. */ + +void +arc_print_operand_address (file, addr) + FILE *file; + rtx addr; +{ + register rtx base, index = 0; + int offset = 0; + + switch (GET_CODE (addr)) + { + case REG : + fputs (reg_names[REGNO (addr)], file); + break; + case SYMBOL_REF : + if (/*???*/ 0 && SYMBOL_REF_FLAG (addr)) + { + fprintf (file, "%%st("); + output_addr_const (file, addr); + fprintf (file, ")"); + } + else + output_addr_const (file, addr); + break; + case PLUS : + if (GET_CODE (XEXP (addr, 0)) == CONST_INT) + offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1); + else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) + offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0); + else + base = XEXP (addr, 0), index = XEXP (addr, 1); + if (GET_CODE (base) != REG) + abort (); + fputs (reg_names[REGNO (base)], file); + if (index == 0) + { + if (offset != 0) + fprintf (file, ",%d", offset); + } + else if (GET_CODE (index) == REG) + fprintf (file, ",%s", reg_names[REGNO (index)]); + else if (GET_CODE (index) == SYMBOL_REF) + fputc (',', file), output_addr_const (file, index); + else + abort (); + break; + case PRE_INC : + case PRE_DEC : + /* We shouldn't get here as we've lost the mode of the memory object + (which says how much to inc/dec by. */ + abort (); + break; + default : + output_addr_const (file, addr); + break; + } +} + +/* Update compare/branch separation marker. */ + +static void +record_cc_ref (insn) + rtx insn; +{ + last_insn_set_cc_p = current_insn_set_cc_p; + + switch (get_attr_cond (insn)) + { + case COND_SET : + case COND_SET_ZN : + case COND_SET_ZNC : + if (get_attr_length (insn) == 1) + current_insn_set_cc_p = 1; + else + current_insn_set_cc_p = 0; + break; + default : + current_insn_set_cc_p = 0; + break; + } +} + +/* Conditional execution support. + + This is based on the ARM port but for now is much simpler. + + A finite state machine takes care of noticing whether or not instructions + can be conditionally executed, and thus decrease execution time and code + size by deleting branch instructions. The fsm is controlled by + final_prescan_insn, and controls the actions of PRINT_OPERAND. The patterns + in the .md file for the branch insns also have a hand in this. */ + +/* The state of the fsm controlling condition codes are: + 0: normal, do nothing special + 1: don't output this insn + 2: don't output this insn + 3: make insns conditional + 4: make insns conditional + + State transitions (state->state by whom, under what condition): + 0 -> 1 final_prescan_insn, if insn is conditional branch + 0 -> 2 final_prescan_insn, if the `target' is an unconditional branch + 1 -> 3 branch patterns, after having not output the conditional branch + 2 -> 4 branch patterns, after having not output the conditional branch + 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached + (the target label has CODE_LABEL_NUMBER equal to + arc_ccfsm_target_label). + 4 -> 0 final_prescan_insn, if `target' unconditional branch is reached + + If the jump clobbers the conditions then we use states 2 and 4. + + A similar thing can be done with conditional return insns. + + We also handle separating branches from sets of the condition code. + This is done here because knowledge of the ccfsm state is required, + we may not be outputting the branch. */ + +void +arc_final_prescan_insn (insn, opvec, noperands) + rtx insn; + rtx *opvec; + int noperands; +{ + /* BODY will hold the body of INSN. */ + register rtx body = PATTERN (insn); + + /* This will be 1 if trying to repeat the trick (ie: do the `else' part of + an if/then/else), and things need to be reversed. */ + int reverse = 0; + + /* If we start with a return insn, we only succeed if we find another one. */ + int seeking_return = 0; + + /* START_INSN will hold the insn from where we start looking. This is the + first insn after the following code_label if REVERSE is true. */ + rtx start_insn = insn; + + /* Update compare/branch separation marker. */ + record_cc_ref (insn); + + /* Allow -mdebug-ccfsm to turn this off so we can see how well it does. + We can't do this in macro FINAL_PRESCAN_INSN because it's called from + final_scan_insn which has `optimize' as a local. */ + if (optimize < 2 || TARGET_NO_COND_EXEC) + return; + + /* If in state 4, check if the target branch is reached, in order to + change back to state 0. */ + if (arc_ccfsm_state == 4) + { + if (insn == arc_ccfsm_target_insn) + { + arc_ccfsm_target_insn = NULL; + arc_ccfsm_state = 0; + } + return; + } + + /* If in state 3, it is possible to repeat the trick, if this insn is an + unconditional branch to a label, and immediately following this branch + is the previous target label which is only used once, and the label this + branch jumps to is not too far off. Or in other words "we've done the + `then' part, see if we can do the `else' part." */ + if (arc_ccfsm_state == 3) + { + if (simplejump_p (insn)) + { + start_insn = next_nonnote_insn (start_insn); + if (GET_CODE (start_insn) == BARRIER) + { + /* ??? Isn't this always a barrier? */ + start_insn = next_nonnote_insn (start_insn); + } + if (GET_CODE (start_insn) == CODE_LABEL + && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label + && LABEL_NUSES (start_insn) == 1) + reverse = TRUE; + else + return; + } + else if (GET_CODE (body) == RETURN) + { + start_insn = next_nonnote_insn (start_insn); + if (GET_CODE (start_insn) == BARRIER) + start_insn = next_nonnote_insn (start_insn); + if (GET_CODE (start_insn) == CODE_LABEL + && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label + && LABEL_NUSES (start_insn) == 1) + { + reverse = TRUE; + seeking_return = 1; + } + else + return; + } + else + return; + } + + if (GET_CODE (insn) != JUMP_INSN) + return; + + /* This jump might be paralleled with a clobber of the condition codes, + the jump should always come first. */ + if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0) + body = XVECEXP (body, 0, 0); + + if (reverse + || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC + && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)) + { + int insns_skipped = 0, fail = FALSE, succeed = FALSE; + /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */ + int then_not_else = TRUE; + /* Nonzero if next insn must be the target label. */ + int next_must_be_target_label_p; + rtx this_insn = start_insn, label = 0; + + /* Register the insn jumped to. */ + if (reverse) + { + if (!seeking_return) + label = XEXP (SET_SRC (body), 0); + } + else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF) + label = XEXP (XEXP (SET_SRC (body), 1), 0); + else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF) + { + label = XEXP (XEXP (SET_SRC (body), 2), 0); + then_not_else = FALSE; + } + else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN) + seeking_return = 1; + else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN) + { + seeking_return = 1; + then_not_else = FALSE; + } + else + abort (); + + /* See how many insns this branch skips, and what kind of insns. If all + insns are okay, and the label or unconditional branch to the same + label is not too far away, succeed. */ + for (insns_skipped = 0, next_must_be_target_label_p = FALSE; + !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED; + insns_skipped++) + { + rtx scanbody; + + this_insn = next_nonnote_insn (this_insn); + if (!this_insn) + break; + + if (next_must_be_target_label_p) + { + if (GET_CODE (this_insn) == BARRIER) + continue; + if (GET_CODE (this_insn) == CODE_LABEL + && this_insn == label) + { + arc_ccfsm_state = 1; + succeed = TRUE; + } + else + fail = TRUE; + break; + } + + scanbody = PATTERN (this_insn); + + switch (GET_CODE (this_insn)) + { + case CODE_LABEL: + /* Succeed if it is the target label, otherwise fail since + control falls in from somewhere else. */ + if (this_insn == label) + { + arc_ccfsm_state = 1; + succeed = TRUE; + } + else + fail = TRUE; + break; + + case BARRIER: + /* Succeed if the following insn is the target label. + Otherwise fail. + If return insns are used then the last insn in a function + will be a barrier. */ + next_must_be_target_label_p = TRUE; + break; + + case CALL_INSN: + /* Can handle a call insn if there are no insns after it. + IE: The next "insn" is the target label. We don't have to + worry about delay slots as such insns are SEQUENCE's inside + INSN's. ??? It is possible to handle such insns though. */ + if (get_attr_cond (this_insn) == COND_CANUSE) + next_must_be_target_label_p = TRUE; + else + fail = TRUE; + break; + + case JUMP_INSN: + /* If this is an unconditional branch to the same label, succeed. + If it is to another label, do nothing. If it is conditional, + fail. */ + /* ??? Probably, the test for the SET and the PC are unnecessary. */ + + if (GET_CODE (scanbody) == SET + && GET_CODE (SET_DEST (scanbody)) == PC) + { + if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF + && XEXP (SET_SRC (scanbody), 0) == label && !reverse) + { + arc_ccfsm_state = 2; + succeed = TRUE; + } + else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE) + fail = TRUE; + } + else if (GET_CODE (scanbody) == RETURN + && seeking_return) + { + arc_ccfsm_state = 2; + succeed = TRUE; + } + else if (GET_CODE (scanbody) == PARALLEL) + { + if (get_attr_cond (this_insn) != COND_CANUSE) + fail = TRUE; + } + break; + + case INSN: + /* We can only do this with insns that can use the condition + codes (and don't set them). */ + if (GET_CODE (scanbody) == SET + || GET_CODE (scanbody) == PARALLEL) + { + if (get_attr_cond (this_insn) != COND_CANUSE) + fail = TRUE; + } + /* We can't handle other insns like sequences. */ + else + fail = TRUE; + break; + + default: + break; + } + } + + if (succeed) + { + if ((!seeking_return) && (arc_ccfsm_state == 1 || reverse)) + arc_ccfsm_target_label = CODE_LABEL_NUMBER (label); + else if (seeking_return || arc_ccfsm_state == 2) + { + while (this_insn && GET_CODE (PATTERN (this_insn)) == USE) + { + this_insn = next_nonnote_insn (this_insn); + if (this_insn && (GET_CODE (this_insn) == BARRIER + || GET_CODE (this_insn) == CODE_LABEL)) + abort (); + } + if (!this_insn) + { + /* Oh dear! we ran off the end, give up. */ + insn_extract (insn); + arc_ccfsm_state = 0; + arc_ccfsm_target_insn = NULL; + return; + } + arc_ccfsm_target_insn = this_insn; + } + else + abort (); + + /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from + what it was. */ + if (!reverse) + arc_ccfsm_current_cc = get_arc_condition_code (XEXP (SET_SRC (body), + 0)); + + if (reverse || then_not_else) + arc_ccfsm_current_cc = ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc); + } + + /* Restore recog_operand. Getting the attributes of other insns can + destroy this array, but final.c assumes that it remains intact + across this call; since the insn has been recognized already we + call insn_extract direct. */ + insn_extract (insn); + } +} + +/* Record that we are currently outputting label NUM with prefix PREFIX. + It it's the label we're looking for, reset the ccfsm machinery. + + Called from ASM_OUTPUT_INTERNAL_LABEL. */ + +void +arc_ccfsm_at_label (prefix, num) + char *prefix; + int num; +{ + if (arc_ccfsm_state == 3 && arc_ccfsm_target_label == num + && !strcmp (prefix, "L")) + { + arc_ccfsm_state = 0; + arc_ccfsm_target_insn = NULL_RTX; + } +} + +/* See if the current insn, which is a conditional branch, is to be + deleted. */ + +int +arc_ccfsm_branch_deleted_p () +{ + if (arc_ccfsm_state == 1 || arc_ccfsm_state == 2) + return 1; + return 0; +} + +/* Record a branch isn't output because subsequent insns can be + conditionalized. */ + +void +arc_ccfsm_record_branch_deleted () +{ + /* Indicate we're conditionalizing insns now. */ + arc_ccfsm_state += 2; + + /* If the next insn is a subroutine call, we still need a nop between the + cc setter and user. We need to undo the effect of calling record_cc_ref + for the just deleted branch. */ + current_insn_set_cc_p = last_insn_set_cc_p; +} diff --git a/gnu/usr.bin/gcc/config/arc/arc.h b/gnu/usr.bin/gcc/config/arc/arc.h new file mode 100644 index 00000000000..4257efaee3b --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/arc.h @@ -0,0 +1,1643 @@ +/* Definitions of target machine for GNU compiler, Argonaut ARC cpu. + Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* ??? This is an old port, and is undoubtedly suffering from bit rot. */ + +/* Things to do: + + - PREDICATE_CODES + - incscc, decscc? + - print active compiler options in assembler output +*/ + +/* ??? Create elf.h and have svr4.h include it. */ +#include "svr4.h" + +#undef ASM_SPEC +#undef LINK_SPEC +#undef STARTFILE_SPEC +#undef ENDFILE_SPEC +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE + +/* Print subsidiary information on the compiler version in use. */ +#define TARGET_VERSION fprintf (stderr, " (arc)") + +/* Names to predefine in the preprocessor for this target machine. */ +#define CPP_PREDEFINES "-Acpu(arc) -Amachine(arc) -D__arc__" + +/* Additional flags for the preprocessor. */ +#define CPP_SPEC "\ +%{!mcpu=*:-D__base__} %{mcpu=base:-D__base__} \ +%{EB:-D__big_endian__} \ +" + +/* Pass -mmangle-cpu if we get -mcpu=*. + Doing it this way lets one have it on as default with -mcpu=*, + but also lets one turn it off with -mno-mangle-cpu. */ +#define CC1_SPEC "\ +%{mcpu=*:-mmangle-cpu} \ +%{EB:%{EL:%emay not use both -EB and -EL}} \ +%{EB:-mbig-endian} %{EL:-mlittle-endian} \ +" + +#define ASM_SPEC "%{v} %{EB} %{EL}" + +#define LINK_SPEC "%{v} %{EB} %{EL}" + +#define STARTFILE_SPEC "%{!shared:crt0.o%s} crtinit.o%s" + +#define ENDFILE_SPEC "crtfini.o%s" + +/* Run-time compilation parameters selecting different hardware subsets. */ + +extern int target_flags; + +/* Mangle all user symbols for the specified cpu. + ARC's can be shipped in which a collection of cpus are coupled together. + Each CPU may be different in some way, and thus we may need to distinguish + code compiled for one to ensure it isn't linked with code compiled for + another. */ +#define TARGET_MASK_MANGLE_CPU 1 +#define TARGET_MANGLE_CPU (target_flags & TARGET_MASK_MANGLE_CPU) + +#if 0 +/* Mangle libgcc symbols by adding a suffix for the specified cpu. */ +#define TARGET_MASK_MANGLE_CPU_LIBGCC 2 +#define TARGET_MANGLE_CPU_LIBGCC (target_flags & TARGET_MASK_MANGLE_CPU_LIBGCC) +#endif + +/* Align loops to 32 byte boundaries (cache line size). */ +#define TARGET_MASK_ALIGN_LOOPS 4 +#define TARGET_ALIGN_LOOPS (target_flags & TARGET_MASK_ALIGN_LOOPS) + +/* Big Endian. */ +#define TARGET_MASK_BIG_ENDIAN 8 +#define TARGET_BIG_ENDIAN (target_flags & TARGET_MASK_BIG_ENDIAN) + +/* Turn off conditional execution optimization, + so we can see how well it does, or in case it's buggy. */ +#define TARGET_MASK_NO_COND_EXEC 0x10 +#define TARGET_NO_COND_EXEC (target_flags & TARGET_MASK_NO_COND_EXEC) + +/* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +#define TARGET_SWITCHES \ +{ \ + { "mangle-cpu", TARGET_MASK_MANGLE_CPU }, \ + { "no-mangle-cpu", -TARGET_MASK_MANGLE_CPU }, \ +/* { "mangle-cpu-libgcc", TARGET_MASK_MANGLE_CPU_LIBGCC }, */ \ +/* { "no-mangle-cpu-libgcc", -TARGET_MASK_MANGLE_CPU_LIBGCC }, */ \ + { "align-loops", TARGET_MASK_ALIGN_LOOPS }, \ + { "no-align-loops", -TARGET_MASK_ALIGN_LOOPS }, \ + { "big-endian", TARGET_MASK_BIG_ENDIAN }, \ + { "little-endian", -TARGET_MASK_BIG_ENDIAN }, \ + { "no-cond-exec", TARGET_MASK_NO_COND_EXEC }, \ + SUBTARGET_SWITCHES \ + { "", TARGET_DEFAULT } \ +} + +#define TARGET_DEFAULT (0) + +#define SUBTARGET_SWITCHES + +/* Instruction set characteristics. + These are internal macros, set by the appropriate -mcpu= option. */ + +/* Non-zero means the cpu has a barrel shifter. */ +#define TARGET_SHIFTER 0 + +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an + initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + fixed part of the option name, and the address of a variable. + The variable, type `char *', is set to the variable part of the + given option if the fixed part matches. The actual option name + is made by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the + given option is `-mshort-data-512', the variable `m88k_short_data' + will be set to the string `"512"'. + + extern char *m88k_short_data; + #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ + +extern char *arc_cpu_string; +extern char *arc_text_string,*arc_data_string,*arc_rodata_string; + +#define TARGET_OPTIONS \ +{ \ + { "cpu=", &arc_cpu_string }, \ + { "text=", &arc_text_string }, \ + { "data=", &arc_data_string }, \ + { "rodata=", &arc_rodata_string }, \ +} + +/* Which cpu we're compiling for. */ +extern int arc_cpu_type; + +/* Check if CPU is an extension and set `arc_cpu_type' and `arc_mangle_cpu' + appropriately. The result should be non-zero if the cpu is recognized, + otherwise zero. This is intended to be redefined in a cover file. + This is used by arc_init. */ +#define ARC_EXTENSION_CPU(cpu) 0 + +/* Sometimes certain combinations of command options do not make + sense on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + Don't use this macro to turn on various extra optimizations for + `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ + +extern void arc_init (); + +#define OVERRIDE_OPTIONS \ +do { \ + /* These need to be done at start up. It's convenient to do them here. */ \ + arc_init (); \ +} while (0) + +/* Target machine storage layout. */ + +/* Define to use software floating point emulator for REAL_ARITHMETIC and + decimal <-> binary conversion. */ +#define REAL_ARITHMETIC + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. */ +#define BITS_BIG_ENDIAN 1 + +/* Define this if most significant byte of a word is the lowest numbered. */ +#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN) + +/* Define this if most significant word of a multiword number is the lowest + numbered. */ +#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN) + +/* Define this to set the endianness to use in libgcc2.c, which can + not depend on target_flags. */ +#ifdef __big_endian__ +#define LIBGCC2_WORDS_BIG_ENDIAN 1 +#else +#define LIBGCC2_WORDS_BIG_ENDIAN 0 +#endif + +/* Number of bits in an addressable storage unit. */ +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ +#define BITS_PER_WORD 32 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD 4 + +/* Define this macro if it is advisable to hold scalars in registers + in a wider mode than that declared by the program. In such cases, + the value is constrained to be within the bounds of the declared + type, but kept valid in the wider mode. The signedness of the + extension may differ from that of the type. */ +#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ +if (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ +{ \ + (MODE) = SImode; \ +} + +/* Define this macro if the promotion described by `PROMOTE_MODE' + should also be done for outgoing function arguments. */ +#define PROMOTE_FUNCTION_ARGS + +/* Likewise, if the function return value is promoted. */ +#define PROMOTE_FUNCTION_RETURN + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ +#define POINTER_SIZE 32 + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY 32 + +/* Boundary (in *bits*) on which stack pointer should be aligned. */ +#define STACK_BOUNDARY 64 + +/* ALIGN FRAMES on word boundaries */ +#define ARC_STACK_ALIGN(LOC) (((LOC)+7) & ~7) + +/* Allocation boundary (in *bits*) for the code of a function. */ +#define FUNCTION_BOUNDARY 32 + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY 32 + +/* Every structure's size must be a multiple of this. */ +#define STRUCTURE_SIZE_BOUNDARY 8 + +/* A bitfield declared as `int' forces `int' alignment for the struct. */ +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* No data type wants to be aligned rounder than this. */ +/* This is bigger than currently necessary for the ARC. If 8 byte floats are + ever added it's not clear whether they'll need such alignment or not. For + now we assume they will. We can always relax it if necessary but the + reverse isn't true. */ +#define BIGGEST_ALIGNMENT 64 + +/* The best alignment to use in cases where we have a choice. */ +#define FASTEST_ALIGNMENT 32 + +/* Make strings word-aligned so strcpy from constants will be faster. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST \ + && (ALIGN) < FASTEST_ALIGNMENT) \ + ? FASTEST_ALIGNMENT : (ALIGN)) + +/* Make arrays of chars word-aligned for the same reasons. */ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + (TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN)) + +/* Set this nonzero if move instructions will actually fail to work + when given unaligned data. */ +/* On the ARC the lower address bits are masked to 0 as necessary. The chip + won't croak when given an unaligned address, but the insn will still fail + to produce the correct result. */ +#define STRICT_ALIGNMENT 1 + +/* Layout of source language data types. */ + +#define SHORT_TYPE_SIZE 16 +#define INT_TYPE_SIZE 32 +#define LONG_TYPE_SIZE 32 +#define LONG_LONG_TYPE_SIZE 64 +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 64 +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* Define this as 1 if `char' should by default be signed; else as 0. */ +#define DEFAULT_SIGNED_CHAR 1 + +#define SIZE_TYPE "long unsigned int" +#define PTRDIFF_TYPE "long int" +#define WCHAR_TYPE "short unsigned int" +#define WCHAR_TYPE_SIZE 16 + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ +/* Registers 61, 62, and 63 are not really registers and we needn't treat + them as such. We still need a register for the condition code. */ +#define FIRST_PSEUDO_REGISTER 62 + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + + 0-28 - general purpose registers + 29 - ilink1 (interrupt link register) + 30 - ilink2 (interrupt link register) + 31 - blink (branch link register) + 32-59 - reserved for extensions + 60 - LP_COUNT + 61 - condition code + + For doc purposes: + 61 - short immediate data indicator (setting flags) + 62 - long immediate data indicator + 63 - short immediate data indicator (not setting flags). + + The general purpose registers are further broken down into: + 0-7 - arguments/results + 8-15 - call used + 16-23 - call saved + 24 - call used, static chain pointer + 25 - call used, gptmp + 26 - global pointer + 27 - frame pointer + 28 - stack pointer + + By default, the extension registers are not available. */ + +#define FIXED_REGISTERS \ +{ 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 1, 1, 1, 1, 0, \ + \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1 } + +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. */ + +#define CALL_USED_REGISTERS \ +{ 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1 } + +/* If defined, an initializer for a vector of integers, containing the + numbers of hard registers in the order in which GNU CC should + prefer to use them (from most preferred to least). */ +#define REG_ALLOC_ORDER \ +{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, \ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 31, \ + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, \ + 27, 28, 29, 30 } + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. */ +#define HARD_REGNO_NREGS(REGNO, MODE) \ +((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ +extern unsigned int arc_hard_regno_mode_ok[]; +extern unsigned int arc_mode_class[]; +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ +((arc_hard_regno_mode_ok[REGNO] & arc_mode_class[MODE]) != 0) + +/* A C expression that is nonzero if it is desirable to choose + register allocation so as to avoid move instructions between a + value of mode MODE1 and a value of mode MODE2. + + If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, + MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, + MODE2)' must be zero. */ + +/* Tie QI/HI/SI modes together. */ +#define MODES_TIEABLE_P(MODE1, MODE2) \ +(GET_MODE_CLASS (MODE1) == MODE_INT \ + && GET_MODE_CLASS (MODE2) == MODE_INT \ + && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \ + && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD) + +/* Register classes and constants. */ + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. + + It is important that any condition codes have class NO_REGS. + See `register_operand'. */ + +enum reg_class { + NO_REGS, LPCOUNT_REG, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ +#define REG_CLASS_NAMES \ +{ "NO_REGS", "LPCOUNT_REG", "GENERAL_REGS", "ALL_REGS" } + +/* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS \ +{ {0, 0}, {0, 0x10000000}, {0xffffffff, 0xfffffff}, \ + {0xffffffff, 0x1fffffff} } + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ +extern enum reg_class arc_regno_reg_class[]; +#define REGNO_REG_CLASS(REGNO) \ +(arc_regno_reg_class[REGNO]) + +/* The class value for index registers, and the one for base regs. */ +#define INDEX_REG_CLASS GENERAL_REGS +#define BASE_REG_CLASS GENERAL_REGS + +/* Get reg_class from a letter such as appears in the machine description. */ +#define REG_CLASS_FROM_LETTER(C) \ +((C) == 'l' ? LPCOUNT_REG /* ??? needed? */ \ + : NO_REGS) + +/* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ +#define REGNO_OK_FOR_BASE_P(REGNO) \ +((REGNO) < 29 || (unsigned) reg_renumber[REGNO] < 29) +#define REGNO_OK_FOR_INDEX_P(REGNO) \ +((REGNO) < 29 || (unsigned) reg_renumber[REGNO] < 29) + +/* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. */ +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ +(CLASS) + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ +#define CLASS_MAX_NREGS(CLASS, MODE) \ +((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* The letters I, J, K, L, M, N, O, P in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ +/* 'I' is used for short immediates (always signed). + 'J' is used for long immediates. + 'K' is used for any constant up to 64 bits (for 64x32 situations?). */ + +/* local to this file */ +#define SMALL_INT(X) ((unsigned) ((X) + 0x100) < 0x200) +/* local to this file */ +#define LARGE_INT(X) \ +((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \ + && (X) <= (unsigned HOST_WIDE_INT) 0xffffffff) + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ +((C) == 'I' ? SMALL_INT (VALUE) \ + : (C) == 'J' ? LARGE_INT (VALUE) \ + : (C) == 'K' ? 1 \ + : 0) + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. */ +/* 'G' is used for integer values for the multiplication insns where the + operands are extended from 4 bytes to 8 bytes. + 'H' is used when any 64 bit constant is allowed. */ +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ +((C) == 'G' ? arc_double_limm_p (VALUE) \ + : (C) == 'H' ? 1 \ + : 0) + +/* A C expression that defines the optional machine-dependent constraint + letters that can be used to segregate specific types of operands, + usually memory references, for the target machine. It should return 1 if + VALUE corresponds to the operand type represented by the constraint letter + C. If C is not defined as an extra constraint, the value returned should + be 0 regardless of VALUE. */ +/* ??? This currently isn't used. Waiting for PIC. */ +#if 0 +#define EXTRA_CONSTRAINT(VALUE, C) \ +((C) == 'R' ? (SYMBOL_REF_FLAG (VALUE) || GET_CODE (VALUE) == LABEL_REF) \ + : 0) +#endif + +/* Stack layout and stack pointer usage. */ + +/* Define this macro if pushing a word onto the stack moves the stack + pointer to a smaller address. */ +#define STACK_GROWS_DOWNWARD + +/* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ +#define FRAME_GROWS_DOWNWARD + +/* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ +#define STARTING_FRAME_OFFSET 0 + +/* Offset from the stack pointer register to the first location at which + outgoing arguments are placed. */ +#define STACK_POINTER_OFFSET FIRST_PARM_OFFSET (0) + +/* Offset of first parameter from the argument pointer register value. */ +/* 4 bytes for each of previous fp, return address, and previous gp. + 4 byte reserved area for future considerations. */ +#define FIRST_PARM_OFFSET(FNDECL) 16 + +/* A C expression whose value is RTL representing the address in a + stack frame where the pointer to the caller's frame is stored. + Assume that FRAMEADDR is an RTL expression for the address of the + stack frame itself. + + If you don't define this macro, the default is to return the value + of FRAMEADDR--that is, the stack frame address is also the address + of the stack word that points to the previous frame. */ +/* ??? unfinished */ +/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/ + +/* A C expression whose value is RTL representing the value of the + return address for the frame COUNT steps up from the current frame. + FRAMEADDR is the frame pointer of the COUNT frame, or the frame + pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' + is defined. */ +/* The current return address is in r31. The return address of anything + farther back is at [%fp,4]. */ +#if 0 /* The default value should work. */ +#define RETURN_ADDR_RTX(COUNT, FRAME) \ +(((COUNT) == -1) \ + ? gen_rtx (REG, Pmode, 31) \ + : copy_to_reg (gen_rtx (MEM, Pmode, \ + memory_address (Pmode, plus_constant ((FRAME), UNITS_PER_WORD))))) +#endif + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 28 + +/* Base register for access to local variables of the function. */ +#define FRAME_POINTER_REGNUM 27 + +/* Base register for access to arguments of the function. */ +#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM + +/* Register in which static-chain is passed to a function. This must + not be a register used by the prologue. */ +#define STATIC_CHAIN_REGNUM 24 + +/* A C expression which is nonzero if a function must have and use a + frame pointer. This expression is evaluated in the reload pass. + If its value is nonzero the function will have a frame pointer. */ +#define FRAME_POINTER_REQUIRED \ +(current_function_calls_alloca) + +/* C statement to store the difference between the frame pointer + and the stack pointer values immediately after the function prologue. */ +#define INITIAL_FRAME_POINTER_OFFSET(VAR) \ +((VAR) = arc_compute_frame_size (get_frame_size ())) + +/* Function argument passing. */ + +/* When a prototype says `char' or `short', really pass an `int'. */ +#define PROMOTE_PROTOTYPES + +/* If defined, the maximum amount of space required for outgoing + arguments will be computed and placed into the variable + `current_function_outgoing_args_size'. No space will be pushed + onto the stack for each call; instead, the function prologue should + increase the stack frame size by this amount. */ +#define ACCUMULATE_OUTGOING_ARGS + +/* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + SIZE is the number of bytes of arguments passed on the stack. */ +#define RETURN_POPS_ARGS(DECL, FUNTYPE, SIZE) 0 + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. */ +#define CUMULATIVE_ARGS int + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ +((CUM) = 0) + +/* The number of registers used for parameter passing. Local to this file. */ +#define MAX_ARC_PARM_REGS 8 + +/* 1 if N is a possible register number for function argument passing. */ +#define FUNCTION_ARG_REGNO_P(N) \ +((unsigned) (N) < MAX_ARC_PARM_REGS) + +/* The ROUND_ADVANCE* macros are local to this file. */ +/* Round SIZE up to a word boundary. */ +#define ROUND_ADVANCE(SIZE) \ +(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Round arg MODE/TYPE up to the next word boundary. */ +#define ROUND_ADVANCE_ARG(MODE, TYPE) \ +((MODE) == BLKmode \ + ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ + : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) + +/* Round CUM up to the necessary point for argument MODE/TYPE. */ +#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \ +((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \ + > BITS_PER_WORD) \ + ? ((CUM) + 1 & ~1) \ + : (CUM)) + +/* Return boolean indicating arg of type TYPE and mode MODE will be passed in + a reg. This includes arguments that have to be passed by reference as the + pointer to them is passed in a reg if one is available (and that is what + we're given). + When passing arguments NAMED is always 1. When receiving arguments NAMED + is 1 for each argument except the last in a stdarg/varargs function. In + a stdarg function we want to treat the last named arg as named. In a + varargs function we want to treat the last named arg (which is + `__builtin_va_alist') as unnamed. + This macro is only used in this file. */ +extern int current_function_varargs; +#define PASS_IN_REG_P(CUM, MODE, TYPE, NAMED) \ +((!current_function_varargs || (NAMED)) \ + && (CUM) < MAX_ARC_PARM_REGS \ + && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \ + + ROUND_ADVANCE_ARG ((MODE), (TYPE)) \ + <= MAX_ARC_PARM_REGS))) + +/* Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ +/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers + and the rest are pushed. */ +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +(PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED)) \ + ? gen_rtx (REG, (MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \ + : 0) + +/* A C expression for the number of words, at the beginning of an + argument, must be put in registers. The value must be zero for + arguments that are passed entirely in registers or that are entirely + pushed on the stack. + + On some machines, certain arguments must be passed partially in + registers and partially in memory. On these machines, typically the + first @var{n} words of arguments are passed in registers, and the rest + on the stack. If a multi-word argument (a @code{double} or a + structure) crosses that boundary, its first few words must be passed + in registers and the rest must be pushed. This macro tells the + compiler when this occurs, and how many of the words should go in + registers. */ +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 + +/* A C expression that indicates when an argument must be passed by + reference. If nonzero for an argument, a copy of that argument is + made in memory and a pointer to the argument is passed instead of + the argument itself. The pointer is passed in whatever way is + appropriate for passing a pointer to that type. */ +/* All aggregates and arguments greater than 8 bytes are passed this way. */ +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ +(TYPE \ + && (AGGREGATE_TYPE_P (TYPE) \ + || int_size_in_bytes (TYPE) > 8)) + +/* A C expression that indicates when it is the called function's + responsibility to make copies of arguments passed by reference. + If the callee can determine that the argument won't be modified, it can + avoid the copy. */ +/* ??? We'd love to be able to use NAMED here. Unfortunately, it doesn't + include the last named argument so we keep track of the args ourselves. */ + +#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ +FUNCTION_ARG_PASS_BY_REFERENCE ((CUM), (MODE), (TYPE), (NAMED)) + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ +((CUM) = (ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \ + + ROUND_ADVANCE_ARG ((MODE), (TYPE)))) + +/* If defined, a C expression that gives the alignment boundary, in bits, + of an argument with the specified mode and type. If it is not defined, + PARM_BOUNDARY is used for all arguments. */ +#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ +(((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ + ? PARM_BOUNDARY \ + : 2 * PARM_BOUNDARY) + +/* This macro offers an alternative + to using `__builtin_saveregs' and defining the macro + `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register + arguments into the stack so that all the arguments appear to have + been passed consecutively on the stack. Once this is done, you + can use the standard implementation of varargs that works for + machines that pass all their arguments on the stack. + + The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, + containing the values that obtain after processing of the named + arguments. The arguments MODE and TYPE describe the last named + argument--its machine mode and its data type as a tree node. + + The macro implementation should do two things: first, push onto the + stack all the argument registers *not* used for the named + arguments, and second, store the size of the data thus pushed into + the `int'-valued variable whose name is supplied as the argument + PRETEND_SIZE. The value that you store here will serve as + additional offset for setting up the stack frame. + + If the argument NO_RTL is nonzero, it means that the + arguments of the function are being analyzed for the second time. + This happens for an inline function, which is not actually + compiled until the end of the source file. The macro + `SETUP_INCOMING_VARARGS' should not generate any instructions in + this case. */ + +#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_SIZE, NO_RTL) \ +arc_setup_incoming_varargs(&ARGS_SO_FAR, MODE, TYPE, &PRETEND_SIZE, NO_RTL) + +/* Function results. */ + +/* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ +#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0) + +/* Define how to find the value returned by a library function + assuming the value has mode MODE. */ +#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + +/* 1 if N is a possible register number for a function value + as seen by the caller. */ +/* ??? What about r1 in DI/DF values. */ +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + +/* A C expression which can inhibit the returning of certain function + values in registers, based on the type of value. A nonzero value says + to return the function value in memory, just as large structures are + always returned. Here TYPE will be a C expression of type `tree', + representing the data type of the value. */ +#define RETURN_IN_MEMORY(TYPE) \ +(AGGREGATE_TYPE_P (TYPE) \ + || int_size_in_bytes (TYPE) > 8 \ + || TREE_ADDRESSABLE (TYPE)) + +/* Tell GCC to use RETURN_IN_MEMORY. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Register in which address to store a structure value + is passed to a function, or 0 to use `invisible' first argument. */ +#define STRUCT_VALUE 0 + +/* Function entry and exit. */ + +/* This macro generates the assembly code for function entry. + FILE is a stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. */ +#define FUNCTION_PROLOGUE(FILE, SIZE) \ +arc_output_function_prologue (FILE, SIZE) + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ +#define EXIT_IGNORE_STACK 0 + +/* This macro generates the assembly code for function exit, + on machines that need it. If FUNCTION_EPILOGUE is not defined + then individual return instructions are generated for each + return statement. Args are same as for FUNCTION_PROLOGUE. + + The function epilogue should not depend on the current stack pointer! + It should use the frame pointer only. This is mandatory because + of alloca; we also take advantage of it to omit stack adjustments + before returning. */ +#define FUNCTION_EPILOGUE(FILE, SIZE) \ +arc_output_function_epilogue (FILE, SIZE) + +/* Epilogue delay slots. */ +#define DELAY_SLOTS_FOR_EPILOGUE arc_delay_slots_for_epilogue () + +#define ELIGIBLE_FOR_EPILOGUE_DELAY(TRIAL, SLOTS_FILLED) \ +arc_eligible_for_epilogue_delay (TRIAL, SLOTS_FILLED) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ +#define FUNCTION_PROFILER(FILE, LABELNO) + +/* Trampolines. */ +/* ??? This doesn't work yet because GCC will use as the address of a nested + function the address of the trampoline. We need to use that address + right shifted by 2. It looks like we'll need PSImode after all. :-( */ + +/* Output assembler code for a block containing the constant parts + of a trampoline, leaving space for the variable parts. */ +/* On the ARC, the trampoline is quite simple as we have 32 bit immediate + constants. + + mov r24,STATIC + j.nd FUNCTION +*/ +#define TRAMPOLINE_TEMPLATE(FILE) \ +do { \ + ASM_OUTPUT_INT (FILE, GEN_INT (0x631f7c00)); \ + ASM_OUTPUT_INT (FILE, const0_rtx); \ + ASM_OUTPUT_INT (FILE, GEN_INT (0x381f0000)); \ + ASM_OUTPUT_INT (FILE, const0_rtx); \ +} while (0) + +/* Length in units of the trampoline for entering a nested function. */ +#define TRAMPOLINE_SIZE 16 + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +do { \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), CXT); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 12)), FNADDR); \ + emit_insn (gen_flush_icache (validize_mem (gen_rtx (MEM, SImode, TRAMP)))); \ +} while (0) + +/* Library calls. */ + +/* Generate calls to memcpy, memcmp and memset. */ +#define TARGET_MEM_FUNCTIONS + +/* Addressing modes, and classification of registers for them. */ + +/* Maximum number of registers that can appear in a valid memory address. */ +/* The `ld' insn allows 2, but the `st' insn only allows 1. */ +#define MAX_REGS_PER_ADDRESS 1 + +/* We have pre inc/dec (load/store with update). */ +#define HAVE_PRE_INCREMENT +#define HAVE_PRE_DECREMENT + +/* Recognize any constant value that is a valid address. */ +#define CONSTANT_ADDRESS_P(X) \ +(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST) + +/* Nonzero if the constant value X is a legitimate general operand. + We can handle any 32 or 64 bit constant. */ +/* "1" should work since the largest constant should be a 64 bit critter. */ +/* ??? Not sure what to do for 64x32 compiler. */ +#define LEGITIMATE_CONSTANT_P(X) 1 + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + +#ifndef REG_OK_STRICT + +/* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ +#define REG_OK_FOR_INDEX_P(X) \ +((unsigned) REGNO (X) - 29 >= FIRST_PSEUDO_REGISTER - 29) +/* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ +#define REG_OK_FOR_BASE_P(X) \ +((unsigned) REGNO (X) - 29 >= FIRST_PSEUDO_REGISTER - 29) + +#else + +/* Nonzero if X is a hard reg that can be used as an index. */ +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) +/* Nonzero if X is a hard reg that can be used as a base reg. */ +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) + +#endif + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. */ +/* The `ld' insn allows [reg],[reg+shimm],[reg+limm],[reg+reg],[limm] + but the `st' insn only allows [reg],[reg+shimm],[limm]. + The only thing we can do is only allow the most strict case `st' and hope + other parts optimize out the restrictions for `ld'. */ + +/* local to this file */ +#define RTX_OK_FOR_BASE_P(X) \ +(REG_P (X) && REG_OK_FOR_BASE_P (X)) + +/* local to this file */ +#define RTX_OK_FOR_INDEX_P(X) \ +(0 && /*???*/ REG_P (X) && REG_OK_FOR_INDEX_P (X)) + +/* local to this file */ +/* ??? Loads can handle any constant, stores can only handle small ones. */ +#define RTX_OK_FOR_OFFSET_P(X) \ +(GET_CODE (X) == CONST_INT && SMALL_INT (INTVAL (X))) + +#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \ +(GET_CODE (X) == PLUS \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ + && (RTX_OK_FOR_INDEX_P (XEXP (X, 1)) \ + || RTX_OK_FOR_OFFSET_P (XEXP (X, 1)))) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ if (RTX_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \ + goto ADDR; \ + if (GET_CODE (X) == CONST_INT && LARGE_INT (INTVAL (X))) \ + goto ADDR; \ + if (GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == LABEL_REF \ + || GET_CODE (X) == CONST) \ + goto ADDR; \ + if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \ + /* We're restricted here by the `st' insn. */ \ + && RTX_OK_FOR_BASE_P (XEXP ((X), 0))) \ + goto ADDR; \ +} + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. */ + +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) + +/* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. */ +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ +{ if (GET_CODE (ADDR) == PRE_DEC) \ + goto LABEL; \ + if (GET_CODE (ADDR) == PRE_INC) \ + goto LABEL; \ +} + +/* Condition code usage. */ + +/* Some insns set all condition code flags, some only set the ZNC flags, and + some only set the ZN flags. */ + +#define EXTRA_CC_MODES CCZNCmode, CCZNmode + +#define EXTRA_CC_NAMES "CCZNC", "CCZN" + +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, + return the mode to be used for the comparison. */ +extern enum machine_mode arc_select_cc_mode (); +#define SELECT_CC_MODE(OP, X, Y) \ +arc_select_cc_mode (OP, X, Y) + +/* Return non-zero if SELECT_CC_MODE will never return MODE for a + floating point inequality comparison. */ +#define REVERSIBLE_CC_MODE(MODE) 1 /*???*/ + +/* Costs. */ + +/* An insn is define to cost 4 "units", and we work from there. + COSTS_N_INSNS (N) is defined as (N) * 4 - 2 so that seems reasonable. + Some values are supposed to be defined relative to each other and thus + aren't necessarily related to COSTS_N_INSNS. */ + +/* Compute the cost of computing a constant rtl expression RTX + whose rtx-code is CODE. The body of this macro is a portion + of a switch statement. If the code is computed here, + return it with a return statement. Otherwise, break from the switch. */ +/* Small integers are as cheap as registers. 4 byte values can be fetched + as immediate constants - let's give that the cost of an extra insn. */ +#define CONST_COSTS(X, CODE, OUTER_CODE) \ + case CONST_INT : \ + if (SMALL_INT (INTVAL (X))) \ + return 0; \ + /* fall through */ \ + case CONST : \ + case LABEL_REF : \ + case SYMBOL_REF : \ + return 4; \ + case CONST_DOUBLE : \ + { \ + rtx high, low; \ + split_double (X, &high, &low); \ + return 4 * (!SMALL_INT (INTVAL (high)) \ + + !SMALL_INT (INTVAL (low))); \ + } + +/* Compute the cost of an address. */ +#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : arc_address_cost (ADDR)) + +/* Compute extra cost of moving data between one register class + and another. */ +#define REGISTER_MOVE_COST(CLASS1, CLASS2) 2 + +/* Compute the cost of moving data between registers and memory. */ +/* Memory is 3 times as expensive as registers. + ??? Is that the right way to look at it? */ +#define MEMORY_MOVE_COST(MODE) \ +(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12) + +/* The cost of a branch insn. */ +/* ??? What's the right value here? Branches are certainly more + expensive than reg->reg moves. */ +#define BRANCH_COST 2 + +/* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. The purpose for the cost of MULT is to encourage + `synth_mult' to find a synthetic multiply when reasonable. + + If we need more than 12 insns to do a multiply, then go out-of-line, + since the call overhead will be < 10% of the cost of the multiply. */ +#define RTX_COSTS(X, CODE, OUTER_CODE) \ + case ASHIFT : \ + case ASHIFTRT : \ + case LSHIFTRT : \ + if (TARGET_SHIFTER) \ + return COSTS_N_INSNS (1); \ + if (GET_CODE (XEXP ((X), 1)) != CONST_INT) \ + return COSTS_N_INSNS (16); \ + return COSTS_N_INSNS (INTVAL (XEXP ((X), 1))); + +/* Nonzero if access to memory by bytes is slow and undesirable. + For RISC chips, it means that access to memory by bytes is no + better than access by words when possible, so grab a whole word + and maybe make use of that. */ +#define SLOW_BYTE_ACCESS 1 + +/* Define this macro if it is as good or better to call a constant + function address than to call an address kept in a register. */ +/* On the ARC, calling through registers is slow. */ +#define NO_FUNCTION_CSE + +/* Define this macro if it is as good or better for a function to call + itself with an explicit address than to call an address kept in a + register. */ +/* On the ARC, calling through registers is slow. */ +#define NO_RECURSIVE_FUNCTION_CSE + +/* Section selection. */ +/* WARNING: These section names also appear in dwarfout.c. */ + +/* The names of the text, data, and readonly-data sections are runtime + selectable. */ + +#define ARC_SECTION_FORMAT "\t.section %s" +#define ARC_DEFAULT_TEXT_SECTION ".text" +#define ARC_DEFAULT_DATA_SECTION ".data" +#define ARC_DEFAULT_RODATA_SECTION ".rodata" + +extern char *arc_text_section,*arc_data_section,*arc_rodata_section; + +/* initfini.c uses this in an asm. */ +#if defined (CRT_INIT) || defined (CRT_FINI) +#define TEXT_SECTION_ASM_OP "\t.section .text" +#else +#define TEXT_SECTION_ASM_OP arc_text_section /*"\t.section .text"*/ +#endif +#define DATA_SECTION_ASM_OP arc_data_section /*"\t.section .data"*/ + +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP arc_rodata_section /*"\t.section .rodata"*/ + +#define BSS_SECTION_ASM_OP "\t.section .bss" + +/* Define this macro if jump tables (for tablejump insns) should be + output in the text section, along with the assembler instructions. + Otherwise, the readonly data section is used. + This macro is irrelevant if there is no separate readonly data section. */ +/*#define JUMP_TABLES_IN_TEXT_SECTION*/ + +/* Define this macro if references to a symbol must be treated + differently depending on something about the variable or + function named by the symbol (such as what section it is in). + + The macro definition, if any, is executed immediately after the + rtl for DECL or other node is created. + The value of the rtl will be a `mem' whose address is a + `symbol_ref'. + + The usual thing for this macro to do is to store a flag in the + `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified + name string in the `symbol_ref' (if one bit is not enough + information). */ + +/* On the ARC, function addresses are not the same as normal addresses. + Branch to absolute address insns take an address that is right-shifted + by 2. We encode the fact that we have a function here, and then emit a + special assembler op when outputting the address. */ +#define ENCODE_SECTION_INFO(DECL) \ +do { \ + if (TREE_CODE (DECL) == FUNCTION_DECL) \ + SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ +} while (0) + +/* Decode SYM_NAME and store the real name part in VAR, sans + the characters that encode section info. Define this macro if + ENCODE_SECTION_INFO alters the symbol's name string. */ +/*#define STRIP_NAME_ENCODING(VAR, SYM_NAME)*/ + +/* For DWARF. Marginally different than default so output is "prettier" + (and consistent with above). */ +#define PUSHSECTION_FORMAT "\t%s %s\n" + +/* Tell crtstuff.c we're using ELF. */ +#define OBJECT_FORMAT_ELF + +/* PIC */ + +/* The register number of the register used to address a table of static + data addresses in memory. In some cases this register is defined by a + processor's ``application binary interface'' (ABI). When this macro + is defined, RTL is generated for this register once, as with the stack + pointer and frame pointer registers. If this macro is not defined, it + is up to the machine-dependent files to allocate such a register (if + necessary). */ +#define PIC_OFFSET_TABLE_REGNUM 26 + +/* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is + clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM + is not defined. */ +/* This register is call-saved on the ARC. */ +/*#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED*/ + +/* By generating position-independent code, when two different programs (A + and B) share a common library (libC.a), the text of the library can be + shared whether or not the library is linked at the same address for both + programs. In some of these environments, position-independent code + requires not only the use of different addressing modes, but also + special code to enable the use of these addressing modes. + + The FINALIZE_PIC macro serves as a hook to emit these special + codes once the function is being compiled into assembly code, but not + before. (It is not done before, because in the case of compiling an + inline function, it would lead to multiple PIC prologues being + included in functions which used inline functions and were compiled to + assembly language.) */ + +#define INITIALIZE_PIC arc_initialize_pic () +#define FINALIZE_PIC arc_finalize_pic () + +/* A C expression that is nonzero if X is a legitimate immediate + operand on the target machine when generating position independent code. + You can assume that X satisfies CONSTANT_P, so you need not + check this. You can also assume `flag_pic' is true, so you need not + check it either. You need not define this macro if all constants + (including SYMBOL_REF) can be immediate operands when generating + position independent code. */ +/*#define LEGITIMATE_PIC_OPERAND_P(X)*/ + +/* Control the assembler format that we output. */ + +/* Output at beginning of assembler file. */ +extern void arc_asm_file_start (); +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) arc_asm_file_start (FILE) + +/* A C statement to output assembler commands which will identify the + object file as having been compiled with GNU CC (or another GNU + compiler). */ +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(FILE) /* nothing */ + +/* Needed because we define ASM_IDENTIFY_GCC. */ +#define ASM_IDENTIFY_LANGUAGE(FILE) output_lang_identify (FILE) + +/* A C string constant describing how to begin a comment in the target + assembler language. The compiler assumes that the comment will + end at the end of the line. */ +#define ASM_COMMENT_START ";" + +/* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ +#define ASM_APP_ON "" + +/* Output to assembler file text saying following lines + no longer contain unusual constructs. */ +#define ASM_APP_OFF "" + +/* This is how to output an assembler line defining a `char' constant. */ +#define ASM_OUTPUT_CHAR(FILE, VALUE) \ +( fprintf (FILE, "\t.byte\t"), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line defining a `short' constant. */ +#define ASM_OUTPUT_SHORT(FILE, VALUE) \ +( fprintf (FILE, "\t.hword\t"), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line defining an `int' constant. + We also handle symbol output here. Code addresses must be right shifted + by 2 because that's how the jump instruction wants them. */ +#define ASM_OUTPUT_INT(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.word\t"); \ + if ((GET_CODE (VALUE) == SYMBOL_REF && SYMBOL_REF_FLAG (VALUE)) \ + || GET_CODE (VALUE) == LABEL_REF) \ + { \ + fprintf (FILE, "%%st("); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, ")"); \ + } \ + else \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an assembler line defining a `float' constant. */ +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ +{ \ + long t; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.word\t0x%lx %s %s\n", \ + t, ASM_COMMENT_START, str); \ +} + +/* This is how to output an assembler line defining a `double' constant. */ +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ +{ \ + long t[2]; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.word\t0x%lx %s %s\n\t.word\t0x%lx\n", \ + t[0], ASM_COMMENT_START, str, t[1]); \ +} + +/* This is how to output an assembler line for a numeric constant byte. */ +#define ASM_BYTE_OP ".byte" +#define ASM_OUTPUT_BYTE(FILE, VALUE) \ + fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) + +/* The assembler's parentheses characters. */ +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ +#define ASM_OUTPUT_LABEL(FILE, NAME) \ +do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + +/* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ +#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ +do { \ + fputs ("\t.global\t", FILE); \ + assemble_name (FILE, NAME); \ + fputs ("\n", FILE); \ +} while (0) + +/* A C statement (sans semicolon) to output on FILE an assembler pseudo-op to + declare a library function name external. The name of the library function + is given by SYMREF, which has type RTX and is a SYMBOL_REF. */ +#if 0 +/* On the ARC we want to have libgcc's for multiple cpus in one binary. + We can't use `assemble_name' here as that will call ASM_OUTPUT_LABELREF + and we'll get another suffix added on if -mmangle-cpu. */ +extern char *arc_mangle_cpu; +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, SYMREF) \ +do { \ + if (TARGET_MANGLE_CPU_LIBGCC) \ + { \ + fprintf (FILE, "\t.rename\t_%s, _%s%s\n", \ + XSTR (SYMREF, 0), XSTR (SYMREF, 0), \ + arc_mangle_suffix); \ + } \ +} while (0) +#endif + +/* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. */ +/* We mangle all user labels to provide protection from linking code + compiled for different cpus. */ +/* We work around a dwarfout.c deficiency by watching for labels from it and + not adding the '_' prefix nor the cpu suffix. There is a comment in + dwarfout.c that says it should be using ASM_OUTPUT_INTERNAL_LABEL. */ +extern char *arc_mangle_cpu; +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ +do { \ + if ((NAME)[0] == '.' && (NAME)[1] == 'L') \ + fprintf (FILE, "%s", NAME); \ + else \ + { \ + fputc ('_', FILE); \ + if (TARGET_MANGLE_CPU && arc_mangle_cpu != NULL) \ + fprintf (FILE, "%s_", arc_mangle_cpu); \ + fprintf (FILE, "%s", NAME); \ + } \ +} while (0) + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ +do { \ + arc_ccfsm_at_label (PREFIX, NUM); \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \ +} while (0) + +/* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) + +/* Assembler pseudo-op to equate one value with another. */ +/* ??? This is needed because dwarfout.c provides a default definition too + late for defaults.h (which contains the default definition of ASM_OUTPUT_DEF + that we use). */ +#define SET_ASM_OP ".set" + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#undef ASM_OUTPUT_CONSTRUCTOR +#define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME) \ +do { \ + ctors_section (); \ + fprintf (FILE, "\t.word\t%%st("); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ")\n"); \ +} while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#undef ASM_OUTPUT_DESTRUCTOR +#define ASM_OUTPUT_DESTRUCTOR(FILE, NAME) \ +do { \ + dtors_section (); \ + fprintf (FILE, "\t.word\t%%st("); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ")\n"); \ +} while (0) + +/* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ +#define REGISTER_NAMES \ +{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "fp", "sp", "ilink1", "ilink2", "blink", \ + "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \ + "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", \ + "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \ + "r56", "r57", "r58", "r59", "lp_count", "cc"} + +/* Entry to the insn conditionalizer. */ +#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ +arc_final_prescan_insn (INSN, OPVEC, NOPERANDS) + +/* A C expression which evaluates to true if CODE is a valid + punctuation character for use in the `PRINT_OPERAND' macro. */ +extern char arc_punct_chars[]; +#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ +arc_punct_chars[(unsigned char) (CHAR)] + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ +#define PRINT_OPERAND(FILE, X, CODE) \ +arc_print_operand (FILE, X, CODE) + +/* A C compound statement to output to stdio stream STREAM the + assembler syntax for an instruction operand that is a memory + reference whose address is ADDR. ADDR is an RTL expression. + + On some machines, the syntax for a symbolic address depends on + the section that the address refers to. On these machines, + define the macro `ENCODE_SECTION_INFO' to store the information + into the `symbol_ref', and then check for it here. */ +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ +arc_print_operand_address (FILE, ADDR) + +/* This is how to output an element of a case-vector that is absolute. */ +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ +do { \ + char label[30]; \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ + fprintf (FILE, "\t.word %%st("); \ + assemble_name (FILE, label); \ + fprintf (FILE, ")\n"); \ +} while (0) + +/* This is how to output an element of a case-vector that is relative. */ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +do { \ + char label[30]; \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ + fprintf (FILE, "\t.word %%st("); \ + assemble_name (FILE, label); \ + fprintf (FILE, "-"); \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \ + assemble_name (FILE, label); \ + fprintf (FILE, ")\n"); \ +} while (0) + +/* A C expression to output text to align the location counter in the way + that is desirable at the beginning of a loop. */ +/* On the ARC, align loops to 32 byte boundaries (cache line size) + if -malign-loops. */ +#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ +do { if (TARGET_ALIGN_LOOPS) ASM_OUTPUT_SKIP (FILE, 5); } while (0) + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ +do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0) + +/* Debugging information. */ + +/* Generate DBX and DWARF debugging information. */ +#define DBX_DEBUGGING_INFO +#define DWARF_DEBUGGING_INFO + +/* Prefer STABS (for now). */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* How to renumber registers for dbx and gdb. */ +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* Turn off splitting of long stabs. */ +#define DBX_CONTIN_LENGTH 0 + +/* Miscellaneous. */ + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE Pmode + +/* Define this if the tablejump instruction expects the table + to contain offsets from the address of the table. + Do not define this if the table should contain absolute addresses. */ +/* It's not clear what PIC will look like or whether we want to use -fpic + for the embedded form currently being talked about. For now require -fpic + to get pc relative switch tables. */ +/*#define CASE_VECTOR_PC_RELATIVE*/ + +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD + will either zero-extend or sign-extend. The value of this macro should + be the code that says which one of the two operations is implicitly + done, NIL if none. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Specify the tree operation to be used to convert reals to integers. */ +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* This is the kind of divide that is easiest to do in the general case. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ +#define MOVE_MAX 4 + +/* Define this to be nonzero if shift instructions ignore all but the low-order + few bits. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* We assume that the store-condition-codes instructions store 0 for false + and some other value for true. This is the value stored for true. */ +#define STORE_FLAG_VALUE 1 + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +/* ??? The arc doesn't have full 32 bit pointers, but making this PSImode has + it's own problems (you have to add extendpsisi2 and trucnsipsi2 but how does + one do it without getting excess code?). Try to avoid it. */ +#define Pmode SImode + +/* A function address in a call instruction. */ +#define FUNCTION_MODE SImode + +/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS + is a valid machine specific attribute for DECL. + The attributes in ATTRIBUTES have previously been assigned to TYPE. */ +extern int arc_valid_machine_attribute (); +#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ +arc_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) + +/* A C expression that returns zero if the attributes on TYPE1 and TYPE2 are + incompatible, one if they are compatible, and two if they are + nearly compatible (which causes a warning to be generated). */ +extern int arc_comp_type_attributes (); +#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \ +arc_comp_type_attributes (TYPE1, TYPE2) + +/* Give newly defined TYPE some default attributes. */ +extern void arc_set_default_type_attributes (); +#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \ +arc_set_default_type_attributes (TYPE) + +/* Define this if the target system supports the function + atexit from the ANSI C standard. If this is not defined, + and INIT_SECTION_ASM_OP is not defined, a default + exit function will be provided to support C++. */ +#define HAVE_ATEXIT + +/* alloca should avoid clobbering the old register save area. */ +/* ??? Not defined in tm.texi. */ +#define SETJMP_VIA_SAVE_AREA + +/* Define the information needed to generate branch and scc insns. This is + stored from the compare operation. Note that we can't use "rtx" here + since it hasn't been defined! */ +extern struct rtx_def *arc_compare_op0, *arc_compare_op1; + +/* Define the function that build the compare insn for scc and bcc. */ +extern struct rtx_def *gen_compare_reg (); + +/* Declarations for various fns used in the .md file. */ +extern char *output_shift (); + +/* ARC function types. */ +enum arc_function_type { + ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL, + /* These are interrupt handlers. The name corresponds to the register + name that contains the return address. */ + ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2 +}; +#define ARC_INTERRUPT_P(TYPE) \ +((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2) +/* Compute the type of a function from its DECL. */ +enum arc_function_type arc_compute_function_type (); diff --git a/gnu/usr.bin/gcc/config/arc/arc.md b/gnu/usr.bin/gcc/config/arc/arc.md new file mode 100644 index 00000000000..328b1ebd991 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/arc.md @@ -0,0 +1,1630 @@ +;; Machine description of the Argonaut ARC cpu for GNU C compiler +;; Copyright (C) 1994, 1997 Free Software Foundation, Inc. + +;; This file is part of GNU CC. + +;; GNU CC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU CC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU CC; see the file COPYING. If not, write to +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; ??? This is an old port, and is undoubtedly suffering from bit rot. + +;; Insn type. Used to default other attribute values. + +(define_attr "type" + "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc" + (const_string "binary")) + +;; Length (in # of insns, long immediate constants counted too). +;; ??? There's a nasty interaction between the conditional execution fsm +;; and insn lengths: insns with shimm values cannot be conditionally executed. +(define_attr "length" "" + (cond [(eq_attr "type" "load") + (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "") + (const_int 2) (const_int 1)) + + (eq_attr "type" "store") + (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "") + (const_int 2) (const_int 1)) + + (eq_attr "type" "move,unary,compare") + (if_then_else (match_operand 1 "long_immediate_operand" "") + (const_int 2) (const_int 1)) + + (eq_attr "type" "binary,mul") + (if_then_else (match_operand 2 "long_immediate_operand" "") + (const_int 2) (const_int 1)) + + (eq_attr "type" "cmove") + (if_then_else (match_operand 2 "register_operand" "") + (const_int 1) (const_int 2)) + + (eq_attr "type" "multi") (const_int 2) + ] + + (const_int 1))) + +;; The length here is the length of a single asm. Unfortunately it might be +;; 1 or 2 so we must allow for 2. That's ok though. How often will users +;; lament asm's not being put in delay slots? +(define_asm_attributes + [(set_attr "length" "2") + (set_attr "type" "multi")]) + +;; Condition codes: this one is used by final_prescan_insn to speed up +;; conditionalizing instructions. It saves having to scan the rtl to see if +;; it uses or alters the condition codes. + +;; USE: This insn uses the condition codes (eg: a conditional branch). +;; CANUSE: This insn can use the condition codes (for conditional execution). +;; SET: All condition codes are set by this insn. +;; SET_ZN: the Z and N flags are set by this insn. +;; SET_ZNC: the Z, N, and C flags are set by this insn. +;; CLOB: The condition codes are set to unknown values by this insn. +;; NOCOND: This insn can't use and doesn't affect the condition codes. + +(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond" + (cond [(and (eq_attr "type" "unary,binary,move") + (eq_attr "length" "1")) + (const_string "canuse") + + (eq_attr "type" "compare") + (const_string "set") + + (eq_attr "type" "cmove,branch") + (const_string "use") + + (eq_attr "type" "multi,misc") + (const_string "clob") + ] + + (const_string "nocond"))) + +;; Delay slots. + +(define_attr "in_delay_slot" "false,true" + (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") + (const_string "false") + ] + + (if_then_else (eq_attr "length" "1") + (const_string "true") + (const_string "false")))) + +(define_delay (eq_attr "type" "call") + [(eq_attr "in_delay_slot" "true") + (eq_attr "in_delay_slot" "true") + (eq_attr "in_delay_slot" "true")]) + +(define_delay (eq_attr "type" "branch,uncond_branch") + [(eq_attr "in_delay_slot" "true") + (eq_attr "in_delay_slot" "true") + (eq_attr "in_delay_slot" "true")]) + +;; Function units of the ARC + +;; (define_function_unit {name} {num-units} {n-users} {test} +;; {ready-delay} {issue-delay} [{conflict-list}]) + +;; 1) A conditional jump cannot immediately follow the insn setting the flags. +;; This isn't a complete solution as it doesn't come with guarantees. That +;; is done in the branch patterns and in arc_print_operand. This exists to +;; avoid inserting a nop when we can. +(define_function_unit "compare" 1 0 (eq_attr "type" "compare") 2 2 [(eq_attr "type" "branch")]) + +;; 2) References to loaded registers should wait a cycle. + +;; Memory with load-delay of 1 (i.e., 2 cycle load). +(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) + +;; Units that take one cycle do not need to be specified. + +;; Move instructions. + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (QImode, operands[1]); +}") + +(define_insn "*movqi_insn" + [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m") + (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))] +;; ??? Needed? + "register_operand (operands[0], QImode) + || register_operand (operands[1], QImode)" + "@ + mov%? %0,%1 + mov%? %0,%1 + ldb%U1%V1 %0,%1 + stb%U0%V0 %1,%0" + [(set_attr "type" "move,move,load,store")]) + +;; ??? This may never match since there's no cmpqi insn. + +(define_insn "*movqi_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi")) + (const_int 0))) + (set (match_operand:QI 0 "move_dest_operand" "=r") + (match_dup 1))] + "" + "mov%?.f %0,%1" + [(set_attr "type" "move") + (set_attr "cond" "set_zn")]) + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (HImode, operands[1]); +}") + +(define_insn "*movhi_insn" + [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m") + (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))] + "register_operand (operands[0], HImode) + || register_operand (operands[1], HImode)" + "@ + mov%? %0,%1 + mov%? %0,%1 + ldw%U1%V1 %0,%1 + stw%U0%V0 %1,%0" + [(set_attr "type" "move,move,load,store")]) + +;; ??? Will this ever match? + +(define_insn "*movhi_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi")) + (const_int 0))) + (set (match_operand:HI 0 "move_dest_operand" "=r") + (match_dup 1))] +;; ??? Needed? + "register_operand (operands[0], HImode) + || register_operand (operands[1], HImode)" + "mov%?.f %0,%1" + [(set_attr "type" "move") + (set_attr "cond" "set_zn")]) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (SImode, operands[1]); +}") + +(define_insn "*movsi_insn" + [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m") + (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))] + "register_operand (operands[0], SImode) + || register_operand (operands[1], SImode)" + "@ + mov%? %0,%1 + mov%? %0,%S1 + ld%U1%V1 %0,%1 + st%U0%V0 %1,%0" + [(set_attr "type" "move,move,load,store")]) + +(define_insn "*movsi_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (match_operand:SI 1 "move_src_operand" "rIJi") + (const_int 0))) + (set (match_operand:SI 0 "move_dest_operand" "=r") + (match_dup 1))] + "register_operand (operands[0], SImode) + || register_operand (operands[1], SImode)" + "mov%?.f %0,%S1" + [(set_attr "type" "move") + (set_attr "cond" "set_zn")]) + +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (DImode, operands[1]); +}") + +(define_insn "*movdi_insn" + [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m") + (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))] + "register_operand (operands[0], DImode) + || register_operand (operands[1], DImode)" + "* +{ + switch (which_alternative) + { + case 0 : + /* We normally copy the low-numbered register first. However, if + the first register operand 0 is the same as the second register of + operand 1, we must copy in the opposite order. */ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"mov %R0,%R1\;mov %0,%1\"; + else + return \"mov %0,%1\;mov %R0,%R1\"; + case 1 : + return \"mov %0,%L1\;mov %R0,%H1\"; + case 2 : + /* If the low-address word is used in the address, we must load it + last. Otherwise, load it first. Note that we cannot have + auto-increment in that case since the address register is known to be + dead. */ + if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, + operands [1], 0)) + return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; + else + return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; + case 3 : + return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; + } +}" + [(set_attr "type" "move,move,load,store") + ;; ??? The ld/st values could be 4 if it's [reg,bignum]. + (set_attr "length" "2,4,2,2")]) + +;(define_expand "movdi" +; [(set (match_operand:DI 0 "general_operand" "") +; (match_operand:DI 1 "general_operand" ""))] +; "" +; " +;{ +; /* Flow doesn't understand that this is effectively a DFmode move. +; It doesn't know that all of `operands[0]' is set. */ +; emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); +; +; /* Emit insns that movsi_insn can handle. */ +; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode), +; operand_subword (operands[1], 0, 0, DImode))); +; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode), +; operand_subword (operands[1], 1, 0, DImode))); +; DONE; +;}") + +;; Floating point move insns. + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + +#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT + if (GET_CODE (operands[1]) == CONST_DOUBLE) + operands[1] = force_const_mem (SFmode, operands[1]); +#endif + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (SFmode, operands[1]); +}") + +(define_insn "*movsf_insn" + [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m") + (match_operand:SF 1 "move_src_operand" "r,E,m,r"))] + "register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode)" + "@ + mov%? %0,%1 + mov%? %0,%1 ; %A1 + ld%U1%V1 %0,%1 + st%U0%V0 %1,%0" + [(set_attr "type" "move,move,load,store")]) + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + +#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT + if (GET_CODE (operands[1]) == CONST_DOUBLE) + operands[1] = force_const_mem (DFmode, operands[1]); +#endif + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (DFmode, operands[1]); +}") + +(define_insn "*movdf_insn" + [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") + (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))] + "register_operand (operands[0], DFmode) + || register_operand (operands[1], DFmode)" + "* +{ + switch (which_alternative) + { + case 0 : + /* We normally copy the low-numbered register first. However, if + the first register operand 0 is the same as the second register of + operand 1, we must copy in the opposite order. */ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"mov %R0,%R1\;mov %0,%1\"; + else + return \"mov %0,%1\;mov %R0,%R1\"; + case 1 : + return \"mov %0,%L1\;mov %R0,%H1 ; %A1\"; + case 2 : + /* If the low-address word is used in the address, we must load it + last. Otherwise, load it first. Note that we cannot have + auto-increment in that case since the address register is known to be + dead. */ + if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, + operands [1], 0)) + return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; + else + return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; + case 3 : + return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; + } +}" + [(set_attr "type" "move,move,load,store") + ;; ??? The ld/st values could be 4 if it's [reg,bignum]. + (set_attr "length" "2,4,2,2")]) + +;(define_expand "movdf" +; [(set (match_operand:DF 0 "general_operand" "") +; (match_operand:DF 1 "general_operand" ""))] +; "" +; " +;{ +; /* Flow doesn't understand that this is effectively a DFmode move. +; It doesn't know that all of `operands[0]' is set. */ +; emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); +; +; /* Emit insns that movsi_insn can handle. */ +; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode), +; operand_subword (operands[1], 0, 0, DFmode))); +; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode), +; operand_subword (operands[1], 1, 0, DFmode))); +; DONE; +;}") + +;; Load/Store with update instructions. +;; +;; Some of these we can get by using pre-decrement or pre-increment, but the +;; hardware can also do cases where the increment is not the size of the +;; object. +;; +;; In all these cases, we use operands 0 and 1 for the register being +;; incremented because those are the operands that local-alloc will +;; tie and these are the pair most likely to be tieable (and the ones +;; that will benefit the most). +;; +;; We use match_operator here because we need to know whether the memory +;; object is volatile or not. + +(define_insn "*loadqi_update" + [(set (match_operand:QI 3 "register_operand" "=r,r") + (match_operator:QI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")])) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ldb.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*load_zeroextendqisi_update" + [(set (match_operand:SI 3 "register_operand" "=r,r") + (zero_extend:SI (match_operator:QI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ldb.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*load_signextendqisi_update" + [(set (match_operand:SI 3 "register_operand" "=r,r") + (sign_extend:SI (match_operator:QI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ldb.x.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*storeqi_update" + [(set (match_operator:QI 4 "store_update_operand" + [(match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "short_immediate_operand" "I")]) + (match_operand:QI 3 "register_operand" "r")) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "stb.a%V4 %3,[%0,%2]" + [(set_attr "type" "store") + (set_attr "length" "1")]) + +(define_insn "*loadhi_update" + [(set (match_operand:HI 3 "register_operand" "=r,r") + (match_operator:HI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")])) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ldw.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*load_zeroextendhisi_update" + [(set (match_operand:SI 3 "register_operand" "=r,r") + (zero_extend:SI (match_operator:HI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ldw.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*load_signextendhisi_update" + [(set (match_operand:SI 3 "register_operand" "=r,r") + (sign_extend:SI (match_operator:HI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ldw.x.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*storehi_update" + [(set (match_operator:HI 4 "store_update_operand" + [(match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "short_immediate_operand" "I")]) + (match_operand:HI 3 "register_operand" "r")) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "stw.a%V4 %3,[%0,%2]" + [(set_attr "type" "store") + (set_attr "length" "1")]) + +(define_insn "*loadsi_update" + [(set (match_operand:SI 3 "register_operand" "=r,r") + (match_operator:SI 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")])) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ld.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*storesi_update" + [(set (match_operator:SI 4 "store_update_operand" + [(match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "short_immediate_operand" "I")]) + (match_operand:SI 3 "register_operand" "r")) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "st.a%V4 %3,[%0,%2]" + [(set_attr "type" "store") + (set_attr "length" "1")]) + +(define_insn "*loadsf_update" + [(set (match_operand:SF 3 "register_operand" "=r,r") + (match_operator:SF 4 "load_update_operand" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "rI,J")])) + (set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "ld.a%V4 %3,[%0,%2]" + [(set_attr "type" "load,load") + (set_attr "length" "1,2")]) + +(define_insn "*storesf_update" + [(set (match_operator:SF 4 "store_update_operand" + [(match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "short_immediate_operand" "I")]) + (match_operand:SF 3 "register_operand" "r")) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "" + "st.a%V4 %3,[%0,%2]" + [(set_attr "type" "store") + (set_attr "length" "1")]) + +;; Conditional move instructions. + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "nonmemory_operand" "") + (match_operand:SI 3 "register_operand" "")))] + "" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx ccreg = gen_rtx (REG, + SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), + 61); + + operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); +}") + +;(define_expand "movdicc" +; [(set (match_operand:DI 0 "register_operand" "") +; (if_then_else (match_operand 1 "comparison_operator" "") +; (match_operand:DI 2 "nonmemory_operand" "") +; (match_operand:DI 3 "register_operand" "")))] +; "0 /* ??? this would work better if we had cmpdi */" +; " +;{ +; enum rtx_code code = GET_CODE (operands[1]); +; rtx ccreg = gen_rtx (REG, +; SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), +; 61); +; +; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); +;}") + +(define_expand "movsfcc" + [(set (match_operand:SF 0 "register_operand" "") + (if_then_else (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "nonmemory_operand" "") + (match_operand:SF 3 "register_operand" "")))] + "" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx ccreg = gen_rtx (REG, + SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), + 61); + + operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); +}") + +;(define_expand "movdfcc" +; [(set (match_operand:DF 0 "register_operand" "") +; (if_then_else (match_operand 1 "comparison_operator" "") +; (match_operand:DF 2 "nonmemory_operand" "") +; (match_operand:DF 3 "register_operand" "")))] +; "0 /* ??? can generate less efficient code if constants involved */" +; " +;{ +; enum rtx_code code = GET_CODE (operands[1]); +; rtx ccreg = gen_rtx (REG, +; SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), +; 61); +; +; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); +;}") + +(define_insn "*movsicc_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (if_then_else (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "nonmemory_operand" "rJi") + (match_operand:SI 3 "register_operand" "0")))] + "" + "mov.%d1 %0,%S2" + [(set_attr "type" "cmove")]) + +; ??? This doesn't properly handle constants. +;(define_insn "*movdicc_insn" +; [(set (match_operand:DI 0 "register_operand" "=r,r") +; (if_then_else (match_operand 1 "comparison_operator" "") +; (match_operand:DI 2 "nonmemory_operand" "r,Ji") +; (match_operand:DI 3 "register_operand" "0,0")))] +; "0" +; "* +;{ +; switch (which_alternative) +; { +; case 0 : +; /* We normally copy the low-numbered register first. However, if +; the first register operand 0 is the same as the second register of +; operand 1, we must copy in the opposite order. */ +; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) +; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; +; else +; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; +; case 1 : +; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; +; } +;}" +; [(set_attr "type" "cmove,cmove") +; (set_attr "length" "2,4")]) + +(define_insn "*movsfcc_insn" + [(set (match_operand:SF 0 "register_operand" "=r,r") + (if_then_else (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "nonmemory_operand" "r,E") + (match_operand:SF 3 "register_operand" "0,0")))] + "" + "@ + mov.%d1 %0,%2 + mov.%d1 %0,%2 ; %A2" + [(set_attr "type" "cmove,cmove")]) + +;(define_insn "*movdfcc_insn" +; [(set (match_operand:DF 0 "register_operand" "=r,r") +; (if_then_else (match_operand 1 "comparison_operator" "") +; (match_operand:DF 2 "nonmemory_operand" "r,E") +; (match_operand:DF 3 "register_operand" "0,0")))] +; "0" +; "* +;{ +; switch (which_alternative) +; { +; case 0 : +; /* We normally copy the low-numbered register first. However, if +; the first register operand 0 is the same as the second register of +; operand 1, we must copy in the opposite order. */ +; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) +; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; +; else +; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; +; case 1 : +; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\"; +; } +;}" +; [(set_attr "type" "cmove,cmove") +; (set_attr "length" "2,4")]) + +;; Zero extension instructions. +;; ??? We don't support volatile memrefs here, but I'm not sure why. + +(define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] + "" + "@ + extb%? %0,%1 + ldb%U1 %0,%1" + [(set_attr "type" "unary,load")]) + +(define_insn "*zero_extendqihi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:HI 0 "register_operand" "=r") + (zero_extend:HI (match_dup 1)))] + "" + "extb%?.f %0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] + "" + "@ + extb%? %0,%1 + ldb%U1 %0,%1" + [(set_attr "type" "unary,load")]) + +(define_insn "*zero_extendqisi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_dup 1)))] + "" + "extb%?.f %0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] + "" + "@ + extw%? %0,%1 + ldw%U1 %0,%1" + [(set_attr "type" "unary,load")]) + +(define_insn "*zero_extendhisi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_dup 1)))] + "" + "extw%?.f %0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +;; Sign extension instructions. + +(define_insn "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] + "" + "@ + sexb%? %0,%1 + ldb.x%U1 %0,%1" + [(set_attr "type" "unary,load")]) + +(define_insn "*extendqihi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:HI 0 "register_operand" "=r") + (sign_extend:HI (match_dup 1)))] + "" + "sexb%?.f %0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +(define_insn "extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] + "" + "@ + sexb%? %0,%1 + ldb.x%U1 %0,%1" + [(set_attr "type" "unary,load")]) + +(define_insn "*extendqisi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_dup 1)))] + "" + "sexb%?.f %0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +(define_insn "extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] + "" + "@ + sexw%? %0,%1 + ldw.x%U1 %0,%1" + [(set_attr "type" "unary,load")]) + +(define_insn "*extendhisi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_dup 1)))] + "" + "sexw%?.f %0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +;; Arithmetic instructions. + +(define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")))] + "" + "add%? %0,%1,%2") + +(define_insn "*addsi3_set_cc_insn" + [(set (reg:CC 61) (compare:CC + (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) + (match_dup 2)))] + "" + "add%?.f %0,%1,%2" + [(set_attr "cond" "set")]) + +(define_insn "adddi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r") + (match_operand:DI 2 "nonmemory_operand" "ri"))) + (clobber (reg:CC 61))] + "" + "* +{ + rtx op2 = operands[2]; + + if (GET_CODE (op2) == CONST_INT) + { + int sign = INTVAL (op2); + if (sign < 0) + return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\"; + else + return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\"; + } + else + return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\"; +}" + [(set_attr "length" "2")]) + +(define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")))] + "" + "sub%? %0,%1,%2") + +(define_insn "*subsi3_set_cc_insn" + [(set (reg:CC 61) (compare:CC + (minus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_dup 1) + (match_dup 2)))] + "" + "sub%?.f %0,%1,%2" + [(set_attr "cond" "set")]) + +(define_insn "subdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (match_operand:DI 1 "nonmemory_operand" "r") + (match_operand:DI 2 "nonmemory_operand" "ri"))) + (clobber (reg:CC 61))] + "" + "* +{ + rtx op2 = operands[2]; + + if (GET_CODE (op2) == CONST_INT) + { + int sign = INTVAL (op2); + if (sign < 0) + return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\"; + else + return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\"; + } + else + return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\"; +}" + [(set_attr "length" "2")]) + +;; Boolean instructions. +;; +;; We don't define the DImode versions as expand_binop does a good enough job. + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")))] + "" + "and%? %0,%1,%2") + +(define_insn "*andsi3_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (and:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (and:SI (match_dup 1) + (match_dup 2)))] + "" + "and%?.f %0,%1,%2" + [(set_attr "cond" "set_zn")]) + +(define_insn "*bicsi3_insn" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") + (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))] + "" + "bic%? %0,%1,%2" + [(set_attr "length" "1,2,1,2")]) + +(define_insn "*bicsi3_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (and:SI (match_operand:SI 1 "register_operand" "%r") + (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ"))) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (and:SI (match_dup 1) + (not:SI (match_dup 2))))] + "" + "bic%?.f %0,%1,%2" + [(set_attr "cond" "set_zn")]) + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")))] + "" + "or%? %0,%1,%2") + +(define_insn "*iorsi3_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (ior:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_dup 1) + (match_dup 2)))] + "" + "or%?.f %0,%1,%2" + [(set_attr "cond" "set_zn")]) + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (xor:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")))] + "" + "xor%? %0,%1,%2") + +(define_insn "*xorsi3_set_cc_insn" + [(set (reg:CCZN 61) (compare:CCZN + (xor:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "nonmemory_operand" "rIJ")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (xor:SI (match_dup 1) + (match_dup 2)))] + "" + "xor%?.f %0,%1,%2" + [(set_attr "cond" "set_zn")]) + +(define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "sub%? %0,0,%1" + [(set_attr "type" "unary")]) + +(define_insn "*negsi2_set_cc_insn" + [(set (reg:CC 61) (compare:CC + (neg:SI (match_operand:SI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_dup 1)))] + "" + "sub%?.f %0,0,%1" + [(set_attr "type" "unary") + (set_attr "cond" "set")]) + +(define_insn "negdi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (match_operand:DI 1 "register_operand" "r"))) + (clobber (reg:SI 61))] + "" + "sub.f %L0,0,%L1\;sbc %H0,0,%H1" + [(set_attr "type" "unary") + (set_attr "length" "2")]) + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "xor%? %0,%1,-1" + [(set_attr "type" "unary")]) + +(define_insn "*one_cmplsi2_set_cc_insn" + [(set (reg:CCZN 61) (compare:CC + (not:SI (match_operand:SI 1 "register_operand" "r")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_dup 1)))] + "" + "xor%?.f %0,%1,-1" + [(set_attr "type" "unary") + (set_attr "cond" "set_zn")]) + +;; Shift instructions. + +(define_expand "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ashift:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + " +{ + if (! TARGET_SHIFTER) + { + emit_insn (gen_rtx + (PARALLEL, VOIDmode, + gen_rtvec (2, + gen_rtx (SET, VOIDmode, operands[0], + gen_rtx (ASHIFT, SImode, operands[1], operands[2])), + gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0))))); + DONE; + } +}") + +(define_expand "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + " +{ + if (! TARGET_SHIFTER) + { + emit_insn (gen_rtx + (PARALLEL, VOIDmode, + gen_rtvec (2, + gen_rtx (SET, VOIDmode, operands[0], + gen_rtx (ASHIFTRT, SImode, operands[1], operands[2])), + gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0))))); + DONE; + } +}") + +(define_expand "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + " +{ + if (! TARGET_SHIFTER) + { + emit_insn (gen_rtx + (PARALLEL, VOIDmode, + gen_rtvec (2, + gen_rtx (SET, VOIDmode, operands[0], + gen_rtx (LSHIFTRT, SImode, operands[1], operands[2])), + gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0))))); + DONE; + } +}") + +(define_insn "*ashlsi3_insn" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") + (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] + "TARGET_SHIFTER" + "asl%? %0,%1,%2" + [(set_attr "type" "shift") + (set_attr "length" "1,2,1,2")]) + +(define_insn "*ashrsi3_insn" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") + (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] + "TARGET_SHIFTER" + "asr%? %0,%1,%2" + [(set_attr "type" "shift") + (set_attr "length" "1,2,1,2")]) + +(define_insn "*lshrsi3_insn" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") + (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] + "TARGET_SHIFTER" + "lsr%? %0,%1,%2" + [(set_attr "type" "shift") + (set_attr "length" "1,2,1,2")]) + +(define_insn "*shift_si3" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 3 "shift_operator" + [(match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "rIJ")])) + (clobber (match_scratch:SI 4 "=&r"))] + "! TARGET_SHIFTER" + "* return output_shift (operands);" + [(set_attr "type" "shift") + (set_attr "length" "8")]) + +;; Compare instructions. +;; This controls RTL generation and register allocation. + +;; We generate RTL for comparisons and branches by having the cmpxx +;; patterns store away the operands. Then, the scc and bcc patterns +;; emit RTL for both the compare and the branch. + +(define_expand "cmpsi" + [(set (reg:CC 61) + (compare:CC (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "nonmemory_operand" "")))] + "" + " +{ + arc_compare_op0 = operands[0]; + arc_compare_op1 = operands[1]; + DONE; +}") + +;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. +;; This assumes sub.f 0,symbol,0 is a valid insn. +;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily +;; creating 8 byte insns we duplicate %1 in the destination reg of the insn +;; if it's a small constant. + +(define_insn "*cmpsi_cc_insn" + [(set (reg:CC 61) + (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") + (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] + "" + "@ + sub.f 0,%0,%1 + sub.f %1,%0,%1 + sub.f 0,%0,%1" + [(set_attr "type" "compare,compare,compare")]) + +(define_insn "*cmpsi_cczn_insn" + [(set (reg:CCZN 61) + (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r") + (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] + "" + "@ + sub.f 0,%0,%1 + sub.f %1,%0,%1 + sub.f 0,%0,%1" + [(set_attr "type" "compare,compare,compare")]) + +(define_insn "*cmpsi_ccznc_insn" + [(set (reg:CCZNC 61) + (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r") + (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] + "" + "@ + sub.f 0,%0,%1 + sub.f %1,%0,%1 + sub.f 0,%0,%1" + [(set_attr "type" "compare,compare,compare")]) + +;; Next come the scc insns. + +(define_expand "seq" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sne" + [(set (match_operand:SI 0 "register_operand" "=r") + (ne:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sgt" + [(set (match_operand:SI 0 "register_operand" "=r") + (gt:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sle" + [(set (match_operand:SI 0 "register_operand" "=r") + (le:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sge" + [(set (match_operand:SI 0 "register_operand" "=r") + (ge:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "slt" + [(set (match_operand:SI 0 "register_operand" "=r") + (lt:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sgtu" + [(set (match_operand:SI 0 "register_operand" "=r") + (gtu:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sleu" + [(set (match_operand:SI 0 "register_operand" "=r") + (leu:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sgeu" + [(set (match_operand:SI 0 "register_operand" "=r") + (geu:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "sltu" + [(set (match_operand:SI 0 "register_operand" "=r") + (ltu:SI (match_dup 1) (const_int 0)))] + "" + " +{ + operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); +}") + +(define_insn "*scc_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))] + "" + "mov %0,1\;sub.%D1 %0,%0,%0" + [(set_attr "type" "unary") + (set_attr "length" "2")]) + +;; ??? Look up negscc insn. See pa.md for example. +(define_insn "*neg_scc_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operator:SI 1 "comparison_operator" + [(reg 61) (const_int 0)])))] + "" + "mov %0,-1\;sub.%D1 %0,%0,%0" + [(set_attr "type" "unary") + (set_attr "length" "2")]) + +(define_insn "*not_scc_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operator:SI 1 "comparison_operator" + [(reg 61) (const_int 0)])))] + "" + "mov %0,1\;sub.%d1 %0,%0,%0" + [(set_attr "type" "unary") + (set_attr "length" "2")]) + +;; These control RTL generation for conditional jump insns + +(define_expand "beq" + [(set (pc) + (if_then_else (eq (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bne" + [(set (pc) + (if_then_else (ne (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bgt" + [(set (pc) + (if_then_else (gt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "ble" + [(set (pc) + (if_then_else (le (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bge" + [(set (pc) + (if_then_else (ge (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "blt" + [(set (pc) + (if_then_else (lt (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bgtu" + [(set (pc) + (if_then_else (gtu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bleu" + [(set (pc) + (if_then_else (leu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bgeu" + [(set (pc) + (if_then_else (geu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); +}") + +(define_expand "bltu" + [(set (pc) + (if_then_else (ltu (match_dup 1) (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); +}") + +;; Now match both normal and inverted jump. + +(define_insn "*branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "proper_comparison_operator" + [(reg 61) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + if (arc_ccfsm_branch_deleted_p ()) + { + arc_ccfsm_record_branch_deleted (); + return \"; branch deleted, next insns conditionalized\"; + } + else + return \"%~b%d1%# %l0\"; +}" + [(set_attr "type" "branch")]) + +(define_insn "*rev_branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "proper_comparison_operator" + [(reg 61) (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" + "* +{ + if (arc_ccfsm_branch_deleted_p ()) + { + arc_ccfsm_record_branch_deleted (); + return \"; branch deleted, next insns conditionalized\"; + } + else + return \"%~b%D1%# %l0\"; +}" + [(set_attr "type" "branch")]) + +;; Unconditional and other jump instructions. + +(define_insn "jump" + [(set (pc) (label_ref (match_operand 0 "" "")))] + "" + "b%* %l0" + [(set_attr "type" "uncond_branch")]) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "address_operand" "p"))] + "" + "j%* %a0" + [(set_attr "type" "uncond_branch")]) + +;; Implement a switch statement. +;; This wouldn't be necessary in the non-pic case if we could distinguish +;; label refs of the jump table from other label refs. The problem is that +;; label refs are output as "%st(.LL42)" but we don't want the %st - we want +;; the real address since it's the address of the table. + +(define_expand "casesi" + [(set (match_dup 5) + (minus:SI (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "nonmemory_operand" ""))) + (set (reg:CC 61) + (compare:CC (match_dup 5) + (match_operand:SI 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else (gtu (reg:CC 61) + (const_int 0)) + (label_ref (match_operand 4 "" "")) + (pc))) + (parallel + [(set (pc) + (mem:SI (plus:SI (mult:SI (match_dup 5) + (const_int 4)) + (label_ref (match_operand 3 "" ""))))) + (clobber (match_scratch:SI 6 "")) + (clobber (match_scratch:SI 7 ""))])] + "" + " +{ + operands[5] = gen_reg_rtx (SImode); +}") + +(define_insn "*casesi_insn" + [(set (pc) + (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") + (const_int 4)) + (label_ref (match_operand 1 "" ""))))) + (clobber (match_scratch:SI 2 "=r")) + (clobber (match_scratch:SI 3 "=r"))] + "" + "* +{ + output_asm_insn (\"mov %2,%1\", operands); + if (TARGET_SHIFTER) + output_asm_insn (\"asl %3,%0,2\", operands); + else + output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands); + output_asm_insn (\"ld %2,[%2,%3]\", operands); + output_asm_insn (\"j.nd %a2\", operands); + return \"\"; +}" + [(set_attr "type" "uncond_branch") + (set_attr "length" "6")]) + +(define_insn "tablejump" + [(set (pc) (match_operand:SI 0 "address_operand" "p")) + (use (label_ref (match_operand 1 "" "")))] + "0 /* disabled -> using casesi now */" + "j%* %a0" + [(set_attr "type" "uncond_branch")]) + +(define_expand "call" + ;; operands[1] is stack_size_rtx + ;; operands[2] is next_arg_register + [(parallel [(call (match_operand:SI 0 "call_operand" "") + (match_operand 1 "" "")) + (clobber (reg:SI 31))])] + "" + "") + +(define_insn "*call_via_reg" + [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "")) + (clobber (reg:SI 31))] + "" + "lr blink,[status]\;j.d %0\;add blink,blink,2" + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "3")]) + +(define_insn "*call_via_label" + [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) + (match_operand 1 "" "")) + (clobber (reg:SI 31))] + "" + ; The %~ is necessary in case this insn gets conditionalized and the previous + ; insn is the cc setter. + "%~bl%!%* %0" + [(set_attr "type" "call") + (set_attr "cond" "canuse")]) + +(define_expand "call_value" + ;; operand 2 is stack_size_rtx + ;; operand 3 is next_arg_register + [(parallel [(set (match_operand 0 "register_operand" "=r") + (call (match_operand:SI 1 "call_operand" "") + (match_operand 2 "" ""))) + (clobber (reg:SI 31))])] + "" + "") + +(define_insn "*call_value_via_reg" + [(set (match_operand 0 "register_operand" "=r") + (call (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand 2 "" ""))) + (clobber (reg:SI 31))] + "" + "lr blink,[status]\;j.d %1\;add blink,blink,2" + [(set_attr "type" "call_no_delay_slot") + (set_attr "length" "3")]) + +(define_insn "*call_value_via_label" + [(set (match_operand 0 "register_operand" "=r") + (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) + (match_operand 2 "" ""))) + (clobber (reg:SI 31))] + "" + ; The %~ is necessary in case this insn gets conditionalized and the previous + ; insn is the cc setter. + "%~bl%!%* %1" + [(set_attr "type" "call") + (set_attr "cond" "canuse")]) + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "type" "misc")]) + +;; Special pattern to flush the icache. +;; ??? Not sure what to do here. Some ARC's are known to support this. + +(define_insn "flush_icache" + [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] + "" + "* return \"\";" + [(set_attr "type" "misc")]) + +;; Split up troublesome insns for better scheduling. + +;; Peepholes go at the end. diff --git a/gnu/usr.bin/gcc/config/arc/initfini.c b/gnu/usr.bin/gcc/config/arc/initfini.c new file mode 100644 index 00000000000..084e2292bf5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/initfini.c @@ -0,0 +1,157 @@ +/* .init/.fini section handling + C++ global constructor/destructor handling. + This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm. + +Copyright (C) 1995, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this file 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. */ + +/* Declare a pointer to void function type. */ +typedef void (*func_ptr) (void); + +#ifdef CRT_INIT + +/* NOTE: In order to be able to support SVR4 shared libraries, we arrange + to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__, + __DTOR_END__ } per root executable and also one set of these symbols + per shared library. So in any given whole process image, we may have + multiple definitions of each of these symbols. In order to prevent + these definitions from conflicting with one another, and in order to + ensure that the proper lists are used for the initialization/finalization + of each individual shared library (respectively), we give these symbols + only internal (i.e. `static') linkage, and we also make it a point to + refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__ + symbol in crtinit.o, where they are defined. */ + +static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors"))) + = { (func_ptr) (-1) }; + +static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"))) + = { (func_ptr) (-1) }; + +/* Run all the global destructors on exit from the program. */ + +/* Some systems place the number of pointers in the first word of the + table. On SVR4 however, that word is -1. In all cases, the table is + null-terminated. On SVR4, we start from the beginning of the list and + invoke each per-compilation-unit destructor routine in order + until we find that null. + + Note that this function MUST be static. There will be one of these + functions in each root executable and one in each shared library, but + although they all have the same code, each one is unique in that it + refers to one particular associated `__DTOR_LIST__' which belongs to the + same particular root executable or shared library file. */ + +static void __do_global_dtors () +asm ("__do_global_dtors") __attribute__ ((section (".text"))); + +static void +__do_global_dtors () +{ + func_ptr *p; + for (p = __DTOR_LIST__ + 1; *p; p++) + (*p) (); +} + +/* .init section start. + This must appear at the start of the .init section. */ + +asm (" + .section .init\n + .global init\n + .word 0\n +init:\n + st blink,[sp,4]\n + st fp,[sp]\n + mov fp,sp\n + sub sp,sp,16\n +"); + +/* .fini section start. + This must appear at the start of the .init section. */ + +asm (" + .section .fini\n + .global fini\n + .word 0\n +fini:\n + st blink,[sp,4]\n + st fp,[sp]\n + mov fp,sp\n + sub sp,sp,16\n + bl.nd __do_global_dtors +"); + +#endif /* CRT_INIT */ + +#ifdef CRT_FINI + +/* Put a word containing zero at the end of each of our two lists of function + addresses. Note that the words defined here go into the .ctors and .dtors + sections of the crtend.o file, and since that file is always linked in + last, these words naturally end up at the very ends of the two lists + contained in these two sections. */ + +static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors"))) + = { (func_ptr) 0 }; + +static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors"))) + = { (func_ptr) 0 }; + +/* Run all global constructors for the program. + Note that they are run in reverse order. */ + +static void __do_global_ctors () +asm ("__do_global_ctors") __attribute__ ((section (".text"))); + +static void +__do_global_ctors () +{ + func_ptr *p; + for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) + (*p) (); +} + +/* .init section end. + This must live at the end of the .init section. */ + +asm (" + .section .init\n + bl.nd __do_global_ctors + ld blink,[fp,4]\n + j.d blink\n + ld.a fp,[sp,16]\n +"); + +/* .fini section end. + This must live at the end of the .fini section. */ + +asm (" + .section .fini\n + ld blink,[fp,4]\n + j.d blink\n + ld.a fp,[sp,16]\n +"); + +#endif /* CRT_FINI */ diff --git a/gnu/usr.bin/gcc/config/arc/lib1funcs.asm b/gnu/usr.bin/gcc/config/arc/lib1funcs.asm new file mode 100644 index 00000000000..a2d509ac765 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/lib1funcs.asm @@ -0,0 +1,273 @@ +; libgcc1 routines for ARC cpu. + +/* Copyright (C) 1995, 1997 Free Software Foundation, Inc. + +This file 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 other files, + some of which are compiled with GCC, to produce an executable, + this library does not by itself 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. */ + +#ifdef L_mulsi3 + .section .text + .align 4 + +#ifdef __base__ + .cpu base + .global ___mulsi3 +___mulsi3: + +/* This the simple version. + + while (a) + { + if (a & 1) + r += b; + a >>= 1; + b <<= 1; + } +*/ + mov r2,0 ; Accumulate result here. +.Lloop: + sub.f 0,r0,0 ; while (a) + nop + beq.nd .Ldone + and.f 0,r0,1 ; if (a & 1) + add.nz r2,r2,r1 ; r += b + lsr r0,r0 ; a >>= 1 + b.d .Lloop + lsl r1,r1 ; b <<= 1 +.Ldone: + j.d blink + mov r0,r2 +#endif + +#endif /* L_mulsi3 */ + +#ifdef L_umulsidi3 + .section .text + .align 4 + +#ifdef __base__ + .cpu base + .global ___umulsidi3 +___umulsidi3: + +/* This the simple version. + + while (a) + { + if (a & 1) + r += b; + a >>= 1; + b <<= 1; + } +*/ + mov r2,0 ; Top part of b. + mov r3,0 ; Accumulate result here. + mov r4,0 +.Lloop: + sub.f 0,r0,0 ; while (a) + nop + beq.nd .Ldone + and.f 0,r0,1 ; if (a & 1) + add.nz r4,r4,r1 ; r += b + adc.nz r3,r3,r2 + lsr r0,r0 ; a >>= 1 + lsl.f r1,r1 ; b <<= 1 + b.d .Lloop + rlc r2,r2 +.Ldone: +#ifdef __big_endian__ + mov r1,r4 + j.d blink + mov r0,r3 +#else + mov r0,r4 + j.d blink + mov r1,r3 +#endif +#endif + +#endif /* L_umulsidi3 */ + +#ifdef L_divmod_tools + +; Utilities used by all routines. + + .section .text + .align 4 + +; inputs: r0 = numerator, r1 = denominator +; outputs: positive r0/r1, +; r6.bit1 = sign of numerator, r6.bit0 = sign of result + + .global ___divnorm +___divnorm: + mov r6,0 ; keep sign in r6 + sub.f 0,r0,0 ; is numerator -ve? + sub.lt r0,0,r0 ; negate numerator + mov.lt r6,3 ; sign is -ve + sub.f 0,r1,0 ; is denominator -ve? + sub.lt r1,0,r1 ; negate denominator + xor.lt r6,r6,1 ; toggle sign + j.nd blink + +/* +unsigned long +udivmodsi4(int modwanted, unsigned long num, unsigned long den) +{ + unsigned long bit = 1; + unsigned long res = 0; + + while (den < num && bit && !(den & (1L<<31))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) return num; + return res; +} +*/ + +; inputs: r0 = numerator, r1 = denominator +; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed + + .global ___udivmodsi4 +___udivmodsi4: + mov r2,1 ; bit = 1 + mov r3,0 ; res = 0 +.Lloop1: + sub.f 0,r1,r0 ; while (den < num + nop + bnc.nd .Lloop2 + sub.f 0,r2,0 ; && bit + nop + bz.nd .Lloop2 + lsl.f 0,r1 ; && !(den & (1<<31)) + nop + bc.nd .Lloop2 + lsl r1,r1 ; den <<= 1 + b.d .Lloop1 + lsl r2,r2 ; bit <<= 1 +.Lloop2: + sub.f 0,r2,0 ; while (bit) + nop + bz.nd .Ldivmodend + sub.f 0,r0,r1 ; if (num >= den) + nop + bc.nd .Lshiftdown + sub r0,r0,r1 ; num -= den + or r3,r3,r2 ; res |= bit +.Lshiftdown: + lsr r2,r2 ; bit >>= 1 + b.d .Lloop2 + lsr r1,r1 ; den >>= 1 +.Ldivmodend: + mov r1,r0 ; r1 = mod + j.d blink + mov r0,r3 ; r0 = res + +#endif + +#ifdef L_udivsi3 + .section .text + .align 4 + +#ifdef __base__ + .cpu base + .global ___udivsi3 +___udivsi3: + mov r7,blink + bl.nd ___udivmodsi4 + j.nd r7 +#endif + +#endif /* L_udivsi3 */ + +#ifdef L_divsi3 + .section .text + .align 4 + +#ifdef __base__ + .cpu base + .global ___divsi3 +___divsi3: + mov r7,blink + bl.nd ___divnorm + bl.nd ___udivmodsi4 + and.f 0,r6,1 + sub.nz r0,0,r0 ; cannot go in delay slot, has limm value + j.nd r7 +#endif + +#endif /* L_divsi3 */ + +#ifdef L_umodsi3 + .section .text + .align 4 + +#ifdef __base__ + .cpu base + .global ___umodsi3 +___umodsi3: + mov r7,blink + bl.nd ___udivmodsi4 + j.d r7 + mov r0,r1 +#endif + +#endif /* L_umodsi3 */ + +#ifdef L_modsi3 + .section .text + .align 4 + +#ifdef __base__ + .cpu base + .global ___modsi3 +___modsi3: + mov r7,blink + bl.nd ___divnorm + bl.nd ___udivmodsi4 + and.f 0,r6,2 + sub.nz r1,0,r1 + j.d r7 + mov r0,r1 +#endif + +#endif /* L_modsi3 */ diff --git a/gnu/usr.bin/gcc/config/arc/t-arc b/gnu/usr.bin/gcc/config/arc/t-arc new file mode 100644 index 00000000000..d922c27ca5f --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/t-arc @@ -0,0 +1,72 @@ +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = arc/lib1funcs.asm +LIB1ASMFUNCS = _mulsi3 _umulsidi3 _udivsi3 _divsi3 _umodsi3 _modsi3 _divmod_tools + +# We need libgcc routines to be mangled according to which cpu they +# were compiled for. +# ??? -mmangle-cpu passed by default for now. +#LIBGCC2_CFLAGS = -g1 -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -mmangle-cpu + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + echo '#ifndef __big_endian__' > dp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c + echo '#endif' >> dp-bit.c + cat $(srcdir)/config/fp-bit.c >> dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + echo '#ifndef __big_endian__' >> fp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c + echo '#endif' >> fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +# .init/.fini section routines + +x-crtinit.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ + -DCRT_INIT -finhibit-size-directive -fno-inline-functions \ + -g0 -c $(srcdir)/config/arc/initfini.c -o $(dir)/crtinit.o + +x-crtfini.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ + -DCRT_FINI -finhibit-size-directive -fno-inline-functions \ + -g0 -c $(srcdir)/config/arc/initfini.c -o $(dir)/crtfini.o + +MULTILIB_OPTIONS = EB +MULTILIB_DIRNAMES = be + +# We need our own versions to build multiple copies of crt*.o. +# ??? Use new support in Makefile. + +LIBGCC = stmp-multilib-arc +INSTALL_LIBGCC = install-multilib-arc + +stmp-multilib-arc: stmp-multilib + for i in `$(GCC_FOR_TARGET) --print-multi-lib`; do \ + dir=`echo $$i | sed -e 's/;.*$$//'`; \ + flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \ + $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ + CC="$(CC)" CFLAGS="$(CFLAGS)" \ + HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ + GCC_CFLAGS="$(GCC_CFLAGS) $${flags}" \ + INCLUDES="$(INCLUDES)" CRTSTUFF_T_CFLAGS=$(CRTSTUFF_T_CFLAGS) \ + dir="$${dir}" x-crtinit.o x-crtfini.o; \ + if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ + done + touch stmp-multilib-arc + +install-multilib-arc: install-multilib + for i in `$(GCC_FOR_TARGET) --print-multi-lib`; do \ + dir=`echo $$i | sed -e 's/;.*$$//'`; \ + rm -f $(libsubdir)/$${dir}/crtinit.o; \ + $(INSTALL_DATA) $${dir}/crtinit.o $(libsubdir)/$${dir}/crtinit.o; \ + chmod a-x $(libsubdir)/$${dir}/crtinit.o; \ + rm -f $(libsubdir)/$${dir}/crtfini.o; \ + $(INSTALL_DATA) $${dir}/crtfini.o $(libsubdir)/$${dir}/crtfini.o; \ + chmod a-x $(libsubdir)/$${dir}/crtfini.o; \ + done diff --git a/gnu/usr.bin/gcc/config/arc/xm-arc.h b/gnu/usr.bin/gcc/config/arc/xm-arc.h new file mode 100644 index 00000000000..ba011e94be6 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arc/xm-arc.h @@ -0,0 +1,47 @@ +/* Configuration for GNU C-compiler for the ARC processor. + Copyright (C) 1994, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Doubles are stored in memory with the high order word first. This + matters when cross-compiling. */ +#define HOST_WORDS_BIG_ENDIAN 1 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ +#include "tm.h" + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* If compiled with Sun CC, the use of alloca requires this #include. */ +#ifndef __GNUC__ +#include "alloca.h" +#endif diff --git a/gnu/usr.bin/gcc/config/arm/aof.h b/gnu/usr.bin/gcc/config/arm/aof.h new file mode 100644 index 00000000000..4d30defd5cf --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/aof.h @@ -0,0 +1,453 @@ +/* Definitions of target machine for GNU compiler, for Advanced RISC Machines + ARM compilation, AOF Assembler. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Earnshaw (rearnsha@armltd.co.uk) + +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. */ + + + +#define AOF_ASSEMBLER + +#define LINK_LIBGCC_SPECIAL 1 + +#define LINK_SPEC "%{aof} %{bin} %{aif} %{ihf} %{shl,*} %{reent*} %{split} \ + %{ov*,*} %{reloc*} -nodebug" + +#define STARTFILE_SPEC "crtbegin.o%s" + +#define ENDFILE_SPEC "crtend.o%s" + +#ifndef ASM_SPEC +#define ASM_SPEC "%{g -g} -arch 4 \ +-apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/26bit}}" +#endif + +#ifndef LIB_SPEC +#define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}" +#endif + +#define LIBGCC_SPEC "libgcc.a%s" + +/* Dividing the Output into Sections (Text, Data, ...) */ +/* AOF Assembler syntax is a nightmare when it comes to areas, since once + we change from one area to another, we can't go back again. Instead, + we must create a new area with the same attributes and add the new output + to that. Unfortunately, there is nothing we can do here to guarantee that + two areas with the same attributes will be linked adjacently in the + resulting executable, so we have to be careful not to do pc-relative + addressing across such boundaries. */ +char *aof_text_section (); +#define TEXT_SECTION_ASM_OP aof_text_section () + +#define SELECT_RTX_SECTION(MODE,RTX) text_section (); + +char *aof_data_section (); +#define DATA_SECTION_ASM_OP aof_data_section () + +#define EXTRA_SECTIONS in_zero_init, in_ctor, in_dtor, in_common + +#define EXTRA_SECTION_FUNCTIONS \ +ZERO_INIT_SECTION \ +CTOR_SECTION \ +DTOR_SECTION \ +COMMON_SECTION + +#define ZERO_INIT_SECTION \ +void \ +zero_init_section () \ +{ \ + static int zero_init_count = 1; \ + if (in_section != in_zero_init) \ + { \ + fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", \ + zero_init_count++); \ + in_section = in_zero_init; \ + } \ +} + +#define CTOR_SECTION \ +void \ +ctor_section () \ +{ \ + static int ctors_once = 0; \ + if (in_section != in_ctor) \ + { \ + if (ctors_once) \ + { \ + fprintf (stderr, \ + "Attempt to output more than one ctor section\n"); \ + abort (); \ + } \ + fprintf (asm_out_file, "\t%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctor; \ + ctors_once = 1; \ + } \ +} + +#define DTOR_SECTION \ +void \ +dtor_section () \ +{ \ + static int dtors_once = 0; \ + if (in_section != in_dtor) \ + { \ + if (dtors_once) \ + { \ + fprintf (stderr, \ + "Attempt to output more than one dtor section\n"); \ + abort (); \ + } \ + fprintf (asm_out_file, "\t%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtor; \ + dtors_once = 1; \ + } \ +} + +/* Used by ASM_OUTPUT_COMMON (below) to tell varasm.c that we've + changed areas. */ +#define COMMON_SECTION \ +void \ +common_section () \ +{ \ + static int common_count = 1; \ + if (in_section != in_common) \ + { \ + in_section = in_common; \ + } \ +} +#define CTOR_LIST_BEGIN \ +asm (CTORS_SECTION_ASM_OP); \ +extern func_ptr __CTOR_END__[1]; \ +func_ptr __CTOR_LIST__[1] = {__CTOR_END__}; + +#define CTOR_LIST_END \ +asm (CTORS_SECTION_ASM_OP); \ +func_ptr __CTOR_END__[1] = { (func_ptr) 0 }; + +#define DO_GLOBAL_CTORS_BODY \ +do { \ + func_ptr *ptr = __CTOR_LIST__ + 1; \ + while (*ptr) \ + (*ptr++) (); \ +} while (0) + +#define DTOR_LIST_BEGIN \ +asm (DTORS_SECTION_ASM_OP); \ +extern func_ptr __DTOR_END__[1]; \ +func_ptr __DTOR_LIST__[1] = {__DTOR_END__}; + +#define DTOR_LIST_END \ +asm (DTORS_SECTION_ASM_OP); \ +func_ptr __DTOR_END__[1] = { (func_ptr) 0 }; + +#define DO_GLOBAL_DTORS_BODY \ +do { \ + func_ptr *ptr = __DTOR_LIST__ + 1; \ + while (*ptr) \ + (*ptr++) (); \ +} while (0) + +#define JUMP_TABLES_IN_TEXT_SECTION 1 + +#ifndef ARM_OS_NAME +#define ARM_OS_NAME "(generic)" +#endif + +/* For the AOF linker, we need to reference __main to force the standard + library to get linked in. */ + +#define ASM_FILE_START(STREAM) \ +{ \ + extern char *version_string; \ + fprintf ((STREAM), "%s Generated by gcc %s for ARM/%s\n", \ + ASM_COMMENT_START, version_string, ARM_OS_NAME); \ + fprintf ((STREAM), "__a1\tRN\t0\n"); \ + fprintf ((STREAM), "__a2\tRN\t1\n"); \ + fprintf ((STREAM), "__a3\tRN\t2\n"); \ + fprintf ((STREAM), "__a4\tRN\t3\n"); \ + fprintf ((STREAM), "__v1\tRN\t4\n"); \ + fprintf ((STREAM), "__v2\tRN\t5\n"); \ + fprintf ((STREAM), "__v3\tRN\t6\n"); \ + fprintf ((STREAM), "__v4\tRN\t7\n"); \ + fprintf ((STREAM), "__v5\tRN\t8\n"); \ + fprintf ((STREAM), "__v6\tRN\t9\n"); \ + fprintf ((STREAM), "__sl\tRN\t10\n"); \ + fprintf ((STREAM), "__fp\tRN\t11\n"); \ + fprintf ((STREAM), "__ip\tRN\t12\n"); \ + fprintf ((STREAM), "__sp\tRN\t13\n"); \ + fprintf ((STREAM), "__lr\tRN\t14\n"); \ + fprintf ((STREAM), "__pc\tRN\t15\n"); \ + fprintf ((STREAM), "__f0\tFN\t0\n"); \ + fprintf ((STREAM), "__f1\tFN\t1\n"); \ + fprintf ((STREAM), "__f2\tFN\t2\n"); \ + fprintf ((STREAM), "__f3\tFN\t3\n"); \ + fprintf ((STREAM), "__f4\tFN\t4\n"); \ + fprintf ((STREAM), "__f5\tFN\t5\n"); \ + fprintf ((STREAM), "__f6\tFN\t6\n"); \ + fprintf ((STREAM), "__f7\tFN\t7\n"); \ + text_section (); \ +} + +/* Some systems use __main in a way incompatible with its use in gcc, in these + cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to + give the same symbol without quotes for an alternative entry point. You + must define both, or neither. */ +#define NAME__MAIN "__gccmain" +#define SYMBOL__MAIN __gccmain + +#define ASM_FILE_END(STREAM) \ +do \ +{ \ + if (flag_pic) \ + aof_dump_pic_table (STREAM); \ + aof_dump_imports (STREAM); \ + fputs ("\tEND\n", (STREAM)); \ +} while (0); + +#define ASM_IDENTIFY_GCC(STREAM) fputs ("|gcc2_compiled.|\n", (STREAM)) + +#define ASM_COMMENT_START ";" + +#define ASM_APP_ON "" + +#define ASM_APP_OFF "" + +#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \ + ASM_OUTPUT_DOUBLE((STREAM),(VALUE)) + +#define ASM_OUTPUT_DOUBLE(STREAM,VALUE) \ +do { \ + char dstr[30]; \ + long l[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), l); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.14g", dstr); \ + fprintf ((STREAM), "\tDCD &%lx, &%lx\t%s double %s\n", \ + l[0], l[1], ASM_COMMENT_START, dstr); \ +} while (0) + +#define ASM_OUTPUT_FLOAT(STREAM,VALUE) \ +do { \ + char dstr[30]; \ + long l; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), l); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.7g", dstr); \ + fprintf ((STREAM), "\tDCD &%lx\t%s double %s\n", \ + l, ASM_COMMENT_START, dstr); \ +} while (0) + +#define ASM_OUTPUT_INT(STREAM,VALUE) \ + (fprintf ((STREAM), "\tDCD\t"), \ + output_addr_const ((STREAM), (VALUE)), \ + fputc ('\n', (STREAM))) + +#define ASM_OUTPUT_SHORT(STREAM,VALUE) \ + (fprintf ((STREAM), "\tDCW\t"), \ + output_addr_const ((STREAM), (VALUE)), \ + fputc ('\n', (STREAM))) + +#define ASM_OUTPUT_CHAR(STREAM,VALUE) \ + (fprintf ((STREAM), "\tDCB\t"), \ + output_addr_const ((STREAM), (VALUE)), \ + fputc ('\n', (STREAM))) + +#define ASM_OUTPUT_BYTE(STREAM,VALUE) \ + fprintf ((STREAM), "\tDCB\t%d\n", (VALUE)) + +#define ASM_OUTPUT_ASCII(STREAM,PTR,LEN) \ +{ \ + int i; \ + char *ptr = (PTR); \ + fprintf ((STREAM), "\tDCB"); \ + for (i = 0; i < (LEN); i++) \ + fprintf ((STREAM), " &%02x%s", \ + (unsigned ) *(ptr++), \ + (i + 1 < (LEN) \ + ? ((i & 3) == 3 ? "\n\tDCB" : ",") \ + : "\n")); \ +} + +#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n') + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* Output of Uninitialized Variables */ + +#define ASM_OUTPUT_COMMON(STREAM,NAME,SIZE,ROUNDED) \ + (common_section (), \ + fprintf ((STREAM), "\tAREA "), \ + assemble_name ((STREAM), (NAME)), \ + fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \ + (ROUNDED), ASM_COMMENT_START, SIZE)) + +#define ASM_OUTPUT_LOCAL(STREAM,NAME,SIZE,ROUNDED) \ + (zero_init_section (), \ + assemble_name ((STREAM), (NAME)), \ + fprintf ((STREAM), "\n"), \ + fprintf ((STREAM), "\t%% %d\t%s size=%d\n", \ + (ROUNDED), ASM_COMMENT_START, SIZE)) + +/* Output and Generation of Labels */ + +extern int arm_main_function; + +#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \ +do { \ + fprintf ((STREAM), "\tEXPORT\t"); \ + assemble_name ((STREAM), (NAME)); \ + fputc ('\n', (STREAM)); \ + if ((NAME)[0] == 'm' && ! strcmp ((NAME), "main")) \ + arm_main_function = 1; \ +} while (0) + +#define ASM_OUTPUT_LABEL(STREAM,NAME) \ +do { \ + assemble_name (STREAM,NAME); \ + fputs ("\n", STREAM); \ +} while (0) + +#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \ +{ \ + ASM_OUTPUT_LABEL (STREAM, NAME); \ + if (! TREE_PUBLIC (DECL)) \ + { \ + fputs ("\tKEEP ", STREAM); \ + ASM_OUTPUT_LABEL (STREAM, NAME); \ + } \ + aof_delete_import ((NAME)); \ +} + +#define ASM_DECLARE_OBJECT_NAME(STREAM,NAME,DECL) \ +{ \ + ASM_OUTPUT_LABEL (STREAM, NAME); \ + if (! TREE_PUBLIC (DECL)) \ + { \ + fputs ("\tKEEP ", STREAM); \ + ASM_OUTPUT_LABEL (STREAM, NAME); \ + } \ + aof_delete_import ((NAME)); \ +} + +#define ASM_OUTPUT_EXTERNAL(STREAM,DECL,NAME) \ + aof_add_import ((NAME)) + +#define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM,SYMREF) \ + (fprintf ((STREAM), "\tIMPORT\t"), \ + assemble_name ((STREAM), XSTR ((SYMREF), 0)), \ + fputc ('\n', (STREAM))) + +#define ASM_OUTPUT_LABELREF(STREAM,NAME) \ + fprintf ((STREAM), "|%s|", NAME) + +#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \ + sprintf ((STRING), "*|%s..%d|", (PREFIX), (NUM)) + +#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \ + ((OUTVAR) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER))) + +/* How initialization functions are handled */ + +#define CTORS_SECTION_ASM_OP "AREA\t|C$$gnu_ctorsvec|, DATA, READONLY" +#define DTORS_SECTION_ASM_OP "AREA\t|C$$gnu_dtorsvec|, DATA, READONLY" + +#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \ +do { \ + ctor_section (); \ + fprintf ((STREAM), "\tDCD\t"); \ + assemble_name ((STREAM), (NAME)); \ + fputc ('\n', (STREAM)); \ +} while (0); + +#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \ +do { \ + dtor_section (); \ + fprintf ((STREAM), "\tDCD\t"); \ + assemble_name ((STREAM), (NAME)); \ + fputc ('\n', (STREAM)); \ +} while (0); + +/* Output of Assembler Instructions */ + +#define REGISTER_NAMES \ +{ \ + "a1", "a2", "a3", "a4", \ + "v1", "v2", "v3", "v4", \ + "v5", "v6", "sl", "fp", \ + "ip", "sp", "lr", "pc", \ + "f0", "f1", "f2", "f3", \ + "f4", "f5", "f6", "f7", \ + "cc", "sfp", "afp" \ +} + +#define ADDITIONAL_REGISTER_NAMES \ +{ \ + {"r0", 0}, {"a1", 0}, \ + {"r1", 1}, {"a2", 1}, \ + {"r2", 2}, {"a3", 2}, \ + {"r3", 3}, {"a4", 3}, \ + {"r4", 4}, {"v1", 4}, \ + {"r5", 5}, {"v2", 5}, \ + {"r6", 6}, {"v3", 6}, \ + {"r7", 7}, {"wr", 7}, \ + {"r8", 8}, {"v5", 8}, \ + {"r9", 9}, {"v6", 9}, \ + {"r10", 10}, {"sl", 10}, {"v7", 10}, \ + {"r11", 11}, {"fp", 11}, \ + {"r12", 12}, {"ip", 12}, \ + {"r13", 13}, {"sp", 13}, \ + {"r14", 14}, {"lr", 14}, \ + {"r15", 15}, {"pc", 15} \ +} + +#define REGISTER_PREFIX "__" +#define USER_LABEL_PREFIX "" +#define LOCAL_LABEL_PREFIX "" + +/* Output of Dispatch Tables */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL) \ + fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE)) + +#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \ + fprintf ((STREAM), "\tDCD\t|L..%d|\n", (VALUE)) + +/* A label marking the start of a jump table is a data label. */ +#define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) \ + fprintf ((STREAM), "\tALIGN\n|%s..%d|\n", (PREFIX), (NUM)) + +/* Assembler Commands for Alignment */ + +#define ASM_OUTPUT_SKIP(STREAM,NBYTES) \ + fprintf ((STREAM), "\t%%\t%d\n", (NBYTES)) + +#define ASM_OUTPUT_ALIGN(STREAM,POWER) \ +do { \ + register int amount = 1 << (POWER); \ + if (amount == 2) \ + fprintf ((STREAM), "\tALIGN 2\n"); \ + else if (amount == 4) \ + fprintf ((STREAM), "\tALIGN\n"); \ + else \ + fprintf ((STREAM), "\tALIGN %d\n", amount); \ +} while (0) + +#include "arm/arm.h" + +#undef DBX_DEBUGGING_INFO diff --git a/gnu/usr.bin/gcc/config/arm/aout.h b/gnu/usr.bin/gcc/config/arm/aout.h new file mode 100644 index 00000000000..68e7227f7fc --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/aout.h @@ -0,0 +1,259 @@ +/* Definitions of target machine for GNU compiler, for ARM with a.out + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Earnshaw (rearnsha@armltd.co.uk). + +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. */ + +#ifndef ARM_OS_NAME +#define ARM_OS_NAME "(generic)" +#endif + +/* The text to go at the start of the assembler file */ +#define ASM_FILE_START(STREAM) \ +{ \ + fprintf (STREAM,"%srfp\t.req\t%sr9\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%ssl\t.req\t%sr10\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%sfp\t.req\t%sr11\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%sip\t.req\t%sr12\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%ssp\t.req\t%sr13\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%slr\t.req\t%sr14\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf (STREAM,"%spc\t.req\t%sr15\n", REGISTER_PREFIX, REGISTER_PREFIX); \ +} + +#define ASM_APP_ON "" +#define ASM_APP_OFF "" + +/* Switch to the text or data segment. */ +#define TEXT_SECTION_ASM_OP ".text" +#define DATA_SECTION_ASM_OP ".data" +#define BSS_SECTION_ASM_OP ".bss" + +#define REGISTER_PREFIX "" +#define USER_LABEL_PREFIX "_" +#define LOCAL_LABEL_PREFIX "" + +/* The assembler's names for the registers. */ +#ifndef REGISTER_NAMES +#define REGISTER_NAMES \ +{ \ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ + "cc", "sfp", "afp" \ +} +#endif + +#ifndef ADDITIONAL_REGISTER_NAMES +#define ADDITIONAL_REGISTER_NAMES \ +{ \ + {"a1", 0}, \ + {"a2", 1}, \ + {"a3", 2}, \ + {"a4", 3}, \ + {"v1", 4}, \ + {"v2", 5}, \ + {"v3", 6}, \ + {"v4", 7}, \ + {"v5", 8}, \ + {"v6", 9}, \ + {"rfp", 9}, /* Gcc used to call it this */ \ + {"sb", 9}, \ + {"v7", 10}, \ + {"r10", 10}, /* sl */ \ + {"r11", 11}, /* fp */ \ + {"r12", 12}, /* ip */ \ + {"r13", 13}, /* sp */ \ + {"r14", 14}, /* lr */ \ + {"r15", 15} /* pc */ \ +} +#endif + +/* Arm Assembler barfs on dollars */ +#define DOLLARS_IN_IDENTIFIERS 0 + +#define NO_DOLLAR_IN_LABEL + +/* DBX register number for a given compiler register number */ +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* Generate DBX debugging information. riscix.h will undefine this because + the native assembler does not support stabs. */ +#define DBX_DEBUGGING_INFO 1 + +/* Acorn dbx moans about continuation chars, so don't use any. */ +#ifndef DBX_CONTIN_LENGTH +#define DBX_CONTIN_LENGTH 0 +#endif + +/* Output a source filename for the debugger. RISCiX dbx insists that the + ``desc'' field is set to compiler version number >= 315 (sic). */ +#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM,NAME) \ +do { \ + fprintf (STREAM, ".stabs \"%s\",%d,0,315,%s\n", (NAME), N_SO, \ + <ext_label_name[1]); \ + text_section (); \ + ASM_OUTPUT_INTERNAL_LABEL (STREAM, "Ltext", 0); \ +} while (0) + +/* Output a function label definition. */ +#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \ + ASM_OUTPUT_LABEL(STREAM, NAME) + +#define ASM_OUTPUT_LABEL(STREAM,NAME) \ +do { \ + assemble_name (STREAM,NAME); \ + fputs (":\n", STREAM); \ +} while (0) + +/* Output a globalising directive for a label. */ +#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \ + (fprintf (STREAM, "\t.global\t"), \ + assemble_name (STREAM, NAME), \ + fputc ('\n',STREAM)) \ + +/* Make an internal label into a string. */ +#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \ + sprintf (STRING, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM) + +/* Nothing special is done about jump tables */ +/* #define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) */ +/* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE) */ + +/* Construct a private name. */ +#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \ + ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \ + sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER))) + +/* Output an element of a dispatch table. */ +#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \ + fprintf (STREAM, "\t.word\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE) + +#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL) \ + fprintf (STREAM, "\tb\t%sL%d\n", LOCAL_LABEL_PREFIX, (VALUE)) + +/* Output various types of constants. For real numbers we output hex, with + a comment containing the "human" value, this allows us to pass NaN's which + the riscix assembler doesn't understand (it also makes cross-assembling + less likely to fail). */ + +#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \ +do { char dstr[30]; \ + long l[3]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \ + REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \ + fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n", \ + l[0], l[1], l[2], ASM_COMMENT_START, dstr); \ + } while (0) + + +#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \ +do { char dstr[30]; \ + long l[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ + REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \ + fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \ + l[1], ASM_COMMENT_START, dstr); \ + } while (0) + +#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \ +do { char dstr[30]; \ + long l; \ + REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ + REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \ + fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \ + ASM_COMMENT_START, dstr); \ + } while (0); + +#define ASM_OUTPUT_INT(STREAM, EXP) \ + { \ + fprintf (STREAM, "\t.word\t"); \ + OUTPUT_INT_ADDR_CONST (STREAM, (EXP)); \ + fputc ('\n', STREAM); \ + } + +#define ASM_OUTPUT_SHORT(STREAM, EXP) \ + (fprintf (STREAM, "\t.short\t"), \ + output_addr_const (STREAM, (EXP)), \ + fputc ('\n', STREAM)) + +#define ASM_OUTPUT_CHAR(STREAM, EXP) \ + (fprintf (STREAM, "\t.byte\t"), \ + output_addr_const (STREAM, (EXP)), \ + fputc ('\n', STREAM)) + +#define ASM_OUTPUT_BYTE(STREAM, VALUE) \ + fprintf (STREAM, "\t.byte\t%d\n", VALUE) + +#define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) \ + output_ascii_pseudo_op ((STREAM), (unsigned char *)(PTR), (LEN)) + +/* Output a gap. In fact we fill it with nulls. */ +#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \ + fprintf (STREAM, "\t.space\t%d\n", NBYTES) + +/* Align output to a power of two. Horrible /bin/as. */ +#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ + do \ + { \ + register int amount = 1 << (POWER); \ + \ + if (amount == 2) \ + fprintf (STREAM, "\t.even\n"); \ + else if (amount != 1) \ + fprintf (STREAM, "\t.align\t%d\n", amount - 4); \ + } while (0) + +/* Output a common block */ +#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ + (fprintf (STREAM, "\t.comm\t"), \ + assemble_name ((STREAM), (NAME)), \ + fprintf(STREAM, ", %d\t%s %d\n", ROUNDED, ASM_COMMENT_START, SIZE)) + +/* Output a local common block. /bin/as can't do this, so hack a + `.space' into the bss segment. Note that this is *bad* practice. */ +#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM,NAME,SIZE,ALIGN) \ + do { \ + bss_section (); \ + ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \ + ASM_OUTPUT_LABEL (STREAM, NAME); \ + fprintf (STREAM, "\t.space\t%d\n", SIZE); \ + } while (0) + +/* Output a zero-initialized block. */ +#define ASM_OUTPUT_ALIGNED_BSS(STREAM,DECL,NAME,SIZE,ALIGN) \ + asm_output_aligned_bss(STREAM, DECL, NAME, SIZE, ALIGN) + +/* Output a source line for the debugger. */ +/* #define ASM_OUTPUT_SOURCE_LINE(STREAM,LINE) */ + +/* Output a #ident directive. */ +#define ASM_OUTPUT_IDENT(STREAM,STRING) \ + fprintf (STREAM,"- - - ident %s\n",STRING) + +/* The assembler's parentheses characters. */ +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +#ifndef ASM_COMMENT_START +#define ASM_COMMENT_START "@" +#endif + +/* This works for GAS and some other assemblers. */ +#define SET_ASM_OP ".set" + +#include "arm/arm.h" diff --git a/gnu/usr.bin/gcc/config/arm/coff.h b/gnu/usr.bin/gcc/config/arm/coff.h new file mode 100644 index 00000000000..92101588c8f --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/coff.h @@ -0,0 +1,209 @@ +/* Definitions of target machine for GNU compiler, + for ARM with COFF obj format. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Doug Evans (dje@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. */ + +#include "arm/semi.h" + +/* Run-time Target Specification. */ +#undef TARGET_VERSION +#define TARGET_VERSION fputs (" (ARM/coff)", stderr) + +/* ??? Maybe use --with{enable?}-fpu or some such to make hardware floating + point the default. NOT --nfp! --with{enable?} is supposed to replace it + (right?), so let's stop using it. */ +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32) + +/* ??? Is a big-endian default intended to be supported? */ +#if 0 /*TARGET_CPU_DEFAULT & ARM_FLAG_BIG_END*/ +#define MULTILIB_DEFAULTS { "mbig-endian" } +#else +#define MULTILIB_DEFAULTS { "mlittle-endian" } +#endif + +/* ??? Does arm.h really need to set this to 32? */ +#undef STRUCTURE_SIZE_BOUNDARY +#define STRUCTURE_SIZE_BOUNDARY 8 + +/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS + is a valid machine specific attribute for DECL. + The attributes in ATTRIBUTES have previously been assigned to DECL. */ +extern int arm_valid_machine_decl_attribute (); +#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ +arm_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) + +/* This is COFF, but prefer stabs. */ +#define SDB_DEBUGGING_INFO + +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "dbxcoff.h" + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX "." + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +/* A C statement to output assembler commands which will identify the + object file as having been compiled with GNU CC (or another GNU + compiler). */ +/* Define this to NULL so we don't get anything. + We have ASM_IDENTIFY_LANGUAGE. + Also, when using stabs, gcc2_compiled must be a stabs entry, not an + ordinary symbol, or gdb won't see it. The stabs entry must be + before the N_SO in order for gdb to find it. */ +#define ASM_IDENTIFY_GCC(STREAM) + +/* This outputs a lot of .req's to define alias for various registers. + Let's try to avoid this. */ +#undef ASM_FILE_START +#define ASM_FILE_START(STREAM) \ +do { \ + extern char *version_string; \ + fprintf (STREAM, "%s Generated by gcc %s for ARM/coff\n", \ + ASM_COMMENT_START, version_string); \ +} while (0) + +/* A C statement to output something to the assembler file to switch to section + NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or + NULL_TREE. Some target formats do not support arbitrary sections. Do not + define this macro in such cases. */ +#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \ +do { \ + if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \ + fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \ + else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \ + fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \ + else \ + fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \ +} while (0) + +/* Support the ctors/dtors and other sections. */ + +#undef INIT_SECTION_ASM_OP + +/* Define this macro if jump tables (for `tablejump' insns) should be + output in the text section, along with the assembler instructions. + Otherwise, the readonly data section is used. */ +#define JUMP_TABLES_IN_TEXT_SECTION + +#undef READONLY_DATA_SECTION +#define READONLY_DATA_SECTION rdata_section +#undef RDATA_SECTION_ASM_OP +#define RDATA_SECTION_ASM_OP "\t.section .rdata" + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"x\"" +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"x\"" + +/* A list of other sections which the compiler might be "in" at any + given time. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_rdata, in_ctors, in_dtors + +#define SUBTARGET_EXTRA_SECTIONS + +/* A list of extra section function definitions. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + RDATA_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION \ + SUBTARGET_EXTRA_SECTION_FUNCTIONS + +#define SUBTARGET_EXTRA_SECTION_FUNCTIONS + +#define RDATA_SECTION_FUNCTION \ +void \ +rdata_section () \ +{ \ + if (in_section != in_rdata) \ + { \ + fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \ + in_section = in_rdata; \ + } \ +} + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +/* Support the ctors/dtors sections for g++. */ + +#define INT_ASM_OP ".word" + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#undef ASM_OUTPUT_CONSTRUCTOR +#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \ +do { \ + ctors_section (); \ + fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \ + assemble_name (STREAM, NAME); \ + fprintf (STREAM, "\n"); \ +} while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#undef ASM_OUTPUT_DESTRUCTOR +#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \ +do { \ + dtors_section (); \ + fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \ + assemble_name (STREAM, NAME); \ + fprintf (STREAM, "\n"); \ +} while (0) + +/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script. */ +#define CTOR_LISTS_DEFINED_EXTERNALLY + +#undef DO_GLOBAL_CTORS_BODY +#undef DO_GLOBAL_DTORS_BODY + +/* The ARM development system has atexit and doesn't have _exit, + so define this for now. */ +#define HAVE_ATEXIT + +/* The ARM development system defines __main. */ +#define NAME__MAIN "__gccmain" +#define SYMBOL__MAIN __gccmain diff --git a/gnu/usr.bin/gcc/config/arm/linux-gas.h b/gnu/usr.bin/gcc/config/arm/linux-gas.h new file mode 100644 index 00000000000..ea8b4f0a37e --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/linux-gas.h @@ -0,0 +1,34 @@ +/* Definitions of target machine for GNU compiler. ARM Linux-based GNU + systems version. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Russell King <rmk92@ecs.soton.ac.uk>. + +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 this program; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Limit the length of a stabs entry (for the broken Acorn assembler) */ +#define DBX_CONTIN_LENGTH 80 + +#include "arm/linux.h" + +/* + * We are using GAS, so stabs should work. + */ + +#ifndef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO 1 +#endif diff --git a/gnu/usr.bin/gcc/config/arm/linux.h b/gnu/usr.bin/gcc/config/arm/linux.h new file mode 100644 index 00000000000..fa8fef10e72 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/linux.h @@ -0,0 +1,72 @@ +/* Definitions for ARM running Linux-based GNU systems. + Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. + Contributed by Russell King <rmk92@ecs.soton.ac.uk>. + +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 this program; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include <linux-aout.h> + +/* these are different... */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ +"%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}" + +#undef ASM_APP_ON +#undef ASM_APP_OFF +#undef COMMENT_BEGIN + +/* We default to ARM3. */ +#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm3 + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ +"-Dunix -Darm -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(arm) -Amachine(arm)" + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#define HANDLE_SYSV_PRAGMA + +/* Run-time Target Specification. */ +#define TARGET_VERSION fputs (" (ARM GNU/Linux with a.out)", stderr); + +/* This is used in ASM_FILE_START */ +#define ARM_OS_NAME "Linux" + +/* Unsigned chars produces much better code than signed. */ +#define DEFAULT_SIGNED_CHAR 0 + +/* Maths operation domain error number, EDOM */ +#define TARGET_EDOM 33 +#include "arm/aout.h" + +#undef SUBTARGET_CPP_SPEC +#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE}" diff --git a/gnu/usr.bin/gcc/config/arm/netbsd.h b/gnu/usr.bin/gcc/config/arm/netbsd.h new file mode 100644 index 00000000000..94fd024d42e --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/netbsd.h @@ -0,0 +1,143 @@ +/* NetBSD/arm (RiscBSD) version. + Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. + Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk) + +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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Run-time Target Specification. */ +#define TARGET_VERSION fputs (" (ARM/NetBSD)", stderr); + +/* This is used in ASM_FILE_START. */ +#define ARM_OS_NAME "NetBSD" + +/* Unsigned chars produces much better code than signed. */ +#define DEFAULT_SIGNED_CHAR 0 + +/* Since we always use GAS as our assembler we support stabs. */ +#define DBX_DEBUGGING_INFO 1 + +/*#undef ASM_DECLARE_FUNCTION_NAME*/ + +/* ARM6 family default cpu. */ +#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6 + +/* Default is to use APCS-32 mode. */ +#define TARGET_DEFAULT ARM_FLAG_APCS_32 + +#include "arm/aout.h" + +/* This gets redefined in config/netbsd.h. */ +#undef TARGET_MEM_FUNCTIONS + +#include <netbsd.h> + +/* Some defines for CPP. + arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */ +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "\ +-Dunix -Driscbsd -Darm32 -D__arm32__ -D__arm__ -D__NetBSD__ \ +-Asystem(unix) -Asystem(NetBSD) -Acpu(arm) -Amachine(arm)" + +/* Define _POSIX_SOURCE if necessary. */ +#undef CPP_SPEC +#define CPP_SPEC "\ +%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) \ +%{posix:-D_POSIX_SOURCE} \ +" + +/* Because TARGET_DEFAULT sets ARM_FLAG_APCS_32 */ +#undef CPP_APCS_PC_DEFAULT_SPEC +#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__" + +/* Pass -X to the linker so that it will strip symbols starting with 'L' */ +#undef LINK_SPEC +#define LINK_SPEC "\ +-X %{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{R*} \ +%{static:-Bstatic} %{assert*} \ +" + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_UNSIGNED +#define WCHAR_UNSIGNED 0 + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +#define HANDLE_SYSV_PRAGMA + +/* We don't have any limit on the length as out debugger is GDB. */ +#undef DBX_CONTIN_LENGTH + +/* NetBSD does its profiling differently to the Acorn compiler. We + don't need a word following the mcount call; and to skip it + requires either an assembly stub or use of fomit-frame-pointer when + compiling the profiling functions. Since we break Acorn CC + compatibility below a little more won't hurt. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(STREAM,LABELNO) \ +{ \ + fprintf(STREAM, "\tmov\t%sip, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX); \ + fprintf(STREAM, "\tbl\tmcount\n"); \ +} + +/* On the ARM `@' introduces a comment, so we must use something else + for .type directives. */ +#undef TYPE_OPERAND_FMT +#define TYPE_OPERAND_FMT "%%%s" + +/* VERY BIG NOTE : Change of structure alignment for RiscBSD. + There are consequences you should be aware of... + + Normally GCC/arm uses a structure alignment of 32 for compatibility + with armcc. This means that structures are padded to a word + boundary. However this causes problems with bugged NetBSD kernel + code (possibly userland code as well - I have not checked every + binary). The nature of this bugged code is to rely on sizeof() + returning the correct size of various structures rounded to the + nearest byte (SCSI and ether code are two examples, the vm system + is another). This code breaks when the structure alignment is 32 + as sizeof() will report a word=rounded size. By changing the + structure alignment to 8. GCC will conform to what is expected by + NetBSD. + + This has several side effects that should be considered. + 1. Structures will only be aligned to the size of the largest member. + i.e. structures containing only bytes will be byte aligned. + structures containing shorts will be half word alinged. + structures containing ints will be word aligned. + + This means structures should be padded to a word boundary if + alignment of 32 is required for byte structures etc. + + 2. A potential performance penalty may exist if strings are no longer + word aligned. GCC will not be able to use word load/stores to copy + short strings. + + This modification is not encouraged but with the present state of the + NetBSD source tree it is currently the only solution that meets the + requirements. */ +#undef STRUCTURE_SIZE_BOUNDARY +#define STRUCTURE_SIZE_BOUNDARY 8 diff --git a/gnu/usr.bin/gcc/config/arm/semiaof.h b/gnu/usr.bin/gcc/config/arm/semiaof.h new file mode 100644 index 00000000000..b16d37803fa --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/semiaof.h @@ -0,0 +1,43 @@ +/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform + AOF Syntax assembler. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Richard Earnshaw (richard.earnshaw@armltd.co.uk) + +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. */ + +#define CPP_PREDEFINES \ + "-Darm -Dsemi -Acpu(arm) -Amachine(arm)" + +#define ASM_SPEC "%{g -g} -arch 4 \ +-apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/32bit}}" + +#define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}" + +#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr); + +#define TARGET_DEFAULT ARM_FLAG_APCS_32 + +/* The Norcroft C library defines size_t as "unsigned int" */ +#define SIZE_TYPE "unsigned int" + +#include "arm/aof.h" + +#undef CPP_APCS_PC_DEFAULT_SPEC +#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__" + + diff --git a/gnu/usr.bin/gcc/config/arm/t-bare b/gnu/usr.bin/gcc/config/arm/t-bare new file mode 100644 index 00000000000..85e6a301aa7 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/t-bare @@ -0,0 +1,30 @@ +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = arm/lib1funcs.asm +LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + echo '#ifndef __ARMEB__' >> fp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c + echo '#endif' >> fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + echo '#ifndef __ARMEB__' > dp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c + echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c + echo '#endif' >> dp-bit.c + cat $(srcdir)/config/fp-bit.c >> dp-bit.c + +# Avoid building a duplicate set of libraries for the default endian-ness. +MULTILIB_OPTIONS = mlittle-endian/mbig-endian mhard-float +MULTILIB_DIRNAMES = le be fpu +MULTILIB_MATCHES = + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/gnu/usr.bin/gcc/config/arm/t-linux b/gnu/usr.bin/gcc/config/arm/t-linux new file mode 100644 index 00000000000..f45e3147e98 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/t-linux @@ -0,0 +1,19 @@ +# Just for these, we omit the frame pointer since it makes such a big +# difference. It is then pointless adding debugging. +LIBGCC2_CFLAGS=-O2 -fomit-frame-pointer $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -g0 + +# Don't build enquire +ENQUIRE= + +# Since libgcc1 is an assembler file, we can build it automatically for the +# cross-compiler. +CROSS_LIBGCC1 = libgcc1-asm.a +LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = arm/lib1funcs.asm +LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx + +MULTILIB_OPTIONS = mapcs-32 +MULTILIB_DIRNAMES = apcs-32 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/gnu/usr.bin/gcc/config/arm/t-netbsd b/gnu/usr.bin/gcc/config/arm/t-netbsd new file mode 100644 index 00000000000..cc2f6583679 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/t-netbsd @@ -0,0 +1,7 @@ +# Just for these, we omit the frame pointer since it makes such a big +# difference. It is then pointless adding debugging. +LIBGCC2_CFLAGS=-O2 -fomit-frame-pointer $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -g0 +# -Dinhibit_libc + +# Don't build enquire +ENQUIRE= diff --git a/gnu/usr.bin/gcc/config/arm/t-semiaof b/gnu/usr.bin/gcc/config/arm/t-semiaof new file mode 100644 index 00000000000..6f1dfca081c --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/t-semiaof @@ -0,0 +1,63 @@ +OLDCC = armcc -w +# Don't build enquire +ENQUIRE= +CROSS_LIBGCC1 = libgcc1-aof.a +LIBGCC2 = libgcc2-aof.a +LIBGCC = libgcc-aof.a +LIBGCC2_CFLAGS = -O2 -fomit-frame-pointer +LIBGCC1_TEST = #libgcc1-atest +EXTRA_PARTS = crtbegin.o crtend.o + +# Rule to build libgcc1.a and libgcc2.a and libgcc.a, since the librarian +# for the ARM tools is somewhat quirky, and needs a special rule to use it. +libgcc1-aof.a: libgcc1.c $(CONFIG_H) config.status + -rm -rf tmplib libgcc1.a libgcc1-aof.a tmplibgcc1.a + mkdir tmplib + for name in $(LIB1FUNCS); \ + do \ + echo $${name}; \ + rm -f $${name}$(objext); \ + $(OLDCC) $(CCLIBFLAGS) $(INCLUDES) -c -DL$${name} $(srcdir)/libgcc1.c; \ + if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ + mv libgcc1$(objext) tmplib/$${name}$(objext); \ + done + (cd tmplib; \ + armlib -c tmplibgcc1.a *; \ + mv tmplibgcc1.a ..) + mv tmplibgcc1.a libgcc1-aof.a + rm -rf tmplib + +libgcc2-aof.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(LIB2FUNCS_EXTRA) \ + machmode.h longlong.h gbl-ctors.h config.status + -rm -f tmplibgcc2.a + -rm -rf tmplib + mkdir tmplib + for name in $(LIB2FUNCS); \ + do \ + echo $${name}; \ + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c -DL$${name} \ + $(srcdir)/libgcc2.c -o tmplib/$${name}$(objext); \ + if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ + done + (cd tmplib; \ + armlib -c tmplibgcc2.a *; \ + mv tmplibgcc2.a ..) + mv tmplibgcc2.a libgcc2-aof.a + rm -rf tmplib + +# Combine the various libraries into a single library, libgcc.a. +libgcc-aof.a: $(CROSS_LIBGCC1) $(LIBGCC2) + -rm -rf tmplibgcc.a libgcc.a tmpcopy libgcc-aof.a + mkdir tmpcopy + (cd tmpcopy; armlib -e ../$(LIBGCC1) \*) + -(cd tmpcopy; chmod +w * > /dev/null 2>&1) + (cd tmpcopy; armlib -e ../$(LIBGCC2) \*) + (cd tmpcopy; armlib -co ../tmplibgcc.a *$(objext)) + rm -rf tmpcopy + mv tmplibgcc.a libgcc.a + ln libgcc.a libgcc-aof.a + +libgcc1-atest: libgcc1-test.o native $(GCC_PARTS) $(EXTRA_PARTS) + @echo "Testing libgcc1. Ignore linker warning messages." + $(GCC_FOR_TARGET) $(GCC_CFLAGS) libgcc1-test.o -o libgcc1-test \ + -v diff --git a/gnu/usr.bin/gcc/config/arm/xm-linux.h b/gnu/usr.bin/gcc/config/arm/xm-linux.h new file mode 100644 index 00000000000..ca120a9c8a6 --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/xm-linux.h @@ -0,0 +1,24 @@ +/* Configuration for GCC for Intel i386 running Linux-based GNU systems./ + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + Contributed by H.J. Lu (hjl@nynexst.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. */ + +#include <arm/xm-arm.h> +#include <xm-linux.h> + diff --git a/gnu/usr.bin/gcc/config/arm/xm-netbsd.h b/gnu/usr.bin/gcc/config/arm/xm-netbsd.h new file mode 100644 index 00000000000..ea9a64ea4bf --- /dev/null +++ b/gnu/usr.bin/gcc/config/arm/xm-netbsd.h @@ -0,0 +1,7 @@ +/* Configuration for GCC for ARM running NetBSD as host. */ + +#include <arm/xm-arm.h> + +#ifndef SYS_SIGLIST_DECLARED +#define SYS_SIGLIST_DECLARED +#endif diff --git a/gnu/usr.bin/gcc/config/dbx.h b/gnu/usr.bin/gcc/config/dbx.h new file mode 100644 index 00000000000..c5cd3b5f2d0 --- /dev/null +++ b/gnu/usr.bin/gcc/config/dbx.h @@ -0,0 +1,30 @@ +/* Prefer DBX (stabs) debugging information. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file causes gcc to prefer using DBX (stabs) debugging + information. The configure script will add a #include of this file + to tm.h when --with-stabs is used for certain targets. */ + +#ifndef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO +#endif + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG diff --git a/gnu/usr.bin/gcc/config/dbxcoff.h b/gnu/usr.bin/gcc/config/dbxcoff.h new file mode 100644 index 00000000000..9497a70b83f --- /dev/null +++ b/gnu/usr.bin/gcc/config/dbxcoff.h @@ -0,0 +1,87 @@ +/* Definitions needed when using stabs embedded in COFF sections. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file may be included by any COFF target which wishes to + support -gstabs generating stabs in sections, as produced by gas + and understood by gdb. */ + +/* Output DBX (stabs) debugging information if doing -gstabs. */ + +#undef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +/* Generate SDB debugging information by default. */ + +#ifndef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG +#endif + +/* Be function-relative for block and source line stab directives. */ + +#undef DBX_BLOCKS_FUNCTION_RELATIVE +#define DBX_BLOCKS_FUNCTION_RELATIVE 1 + +/* but, to make this work, functions must appear prior to line info. */ + +#undef DBX_FUNCTION_FIRST +#define DBX_FUNCTION_FIRST + +/* Generate a blank trailing N_SO to mark the end of the .o file, since + we can't depend upon the linker to mark .o file boundaries with + embedded stabs. */ + +#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END +#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ + fprintf (FILE, \ + "\t.text\n\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO) + +/* Like block addresses, stabs line numbers are relative to the + current function. */ + +#undef ASM_OUTPUT_SOURCE_LINE +#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \ +{ if (write_symbols == SDB_DEBUG) { \ + fprintf ((FILE), "\t.ln\t%d\n", \ + ((sdb_begin_function_line > -1) \ + ? (LINE) - sdb_begin_function_line : 1)); \ + } else if (write_symbols == DBX_DEBUG) { \ + static int sym_lineno = 1; \ + char buffer[256]; \ + ASM_GENERATE_INTERNAL_LABEL (buffer, "LM", sym_lineno); \ + fprintf (FILE, ".stabn 68,0,%d,", LINE); \ + assemble_name (FILE, buffer); \ + putc ('-', FILE); \ + assemble_name (FILE, \ + XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ + putc ('\n', FILE); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, "LM", sym_lineno); \ + sym_lineno++; \ + } } + +/* When generating stabs debugging, use N_BINCL entries. */ + +#undef DBX_USE_BINCL +#define DBX_USE_BINCL + +/* There is no limit to the length of stabs strings. */ + +#ifndef DBX_CONTIN_LENGTH +#define DBX_CONTIN_LENGTH 0 +#endif diff --git a/gnu/usr.bin/gcc/config/float-i128.h b/gnu/usr.bin/gcc/config/float-i128.h new file mode 100644 index 00000000000..6a9dd48b1a3 --- /dev/null +++ b/gnu/usr.bin/gcc/config/float-i128.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32, 64 and 128 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 113 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 33 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-16381) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 3.362103143112093506262677817321752603E-4932L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-4931) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 16384 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.189731495357231765085759326628007016E+4932L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 4932 + +#endif /* _FLOAT_H_ */ diff --git a/gnu/usr.bin/gcc/config/float-i32.h b/gnu/usr.bin/gcc/config/float-i32.h new file mode 100644 index 00000000000..c834926b085 --- /dev/null +++ b/gnu/usr.bin/gcc/config/float-i32.h @@ -0,0 +1,96 @@ +/* float.h for target with only IEEE 32 bit floating point format */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 24 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 6 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-125) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 128 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 24 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 6 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-125) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 128 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 38 + +#endif /* _FLOAT_H_ */ diff --git a/gnu/usr.bin/gcc/config/float-i64.h b/gnu/usr.bin/gcc/config/float-i64.h new file mode 100644 index 00000000000..7dbe4e92a10 --- /dev/null +++ b/gnu/usr.bin/gcc/config/float-i64.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32 bit and 64 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/gnu/usr.bin/gcc/config/float-sh.h b/gnu/usr.bin/gcc/config/float-sh.h new file mode 100644 index 00000000000..9a942987920 --- /dev/null +++ b/gnu/usr.bin/gcc/config/float-sh.h @@ -0,0 +1,130 @@ +/* float.h for target sh3e with optional IEEE 32 bit double format */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + +#ifdef __SH3E__ + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 24 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 6 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-125) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 128 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 38 + +#else + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + +#endif + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/gnu/usr.bin/gcc/config/float-vax.h b/gnu/usr.bin/gcc/config/float-vax.h new file mode 100644 index 00000000000..3c87f795ef2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/float-vax.h @@ -0,0 +1,96 @@ +/* float.h for target with VAX floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-127) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 2.93873588e-39F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-38) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 127 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 1.70141173e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 56 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 16 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.77555756156289135e-17 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-127) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.93873587705571877e-39 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-38) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 127 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.70141183460469229e+38 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 56 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 16 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.77555756156289135e-17 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-127) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.93873587705571877e-39 + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-38) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 127 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.70141183460469229e+38 + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 38 + +#endif /* _FLOAT_H_ */ diff --git a/gnu/usr.bin/gcc/config/i370/i370.c b/gnu/usr.bin/gcc/config/i370/i370.c new file mode 100644 index 00000000000..55189825540 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i370/i370.c @@ -0,0 +1,584 @@ +/* Subroutines for insn-output.c for System/370. + Copyright (C) 1989, 1993, 1995, 1997 Free Software Foundation, Inc. + Contributed by Jan Stein (jan@cd.chalmers.se). + Modified for MVS C/370 by Dave Pitts (dpitts@nyx.cs.du.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 "config.h" +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "recog.h" +#ifdef sun +#include <sys/types.h> +#include <ctype.h> +#endif +#include <time.h> + + +/* Label node, this structure is used to keep track of labels on the + current page. */ +typedef struct label_node + { + struct label_node *label_next; + int label_id; + int label_page; + } +label_node_t; + +/* Is 1 when a label has been generated and the base register must be + reloaded. */ +int mvs_label_emitted = 0; + +/* Current function starting base page. */ +int function_base_page; + +/* Length of the current page code. */ +int mvs_page_code; + +/* Length of the current page literals. */ +int mvs_page_lit; + +/* Current function name. */ +char *mvs_function_name = 0; + +/* Current function name length. */ +int mvs_function_name_length = 0; + +/* Page number for multi-page functions. */ +int mvs_page_num = 0; + +/* Label node list anchor. */ +static label_node_t *label_anchor = 0; + +/* Label node free list anchor. */ +static label_node_t *free_anchor = 0; + +/* Assembler source file descriptor. */ +static FILE *assembler_source = 0; + +/* Define the length of the internal MVS function table. */ +#define MVS_FUNCTION_TABLE_LENGTH 32 + +/* C/370 internal function table. These functions use non-standard linkage + and must handled in a special manner. */ +static char *mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] = +{ + "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos", + "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10", + "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh", + "fabs", "floor", "fmod", "frexp", "hypot", "j0", + "j1", "jn", "ldexp", "modf", "pow", "y0", + "y1", "yn" +}; + +/* ASCII to EBCDIC conversion table. */ +#if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC) +static unsigned char ascebc[256] = +{ + /*00 NL SH SX EX ET NQ AK BL */ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, + /*08 BS HT LF VT FF CR SO SI */ + 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /*10 DL D1 D2 D3 D4 NK SN EB */ + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, + /*18 CN EM SB EC FS GS RS US */ + 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, + /*20 SP ! " # $ % & ' */ + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, + /*28 ( ) * + , - . / */ + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, + /*30 0 1 2 3 4 5 6 7 */ + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + /*38 8 9 : ; < = > ? */ + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, + /*40 @ A B C D E F G */ + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + /*48 H I J K L M N O */ + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + /*50 P Q R S T U V W */ + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + /*58 X Y Z [ \ ] ^ _ */ + 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, + /*60 ` a b c d e f g */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /*68 h i j k l m n o */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + /*70 p q r s t u v w */ + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + /*78 x y z { | } ~ DL */ + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF +}; +#endif + +/* EBCDIC to ASCII conversion table. */ +#if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC) +unsigned char ebcasc[256] = +{ + /*00 NU SH SX EX PF HT LC DL */ + 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F, + /*08 SM VT FF CR SO SI */ + 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + /*10 DE D1 D2 TM RS NL BS IL */ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00, + /*18 CN EM CC C1 FS GS RS US */ + 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F, + /*20 DS SS FS BP LF EB EC */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B, + /*28 SM C2 EQ AK BL */ + 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00, + /*30 SY PN RS UC ET */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + /*38 C3 D4 NK SU */ + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A, + /*40 SP */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*48 . < ( + | */ + 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, + /*50 & */ + 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*58 ! $ * ) ; ^ */ + 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, + /*60 - / */ + 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*68 , % _ > ? */ + 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, + /*70 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*78 ` : # @ ' = " */ + 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, + /*80 a b c d e f g */ + 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + /*88 h i { */ + 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00, + /*90 j k l m n o p */ + 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + /*98 q r } */ + 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, + /*A0 ~ s t u v w x */ + 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + /*A8 y z [ */ + 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, + /*B0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*B8 ] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, + /*C0 { A B C D E F G */ + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /*C8 H I */ + 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*D0 } J K L M N O P */ + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + /*D8 Q R */ + 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*E0 \ S T U V W X */ + 0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + /*E8 Y Z */ + 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /*F0 0 1 2 3 4 5 6 7 */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /*F8 8 9 */ + 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF +}; +#endif + +/* Map characters from one character set to another. + C is the character to be translated. */ + +char +mvs_map_char (c) + char c; +{ +#if defined(TARGET_EBCDIC) && !defined(HOST_EBCDIC) + return ascebc[c]; +#else +#if defined(HOST_EBCDIC) && !defined(TARGET_EBCDIC) + return ebcasc[c]; +#else + return c; +#endif +#endif +} + +/* Emit reload of base register if indicated. This is to eliminate multiple + reloads when several labels are generated pointing to the same place + in the code. */ + +int +check_label_emit (void) +{ + if (mvs_label_emitted) + { + mvs_label_emitted = 0; + mvs_page_code += 4; + fprintf (assembler_source, "\tL\t%d,%d(,%d)\n", + BASE_REGISTER, (mvs_page_num - function_base_page) * 4, + PAGE_REGISTER); + } +} + +/* Add the label to the current page label list. If a free element is available + it will be used for the new label. Otherwise, a label element will be + allocated from memory. + ID is the label number of the label being added to the list. */ + +int +mvs_add_label (id) + int id; +{ + label_node_t *lp; + + if (free_anchor) + { + lp = free_anchor; + free_anchor = lp->label_next; + } + else + { + lp = (label_node_t *) malloc (sizeof (label_node_t)); + if (lp == 0) + { + fatal ("virtual memory exhausted\n"); + abort (); + } + } + lp->label_id = id; + lp->label_page = mvs_page_num; + lp->label_next = label_anchor; + label_anchor = lp; +} + +/* Check to see if the label is in the list. If 1 is returned then a load + and branch on register must be generated. + ID is the label number of the label being checked. */ + +int +mvs_check_label (id) + int id; +{ + label_node_t *lp; + + for (lp = label_anchor; lp; lp = lp->label_next) + { + if (lp->label_id == id) + return 1; + } + return 0; +} + +/* The label list for the current page freed by linking the list onto the free + label element chain. */ + +int +mvs_free_label (void) +{ + if (label_anchor) + { + if (free_anchor) + label_anchor->label_next = free_anchor; + free_anchor = label_anchor; + } + label_anchor = 0; +} + +/* If the page size limit is reached a new code page is started, and the base + register is set to it. This page break point is counted conservatively, + most literals that have the same value are collapsed by the assembler. + True is returned when a new page is started. + FILE is the assembler output file descriptor. + CODE is the length, in bytes, of the instruction to be emitted. + LIT is the length of the literal to be emitted. */ + +int +mvs_check_page (file, code, lit) + FILE *file; + int code, lit; +{ + if (file) + assembler_source = file; + + if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH) + { + fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num); + fprintf (assembler_source, "\tDS\t0F\n"); + fprintf (assembler_source, "\tLTORG\n"); + fprintf (assembler_source, "\tDS\t0F\n"); + fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num); + fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER); + mvs_page_num++; + fprintf (assembler_source, "\tBALR\t%d,0\n", BASE_REGISTER); + fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num); + fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER); + mvs_free_label (); + mvs_page_code = code; + mvs_page_lit = lit; + return 1; + } + mvs_page_code += code; + mvs_page_lit += lit; + return 0; +} + +/* Check for C/370 runtime function, they don't use standard calling + conventions. True is returned if the function is in the table. + NAME is the name of the current function. */ + +int +mvs_function_check (name) + char *name; +{ + int lower, middle, upper; + int i; + + lower = 0; + upper = MVS_FUNCTION_TABLE_LENGTH - 1; + while (lower <= upper) + { + middle = (lower + upper) / 2; + i = strcmp (name, mvs_function_table[middle]); + if (i == 0) + return 1; + if (i < 0) + upper = middle - 1; + else + lower = middle + 1; + } + return 0; +} + + +/* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction. + OP is the current operation. + MODE is the current operation mode. */ + +int +s_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + extern int volatile_ok; + register enum rtx_code code = GET_CODE (op); + + if (CONSTANT_ADDRESS_P (op)) + return 1; + if (mode == VOIDmode || GET_MODE (op) != mode) + return 0; + if (code == MEM) + { + register rtx x = XEXP (op, 0); + + if (!volatile_ok && op->volatil) + return 0; + if (REG_P (x) && REG_OK_FOR_BASE_P (x)) + return 1; + if (GET_CODE (x) == PLUS + && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) + && GET_CODE (XEXP (x, 1)) == CONST_INT + && (unsigned) INTVAL (XEXP (x, 1)) < 4096) + return 1; + } + return 0; +} + + +/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type + instruction. + OP is the current operation. + MODE is the current operation mode. */ + +int +r_or_s_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + extern int volatile_ok; + register enum rtx_code code = GET_CODE (op); + + if (CONSTANT_ADDRESS_P (op)) + return 1; + if (mode == VOIDmode || GET_MODE (op) != mode) + return 0; + if (code == REG) + return 1; + else if (code == MEM) + { + register rtx x = XEXP (op, 0); + + if (!volatile_ok && op->volatil) + return 0; + if (REG_P (x) && REG_OK_FOR_BASE_P (x)) + return 1; + if (GET_CODE (x) == PLUS + && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) + && GET_CODE (XEXP (x, 1)) == CONST_INT + && (unsigned) INTVAL (XEXP (x, 1)) < 4096) + return 1; + } + return 0; +} + + +/* Return 1 if the next instruction is an unsigned jump instruction. + INSN is the current instruction. */ + +unsigned_jump_follows_p (insn) + register rtx insn; +{ + insn = NEXT_INSN (insn); + if (GET_CODE (insn) != JUMP_INSN) + return 0; + + insn = XEXP (insn, 3); + if (GET_CODE (insn) != SET) + return 0; + + if (GET_CODE (XEXP (insn, 0)) != PC) + return 0; + + insn = XEXP (insn, 1); + if (GET_CODE (insn) != IF_THEN_ELSE) + return 0; + + insn = XEXP (insn, 0); + return GET_CODE (insn) != GE && GET_CODE (insn) != GT + && GET_CODE (insn) != LE && GET_CODE (insn) != LT; +} + +void +i370_function_prolog (f, l) + FILE *f; + int l; +{ +#if MACROPROLOGUE == 1 + fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n", + STACK_POINTER_OFFSET + l - 120 + + current_function_outgoing_args_size, BASE_REGISTER); + fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num ); + fprintf (f, "\tLR\t11,1\n"); + fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num); + mvs_page_code = 6; + mvs_page_lit = 4; + mvs_check_page (f, 0, 0); + function_base_page = mvs_page_num; +#else /* MACROPROLOGUE != 1 */ + static int function_label_index = 1; + static int function_first = 0; + static int function_year, function_month, function_day; + static int function_hour, function_minute, function_second; + int i; + if (!function_first) + { + struct tm *function_time; + time_t lcltime; + time (&lcltime); + function_time = localtime (&lcltime); + function_year = function_time->tm_year + 1900; + function_month = function_time->tm_mon + 1; + function_day = function_time->tm_mday; + function_hour = function_time->tm_hour; + function_minute = function_time->tm_min; + function_second = function_time->tm_sec; + fprintf (f, "PPA2\tDS\t0F\n"); + fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n"); + fprintf (f, "\tDC\tV(CEESTART),A(0)\n"); + fprintf (f, "\tDC\tA(CEETIMES)\n"); + fprintf (f, "CEETIMES\tDS\t0F\n"); + fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n", + function_year, function_month, function_day, + function_hour, function_minute, function_second); + fprintf (f, "\tDC\tCL2'01',CL4'0100'\n"); + } + fprintf (f, "$DSD%03d\tDSECT\n", function_label_index); + fprintf (f, "\tDS\tD\n"); + fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l + + current_function_outgoing_args_size); + fprintf (f, "\tORG\t$DSD%03d\n", function_label_index); + fprintf (f, "\tDS\tCL(120+8)\n"); + fprintf (f, "\tORG\n"); + fprintf (f, "\tDS\t0D\n"); + fprintf (f, "$DSL%03d\tEQU\t*-$DSD%03d-8\n", function_label_index, + function_label_index); + fprintf (f, "\tDS\t0H\n"); + assemble_name (f, mvs_function_name); + fprintf (f, "\tEQU\t*\n"); + fprintf (f, "\tUSING\t*,15\n"); + fprintf (f, "\tB\tFPL%03d\n", function_label_index); + fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1); + fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n"); + fprintf (f, "\tDC\tAL4(PPA2)\n"); + fprintf (f, "\tDC\tAL4(0)\n"); + fprintf (f, "\tDC\tAL4($DSL%03d)\n", function_label_index); + fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1); + fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name), + mvs_function_name); + fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index); + fprintf (f, "\tSTM\t14,12,12(13)\n"); + fprintf (f, "\tL\t2,76(,13)\n"); + fprintf (f, "\tL\t0,16(,15)\n"); + fprintf (f, "\tALR\t0,2\n"); + fprintf (f, "\tCL\t0,12(,12)\n"); + fprintf (f, "\tBNH\t*+10\n"); + fprintf (f, "\tL\t15,116(,12)\n"); + fprintf (f, "\tBALR\t14,15\n"); + fprintf (f, "\tL\t15,72(,13)\n"); + fprintf (f, "\tSTM\t15,0,72(2)\n"); + fprintf (f, "\tMVI\t0(2),X'10'\n"); + fprintf (f, "\tST\t2,8(,13)\n "); + fprintf (f, "\tST\t13,4(,2)\n "); + fprintf (f, "\tLR\t13,2\n"); + fprintf (f, "\tDROP\t15\n"); + fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER); + fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num ); + fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER); + fprintf (f, "\tLR\t11,1\n"); + fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num); + mvs_page_code = 4; + mvs_page_lit = 4; + mvs_check_page (f, 0, 0); + function_base_page = mvs_page_num; + function_first = 1; + function_label_index += 2; +#endif /* MACROPROLOGUE */ +} diff --git a/gnu/usr.bin/gcc/config/i370/i370.h b/gnu/usr.bin/gcc/config/i370/i370.h new file mode 100644 index 00000000000..e213883075b --- /dev/null +++ b/gnu/usr.bin/gcc/config/i370/i370.h @@ -0,0 +1,1441 @@ +/* Definitions of target machine for GNU compiler. System/370 version. + Copyright (C) 1989, 1993, 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Jan Stein (jan@cd.chalmers.se). + Modified for C/370 MVS by Dave Pitts (dpitts@nyx.cs.du.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. */ + +#define TARGET_VERSION printf (" (370/MVS)"); + +/* Options for the preprocessor for this target machine. */ + +#define CPP_SPEC "-trigraphs" + +/* Names to predefine in the preprocessor for this target machine. */ + +#define CPP_PREDEFINES "-DGCC -Dgcc -DMVS -Dmvs -Asystem(mvs) -Acpu(i370) -Amachine(i370)" + +/* Run-time compilation parameters selecting different hardware subsets. */ + +extern int target_flags; + +/* The sizes of the code and literals on the current page. */ + +extern int mvs_page_code, mvs_page_lit; + +/* The current page number and the base page number for the function. */ + +extern int mvs_page_num, function_base_page; + +/* True if a label has been emitted. */ + +extern int mvs_label_emitted; + +/* The name of the current function. */ + +extern char *mvs_function_name; + +/* The length of the function name malloc'd area. */ + +extern int mvs_function_name_length; + +/* The amount of space used for outgoing arguments. */ + +extern int current_function_outgoing_args_size; + +/* Compile using char instructions (mvc, nc, oc, xc). On 4341 use this since + these are more than twice as fast as load-op-store. + On 3090 don't use this since load-op-store is much faster. */ + +#define TARGET_CHAR_INSTRUCTIONS (target_flags & 1) + +/* Default target switches */ + +#define TARGET_DEFAULT 1 + +/* Macro to define tables used to set the flags. This is a list in braces + of pairs in braces, each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +#define TARGET_SWITCHES \ +{ { "char-instructions", 1}, \ + { "no-char-instructions", -1}, \ + { "", TARGET_DEFAULT} } + +/* To use IBM supplied macro function prologue and epilogue, define the + following to 1. Should only be needed if IBM changes the definition + of their prologue and epilogue. */ + +#define MACROPROLOGUE 0 +#define MACROEPILOGUE 0 + +/* Target machine storage layout */ + +/* Define this if most significant bit is lowest numbered in instructions + that operate on numbered bit-fields. */ + +#define BITS_BIG_ENDIAN 1 + +/* Define this if most significant byte of a word is the lowest numbered. */ + +#define BYTES_BIG_ENDIAN 1 + +/* Define this if MS word of a multiword is the lowest numbered. */ + +#define WORDS_BIG_ENDIAN 1 + +/* Number of bits in an addressable storage unit. */ + +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. */ + +#define BITS_PER_WORD 32 + +/* Width of a word, in units (bytes). */ + +#define UNITS_PER_WORD 4 + +/* Width in bits of a pointer. See also the macro `Pmode' defined below. */ + +#define POINTER_SIZE 32 + +/* Allocation boundary (in *bits*) for storing pointers in memory. */ + +#define POINTER_BOUNDARY 32 + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ + +#define PARM_BOUNDARY 32 + +/* Boundary (in *bits*) on which stack pointer should be aligned. */ + +#define STACK_BOUNDARY 32 + +/* Allocation boundary (in *bits*) for the code of a function. */ + +#define FUNCTION_BOUNDARY 32 + +/* There is no point aligning anything to a rounder boundary than this. */ + +#define BIGGEST_ALIGNMENT 64 + +/* Alignment of field after `int : 0' in a structure. */ + +#define EMPTY_FIELD_BOUNDARY 32 + +/* Define this if move instructions will actually fail to work when given + unaligned data. */ + +#define STRICT_ALIGNMENT 0 + +/* Define target floating point format. */ + +#define TARGET_FLOAT_FORMAT IBM_FLOAT_FORMAT + +/* Define character mapping for cross-compiling. */ + +#define TARGET_EBCDIC 1 + +#ifdef HOST_EBCDIC +#define MAP_CHARACTER(c) ((char)(c)) +#else +#define MAP_CHARACTER(c) ((char)mvs_map_char (c)) +#endif + +/* Define maximum length of page minus page escape overhead. */ + +#define MAX_MVS_PAGE_LENGTH 4080 + +/* Define if special allocation order desired. */ + +#define REG_ALLOC_ORDER \ +{ 0, 1, 2, 3, 14, 15, 12, 10, 9, 8, 7, 6, 5, 4, 16, 17, 18, 19, 11, 13 } + +/* Standard register usage. */ + +/* Number of actual hardware registers. The hardware registers are + assigned numbers for the compiler from 0 to just below + FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. + For the 370, we give the data registers numbers 0-15, + and the floating point registers numbers 16-19. */ + +#define FIRST_PSEUDO_REGISTER 20 + +/* Define base and page registers. */ + +#define BASE_REGISTER 3 +#define PAGE_REGISTER 4 + +/* 1 for registers that have pervasive standard uses and are not available + for the register allocator. On the 370 under C/370, R13 is stack (DSA) + pointer, R12 is the TCA pointer, R3 is the base register, R4 is the page + origin table pointer and R11 is the arg pointer. */ + +#define FIXED_REGISTERS \ +{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 } +/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/ + +/* 1 for registers not available across function calls. These must include + the FIXED_REGISTERS and also any registers that can be used without being + saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + NOTE: all floating registers are undefined across calls. */ + +#define CALL_USED_REGISTERS \ +{ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 } +/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/ + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. */ + +#define HARD_REGNO_NREGS(REGNO, MODE) \ + ((REGNO) > 15 ? 1 : (GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. + On the 370, the cpu registers can hold QI, HI, SI, SF and DF. The + even registers can hold DI. The floating point registers can hold + either SF or DF. */ + +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((REGNO) < 16 ? ((REGNO) & 1) == 0 || (MODE) != DImode \ + : (MODE) == SFmode || (MODE) == DFmode) + +/* Value is 1 if it is a good idea to tie two pseudo registers when one has + mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ + +#define MODES_TIEABLE_P(MODE1, MODE2) \ + (((MODE1) == SFmode || (MODE1) == DFmode) \ + == ((MODE2) == SFmode || (MODE2) == DFmode)) + +/* Mark external references. */ + +#define ENCODE_SECTION_INFO(decl) \ + if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) \ + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; + +/* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + +/* 370 PC isn't overloaded on a register. */ + +/* #define PC_REGNUM */ + +/* Register to use for pushing function arguments. */ + +#define STACK_POINTER_REGNUM 13 + +/* Base register for access to local variables of the function. */ + +#define FRAME_POINTER_REGNUM 13 + +/* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms may be + accessed via the stack pointer) in functions that seem suitable. + This is computed in `reload', in reload1.c. */ + +#define FRAME_POINTER_REQUIRED 1 + +/* Base register for access to arguments of the function. */ + +#define ARG_POINTER_REGNUM 11 + +/* Register in which static-chain is passed to a function. */ + +#define STATIC_CHAIN_REGNUM 10 + +/* Register in which address to store a structure value is passed to + a function. */ + +#define STRUCT_VALUE_REGNUM 1 + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + +enum reg_class + { + NO_REGS, ADDR_REGS, DATA_REGS, + FP_REGS, ALL_REGS, LIM_REG_CLASSES + }; + +#define GENERAL_REGS DATA_REGS +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ + +#define REG_CLASS_NAMES \ +{ "NO_REGS", "ADDR_REGS", "DATA_REGS", "FP_REGS", "ALL_REGS" } + +/* Define which registers fit in which classes. This is an initializer for + a vector of HARD_REG_SET of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS {0, 0x0fffe, 0x0ffff, 0xf0000, 0xfffff} + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) >= 16 ? FP_REGS : (REGNO) != 0 ? ADDR_REGS : DATA_REGS) + +/* The class value for index registers, and the one for base regs. */ + +#define INDEX_REG_CLASS ADDR_REGS +#define BASE_REG_CLASS ADDR_REGS + +/* Get reg_class from a letter such as appears in the machine description. */ + +#define REG_CLASS_FROM_LETTER(C) \ + ((C) == 'a' ? ADDR_REGS : \ + ((C) == 'd' ? DATA_REGS : \ + ((C) == 'f' ? FP_REGS : NO_REGS))) + +/* The letters I, J, K, L and M in a register constraint string can be used + to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? (unsigned) (VALUE) < 256 : \ + (C) == 'J' ? (unsigned) (VALUE) < 4096 : \ + (C) == 'K' ? (VALUE) >= -32768 && (VALUE) < 32768 : 0) + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. */ + +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 + +/* Given an rtx X being reloaded into a reg required to be in class CLASS, + return the class of reg to actually use. In general this is just CLASS; + but on some machines in some cases it is preferable to use a more + restrictive class. */ + +#define PREFERRED_RELOAD_CLASS(X, CLASS) \ + (GET_CODE(X) == CONST_DOUBLE ? FP_REGS : \ + GET_CODE(X) == CONST_INT ? DATA_REGS : \ + GET_CODE(X) == LABEL_REF || \ + GET_CODE(X) == SYMBOL_REF || \ + GET_CODE(X) == CONST ? ADDR_REGS : (CLASS)) + +/* Return the maximum number of consecutive registers needed to represent + mode MODE in a register of class CLASS. */ + +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((CLASS) == FP_REGS ? 1 : \ + (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Stack layout; function entry, exit and calling. */ + +/* Define this if pushing a word on the stack makes the stack pointer a + smaller address. */ + +/* #define STACK_GROWS_DOWNWARD */ + +/* Define this if the nominal address of the stack frame is at the + high-address end of the local variables; that is, each additional local + variable allocated goes at a more negative offset in the frame. */ + +/* #define FRAME_GROWS_DOWNWARD */ + +/* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ + +#define STARTING_FRAME_OFFSET \ + (STACK_POINTER_OFFSET + current_function_outgoing_args_size) + +#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = STARTING_FRAME_OFFSET + +/* If we generate an insn to push BYTES bytes, this says how many the stack + pointer really advances by. On the 370, we have no push instruction. */ + +/* #define PUSH_ROUNDING(BYTES) */ + +/* Accumulate the outgoing argument count so we can request the right + DSA size and determine stack offset. */ + +#define ACCUMULATE_OUTGOING_ARGS + +/* Define offset from stack pointer, to location where a parm can be + pushed. */ + +#define STACK_POINTER_OFFSET 148 + +/* Offset of first parameter from the argument pointer register value. */ + +#define FIRST_PARM_OFFSET(FNDECL) 0 + +/* 1 if N is a possible register number for function argument passing. + On the 370, no registers are used in this way. */ + +#define FUNCTION_ARG_REGNO_P(N) 0 + +/* Define a data type for recording info about an argument list during + the scan of that argument list. This data type should hold all + necessary information about the function itself and about the args + processed so far, enough to enable macros such as FUNCTION_ARG to + determine where the next arg should go. */ + +#define CUMULATIVE_ARGS int + +/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to + a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) ((CUM) = 0) + +/* Update the data in CUM to advance over an argument of mode MODE and + data type TYPE. (TYPE is null for libcalls where that information + may not be available.) */ + +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM) += ((MODE) == DFmode || (MODE) == SFmode \ + ? 256 \ + : (MODE) != BLKmode \ + ? (GET_MODE_SIZE (MODE) + 3) / 4 \ + : (int_size_in_bytes (TYPE) + 3) / 4)) + +/* Define where to put the arguments to a function. Value is zero to push + the argument on the stack, or a hard register in which to store the + argument. */ + +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 + +/* For an arg passed partly in registers and partly in memory, this is the + number of registers used. For args passed entirely in registers or + entirely in memory, zero. */ + +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 + +/* Define if returning from a function call automatically pops the + arguments described by the number-of-args field in the call. */ + +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 + +/* Define how to find the value returned by a function. VALTYPE is the + data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 15. */ + +#define RET_REG(MODE) ((MODE) == DFmode || (MODE) == SFmode ? 16 : 15) + +/* On the 370 the return value is in R15 or R16. */ + +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx(REG, TYPE_MODE (VALTYPE), RET_REG(TYPE_MODE(VALTYPE))) + +/* Define how to find the value returned by a library function assuming + the value has mode MODE. */ + +#define LIBCALL_VALUE(MODE) gen_rtx(REG, MODE, RET_REG(MODE)) + +/* 1 if N is a possible register number for a function value. + On the 370 under C/370, R15 and R16 are thus used. */ + +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 15 || (N) == 16) + +/* This macro definition sets up a default value for `main' to return. */ + +#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node) + +/* This macro generates the assembly code for function entry. + All of the C/370 environment is preserved. */ +#define FUNCTION_PROLOGUE(FILE, LSIZE) i370_function_prolog ((FILE), (LSIZE)); + +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ +{ \ + if (strlen (NAME) * 2 > mvs_function_name_length) \ + { \ + if (mvs_function_name) \ + free (mvs_function_name); \ + mvs_function_name = 0; \ + } \ + if (!mvs_function_name) \ + { \ + mvs_function_name_length = strlen (NAME) * 2; \ + mvs_function_name = (char *) malloc (mvs_function_name_length); \ + if (mvs_function_name == 0) \ + { \ + fatal ("virtual memory exceeded"); \ + abort (); \ + } \ + } \ + if (!strcmp (NAME, "main")) \ + strcpy (mvs_function_name, "gccmain"); \ + else \ + strcpy (mvs_function_name, NAME); \ +} + +/* This macro generates the assembly code for function exit, on machines + that need it. If FUNCTION_EPILOGUE is not defined then individual + return instructions are generated for each return statement. Args are + same as for FUNCTION_PROLOGUE. + + The function epilogue should not depend on the current stack pointer! + It should use the frame pointer only. This is mandatory because + of alloca; we also take advantage of it to omit stack adjustments + before returning. */ + +#if MACROEPILOGUE == 1 +#define FUNCTION_EPILOGUE(FILE, LSIZE) \ +{ \ + int i; \ + check_label_emit(); \ + mvs_check_page (FILE,14,0); \ + fprintf (FILE, "\tEDCEPIL\n"); \ + mvs_page_num++; \ + fprintf (FILE, "\tDS\t0F\n" ); \ + fprintf (FILE, "\tLTORG\n"); \ + fprintf (FILE, "\tDS\t0F\n"); \ + fprintf (FILE, "PGT%d\tEQU\t*\n", function_base_page); \ + mvs_free_label(); \ + for ( i = function_base_page; i < mvs_page_num; i++ ) \ + fprintf (FILE, "\tDC\tA(PG%d)\n", i); \ +} +#else /* MACROEPILOGUE != 1 */ +#define FUNCTION_EPILOGUE(FILE, LSIZE) \ +{ \ + int i; \ + check_label_emit(); \ + mvs_check_page (FILE,14,0); \ + fprintf (FILE, "\tL\t13,4(,13)\n"); \ + fprintf (FILE, "\tL\t14,12(,13)\n"); \ + fprintf (FILE, "\tLM\t2,12,28(13)\n"); \ + fprintf (FILE, "\tBALR\t1,14\n"); \ + fprintf (FILE, "\tDC\tA("); \ + mvs_page_num++; \ + assemble_name (FILE, mvs_function_name); \ + fprintf (FILE, ")\n" ); \ + fprintf (FILE, "\tDS\t0F\n" ); \ + fprintf (FILE, "\tLTORG\n"); \ + fprintf (FILE, "\tDS\t0F\n"); \ + fprintf (FILE, "PGT%d\tEQU\t*\n", function_base_page); \ + mvs_free_label(); \ + for ( i = function_base_page; i < mvs_page_num; i++ ) \ + fprintf (FILE, "\tDC\tA(PG%d)\n", i); \ +} +#endif /* MACROEPILOGUE */ + + +/* Output assembler code for a block containing the constant parts of a + trampoline, leaving space for the variable parts. + + On the 370, the trampoline contains these instructions: + + BALR 14,0 + USING *,14 + L STATIC_CHAIN_REGISTER,X + L 15,Y + BR 15 + X DS 0F + Y DS 0F */ + +#define TRAMPOLINE_TEMPLATE(FILE) \ +{ \ + ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x05E0)); \ + ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x5800 | \ + STATIC_CHAIN_REGNUM << 4)); \ + ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0xE00A)); \ + ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x58F0)); \ + ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0xE00E)); \ + ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x07FF)); \ + ASM_OUTPUT_SHORT (FILE, const0_rtx); \ + ASM_OUTPUT_SHORT (FILE, const0_rtx); \ + ASM_OUTPUT_SHORT (FILE, const0_rtx); \ + ASM_OUTPUT_SHORT (FILE, const0_rtx); \ +} + +/* Length in units of the trampoline for entering a nested function. */ + +#define TRAMPOLINE_SIZE 20 + +/* Emit RTL insns to initialize the variable parts of a trampoline. */ + +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +{ \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 12)), CXT); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 16)), FNADDR); \ +} + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "Error: No profiling available.\n") + +/* Define EXIT_IGNORE_STACK if, when returning from a function, the stack + pointer does not matter (provided there is a frame pointer). */ + +#define EXIT_IGNORE_STACK 1 + +/* Addressing modes, and classification of registers for them. */ + +/* #define HAVE_POST_INCREMENT */ +/* #define HAVE_POST_DECREMENT */ + +/* #define HAVE_PRE_DECREMENT */ +/* #define HAVE_PRE_INCREMENT */ + +/* These assume that REGNO is a hard or pseudo reg number. They give + nonzero only if REGNO is a hard reg of the suitable class or a pseudo + reg currently allocated to a suitable hard reg. + These definitions are NOT overridden anywhere. */ + +#define REGNO_OK_FOR_INDEX_P(REGNO) \ + (((REGNO) > 0 && (REGNO) < 16) \ + || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16)) + +#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P(REGNO) + +#define REGNO_OK_FOR_DATA_P(REGNO) \ + ((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16) + +#define REGNO_OK_FOR_FP_P(REGNO) \ + ((unsigned) ((REGNO) - 16) < 4 || (unsigned) (reg_renumber[REGNO] - 16) < 4) + +/* Now macros that check whether X is a register and also, + strictly, whether it is in a specified class. */ + +/* 1 if X is a data register. */ + +#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X))) + +/* 1 if X is an fp register. */ + +#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X))) + +/* 1 if X is an address register. */ + +#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) + +/* Maximum number of registers that can appear in a valid memory address. */ + +#define MAX_REGS_PER_ADDRESS 2 + +/* Recognize any constant value that is a valid address. */ + +#define CONSTANT_ADDRESS_P(X) \ + (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE \ + || (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF) \ + || (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ + && !SYMBOL_REF_FLAG (XEXP (XEXP (X, 0), 0)))) + +/* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + +#define LEGITIMATE_CONSTANT_P(X) 1 + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check + its validity for a certain class. We have two alternate definitions + for each of them. The usual definition accepts all pseudo regs; the + other rejects them all. The symbol REG_OK_STRICT causes the latter + definition to be used. + + Most source files want to accept pseudo regs in the hope that they will + get allocated to the class that the insn wants them to be in. + Some source files that are used after register allocation + need to be strict. */ + +#ifndef REG_OK_STRICT + +/* Nonzero if X is a hard reg that can be used as an index or if it is + a pseudo reg. */ + +#define REG_OK_FOR_INDEX_P(X) \ + ((REGNO(X) > 0 && REGNO(X) < 16) || REGNO(X) >= 20) + +/* Nonzero if X is a hard reg that can be used as a base reg or if it is + a pseudo reg. */ + +#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_INDEX_P(X) + +#else /* REG_OK_STRICT */ + +/* Nonzero if X is a hard reg that can be used as an index. */ + +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P(REGNO(X)) + +/* Nonzero if X is a hard reg that can be used as a base reg. */ + +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P(REGNO(X)) + +#endif /* REG_OK_STRICT */ + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a + valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS, + except for CONSTANT_ADDRESS_P which is actually machine-independent. */ + +#define COUNT_REGS(X, REGS, FAIL) \ + if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \ + REGS += 1; \ + else if (GET_CODE (X) != CONST_INT || (unsigned) INTVAL (X) >= 4096) \ + goto FAIL; + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ \ + if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (GET_CODE (X) == PLUS) \ + { \ + int regs = 0; \ + rtx x0 = XEXP (X, 0); \ + rtx x1 = XEXP (X, 1); \ + if (GET_CODE (x0) == PLUS) \ + { \ + COUNT_REGS (XEXP (x0, 0), regs, FAIL); \ + COUNT_REGS (XEXP (x0, 1), regs, FAIL); \ + COUNT_REGS (x1, regs, FAIL); \ + if (regs == 2) \ + goto ADDR; \ + } \ + else if (GET_CODE (x1) == PLUS) \ + { \ + COUNT_REGS (x0, regs, FAIL); \ + COUNT_REGS (XEXP (x1, 0), regs, FAIL); \ + COUNT_REGS (XEXP (x1, 1), regs, FAIL); \ + if (regs == 2) \ + goto ADDR; \ + } \ + else \ + { \ + COUNT_REGS (x0, regs, FAIL); \ + COUNT_REGS (x1, regs, FAIL); \ + if (regs != 0) \ + goto ADDR; \ + } \ + } \ + FAIL: ; \ +} + +/* The 370 has no mode dependent addresses. */ + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. */ + +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ +{ \ + if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ + (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ + copy_to_mode_reg (SImode, XEXP (X, 1))); \ + if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ + (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \ + copy_to_mode_reg (SImode, XEXP (X, 0))); \ + if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \ + (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \ + force_operand (XEXP (X, 0), 0)); \ + if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \ + (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ + force_operand (XEXP (X, 1), 0)); \ + if (memory_address_p (MODE, X)) \ + goto WIN; \ +} + +/* Specify the machine mode that this machine uses for the index in the + tablejump instruction. */ + +#define CASE_VECTOR_MODE SImode + +/* Define this if the tablejump instruction expects the table to contain + offsets from the address of the table. + Do not define this if the table should contain absolute addresses. */ + +/* #define CASE_VECTOR_PC_RELATIVE */ + +/* Specify the tree operation to be used to convert reals to integers. */ + +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* Define this if fixuns_trunc is the same as fix_trunc. */ + +#define FIXUNS_TRUNC_LIKE_FIX_TRUNC + +/* We use "unsigned char" as default. */ + +#define DEFAULT_SIGNED_CHAR 0 + +/* This is the kind of divide that is easiest to do in the general case. */ + +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Max number of bytes we can move from memory to memory in one reasonably + fast instruction. */ + +#define MOVE_MAX 256 + +/* Define this if zero-extension is slow (more than one real instruction). */ + +#define SLOW_ZERO_EXTEND + +/* Nonzero if access to memory by bytes is slow and undesirable. */ + +#define SLOW_BYTE_ACCESS 1 + +/* Define if shifts truncate the shift count which implies one can omit + a sign-extension or zero-extension of a shift count. */ + +/* #define SHIFT_COUNT_TRUNCATED */ + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ + +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) (OUTPREC != 16) + +/* We assume that the store-condition-codes instructions store 0 for false + and some other value for true. This is the value stored for true. */ + +/* #define STORE_FLAG_VALUE -1 */ + +/* When a prototype says `char' or `short', really pass an `int'. */ + +#define PROMOTE_PROTOTYPES + +/* Don't perform CSE on function addresses. */ + +#define NO_FUNCTION_CSE + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ + +#define Pmode SImode + +/* A function address in a call instruction is a byte address (for + indexing purposes) so give the MEM rtx a byte's mode. */ + +#define FUNCTION_MODE QImode + +/* Compute the cost of computing a constant rtl expression RTX whose + rtx-code is CODE. The body of this macro is a portion of a switch + statement. If the code is computed here, return it with a return + statement. Otherwise, break from the switch. */ + +#define CONST_COSTS(RTX, CODE, OUTERCODE) \ + case CONST_INT: \ + if ((unsigned) INTVAL (RTX) < 0xfff) return 1; \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 2; \ + case CONST_DOUBLE: \ + return 4; + +/* Tell final.c how to eliminate redundant test instructions. */ + +/* Here we define machine-dependent flags and fields in cc_status + (see `conditions.h'). */ + +/* Store in cc_status the expressions that the condition codes will + describe after execution of an instruction whose pattern is EXP. + Do not alter them if the instruction would not alter the cc's. + + On the 370, load insns do not alter the cc's. However, in some + cases these instructions can make it possibly invalid to use the + saved cc's. In those cases we clear out some or all of the saved + cc's so they won't be used. */ + +#define NOTICE_UPDATE_CC(EXP, INSN) \ +{ \ + rtx exp = (EXP); \ + if (GET_CODE (exp) == PARALLEL) /* Check this */ \ + exp = XVECEXP (exp, 0, 0); \ + if (GET_CODE (exp) != SET) \ + CC_STATUS_INIT; \ + else \ + { \ + if (XEXP (exp, 0) == cc0_rtx) \ + { \ + cc_status.value1 = XEXP (exp, 0); \ + cc_status.value2 = XEXP (exp, 1); \ + cc_status.flags = 0; \ + } \ + else \ + { \ + if (cc_status.value1 \ + && reg_mentioned_p (XEXP (exp, 0), cc_status.value1)) \ + cc_status.value1 = 0; \ + if (cc_status.value2 \ + && reg_mentioned_p (XEXP (exp, 0), cc_status.value2)) \ + cc_status.value2 = 0; \ + switch (GET_CODE (XEXP (exp, 1))) \ + { \ + case PLUS: case MINUS: case MULT: /* case UMULT: */ \ + case DIV: case UDIV: case NEG: case ASHIFT: \ + case ASHIFTRT: case AND: case IOR: case XOR: \ + case ABS: case NOT: \ + CC_STATUS_SET (XEXP (exp, 0), XEXP (exp, 1)); \ + } \ + } \ + } \ +} + + +#define CC_STATUS_SET(V1, V2) \ +{ \ + cc_status.flags = 0; \ + cc_status.value1 = (V1); \ + cc_status.value2 = (V2); \ + if (cc_status.value1 \ + && reg_mentioned_p (cc_status.value1, cc_status.value2)) \ + cc_status.value2 = 0; \ +} + +#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ +{ if (cc_status.flags & CC_NO_OVERFLOW) return NO_OV; return NORMAL; } + +/* Control the assembler format that we output. */ + +#define TEXT_SECTION_ASM_OP "* Program text area" +#define DATA_SECTION_ASM_OP "* Program data area" +#define INIT_SECTION_ASM_OP "* Program initialization area" +#define CTOR_LIST_BEGIN /* NO OP */ +#define CTOR_LIST_END /* NO OP */ + +/* How to refer to registers in assembler output. This sequence is + indexed by compiler's hard-register-number (see above). */ + +#define REGISTER_NAMES \ +{ "0", "1", "2", "3", "4", "5", "6", "7", \ + "8", "9", "10", "11", "12", "13", "14", "15", \ + "0", "2", "4", "6" \ +} + +/* How to renumber registers for dbx and gdb. */ + +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +#define ASM_FILE_START(FILE) fputs ("\tCSECT\n", FILE); +#define ASM_FILE_END(FILE) fputs ("\tEND\n", FILE); +#define ASM_IDENTIFY_GCC(FILE) +#define ASM_COMMENT_START "*" +#define ASM_APP_OFF "" +#define ASM_APP_ON "" + +#define ASM_OUTPUT_LABEL(FILE, NAME) \ +{ assemble_name (FILE, NAME); fputs ("\tEQU\t*\n", FILE); } + +#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) /* NO OP */ + +#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ +{ fputs ("\tENTRY\t", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE); } + +/* MVS externals are limited to 8 characters, upper case only. + The '_' is mapped to '@', except for MVS functions, then '#'. */ + +#define MAX_MVS_LABEL_SIZE 8 + +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ +{ \ + char *bp, ch, temp[MAX_MVS_LABEL_SIZE + 1]; \ + if (strlen (NAME) > MAX_MVS_LABEL_SIZE) \ + { \ + strncpy (temp, NAME, MAX_MVS_LABEL_SIZE); \ + temp[MAX_MVS_LABEL_SIZE] = '\0'; \ + } \ + else \ + strcpy (temp,NAME); \ + if (!strcmp (temp,"main")) \ + strcpy (temp,"gccmain"); \ + if (mvs_function_check (temp)) \ + ch = '#'; \ + else \ + ch = '@'; \ + for (bp = temp; *bp; bp++) \ + { \ + if (islower (*bp)) *bp = toupper (*bp); \ + if (*bp == '_') *bp = ch; \ + } \ + fprintf (FILE, "%s", temp); \ +} + +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ + sprintf (LABEL, "*%s%d", PREFIX, NUM) + +/* Generate internal label. Since we can branch here from off page, we + must reload the base register. */ + +#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ +{ \ + if (!strcmp (PREFIX,"L")) \ + { \ + mvs_add_label(NUM); \ + mvs_label_emitted = 1; \ + } \ + fprintf (FILE, "%s%d\tEQU\t*\n", PREFIX, NUM); \ +} + +/* Generate case label. */ + +#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \ + fprintf (FILE, "%s%d\tEQU\t*\n", PREFIX, NUM) + +/* This is how to output an element of a case-vector that is absolute. */ + +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + mvs_check_page (FILE, 4, 0); \ + fprintf (FILE, "\tDC\tA(L%d)\n", VALUE) + +/* This is how to output an element of a case-vector that is relative. */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + mvs_check_page (FILE, 4, 0); \ + fprintf (FILE, "\tDC\tA(L%d-L%d)\n", VALUE, REL) + +/* This is how to output an insn to push a register on the stack. + It need not be very fast code. */ + +#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ + mvs_check_page (FILE, 8, 4); \ + fprintf (FILE, "\tS\t13,=F'4'\n\tST\t%s,%d(13)\n", \ + reg_names[REGNO], STACK_POINTER_OFFSET) + +/* This is how to output an insn to pop a register from the stack. + It need not be very fast code. */ + +#define ASM_OUTPUT_REG_POP(FILE, REGNO) \ + mvs_check_page (FILE, 8, 0); \ + fprintf (FILE, "\tL\t%s,%d(13)\n\tLA\t13,4(13)\n", \ + reg_names[REGNO], STACK_POINTER_OFFSET) + +/* This is how to output an assembler line defining a `double' constant. */ + +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ + fprintf (FILE, "\tDC\tD'%.18G'\n", (VALUE)) + +/* This is how to output an assembler line defining a `float' constant. */ + +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ + fprintf (FILE, "\tDC\tE'%.9G'\n", (VALUE)) + +/* This outputs an integer, if not a CONST_INT must be address constant. */ + +#define ASM_OUTPUT_INT(FILE, EXP) \ +{ \ + if (GET_CODE (EXP) == CONST_INT) \ + { \ + fprintf (FILE, "\tDC\tF'"); \ + output_addr_const (FILE, EXP); \ + fprintf (FILE, "'\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tDC\tA("); \ + output_addr_const (FILE, EXP); \ + fprintf (FILE, ")\n"); \ + } \ +} + +/* This outputs a short integer. */ + +#define ASM_OUTPUT_SHORT(FILE, EXP) \ +{ \ + fprintf (FILE, "\tDC\tX'%04X'\n", INTVAL(EXP) & 0xFFFF); \ +} + +/* This outputs a byte sized integer. */ + +#define ASM_OUTPUT_CHAR(FILE, EXP) \ + fprintf (FILE, "\tDC\tX'%02X'\n", INTVAL (EXP) ) + +#define ASM_OUTPUT_BYTE(FILE, VALUE) \ + fprintf (FILE, "\tDC\tX'%02X'\n", VALUE) + +/* This outputs a text string. The string are chopped up to fit into + an 80 byte record. Also, control and special characters, interpreted + by the IBM assembler, are output numerically. */ + +#define MVS_ASCII_TEXT_LENGTH 48 + +#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) \ +{ \ + int i, j; \ + int c; \ + for (j = 0, i = 0; i < LEN; j++, i++) \ + { \ + c = PTR[i]; \ + if (iscntrl (c) || c == '&') \ + { \ + if (j % MVS_ASCII_TEXT_LENGTH != 0 ) \ + fprintf (FILE, "'\n"); \ + j = -1; \ + if (c == '&') c = MAP_CHARACTER (c); \ + fprintf (FILE, "\tDC\tX'%X'\n", c ); \ + } \ + else \ + { \ + if (j % MVS_ASCII_TEXT_LENGTH == 0) \ + fprintf (FILE, "\tDC\tC'"); \ + if ( c == '\'' ) \ + fprintf (FILE, "%c%c", c, c); \ + else \ + fprintf (FILE, "%c", c); \ + if (j % MVS_ASCII_TEXT_LENGTH == MVS_ASCII_TEXT_LENGTH - 1) \ + fprintf (FILE, "'\n" ); \ + } \ + } \ + if (j % MVS_ASCII_TEXT_LENGTH != 0) \ + fprintf (FILE, "'\n"); \ +} + +/* This is how to output an assembler line that says to advance the + location counter to a multiple of 2**LOG bytes. */ + +#define ASM_OUTPUT_ALIGN(FILE, LOG) \ + if (LOG) \ + { \ + if ((LOG) == 1) \ + fprintf (FILE, "\tDS\t0H\n" ); \ + else \ + fprintf (FILE, "\tDS\t0F\n" ); \ + } \ + +/* The maximum length of memory that the IBM assembler will allow in one + DS operation. */ + +#define MAX_CHUNK 32767 + +/* A C statement to output to the stdio stream FILE an assembler + instruction to advance the location counter by SIZE bytes. Those + bytes should be zero when loaded. */ + +#define ASM_OUTPUT_SKIP(FILE, SIZE) \ +{ \ + int s, k; \ + for (s = (SIZE); s > 0; s -= MAX_CHUNK) \ + { \ + if (s > MAX_CHUNK) \ + k = MAX_CHUNK; \ + else \ + k = s; \ + fprintf (FILE, "\tDS\tXL%d\n", k); \ + } \ +} + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of a common-label named NAME whose + size is SIZE bytes. The variable ROUNDED is the size rounded up + to whatever alignment the caller wants. */ + +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +{ \ + fputs ("\tENTRY\t", FILE); \ + assemble_name (FILE, NAME); \ + fputs ("\n", FILE); \ + fprintf (FILE, "\tDS\t0F\n"); \ + ASM_OUTPUT_LABEL (FILE,NAME); \ + ASM_OUTPUT_SKIP (FILE,SIZE); \ +} + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of a local-common-label named NAME + whose size is SIZE bytes. The variable ROUNDED is the size + rounded up to whatever alignment the caller wants. */ + +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +{ \ + fprintf (FILE, "\tDS\t0F\n"); \ + ASM_OUTPUT_LABEL (FILE,NAME); \ + ASM_OUTPUT_SKIP (FILE,SIZE); \ +} + +/* Store in OUTPUT a string (made with alloca) containing an + assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +{ \ + (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10); \ + sprintf ((OUTPUT), "%s%d", (NAME), (LABELNO)); \ +} + +/* Define the parentheses used to group arithmetic operations + in assembler code. */ + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* Define results of standard character escape sequences. */ + +#define TARGET_BELL 47 +#define TARGET_BS 22 +#define TARGET_TAB 5 +#define TARGET_NEWLINE 21 +#define TARGET_VT 11 +#define TARGET_FF 12 +#define TARGET_CR 13 + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ + +#define PRINT_OPERAND(FILE, X, CODE) \ +{ \ + switch (GET_CODE (X)) \ + { \ + static char curreg[4]; \ + case REG: \ + if (CODE == 'N') \ + strcpy (curreg, reg_names[REGNO (X) + 1]); \ + else \ + strcpy (curreg, reg_names[REGNO (X)]); \ + fprintf (FILE, "%s", curreg); \ + break; \ + case MEM: \ + { \ + rtx addr = XEXP (X, 0); \ + if (CODE == 'O') \ + { \ + if (GET_CODE (addr) == PLUS) \ + fprintf (FILE, "%d", INTVAL (XEXP (addr, 1))); \ + else \ + fprintf (FILE, "0"); \ + } \ + else if (CODE == 'R') \ + { \ + if (GET_CODE (addr) == PLUS) \ + fprintf (FILE, "%s", reg_names[REGNO (XEXP (addr, 0))]);\ + else \ + fprintf (FILE, "%s", reg_names[REGNO (addr)]); \ + } \ + else \ + output_address (XEXP (X, 0)); \ + } \ + break; \ + case SYMBOL_REF: \ + case LABEL_REF: \ + mvs_page_lit += 4; \ + if (SYMBOL_REF_FLAG (X)) fprintf (FILE, "=V("); \ + else fprintf (FILE, "=A("); \ + output_addr_const (FILE, X); \ + fprintf (FILE, ")"); \ + break; \ + case CONST_INT: \ + if (CODE == 'B') \ + fprintf (FILE, "%d", INTVAL (X) & 0xff); \ + else if (CODE == 'X') \ + fprintf (FILE, "%02X", INTVAL (X) & 0xff); \ + else if (CODE == 'h') \ + fprintf (FILE, "%d", (INTVAL (X) << 16) >> 16); \ + else if (CODE == 'H') \ + { \ + mvs_page_lit += 2; \ + fprintf (FILE, "=H'%d'", (INTVAL (X) << 16) >> 16); \ + } \ + else \ + { \ + mvs_page_lit += 4; \ + fprintf (FILE, "=F'%d'", INTVAL (X)); \ + } \ + break; \ + case CONST_DOUBLE: \ + if (GET_MODE (X) == DImode) \ + { \ + if (CODE == 'M') \ + { \ + mvs_page_lit += 4; \ + fprintf (FILE, "=XL4'%08X'", CONST_DOUBLE_LOW (X)); \ + } \ + else if (CODE == 'L') \ + { \ + mvs_page_lit += 4; \ + fprintf (FILE, "=XL4'%08X'", CONST_DOUBLE_HIGH (X)); \ + } \ + else \ + { \ + mvs_page_lit += 8; \ + fprintf (FILE, "=XL8'%08X%08X'", CONST_DOUBLE_LOW (X), \ + CONST_DOUBLE_HIGH (X)); \ + } \ + } \ + else \ + { \ + union { double d; int i[2]; } u; \ + u.i[0] = CONST_DOUBLE_LOW (X); \ + u.i[1] = CONST_DOUBLE_HIGH (X); \ + if (GET_MODE (X) == SFmode) \ + { \ + mvs_page_lit += 4; \ + fprintf (FILE, "=E'%.9G'", u.d); \ + } \ + else \ + { \ + mvs_page_lit += 8; \ + fprintf (FILE, "=D'%.18G'", u.d); \ + } \ + } \ + break; \ + case CONST: \ + if (GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \ + { \ + mvs_page_lit += 4; \ + if (SYMBOL_REF_FLAG (XEXP (XEXP (X, 0), 0))) \ + { \ + fprintf (FILE, "=V("); \ + ASM_OUTPUT_LABELREF (FILE, \ + XSTR (XEXP (XEXP (X, 0), 0), 0)); \ + fprintf (FILE, ")\n\tA\t%s,=F'%d'", curreg, \ + INTVAL (XEXP (XEXP (X, 0), 1))); \ + } \ + else \ + { \ + fprintf (FILE, "=A("); \ + output_addr_const (FILE, X); \ + fprintf (FILE, ")"); \ + } \ + } \ + else \ + { \ + mvs_page_lit += 4; \ + fprintf (FILE, "=F'"); \ + output_addr_const (FILE, X); \ + fprintf (FILE, "'"); \ + } \ + break; \ + default: \ + abort(); \ + } \ +} + +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ +{ \ + rtx breg, xreg, offset, plus; \ + \ + switch (GET_CODE (ADDR)) \ + { \ + case REG: \ + fprintf (FILE, "0(%s)", reg_names[REGNO (ADDR)]); \ + break; \ + case PLUS: \ + breg = 0; \ + xreg = 0; \ + offset = 0; \ + if (GET_CODE (XEXP (ADDR, 0)) == PLUS) \ + { \ + if (GET_CODE (XEXP (ADDR, 1)) == REG) \ + breg = XEXP (ADDR, 1); \ + else \ + offset = XEXP (ADDR, 1); \ + plus = XEXP (ADDR, 0); \ + } \ + else \ + { \ + if (GET_CODE (XEXP (ADDR, 0)) == REG) \ + breg = XEXP (ADDR, 0); \ + else \ + offset = XEXP (ADDR, 0); \ + plus = XEXP (ADDR, 1); \ + } \ + if (GET_CODE (plus) == PLUS) \ + { \ + if (GET_CODE (XEXP (plus, 0)) == REG) \ + { \ + if (breg) \ + xreg = XEXP (plus, 0); \ + else \ + breg = XEXP (plus, 0); \ + } \ + else \ + { \ + offset = XEXP (plus, 0); \ + } \ + if (GET_CODE (XEXP (plus, 1)) == REG) \ + { \ + if (breg) \ + xreg = XEXP (plus, 1); \ + else \ + breg = XEXP (plus, 1); \ + } \ + else \ + { \ + offset = XEXP (plus, 1); \ + } \ + } \ + else if (GET_CODE (plus) == REG) \ + { \ + if (breg) \ + xreg = plus; \ + else \ + breg = plus; \ + } \ + else \ + { \ + offset = plus; \ + } \ + if (offset) \ + { \ + if (GET_CODE (offset) == LABEL_REF) \ + fprintf (FILE, "L%d", \ + CODE_LABEL_NUMBER (XEXP (offset, 0))); \ + else \ + output_addr_const (FILE, offset); \ + } \ + else \ + fprintf (FILE, "0"); \ + if (xreg) \ + fprintf (FILE, "(%s,%s)", \ + reg_names[REGNO (xreg)], reg_names[REGNO (breg)]); \ + else \ + fprintf (FILE, "(%s)", reg_names[REGNO (breg)]); \ + break; \ + default: \ + mvs_page_lit += 4; \ + if (SYMBOL_REF_FLAG (ADDR)) fprintf (FILE, "=V("); \ + else fprintf (FILE, "=A("); \ + output_addr_const (FILE, ADDR); \ + fprintf (FILE, ")"); \ + break; \ + } \ +} diff --git a/gnu/usr.bin/gcc/config/i370/t-i370 b/gnu/usr.bin/gcc/config/i370/t-i370 new file mode 100644 index 00000000000..d20ab385dcc --- /dev/null +++ b/gnu/usr.bin/gcc/config/i370/t-i370 @@ -0,0 +1,4 @@ +# There is no libgcc for mvs +LIBGCC = +INSTALL_LIBGCC = +LIBGCC1_TEST = diff --git a/gnu/usr.bin/gcc/config/i370/xm-i370.h b/gnu/usr.bin/gcc/config/i370/xm-i370.h new file mode 100644 index 00000000000..ac753633070 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i370/xm-i370.h @@ -0,0 +1,53 @@ +/* Configuration for GNU C-compiler for System/370. + Copyright (C) 1989, 1993, 1997 Free Software Foundation, Inc. + Contributed by Jan Stein (jan@cd.chalmers.se). + Modified for MVS C/370 by Dave Pitts (dpitts@nyx.cs.du.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. */ + +/* #defines that need visibility everywhere. */ + +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ + +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_FLOAT_FORMAT IBM_FLOAT_FORMAT +#define HOST_EBCDIC 1 + +#define USG +#ifndef MVS +#define MVS +#endif + +/* Target machine dependencies. tm.h is a symbolic link to the actual + target specific file. */ + +#include "tm.h" + +/* Arguments to use with `exit'. */ + +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 12 + +#define NO_DBX_FORMAT + diff --git a/gnu/usr.bin/gcc/config/i386/cygwin32.asm b/gnu/usr.bin/gcc/config/i386/cygwin32.asm new file mode 100644 index 00000000000..4ac4c91a3b1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/cygwin32.asm @@ -0,0 +1,32 @@ +/* stuff needed for libgcc1 on win32. */ + +#ifdef L_chkstk + + .global ___chkstk + .global __alloca +___chkstk: +__alloca: + pushl %ecx /* save temp */ + movl %esp,%ecx /* get sp */ + addl $0x8,%ecx /* and point to return addr */ + +probe: cmpl $0x1000,%eax /* > 4k ?*/ + jb done + + subl $0x1000,%ecx /* yes, move pointer down 4k*/ + orl $0x0,(%ecx) /* probe there */ + subl $0x1000,%eax /* decrement count */ + jmp probe /* and do it again */ + +done: subl %eax,%ecx + orl $0x0,(%ecx) /* less that 4k, just peek here */ + + movl %esp,%eax + movl %ecx,%esp /* decrement stack */ + + movl (%eax),%ecx /* recover saved temp */ + movl 4(%eax),%eax /* get return address */ + jmp *%eax + + +#endif diff --git a/gnu/usr.bin/gcc/config/i386/cygwin32.h b/gnu/usr.bin/gcc/config/i386/cygwin32.h new file mode 100644 index 00000000000..952d8488b34 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/cygwin32.h @@ -0,0 +1,207 @@ +/* Operating system specific defines to be used when targeting GCC for + hosting on Windows NT 3.x, using a Unix style C library and tools, + as distinct from winnt.h, which is used to build GCC for use with a + windows style library and tool set and uses the Microsoft tools. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +#define YES_UNDERSCORES + +#define DBX_DEBUGGING_INFO +#define SDB_DEBUGGING_INFO +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "i386/gas.h" +#include "dbxcoff.h" + +#ifdef CPP_PREDEFINES +#undef CPP_PREDEFINES +#endif + +#define CPP_PREDEFINES "-Di386 -D_WIN32 \ + -DPOSIX -D__CYGWIN32__ -DWINNT -D_X86_=1 -D__STDC__=1\ + -D__stdcall=__attribute__((__stdcall__)) \ + -D__cdecl=__attribute__((__cdecl__)) \ + -Asystem(winnt) -Acpu(i386) -Amachine(i386)" + +#undef CPP_SPEC +#define CPP_SPEC "-remap %(cpp_cpu) %[cpp_cpu] %{posix:-D_POSIX_SOURCE}" + +/* We have to dynamic link to get to the system DLLs. All of libc, libm and + the Unix stuff is in cygwin.dll. The import library is called + 'libcygwin.a'. For Windows applications, include more libraries, but + always include kernel32. We'd like to specific subsystem windows to + ld, but that doesn't work just yet. */ + +#undef LIB_SPEC +#define LIB_SPEC "-lcygwin %{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32" + +#define LINK_SPEC "%{mwindows:--subsystem windows}" + +/* Normally, -lgcc is not needed since everything in it is in the DLL, but we + want to allow things to be added to it when installing new versions of + GCC without making a new CYGWIN.DLL, so we leave it. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0%O%s" + +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_UNSIGNED 1 +#define WCHAR_TYPE_SIZE 16 +#define WCHAR_TYPE "short unsigned int" +#define HAVE_ATEXIT 1 + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_ctor, in_dtor + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CTOR_SECTION_FUNCTION \ + DTOR_SECTION_FUNCTION + +#define CTOR_SECTION_FUNCTION \ +void \ +ctor_section () \ +{ \ + if (in_section != in_ctor) \ + { \ + fprintf (asm_out_file, "\t.section .ctor\n"); \ + in_section = in_ctor; \ + } \ +} + +#define DTOR_SECTION_FUNCTION \ +void \ +dtor_section () \ +{ \ + if (in_section != in_dtor) \ + { \ + fprintf (asm_out_file, "\t.section .dtor\n"); \ + in_section = in_dtor; \ + } \ +} + +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctor_section (); \ + fprintf (FILE, "%s\t", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtor_section (); \ + fprintf (FILE, "%s\t", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* Define this macro if references to a symbol must be treated + differently depending on something about the variable or + function named by the symbol (such as what section it is in). + + On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol + so that we may access it directly in the GOT. + + On i386 running Windows NT, modify the assembler name with a suffix + consisting of an atsign (@) followed by string of digits that represents + the number of bytes of arguments passed to the function, if it has the + attribute STDCALL. */ + +#ifdef ENCODE_SECTION_INFO +#undef ENCODE_SECTION_INFO +#define ENCODE_SECTION_INFO(DECL) \ +do \ + { \ + if (flag_pic) \ + { \ + rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ + ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \ + SYMBOL_REF_FLAG (XEXP (rtl, 0)) \ + = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ + || ! TREE_PUBLIC (DECL)); \ + } \ + if (TREE_CODE (DECL) == FUNCTION_DECL) \ + if (lookup_attribute ("stdcall", \ + TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \ + XEXP (DECL_RTL (DECL), 0) = \ + gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \ + } \ +while (0) +#endif + +/* Emit code to check the stack when allocating more that 4000 + bytes in one go. */ + +#define CHECK_STACK_LIMIT 4000 + +/* By default, target has a 80387, uses IEEE compatible arithmetic, + and returns float values in the 387 and needs stack probes */ +#undef TARGET_DEFAULT + +#define TARGET_DEFAULT \ + (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE) + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) + +/* Define this macro if in some cases global symbols from one translation + unit may not be bound to undefined symbols in another translation unit + without user intervention. For instance, under Microsoft Windows + symbols must be explicitly imported from shared libraries (DLLs). */ +#define MULTIPLE_SYMBOL_SPACES + +#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL) +extern void i386_pe_unique_section (); +#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC) + +#define SUPPORTS_ONE_ONLY 1 + +/* A C statement to output something to the assembler file to switch to section + NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or + NULL_TREE. Some target formats do not support arbitrary sections. Do not + define this macro in such cases. */ +#undef ASM_OUTPUT_SECTION_NAME +#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \ +do { \ + if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \ + fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \ + else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \ + fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \ + else \ + fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \ + /* Functions may have been compiled at various levels of \ + optimization so we can't use `same_size' here. Instead, \ + have the linker pick one. */ \ + if ((DECL) && DECL_ONE_ONLY (DECL)) \ + fprintf (STREAM, "\t.linkonce %s\n", \ + TREE_CODE (DECL) == FUNCTION_DECL \ + ? "discard" : "same_size"); \ +} while (0) + +#undef ASM_COMMENT_START +#define ASM_COMMENT_START " #" diff --git a/gnu/usr.bin/gcc/config/i386/dgux.c b/gnu/usr.bin/gcc/config/i386/dgux.c new file mode 100644 index 00000000000..ff36135380c --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/dgux.c @@ -0,0 +1,190 @@ +/* Subroutines for GNU compiler for Intel 80x86 running DG/ux + Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. + Currently maintained by (gcc@dg-rtp.dg.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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <time.h> +#include "i386/i386.c" + + +extern char *version_string; + +struct option +{ + char *string; + int *variable; + int on_value; +}; + +static int +output_option (file, sep, type, name, indent, pos, max) + FILE *file; + char *sep; + char *type; + char *name; + char *indent; + int pos; + int max; +{ + if (strlen (sep) + strlen (type) + strlen (name) + pos > max) + { + fprintf (file, indent); + return fprintf (file, "%s%s", type, name); + } + return pos + fprintf (file, "%s%s%s", sep, type, name); +} + +static struct { char *name; int value; } m_options[] = TARGET_SWITCHES; + +static void +output_options (file, f_options, f_len, W_options, W_len, + pos, max, sep, indent, term) + FILE *file; + struct option *f_options; + struct option *W_options; + int f_len, W_len; + int pos; + int max; + char *indent; + char *term; +{ + register int j; + + if (optimize) + pos = output_option (file, sep, "-O", "", indent, pos, max); + if (write_symbols != NO_DEBUG) + pos = output_option (file, sep, "-g", "", indent, pos, max); +/* if (flag_traditional) + pos = output_option (file, sep, "-traditional", "", indent, pos, max);*/ + if (profile_flag) + pos = output_option (file, sep, "-p", "", indent, pos, max); + if (profile_block_flag) + pos = output_option (file, sep, "-a", "", indent, pos, max); + + for (j = 0; j < f_len; j++) + if (*f_options[j].variable == f_options[j].on_value) + pos = output_option (file, sep, "-f", f_options[j].string, + indent, pos, max); + + for (j = 0; j < W_len; j++) + if (*W_options[j].variable == W_options[j].on_value) + pos = output_option (file, sep, "-W", W_options[j].string, + indent, pos, max); + + for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++) + if (m_options[j].name[0] != '\0' + && m_options[j].value > 0 + && ((m_options[j].value & target_flags) + == m_options[j].value)) + pos = output_option (file, sep, "-m", m_options[j].name, + indent, pos, max); + + pos = output_option (file, sep, "-mcpu=", ix86_cpu_string, indent, pos, max); + pos = output_option (file, sep, "-march=", ix86_arch_string, indent, pos, max); + fprintf (file, term); +} + +/* Output to FILE the start of the assembler file. */ + +void +output_file_start (file, f_options, f_len, W_options, W_len) + FILE *file; + struct option *f_options; + struct option *W_options; + int f_len, W_len; +{ + register int pos; + + output_file_directive (file, main_input_filename); + fprintf (file, "\t.version\t\"01.01\"\n"); \ + /* Switch to the data section so that the coffsem symbol and the + gcc2_compiled. symbol aren't in the text section. */ + data_section (); + + pos = fprintf (file, "\n// cc1 (%s) arguments:", VERSION_STRING); + output_options (file, f_options, f_len, W_options, W_len, + pos, 75, " ", "\n// ", "\n\n"); + +#ifdef TARGET_IDENTIFY_REVISION + if (TARGET_IDENTIFY_REVISION) + { + char indent[256]; + + time_t now = time ((time_t *)0); + sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename); + fprintf (file, indent+3); + pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now)); + output_options (file, f_options, f_len, W_options, W_len, + pos, 150 - strlen (indent), " ", indent, "]\"\n\n"); + } +#endif /* TARGET_IDENTIFY_REVISION */ +} + +#ifndef CROSS_COMPILE +#if defined (_abort_aux) +/* Debugging aid to be registered via `atexit'. See the definition + of abort in dgux.h. */ +void +abort_aux () +{ + extern int insn_; + extern char * file_; + extern int line_; + static int done; + rtx line_note; + + if (done++) + return; + if (file_ || line_) + { + if (write_symbols != NO_DEBUG) + { + for (line_note = (rtx) insn_ ; line_note != 0 ; line_note = PREV_INSN (line_note)) + if (GET_CODE (line_note) == NOTE && NOTE_LINE_NUMBER (line_note) > 0) + break; + if (line_note != 0) + { + error_with_file_and_line (NOTE_SOURCE_FILE (line_note), + NOTE_LINE_NUMBER (line_note), + "Internal gcc abort from %s:%d", + file_ ? file_ : "<nofile>", line_); + if (insn_ && file_ && strcmp (file_, "toplev.c")) + { + error_with_file_and_line (NOTE_SOURCE_FILE (line_note), + NOTE_LINE_NUMBER (line_note), + "The local variable `insn' has the value:", 0); + debug_rtx ((rtx) insn_); + } + } + } + if (write_symbols == NO_DEBUG || line_note == 0) + { + error ("Internal gcc abort from %s:%d", + file_ ? file_ : "<nofile>", line_); + if (insn_ && file_ && strcmp (file_, "toplev.c")) + { + error ("The local variable `insn' has the value:", 0); + debug_rtx ((rtx) insn_); + } + } + } +} +#endif +#endif + + diff --git a/gnu/usr.bin/gcc/config/i386/dgux.h b/gnu/usr.bin/gcc/config/i386/dgux.h new file mode 100644 index 00000000000..ce0c8235585 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/dgux.h @@ -0,0 +1,265 @@ +/* Target definitions for GNU compiler for Intel 80x86 running DG/ux + Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. + Currently maintained by gcc@dg-rtp.dg.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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* for now, we are just like the sysv4 version with a + few hacks +*/ + +#include "i386/sysv4.h" + +#ifndef VERSION_INFO2 +#define VERSION_INFO2 "$Revision: 1.1 $" +#endif + +#ifndef VERSION_STRING +#define VERSION_STRING version_string +#endif + +/* Identify the compiler. */ +/* TARGET_VERSION used by toplev.c VERSION_STRING used by -midentify-revision */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (%s%s, %s)", \ + VERSION_INFO1, VERSION_INFO2, __DATE__) +#undef VERSION_INFO1 +#define VERSION_INFO1 "ix86 DG/ux, " + +/* Augment TARGET_SWITCHES with the MXDB options. */ +#define MASK_STANDARD 0x40000000 /* Retain standard information */ +#define MASK_NOLEGEND 0x20000000 /* Discard legend information */ +#define MASK_EXTERNAL_LEGEND 0x10000000 /* Make external legends */ +#define MASK_IDENTIFY_REVISION 0x08000000 /* Emit 'ident' to .s */ +#define MASK_WARN_PASS_STRUCT 0x04000000 /* Emit 'ident' to .s */ + +#define TARGET_STANDARD (target_flags & MASK_STANDARD) +#define TARGET_NOLEGEND (target_flags & MASK_NOLEGEND) +#define TARGET_EXTERNAL_LEGEND (target_flags & MASK_EXTERNAL_LEGEND) +#define TARGET_IDENTIFY_REVISION (target_flags & MASK_IDENTIFY_REVISION) +#define TARGET_WARN_PASS_STRUCT (target_flags & MASK_WARN_PASS_STRUCT) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "standard", MASK_STANDARD }, \ + { "legend", -MASK_NOLEGEND }, \ + { "no-legend", MASK_NOLEGEND }, \ + { "external-legend", MASK_EXTERNAL_LEGEND }, \ + { "identify-revision", MASK_IDENTIFY_REVISION }, \ + { "warn-passed-structs", MASK_WARN_PASS_STRUCT }, + +#undef DWARF_DEBUGGING_INFO +#define DWARF_DEBUGGING_INFO + +/* + allow -gstabs so that those who have gnu-as installed + can debug c++ programs. +*/ +#undef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG + +/* Override svr[34].h. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_start (FILE, f_options, sizeof f_options / sizeof f_options[0], \ + W_options, sizeof W_options / sizeof W_options[0]) + +/* ix86 abi specified type for wchar_t */ + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + + +/* Some machines may desire to change what optimizations are performed for + various optimization levels. This macro, if defined, is executed once + just after the optimization level is determined and before the remainder + of the command options have been parsed. Values set in this macro are + used as the default values for the other command line options. + + LEVEL is the optimization level specified; 2 if -O2 is specified, + 1 if -O is specified, and 0 if neither is specified. */ + +/* This macro used to store 0 in flag_signed_bitfields. + Not only is that misuse of this macro; the whole idea is wrong. + + The GNU C dialect makes bitfields signed by default, + regardless of machine type. Making any machine inconsistent in this + regard is bad for portability. + + I chose to make bitfields signed by default because this is consistent + with the way ordinary variables are handled: `int' equals `signed int'. + If there is a good reason to prefer making bitfields unsigned by default, + it cannot have anything to do with the choice of machine. + If the reason is good enough, we should change the convention for all machines. + + -- rms, 20 July 1991. */ + +/* + this really should go into dgux-local.h +*/ + +#undef OPTIMIZATION_OPTIONS +#define OPTIMIZATION_OPTIONS(LEVEL) \ + do { \ + extern int flag_signed_bitfields; \ + flag_signed_bitfields = 0; \ + abort_helper (); \ + optimization_options (LEVEL); \ + } while (0) + + +/* The normal location of the `ld' and `as' programs */ + +#undef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/bin/" + +/* The normal location of the various *crt*.o files is the */ + +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/usr/lib/" + +/* Macros to be automatically defined. + __CLASSIFY_TYPE__ is used in the <varargs.h> and <stdarg.h> header + files with DG/UX revision 5.40 and later. This allows GNU CC to + operate without installing the header files. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -D__ix86 -Dunix -DDGUX -D__CLASSIFY_TYPE__=2\ + -Asystem(unix) -Asystem(svr4) -Acpu(i386) -Amachine(i386)" + + /* + If not -ansi, -traditional, or restricting include files to one + specific source target, specify full DG/UX features. + */ +#undef CPP_SPEC +#define CPP_SPEC "%{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}}" + +/* Assembler support (legends for mxdb). */ +#undef ASM_SPEC +#define ASM_SPEC "\ +%{mno-legend:%{mstandard:-Wc,off}}\ +%{g:%{!mno-legend:-Wc,-fix-bb,-s\"%i\"\ +%{traditional:,-lc}%{!traditional:,-lansi-c}\ +%{mstandard:,-keep-std}\ +%{mexternal-legend:,-external}}}" + +/* Override svr4.h. */ + +/* hassey 3/12/94 keep svr4 ASM_FINAL_SPEC allows -pipe to work */ + +/* Linker and library spec's. + -static, -shared, -symbolic, -h* and -z* access AT&T V.4 link options. + -svr4 instructs gcc to place /usr/lib/values-X[cat].o on link the line. + The absence of -msvr4 indicates linking done in a COFF environment and + adds the link script to the link line. In all environments, the first + and last objects are crtbegin.o and crtend.o. + When the -G link option is used (-shared and -symbolic) a final link is + not being done. */ + +#undef LIB_SPEC +#define LIB_SPEC \ +"%{!shared:%{!symbolic:-lc}}" + +#undef LINK_SPEC +#define LINK_SPEC "%{z*} %{h*} %{v:-V} \ + %{static:-dn -Bstatic} \ + %{shared:-G -dy} \ + %{symbolic:-Bsymbolic -G -dy} \ + %{pg:-L/usr/lib/libp}%{p:-L/usr/lib/libp}" + +#ifdef CROSS_COMPILE + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt1.o%s} \ + %{!pg:%{p:mcrt1.o%s} \ + %{!p:crt1.o%s}}}} \ + %{pg:gcrti.o%s}%{!pg:crti.o%s} \ + crtbegin.o%s \ + %{ansi:values-Xc.o%s} \ + %{!ansi:%{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}" + +#else + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt1.o%s} \ + %{!pg:%{p:/lib/mcrt1.o%s} \ + %{!p:/lib/crt1.o%s}}} \ + %{pg:gcrti.o%s}%{!pg:/lib/crti.o%s}} \ + crtbegin.o%s \ + %{ansi:/lib/values-Xc.o%s} \ + %{!ansi:%{traditional:/lib/values-Xt.o%s} \ + %{!traditional:/lib/values-Xa.o%s}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:/lib/crtn.o}" + +#endif /* CROSS_COMPILE */ + +#if !defined (no_abort) || defined (CRT_BEGIN) || defined (CRT_END) +#undef abort + +char insn; int insn_; char * file_; int line_; +#define abort() \ + (insn_ = (int) insn, \ + file_ = __FILE__, \ + line_ = __LINE__, \ + fancy_abort ()) +#define abort_helper() \ + do { \ + extern void abort_aux (); \ + atexit (abort_aux); \ + } while (0) +#define _abort_aux +#endif /* no abort */ + +/* The maximum alignment which the object file format can support. + page alignment would seem to be enough */ +#undef MAX_OFILE_ALIGNMENT +#define MAX_OFILE_ALIGNMENT 0x1000 + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ +} + +/* This supplements FUNCTION_ARG's definition in i386.h to check + TARGET_WARN_PASS_STRUCT */ + +#undef FUNCTION_ARG +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +((((MODE) == BLKmode && TARGET_WARN_PASS_STRUCT) ? \ + warning ("argument is a structure"),0 : 0), \ + (function_arg (&CUM, MODE, TYPE, NAMED))) + +/* Add .align 1 to avoid .backalign bug in assembler */ +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP ".section\t.rodata\n\t.align 1" diff --git a/gnu/usr.bin/gcc/config/i386/freebsd-elf.h b/gnu/usr.bin/gcc/config/i386/freebsd-elf.h new file mode 100644 index 00000000000..252ebf5cf84 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/freebsd-elf.h @@ -0,0 +1,187 @@ +/* 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. + +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. */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 1 + +/* 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, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Indicate that jump tables go in the text section. This is + necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION + +/* Copy this from the svr4 specifications... */ +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ +{ \ + if (flag_pic) \ + { \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ + LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tcall mcount\n"); \ + } \ +} + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -D__ELF__ -D__FreeBSD__=2 -Asystem(FreeBSD)" + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" + +#undef LIB_SPEC +#if 1 +/* We no longer link with libc_p.a or libg.a by default. If you + * want to profile or debug the C library, please add + * -lc_p or -ggdb to LDFLAGS at the link time, respectively. + */ +#define LIB_SPEC \ + "%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \ + %{!ggdb:-lc} %{ggdb:-lg}}" +#else +#define LIB_SPEC \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif + +/* 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 %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-static}}}" + +/* Get perform_* macros to build libgcc.a. */ diff --git a/gnu/usr.bin/gcc/config/i386/gmon-sol2.c b/gnu/usr.bin/gcc/config/i386/gmon-sol2.c new file mode 100644 index 00000000000..c0743958f90 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/gmon-sol2.c @@ -0,0 +1,402 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Re rework of the solaris 2 version of gmon by J.W.Hawtin 12/8/1996 + * Does not work right yet. + */ + +/* + * This is a modified gmon.c by J.W.Hawtin <J.W.Hawtin@lboro.ac.uk>, + * 14/8/96 based on the original gmon.c in GCC and the hacked version + * solaris 2 sparc version (config/sparc/gmon-sol.c) by Mark Eichin. To do + * process profiling on solaris 2.4 X86 + * + * It must be used in conjunction with sol2-gc1.asm, which is used to start + * and stop process monitoring. + * + * Differences. + * + * On Solaris 2 _mcount is called my library functions not mcount, so support + * has been added for both. + * + * Also the prototype for profil() is different + * + * Solaris 2 does not seem to have char *minbrk whcih allows the setting of + * the minimum SBRK region so this code has been removed and lets pray malloc + * does not mess it up. + * + * Notes + * + * This code could easily be integrated with the original gmon.c and perhaps + * should be. + */ + +#ifndef lint +static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91"; +#endif /* not lint */ + +#if 0 +#include <unistd.h> + +#endif +#ifdef DEBUG +#include <stdio.h> +#endif + +#if 0 +#include "i386/gmon.h" +#else + +struct phdr { + char *lpc; + char *hpc; + int ncnt; +}; + + +#define HISTFRACTION 2 +#define HISTCOUNTER unsigned short +#define HASHFRACTION 1 +#define ARCDENSITY 2 +#define MINARCS 50 +#define BASEADDRESS 0x8000000 /* On Solaris 2 X86 all executables start here + and not at 0 */ + +struct tostruct { + char *selfpc; + long count; + unsigned short link; +}; +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) +#endif + +/* char *minbrk; */ + +#ifdef __alpha +extern char *sbrk (); +#endif + + /* + * froms is actually a bunch of unsigned shorts indexing tos + */ +static int profiling = 3; +static unsigned short *froms; +static struct tostruct *tos = 0; +static long tolimit = 0; +static char *s_lowpc = 0; +static char *s_highpc = 0; +static unsigned long s_textsize = 0; + +static int ssiz; +static char *sbuf; +static int s_scale; + /* see profil(2) where this is describe (incorrectly) */ +#define SCALE_1_TO_1 0x10000L + +#define MSG "No space for profiling buffer(s)\n" + +extern int errno; + +monstartup(lowpc, highpc) + char *lowpc; + char *highpc; +{ + int monsize; + char *buffer; + register int o; + + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + lowpc = (char *) + ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_lowpc = lowpc; + highpc = (char *) + ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_highpc = highpc; + s_textsize = highpc - lowpc; + monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr); + buffer = (char *) sbrk( monsize ); + if ( buffer == (char *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + return; + } + froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION ); + if ( froms == (unsigned short *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + return; + } + tolimit = s_textsize * ARCDENSITY / 100; + if ( tolimit < MINARCS ) { + tolimit = MINARCS; + } else if ( tolimit > 65534 ) { + tolimit = 65534; + } + tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) ); + if ( tos == (struct tostruct *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + tos = 0; + return; + } +/* minbrk = (char *) sbrk(0);*/ + tos[0].link = 0; + sbuf = buffer; + ssiz = monsize; + ( (struct phdr *) buffer ) -> lpc = lowpc; + ( (struct phdr *) buffer ) -> hpc = highpc; + ( (struct phdr *) buffer ) -> ncnt = ssiz; + monsize -= sizeof(struct phdr); + if ( monsize <= 0 ) + return; + o = highpc - lowpc; + if( monsize < o ) +#ifndef hp300 + s_scale = ( (float) monsize / o ) * SCALE_1_TO_1; +#else /* avoid floating point */ + { + int quot = o / monsize; + + if (quot >= 0x10000) + s_scale = 1; + else if (quot >= 0x100) + s_scale = 0x10000 / quot; + else if (o >= 0x800000) + s_scale = 0x1000000 / (o / (monsize >> 8)); + else + s_scale = 0x1000000 / ((o << 8) / monsize); + } +#endif + else + s_scale = SCALE_1_TO_1; + moncontrol(1); +} + +_mcleanup() +{ + int fd; + int fromindex; + int endfrom; + char *frompc; + int toindex; + struct rawarc rawarc; + + moncontrol(0); + fd = creat( "gmon.out" , 0666 ); + if ( fd < 0 ) { + perror( "mcount: gmon.out" ); + return; + } +# ifdef DEBUG + fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); +# endif DEBUG + + write( fd , sbuf , ssiz ); + endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); + for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { + if ( froms[fromindex] == 0 ) { + continue; + } + frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); + for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { +# ifdef DEBUG + fprintf( stderr , + "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , + frompc , tos[toindex].selfpc , tos[toindex].count ); +# endif DEBUG + rawarc.raw_frompc = (unsigned long) frompc; + rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; + rawarc.raw_count = tos[toindex].count; + write( fd , &rawarc , sizeof rawarc ); + } + } + close( fd ); +} + +/* Solaris 2 libraries use _mcount. */ +asm(".globl _mcount; _mcount: jmp internal_mcount"); +/* This is for compatibility with old versions of gcc which used mcount. */ +asm(".globl mcount; mcount: jmp internal_mcount"); + +internal_mcount() +{ + register char *selfpc; + register unsigned short *frompcindex; + register struct tostruct *top; + register struct tostruct *prevtop; + register long toindex; + + /* + * find the return address for mcount, + * and the return address for mcount's caller. + */ + + /* selfpc = pc pushed by mcount call. + This identifies the function that was just entered. */ + selfpc = (void *) __builtin_return_address (0); + /* frompcindex = pc in preceding frame. + This identifies the caller of the function just entered. */ + frompcindex = (void *) __builtin_return_address (1); + + /* + * check that we are profiling + * and that we aren't recursively invoked. + */ + if (profiling) { + goto out; + } + profiling++; + /* + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); + if ((unsigned long)frompcindex > s_textsize) { + goto done; + } + frompcindex = + &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; + toindex = *frompcindex; + if (toindex == 0) { + /* + * first time traversing this arc + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + *frompcindex = toindex; + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &tos[toindex]; + if (top->selfpc == selfpc) { + /* + * arc at front of chain; usual case. + */ + top->count++; + goto done; + } + /* + * have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (; /* goto done */; ) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &tos[top->link]; + if (top->selfpc == selfpc) { + /* + * there it is. + * increment its count + * move it to the head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + + } +done: + profiling--; + /* and fall through */ +out: + return; /* normal return restores saved registers */ + +overflow: + profiling++; /* halt further profiling */ +# define TOLIMIT "mcount: tos overflow\n" + write(2, TOLIMIT, sizeof(TOLIMIT)); + goto out; +} + +/* + * Control profiling + * profiling is what mcount checks to see if + * all the data structures are ready. + */ +moncontrol(mode) + int mode; +{ + if (mode) + { + /* start */ + profil((unsigned short *)(sbuf + sizeof(struct phdr)), + ssiz - sizeof(struct phdr), + (int)s_lowpc, s_scale); + + profiling = 0; + } else { + /* stop */ + profil((unsigned short *)0, 0, 0, 0); + profiling = 3; + } +} diff --git a/gnu/usr.bin/gcc/config/i386/go32-rtems.h b/gnu/usr.bin/gcc/config/i386/go32-rtems.h new file mode 100644 index 00000000000..282465b249b --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/go32-rtems.h @@ -0,0 +1,32 @@ +/* Configuration for an i386 running RTEMS on top of MS-DOS with + djgpp/go32 v1.x. + + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "i386/go32.h" + +/* Specify predefined symbols in preprocessor. */ + +#ifdef CPP_PREDEFINES +#undef CPP_PREDEFINES +#endif +#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DMSDOS -Drtems -D__rtems__ \ + -Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386) -Asystem(rtems)" diff --git a/gnu/usr.bin/gcc/config/i386/mingw32.h b/gnu/usr.bin/gcc/config/i386/mingw32.h new file mode 100644 index 00000000000..984a3692c30 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/mingw32.h @@ -0,0 +1,93 @@ +/* Operating system specific defines to be used when targeting GCC for + hosting on Windows32, using GNU tools and the Windows32 API Library, + as distinct from winnt.h, which is used to build GCC for use with a + windows style library and tool set and uses the Microsoft tools. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Most of this is the same as for Cygwin32, except for changing some + specs. */ + +#include "i386/cygwin32.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \ + -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\ + -D__stdcall=__attribute__((__stdcall__)) \ + -D__cdecl=__attribute__((__cdecl__)) \ + -Asystem(winnt) -Acpu(i386) -Amachine(i386)" + +/* Specific a different directory for the standard include files. */ +#undef STANDARD_INCLUDE_DIR +#define STANDARD_INCLUDE_DIR "/usr/mingw32/include" + +#define STANDARD_INCLUDE_COMPONENT "MINGW32" + +/* For Windows applications, include more libraries, but always include + kernel32. */ +#undef LIB_SPEC +#define LIB_SPEC \ +"%{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32 -ladvapi32 -lshell32" + +/* Include in the mingw32 libraries with libgcc */ +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lcrtdll" + +/* Specify a different entry point when linking a DLL */ +#undef LINK_SPEC +#define LINK_SPEC \ +"%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12}" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{mdll:dllcrt1%O%s} %{!mdll:crt1%O%s}" + +#define MATH_LIBRARY "-lcrtdll" + +/* Output STRING, a string representing a filename, to FILE. We canonicalize + it to be in MS-DOS format. */ +#define OUTPUT_QUOTED_STRING(FILE, STRING) \ +do { \ + char c; \ + \ + putc ('\"', asm_file); \ + if (STRING[1] == ':' \ + && (STRING[2] == '/' || STRING[2] == '\\')) \ + { \ + putc ('/', asm_file); \ + putc ('/', asm_file); \ + putc (*string, asm_file); \ + string += 2; \ + } \ + \ + while ((c = *string++) != 0) \ + { \ + if (c == '\\') \ + c = '/'; \ + \ + if (c == '\"') \ + putc ('\\', asm_file); \ + putc (c, asm_file); \ + } \ + \ + putc ('\"', asm_file); \ +} while (0) + +/* Dwarf2 exception information does not work on this system for some + unknown reason, so turn it off. */ +#undef INCOMING_RETURN_ADDR_RTX diff --git a/gnu/usr.bin/gcc/config/i386/moss.h b/gnu/usr.bin/gcc/config/i386/moss.h new file mode 100644 index 00000000000..dadf3d86af2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/moss.h @@ -0,0 +1,34 @@ +/* Definitions for Intel 386 running MOSS + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Bryan Ford <baford@cs.utah.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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* I believe in reuse... */ +#include "i386/linux.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Di386 -Dmoss -Asystem(posix) -Acpu(i386) -Amachine(i386)" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtn.o%s" + +#undef LINK_SPEC + diff --git a/gnu/usr.bin/gcc/config/i386/ptx4-i.h b/gnu/usr.bin/gcc/config/i386/ptx4-i.h new file mode 100644 index 00000000000..fdf21a471f1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/ptx4-i.h @@ -0,0 +1,247 @@ +/* Target definitions for GNU compiler for Intel 80386 running Dynix/ptx v4 + Copyright (C) 1996 Free Software Foundation, Inc. + + Modified from sysv4.h + Originally written by Ron Guilmette (rfg@netcom.com). + Modified by Tim Wright (timw@sequent.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. */ + +#include "i386/i386.h" /* Base i386 target machine definitions */ +#include "i386/att.h" /* Use the i386 AT&T assembler syntax */ +#include "ptx4.h" /* Rest of definitions (non architecture dependent) */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 Sequent Dynix/ptx Version 4)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ + +#undef RETURN_IN_MEMORY +#define RETURN_IN_MEMORY(TYPE) \ + (TYPE_MODE (TYPE) == BLKmode) + +/* Define which macros to predefine. _SEQUENT_ is our extension. */ +/* This used to define X86, but james@bigtex.cactus.org says that + is supposed to be defined optionally by user programs--not by default. */ +#define CPP_PREDEFINES \ + "-Di386 -Dunix -D_SEQUENT_ -Asystem(unix) -Asystem(ptx4) -Acpu(i386) -Amachine(i386)" + +/* This is how to output assembly code to define a `float' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ +do { long value; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \ + else \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \ + } while (0) + +/* This is how to output assembly code to define a `double' constant. + We always have to use a pair of .long pseudo-ops to do this because + the native SVR4 ELF assembler is buggy and it generates incorrect + values when we try to use the the .double pseudo-op instead. */ + +#undef ASM_OUTPUT_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ +do { long value[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + } \ + } while (0) + + +#undef ASM_OUTPUT_LONG_DOUBLE +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ +do { long value[3]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[2]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[2]); \ + } \ + } while (0) + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* The routine used to output sequences of byte values. 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. Note that if we find subparts of the + character sequence which end with NUL (and which are shorter than + STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */ + +#undef ASM_OUTPUT_ASCII +#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ + do \ + { \ + register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ + register unsigned char *limit = _ascii_bytes + (LENGTH); \ + register unsigned bytes_in_chunk = 0; \ + for (; _ascii_bytes < limit; _ascii_bytes++) \ + { \ + register unsigned char *p; \ + if (bytes_in_chunk >= 64) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ + continue; \ + if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ + { \ + if (bytes_in_chunk > 0) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ + _ascii_bytes = p; \ + } \ + else \ + { \ + if (bytes_in_chunk == 0) \ + fprintf ((FILE), "\t.byte\t"); \ + else \ + fputc (',', (FILE)); \ + fprintf ((FILE), "0x%02x", *_ascii_bytes); \ + bytes_in_chunk += 5; \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\n"); \ + } \ + while (0) + +/* 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, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Indicate that jump tables go in the text section. This is + necessary when compiling PIC code. */ + +#define JUMP_TABLES_IN_TEXT_SECTION diff --git a/gnu/usr.bin/gcc/config/i386/rtems.h b/gnu/usr.bin/gcc/config/i386/rtems.h new file mode 100644 index 00000000000..b31ceb9f799 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/rtems.h @@ -0,0 +1,28 @@ +/* Definitions for rtems targeting an Intel i386 using coff. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "i386/i386-coff.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(i386) -Amachine(i386)" diff --git a/gnu/usr.bin/gcc/config/i386/sco5.h b/gnu/usr.bin/gcc/config/i386/sco5.h new file mode 100644 index 00000000000..5306000e2a0 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/sco5.h @@ -0,0 +1,967 @@ +/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5. + Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Kean Johnston (hug@netcom.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. */ + +#include "i386/i386.h" /* Base i386 target definitions */ +#include "i386/att.h" /* Use AT&T i386 assembler syntax */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386, SCO OpenServer 5 Syntax)"); + +#undef LPREFIX +#define LPREFIX ".L" + +#undef ALIGN_ASM_OP +#define ALIGN_ASM_OP "\t.align" + +#undef ASCII_DATA_ASM_OP +#define ASCII_DATA_ASM_OP "\t.ascii" + +#undef ASM_BYTE_OP +#define ASM_BYTE_OP "\t.byte" + +#undef IDENT_ASM_OP +#define IDENT_ASM_OP "\t.ident" + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.comm" + +#undef SET_ASM_OP +#define SET_ASM_OP "\t.set" + +#undef LOCAL_ASM_OP +#define LOCAL_ASM_OP "\t.local" + +#undef INT_ASM_OP +#define INT_ASM_OP "\t.long" + +#undef ASM_SHORT +#define ASM_SHORT "\t.value" + +#undef ASM_LONG +#define ASM_LONG "\t.long" + +#undef ASM_DOUBLE +#define ASM_DOUBLE "\t.double" + +#undef TYPE_ASM_OP +#define TYPE_ASM_OP "\t.type" + +#undef SIZE_ASM_OP +#define SIZE_ASM_OP "\t.size" + +#undef STRING_ASM_OP +#define STRING_ASM_OP "\t.string" + +#undef SKIP_ASM_OP +#define SKIP_ASM_OP "\t.zero" + +#undef GLOBAL_ASM_OP +#define GLOBAL_ASM_OP "\t.globl" + +#undef EH_FRAME_SECTION_ASM_OP +#define EH_FRAME_SECTION_ASM_OP_COFF "\t.section\t.ehfram, \"x\"" +#define EH_FRAME_SECTION_ASM_OP_ELF "\t.section\t.eh_frame, \"aw\"" +#define EH_FRAME_SECTION_ASM_OP \ + ((TARGET_ELF) ? EH_FRAME_SECTION_ASM_OP_ELF : EH_FRAME_SECTION_ASM_OP_COFF) + +/* Avoid problems (long section names, forward assembler refs) with DWARF + exception unwinding when we're generating COFF */ +#define DWARF2_UNWIND_INFO ((TARGET_ELF) ? 1 : 0 ) + +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP_COFF "\t.section\t.rodata, \"x\"" +#define CONST_SECTION_ASM_OP_ELF "\t.section\t.rodata" +#define CONST_SECTION_ASM_OP \ + ((TARGET_ELF) ? CONST_SECTION_ASM_OP_ELF : CONST_SECTION_ASM_OP_COFF) + +#undef USE_CONST_SECTION +#define USE_CONST_SECTION_ELF 1 +#define USE_CONST_SECTION_COFF 0 +#define USE_CONST_SECTION \ + ((TARGET_ELF) ? USE_CONST_SECTION_ELF : USE_CONST_SECTION_COFF) + +#undef INIT_SECTION_ASM_OP +#define INIT_SECTION_ASM_OP_ELF "\t.section\t.init" +#define INIT_SECTION_ASM_OP_COFF "\t.section\t.init ,\"x\"" +#define INIT_SECTION_ASM_OP \ + ((TARGET_ELF) ? INIT_SECTION_ASM_OP_ELF : INIT_SECTION_ASM_OP_COFF) + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP_ELF "\t.section\t.ctors,\"aw\"" +#define CTORS_SECTION_ASM_OP_COFF INIT_SECTION_ASM_OP_COFF +#define CTORS_SECTION_ASM_OP \ + ((TARGET_ELF) ? CTORS_SECTION_ASM_OP_ELF : CTORS_SECTION_ASM_OP_COFF) + +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP_ELF "\t.section\t.dtors, \"aw\"" +#define DTORS_SECTION_ASM_OP_COFF FINI_SECTION_ASM_OP_COFF +#define DTORS_SECTION_ASM_OP \ + ((TARGET_ELF) ? DTORS_SECTION_ASM_OP_ELF : DTORS_SECTION_ASM_OP_COFF) + +#undef FINI_SECTION_ASM_OP +#define FINI_SECTION_ASM_OP_ELF "\t.section\t.fini" +#define FINI_SECTION_ASM_OP_COFF "\t.section\t.fini, \"x\"" +#define FINI_SECTION_ASM_OP \ + ((TARGET_ELF) ? FINI_SECTION_ASM_OP_ELF : FINI_SECTION_ASM_OP_COFF) + +#undef BSS_SECTION_ASM_OP +#define BSS_SECTION_ASM_OP "\t.data" + +#undef TEXT_SECTION_ASM_OP +#define TEXT_SECTION_ASM_OP "\t.text" + +#undef DATA_SECTION_ASM_OP +#define DATA_SECTION_ASM_OP "\t.data" + +#undef TYPE_OPERAND_FMT +#define TYPE_OPERAND_FMT "@%s" + +#undef APPLY_RESULT_SIZE +#define APPLY_RESULT_SIZE \ +(TARGET_ELF) ? size : 116 + +#ifndef ASM_DECLARE_RESULT +#define ASM_DECLARE_RESULT(FILE, RESULT) +#endif + +#define SCO_DEFAULT_ASM_COFF(FILE,NAME) \ +do { \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + } while (0) + +#undef ASM_DECLARE_FUNCTION_NAME +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ + do { \ + if (TARGET_ELF) { \ + fprintf (FILE, "%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); \ + } else \ + SCO_DEFAULT_ASM_COFF(FILE, NAME); \ +} while (0) + +#undef ASM_DECLARE_FUNCTION_SIZE +#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ + do { \ + if (TARGET_ELF) { if (!flag_inhibit_size_directive) \ + { \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, (FNAME)); \ + fprintf (FILE, ",.-"); \ + assemble_name (FILE, (FNAME)); \ + putc ('\n', FILE); \ + } } \ + } while (0) + +#undef ASM_DECLARE_OBJECT_NAME +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + if (TARGET_ELF) { \ + fprintf (FILE, "%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ + putc ('\n', FILE); \ + size_directive_output = 0; \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } else \ + SCO_DEFAULT_ASM_COFF(FILE, NAME); \ + } while (0) + +#undef ASM_FILE_START_1 +#define ASM_FILE_START_1(FILE) + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +do { \ + output_file_directive((FILE),main_input_filename); \ + fprintf ((FILE), "\t.version\t\"01.01\"\n"); \ +} while (0) + +#undef ASM_FILE_END +#define ASM_FILE_END(FILE) \ +do { \ + fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ +} while (0) + +#undef ASM_FINISH_DECLARE_OBJECT +#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ +do { \ + if (TARGET_ELF) { \ + char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ + && ! AT_END && TOP_LEVEL \ + && DECL_INITIAL (DECL) == error_mark_node \ + && !size_directive_output) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, name); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + } \ +} while (0) + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ +do { \ + if (TARGET_ELF) \ + sprintf (LABEL, "*.%s%d", (PREFIX), (NUM)); \ + else \ + sprintf (LABEL, ".%s%d", (PREFIX), (NUM)); \ +} while (0) + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +do { \ + if (TARGET_ELF) \ + fprintf (FILE, "%s _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", ASM_LONG, LPREFIX, VALUE); \ + else \ + fprintf (FILE, "\t.word %s%d-%s%d\n", LPREFIX,VALUE,LPREFIX,REL); \ +} while (0) + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + if (TARGET_ELF) \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ + else \ + fprintf ((FILE), ",%u\n", (SIZE)); \ +} while (0) + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + if (TARGET_ELF) { \ + fprintf ((FILE), "%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ + } else { \ + int align = exact_log2 (ALIGN); \ + if (align > 2) align = 2; \ + if (TARGET_SVR3_SHLIB) \ + data_section (); \ + else \ + bss_section (); \ + ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \ + fprintf ((FILE), "%s\t", "\t.lcomm"); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u\n", (SIZE)); \ + } \ +} while (0) + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ +asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +#undef ESCAPES +#define ESCAPES \ +"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" + +#undef STRING_LIMIT +#define STRING_LIMIT ((unsigned) 256) + +#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), "%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) + + +#undef ASM_OUTPUT_ASCII +#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ +do { \ + register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ + register unsigned char *limit = _ascii_bytes + (LENGTH); \ + register unsigned bytes_in_chunk = 0; \ + for (; _ascii_bytes < limit; _ascii_bytes++) \ + { \ + register unsigned char *p; \ + if (bytes_in_chunk >= 64) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ + continue; \ + if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ + { \ + if (bytes_in_chunk > 0) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ + _ascii_bytes = p; \ + } \ + else \ + { \ + if (bytes_in_chunk == 0) \ + fprintf ((FILE), "%s\t", ASM_BYTE_OP); \ + else \ + fputc (',', (FILE)); \ + fprintf ((FILE), "0x%02x", *_ascii_bytes); \ + bytes_in_chunk += 5; \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\n"); \ +} while (0) + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (TARGET_ELF) { \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ + } else \ + readonly_data_section(); \ +} + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ +do { \ + if (TARGET_ELF) \ + ASM_OUTPUT_ALIGN ((FILE), 2); \ + ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); \ +} while (0) + + +#undef ASM_OUTPUT_CONSTRUCTOR +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ +do { \ + if (TARGET_ELF) { \ + ctors_section (); \ + fprintf (FILE, "%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } else { \ + init_section (); \ + fprintf (FILE, "\tpushl $"); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); } \ + } while (0) + +#undef ASM_OUTPUT_DESTRUCTOR +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ +do { \ + if (TARGET_ELF) { \ + dtors_section (); \ + fprintf (FILE, "%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } else { \ + fini_section (); \ + fprintf (FILE, "%s\t ", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); } \ + } while (0) + + +#undef ASM_OUTPUT_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ +do { \ + long value[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \ + if (TARGET_ELF) { \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + } \ + } else { \ + if (sizeof (int) == sizeof (long)) \ + fprintf (FILE, "%s 0x%x,0x%x\n", ASM_LONG, value[0], value[1]); \ + else \ + fprintf (FILE, "%s 0x%lx,0x%lx\n", ASM_LONG,value[0],value[1]);} \ +} while (0) + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ +do { \ + long value; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \ + else \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \ +} while (0) + +#undef ASM_OUTPUT_LONG_DOUBLE +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ +do { \ + long l[3]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), l); \ + if (TARGET_ELF) { \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, l[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, l[1]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, l[2]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, l[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, l[1]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, l[2]); \ + } \ + } else { \ + if (sizeof (int) == sizeof (long)) \ + fprintf (FILE, "%s 0x%x,0x%x,0x%x\n", ASM_LONG, l[0], l[1], l[2]); \ + else \ + fprintf (FILE, "%s 0x%lx,0x%lx,0x%lx\n", ASM_LONG,l[0],l[1],l[2]);} \ +} while (0) + +#undef ASM_OUTPUT_IDENT +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +#undef ASM_GLOBALIZE_LABEL +#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + (fprintf ((FILE), "%s ", GLOBAL_ASM_OP), assemble_name (FILE, NAME), fputs ("\n", FILE)) + +#undef ASM_OUTPUT_EXTERNAL_LIBCALL +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + if (TARGET_ELF) ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM) + +/* The prefix to add to user-visible assembler symbols. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +#undef ASM_OUTPUT_SECTION_NAME +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ +do { \ + char *snam = NAME ; \ + if (strcmp(NAME, ".gcc_except_table") == 0) snam = ".gccexc" ; \ + if (TARGET_ELF) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw"); \ + else \ + fprintf (FILE, ".section\t%s,\"%s\"\n", snam, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "x" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "w"); \ +} while (0) + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ +do { \ + if (TARGET_ELF) \ + fprintf (FILE, "%s\t%u\n", SKIP_ASM_OP, (SIZE)); \ + else \ + fprintf ((FILE), "%s\t.,.+%u\n", SET_ASM_OP, (SIZE)); \ +} while (0) + + +#undef CTOR_LIST_BEGIN +#define CTOR_LIST_BEGIN \ +do { \ + asm (CTORS_SECTION_ASM_OP); \ + if (TARGET_ELF) \ + STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) }; \ + else \ + asm ("pushl $0"); \ +} while (0) + +#undef CTOR_LIST_END +#define CTOR_LIST_END \ +do { \ + if (TARGET_ELF) { \ + asm (CTORS_SECTION_ASM_OP); \ + STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (0) }; \ + } else { \ + CTOR_LIST_BEGIN; \ + } \ +} while (0) + +#undef DBX_BLOCKS_FUNCTION_RELATIVE +#define DBX_BLOCKS_FUNCTION_RELATIVE 1 + +#undef DBX_FUNCTION_FIRST +#define DBX_FUNCTION_FIRST 1 + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((TARGET_ELF) ? \ + ((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) \ + : \ + ((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)) + +#undef DWARF_DEBUGGING_INFO +#undef SDB_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO +#undef PREFERRED_DEBUGGING_TYPE + +#define DWARF_DEBUGGING_INFO 1 +#define SDB_DEBUGGING_INFO 1 +#define DBX_DEBUGGING_INFO 1 +#define PREFERRED_DEBUGGING_TYPE \ + ((TARGET_ELF) ? DWARF_DEBUG: SDB_DEBUG) + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + INIT_SECTION_FUNCTION \ + FINI_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#undef CONST_SECTION_FUNCTION +#define CONST_SECTION_FUNCTION \ +void \ +const_section () \ +{ \ + extern void text_section(); \ + if (!USE_CONST_SECTION) \ + text_section(); \ + else if (in_section != in_const) \ + { \ + fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ + in_section = in_const; \ + } \ +} + +#undef FINI_SECTION_FUNCTION +#define FINI_SECTION_FUNCTION \ +void \ +fini_section () \ +{ \ + if ((!TARGET_ELF) && in_section != in_fini) \ + { \ + fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \ + in_section = in_fini; \ + } \ +} + +#undef INIT_SECTION_FUNCTION +#define INIT_SECTION_FUNCTION \ +void \ +init_section () \ +{ \ + if ((!TARGET_ELF) && in_section != in_init) \ + { \ + fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \ + in_section = in_init; \ + } \ +} + +#undef CTORS_SECTION_FUNCTION +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#undef DTORS_SECTION_FUNCTION +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +#undef FRAME_POINTER_REQUIRED +#define FRAME_POINTER_REQUIRED \ + ((TARGET_ELF) ? 0 : \ + (current_function_calls_setjmp || current_function_calls_longjmp)) + +#undef JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION 1 + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX \ + ((TARGET_ELF) ? "" : ".") + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX +#define MD_EXEC_PREFIX "/usr/ccs/bin/" +#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" + +#undef NON_SAVING_SETJMP +#define NON_SAVING_SETJMP \ + ((TARGET_ELF) ? 0 : \ + (current_function_calls_setjmp && current_function_calls_longjmp)) + +#undef NO_IMPLICIT_EXTERN_C +#define NO_IMPLICIT_EXTERN_C 1 + +/* JKJ FIXME - examine the ramifications of RETURN_IN_MEMORY and + RETURN_POPS_ARGS */ + +#undef RETURN_POPS_ARGS +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ + ((TARGET_ELF) ? \ + (i386_return_pops_args (FUNDECL, FUNTYPE, SIZE)) : \ + (((FUNDECL) && (TREE_CODE (FUNDECL) == IDENTIFIER_NODE)) ? 0 \ + : (TARGET_RTD \ + && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ + == void_type_node))) ? (SIZE) \ + : 0)) + +#undef SELECT_SECTION +#define SELECT_SECTION(DECL,RELOC) \ +{ \ + if (TREE_CODE (DECL) == STRING_CST) \ + { \ + if (! flag_writable_strings) \ + const_section (); \ + else \ + data_section (); \ + } \ + else if (TREE_CODE (DECL) == VAR_DECL) \ + { \ + if ((TARGET_ELF && flag_pic && RELOC) \ + || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ + || !DECL_INITIAL (DECL) \ + || (DECL_INITIAL (DECL) != error_mark_node \ + && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else \ + const_section (); \ +} + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ + || (CHAR) == 'h' \ + || (CHAR) == 'R' \ + || (CHAR) == 'Y' \ + || (CHAR) == 'z') + +#undef WORD_SWITCH_TAKES_ARG +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + && strcmp (STR, "Tdata") && strcmp (STR, "Ttext") \ + && strcmp (STR, "Tbss")) + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT 0301 + +#undef HANDLE_SYSV_PRAGMA +#define HANDLE_SYSV_PRAGMA 1 + +#undef SCCS_DIRECTIVE +#define SCCS_DIRECTIVE 1 + +/* + * Define sizes and types + */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 96 +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "long int" +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* + * New for multilib support. Set the default switches for multilib, + * which is -melf. + */ +#define MULTILIB_DEFAULTS { "melf" } + + +/* Please note that these specs may look messy but they are required in + order to emulate the SCO Development system as closely as possible. + With SCO Open Server 5.0, you now get the linker and assembler free, + so that is what these specs are targeted for. These utilities are + very argument sensitive: a space in the wrong place breaks everything. + So RMS, please forgive this mess. It works. + + Parameters which can be passed to gcc, and their SCO equivalents: + GCC Parameter SCO Equivalent + -ansi -a ansi + -posix -a posix + -Xpg4 -a xpg4 + -Xpg4plus -a xpg4plus + -Xods30 -a ods30 + + As with SCO, the default is XPG4 plus mode. SCO also allows you to + specify a C dialect with -Xt, -Xa, -Xc, -Xk and -Xm. These are passed + on to the assembler and linker in the same way that the SCO compiler + does. + + SCO also allows you to compile, link and generate either ELF or COFF + binaries. With gcc, unlike the SCO compiler, the default is ELF. + Specify -mcoff to gcc to produce elf binaries. -fpic will get the + assembler and linker to produce PIC code. +*/ + +/* Set up assembler flags for PIC and ELF compilations */ +#undef ASM_SPEC +#define ASM_SPEC \ + "-b %{!mcoff:elf}%{mcoff:coff \ + %{static:%e-static not valid with -mcoff} \ + %{shared:%e-shared not valid with -mcoff} \ + %{symbolic:%e-symbolic not valid with -mcoff}} \ + %{Ym,*} %{Yd,*} %{Wa,*:%*} \ + %{!mcoff:-E%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},ELF %{Qn:} %{!Qy:-Qn}}" + +/* Use crt1.o as a startup file and crtn.o as a closing file. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared:\ + %{!symbolic: \ + %{pg:gcrt.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}} \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional: \ + %{Xa:values-Xa.o%s} \ + %{!Xa:%{Xc:values-Xc.o%s} \ + %{!Xc:%{Xk:values-Xk.o%s} \ + %{!Xk:%{Xt:values-Xt.o%s} \ + %{!Xt:values-Xa.o%s}}}}}} \ + %{mcoff:crtbeginS.o%s} %{!mcoff:crtbegin.o%s}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!mcoff:crtend.o%s} \ + %{mcoff:crtendS.o%s} \ + %{pg:gcrtn.o%s}%{!pg:crtn.o%s}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-Asystem(svr3)" + +/* You are in a maze of GCC specs ... all alike */ + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] \ + %{fpic:%{mcoff:%e-fpic is not valid with -mcoff}} \ + %{fPIC:%{mcoff:%e-fPIC is not valid with -mcoff}} \ + -D__i386 -D__unix -D_SCO_DS=1 -D_M_I386 -D_M_XENIX -D_M_UNIX \ + %{!Xods30:-D_STRICT_NAMES} \ + %{!ansi:%{!posix:%{!Xods30:-D_SCO_XPG_VERS=4}}} \ + %{ansi:-isystem include/ansi%s -isystem /usr/include/ansi -D_STRICT_ANSI} \ + %{!ansi: \ + %{posix:-isystem include/posix%s -isystem /usr/include/posix \ + -D_POSIX_C_SOURCE=2 -D_POSIX_SOURCE=1} \ + %{!posix:%{Xpg4:-isystem include/xpg4%s -isystem /usr/include/xpg4 \ + -D_XOPEN_SOURCE=1} \ + %{!Xpg4:-D_M_I86 -D_M_I86SM -D_M_INTERNAT -D_M_SDATA -D_M_STEXT \ + -D_M_BITFIELDS -D_M_SYS5 -D_M_SYSV -D_M_SYSIII \ + -D_M_WORDSWAP -Dunix -DM_I386 -DM_UNIX -DM_XENIX \ + %{Xods30:-isystem include/ods_30_compat%s \ + -isystem /usr/include/ods_30_compat \ + -D_SCO_ODS_30 -DM_I86 -DM_I86SM -DM_SDATA -DM_STEXT \ + -DM_BITFIELDS -DM_SYS5 -DM_SYSV -DM_INTERNAT -DM_SYSIII \ + -DM_WORDSWAP}}}} \ + %{scointl:-DM_INTERNAT -D_M_INTERNAT} \ + %{traditional:-D_KR -D_SVID -D_NO_PROTOTYPE} \ + %{!mcoff:-D_SCO_ELF} \ + %{mcoff:-D_M_COFF -D_SCO_COFF} \ + %{!mcoff:%{fpic:-D__PIC__ -D__pic__} \ + %{fPIC:%{!fpic:-D__PIC__ -D__pic__}}} \ + %{Xa:-D_SCO_C_DIALECT=1} \ + %{!Xa:%{Xc:-D_SCO_C_DIALECT=3} \ + %{!Xc:%{Xk:-D_SCO_C_DIALECT=4} \ + %{!Xk:%{Xt:-D_SCO_C_DIALECT=2} \ + %{!Xt:-D_SCO_C_DIALECT=1}}}} \ + %{traditional:-traditional -D_KR -D_NO_PROTOTYPE}" + +#undef LINK_SPEC +#define LINK_SPEC \ + "-b %{!mcoff:elf}%{mcoff:coff \ + %{static:%e-static not valid with -mcoff} \ + %{shared:%e-shared not valid with -mcoff} \ + %{symbolic:%e-symbolic not valid with -mcoff} \ + %{fpic:%e-fpic not valid with -mcoff} \ + %{fPIC:%e-fPIC not valid with -mcoff}} \ + -R%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},%{mcoff:COFF}%{!mcoff:ELF} \ + %{Wl,*%*} %{YP,*} %{YL,*} %{YU,*} \ + %{!YP,*:%{p:-YP,/usr/ccs/libp:/lib/libp:/usr/lib/libp:/usr/ccs/lib:/lib:/usr/lib} \ + %{!p:-YP,/usr/ccs/lib:/lib:/usr/lib}} \ + %{h*} %{static:-dn -Bstatic} %{shared:-G -dy %{!z*:-z text}} \ + %{symbolic:-Bsymbolic -G -dy %{!z*:-z text}} %{z*} %{R*} %{Y*} \ + %{G:-G} %{!mcoff:%{Qn:} %{!Qy:-Qn}}" + +/* The SCO COFF linker gets confused on the difference between "-ofoo" + and "-o foo". So we just always force a single space. */ + +#define SWITCHES_NEED_SPACES "o" + +/* Library spec. If we are not building a shared library, provide the + standard libraries, as per the SCO compiler. */ + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{shared:pic/libgcc.a%s}%{!shared:%{!symbolic:-lcrypt -lgen -lc}}" + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC \ + "%{!shared:-lgcc}" + +#define MASK_COFF 010000000000 /* Mask for elf generation */ +#define TARGET_COFF (target_flags & MASK_COFF) +#define TARGET_ELF (!(target_flags & MASK_COFF)) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "coff", MASK_COFF }, \ + { "elf", -MASK_COFF }, + +#define NO_DOLLAR_IN_LABEL + +/* +Here comes some major hackery to get the crt stuff to compile properly. +Since we can (and do) compile for both COFF and ELF environments, we +set things up accordingly, based on the pre-processor defines for ELF +and COFF. This is insane, but then I guess having one compiler with a +single back-end supporting two vastly different file format types is +a little insane too. But it is not impossible and we get a useful +compiler at the end of the day. Onward we go ... +*/ + +#if defined(CRT_BEGIN) || defined(CRT_END) || defined(IN_LIBGCC2) +# undef OBJECT_FORMAT_ELF +# undef HAVE_ATEXIT +# undef INIT_SECTION_ASM_OP +# undef FINI_SECTION_ASM_OP +# undef CTORS_SECTION_ASM_OP +# undef DTORS_SECTION_ASM_OP +# undef EH_FRAME_SECTION_ASM_OP +# undef CTOR_LIST_BEGIN +# undef CTOR_LIST_END +# undef DO_GLOBAL_CTORS_BODY + +# if defined (_SCO_ELF) +# define OBJECT_FORMAT_ELF +# define HAVE_ATEXIT +# define INIT_SECTION_ASM_OP INIT_SECTION_ASM_OP_ELF +# define FINI_SECTION_ASM_OP FINI_SECTION_ASM_OP_ELF +# define DTORS_SECTION_ASM_OP DTORS_SECTION_ASM_OP_ELF +# define CTORS_SECTION_ASM_OP CTORS_SECTION_ASM_OP_ELF +# define EH_FRAME_SECTION_ASM_OP EH_FRAME_SECTION_ASM_OP_ELF +# else /* ! _SCO_ELF */ +# define INIT_SECTION_ASM_OP INIT_SECTION_ASM_OP_COFF +# define FINI_SECTION_ASM_OP FINI_SECTION_ASM_OP_COFF +# define DTORS_SECTION_ASM_OP DTORS_SECTION_ASM_OP_COFF +# define CTORS_SECTION_ASM_OP CTORS_SECTION_ASM_OP_COFF +# define EH_FRAME_SECTION_ASM_OP "" +# define CTOR_LIST_BEGIN asm (INIT_SECTION_ASM_OP); asm ("pushl $0") +# define CTOR_LIST_END CTOR_LIST_BEGIN +# define DO_GLOBAL_CTORS_BODY \ +do { \ + func_ptr *p, *beg = alloca(0); \ + for (p = beg; *p;) \ + (*p++) (); \ +} while (0) +# endif /* ! _SCO_ELF */ +#endif /* CRT_BEGIN !! CRT_END */ diff --git a/gnu/usr.bin/gcc/config/i386/sol2-gc1.asm b/gnu/usr.bin/gcc/config/i386/sol2-gc1.asm new file mode 100644 index 00000000000..8983a672ac2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/sol2-gc1.asm @@ -0,0 +1,160 @@ +! gcrt1.s for Solaris 2, x86 + +! Copyright (C) 1993 Free Software Foundation, Inc. +! Written By Fred Fish, Nov 1992 +! +! This file 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. +! +! In addition to the permissions in the GNU General Public License, the +! Free Software Foundation gives you unlimited permission to link the +! compiled version of this file with other programs, and to distribute +! those programs without any restriction coming from the use of this +! file. (The General Public License restrictions do apply in other +! respects; for example, they cover modification of the file, and +! distribution when not linked into another program.) +! +! This file 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 this program; 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. +! + +! This file takes control of the process from the kernel, as specified +! in section 3 of the System V Application Binary Interface, Intel386 +! Processor Supplement. It has been constructed from information obtained +! from the ABI, information obtained from single stepping existing +! Solaris executables through their startup code with gdb, and from +! information obtained by single stepping executables on other i386 SVR4 +! implementations. This file is the first thing linked into any executable. + +! This is a modified crt1.s by J.W.Hawtin <J.W.Hawtin@lboro.ac.uk> 15/8/96, +! to allow program profiling, by calling monstartup on entry and _mcleanup +! on exit + + .file "gcrt1.s" + .ident "GNU C gcrt1.s" + .weak _DYNAMIC + .text + +! Start creating the initial frame by pushing a NULL value for the return +! address of the initial frame, and mark the end of the stack frame chain +! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. +! Initialize the first stack frame pointer in %ebp (the contents of which +! are unspecified at process initialization). + + .globl _start +_start: + pushl $0x0 + pushl $0x0 + movl %esp,%ebp + +! As specified per page 3-32 of the ABI, %edx contains a function +! pointer that should be registered with atexit(), for proper +! shared object termination. Just push it onto the stack for now +! to preserve it. We want to register _cleanup() first. + + pushl %edx + +! Check to see if there is an _cleanup() function linked in, and if +! so, register it with atexit() as the last thing to be run by +! atexit(). + + movl $_mcleanup,%eax + testl %eax,%eax + je .L1 + pushl $_mcleanup + call atexit + addl $0x4,%esp +.L1: + +! Now check to see if we have an _DYNAMIC table, and if so then +! we need to register the function pointer previously in %edx, but +! now conveniently saved on the stack as the argument to pass to +! atexit(). + + movl $_DYNAMIC,%eax + testl %eax,%eax + je .L2 + call atexit +.L2: + +! Register _fini() with atexit(). We will take care of calling _init() +! directly. + + pushl $_fini + call atexit + +! Start profiling + + pushl %ebp + movl %esp,%ebp + pushl $_etext + pushl $_start + call monstartup + addl $8,%esp + popl %ebp + +! Compute the address of the environment vector on the stack and load +! it into the global variable _environ. Currently argc is at 8 off +! the frame pointer. Fetch the argument count into %eax, scale by the +! size of each arg (4 bytes) and compute the address of the environment +! vector which is 16 bytes (the two zero words we pushed, plus argc, +! plus the null word terminating the arg vector) further up the stack, +! off the frame pointer (whew!). + + movl 8(%ebp),%eax + leal 16(%ebp,%eax,4),%edx + movl %edx,_environ + +! Push the environment vector pointer, the argument vector pointer, +! and the argument count on to the stack to set up the arguments +! for _init(), _fpstart(), and main(). Note that the environment +! vector pointer and the arg count were previously loaded into +! %edx and %eax respectively. The only new value we need to compute +! is the argument vector pointer, which is at a fixed address off +! the initial frame pointer. + + pushl %edx + leal 12(%ebp),%edx + pushl %edx + pushl %eax + +! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and +! main(argc, argv, environ). + + call _init + call __fpstart + call main + +! Pop the argc, argv, and environ arguments off the stack, push the +! value returned from main(), and call exit(). + + addl $12,%esp + pushl %eax + call exit + +! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. + + pushl $0x0 + movl $0x1,%eax + lcall $7,$0 + +! If all else fails, just try a halt! + + hlt + .type _start,@function + .size _start,.-_start diff --git a/gnu/usr.bin/gcc/config/i386/sol2dbg.h b/gnu/usr.bin/gcc/config/i386/sol2dbg.h new file mode 100644 index 00000000000..9d09c8fd043 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/sol2dbg.h @@ -0,0 +1,16 @@ +/* Target definitions for GNU compiler for Intel 80386 running Solaris + with gas and gdb. + This file is added into the directory .../gcc-2.../config/i386 + Workability without "#undef DWARF_DEBUGGING_INFO" is not tested. */ + +/* Use stabs instead of DWARF debug format. */ +#ifdef PREFERRED_DEBUGGING_TYPE +#undef PREFERRED_DEBUGGING_TYPE +#endif +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "i386/sol2.h" + +#ifdef DWARF_DEBUGGING_INFO +#undef DWARF_DEBUGGING_INFO +#endif diff --git a/gnu/usr.bin/gcc/config/i386/t-cygwin32 b/gnu/usr.bin/gcc/config/i386/t-cygwin32 new file mode 100644 index 00000000000..4be2477fbc9 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-cygwin32 @@ -0,0 +1,7 @@ +LIBGCC1 = libgcc1-asm.a +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = i386/cygwin32.asm +LIB1ASMFUNCS = _chkstk + +winnt.o: $(srcdir)/config/i386/winnt.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c diff --git a/gnu/usr.bin/gcc/config/i386/t-dgux b/gnu/usr.bin/gcc/config/i386/t-dgux new file mode 100644 index 00000000000..292331f22a9 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-dgux @@ -0,0 +1,4 @@ +# +# target makefile for dgux +# +EXTRA_PARTS=crtbegin.o crtend.o diff --git a/gnu/usr.bin/gcc/config/i386/t-freebsd b/gnu/usr.bin/gcc/config/i386/t-freebsd new file mode 100644 index 00000000000..5164669d1ac --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-freebsd @@ -0,0 +1,5 @@ +# Don't run fixproto +STMP_FIXPROTO = +# Use only native include files +USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) + diff --git a/gnu/usr.bin/gcc/config/i386/t-go32 b/gnu/usr.bin/gcc/config/i386/t-go32 new file mode 100644 index 00000000000..6160b7ec945 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-go32 @@ -0,0 +1,2 @@ +LIBGCC1 = libgcc1.null +CROSS_LIBGCC1 = libgcc1.null diff --git a/gnu/usr.bin/gcc/config/i386/t-osf b/gnu/usr.bin/gcc/config/i386/t-osf new file mode 100644 index 00000000000..c996e0c9e77 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-osf @@ -0,0 +1,2 @@ +# If compiling with the osf gcc, avoid sharing code. +TCFLAGS = -pic-none diff --git a/gnu/usr.bin/gcc/config/i386/t-sco5 b/gnu/usr.bin/gcc/config/i386/t-sco5 new file mode 100644 index 00000000000..fd3d6c63b8e --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-sco5 @@ -0,0 +1,16 @@ +# The pushl in CTOR initialization interferes with frame pointer elimination. +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +CRTSTUFF_T_CFLAGS_S = -mcoff -fno-omit-frame-pointer + +# +# I am still a little unsure of the multilib architecture. The following +# 4 lines are based on advice from meissner@cygnus.com. +# +MULTILIB_OPTIONS = mcoff/fPIC +MULTILIB_DIRNAMES = coff pic +MULTILIB_EXCEPTIONS = *mcoff*/*fPIC* +MULTILIB_MATCHES = fPIC=fpic +MULTILIB_EXTRA_OPTS = + +LIBGCC=stmp-multilib +INSTALL_LIBGCC=install-multilib diff --git a/gnu/usr.bin/gcc/config/i386/x-cygwin32 b/gnu/usr.bin/gcc/config/i386/x-cygwin32 new file mode 100644 index 00000000000..5e796a0e916 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/x-cygwin32 @@ -0,0 +1,4 @@ +# Don't run fixproto +STMP_FIXPROTO = +# Don't need collect2 +USE_COLLECT2 = diff --git a/gnu/usr.bin/gcc/config/i386/x-dgux b/gnu/usr.bin/gcc/config/i386/x-dgux new file mode 100644 index 00000000000..322bfe3ae91 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/x-dgux @@ -0,0 +1,11 @@ +# +# host is ix86 running dgux +# +CC = /bin/gcc +X_CFLAGS = -O -mstandard -mlegend +BOOT_CFLAGS = -O2 -g -mstandard -mlegend $(CFLAGS) +CLIB = -lw32 +RANLIB = true +USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) +STMP_FIXPROTO = + diff --git a/gnu/usr.bin/gcc/config/i386/x-sco5 b/gnu/usr.bin/gcc/config/i386/x-sco5 new file mode 100644 index 00000000000..276d74045ed --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/x-sco5 @@ -0,0 +1,10 @@ +RANLIB = : +RANLIB_TEST = false +CC = cc +OLDCC = cc +CCLIBFLAGS = +# We avoid the ALLOCA in -lPW becuase it gives us an evil index() +ALLOCA = alloca.o + +# See all the declarations. +FIXPROTO_DEFINES = -D_XOPEN_SOURCE -D_POSIX_C_SOURCE=2 diff --git a/gnu/usr.bin/gcc/config/i386/xm-cygwin32.h b/gnu/usr.bin/gcc/config/i386/xm-cygwin32.h new file mode 100644 index 00000000000..98327f24b1d --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-cygwin32.h @@ -0,0 +1,26 @@ +/* Configuration for GNU C-compiler for hosting on Windows NT. + using a unix style C library. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define NO_STAB_H +#define EXECUTABLE_SUFFIX ".exe" + +/* Even though we support "/", allow "\" since everybody tests both. */ +#define DIR_SEPARATOR '\\' diff --git a/gnu/usr.bin/gcc/config/i386/xm-dgux.h b/gnu/usr.bin/gcc/config/i386/xm-dgux.h new file mode 100644 index 00000000000..5bdb9be0ebb --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-dgux.h @@ -0,0 +1,12 @@ + +/* Configuration for GCC for Intel i386 running DG/ux */ + +/* looks just like sysv4 for now */ + +#include "i386/xm-i386.h" +#include "xm-svr4.h" + +/* If not compiled with GNU C, use the portable alloca. */ +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif diff --git a/gnu/usr.bin/gcc/config/i386/xm-go32.h b/gnu/usr.bin/gcc/config/i386/xm-go32.h new file mode 100644 index 00000000000..d8182132ac6 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-go32.h @@ -0,0 +1,28 @@ +/* Configuration for GNU C-compiler for Intel 80386 running GO32. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define __MSDOS__ 1 + +#define NO_STAB_H + +#include "i386/xm-i386.h" + +/* Use semicolons to separate elements of a path. */ +#define PATH_SEPARATOR ';' diff --git a/gnu/usr.bin/gcc/config/i386/xm-mingw32.h b/gnu/usr.bin/gcc/config/i386/xm-mingw32.h new file mode 100644 index 00000000000..47356f568d1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-mingw32.h @@ -0,0 +1,45 @@ +/* Configuration for GNU C-compiler for hosting on Windows32. + using GNU tools and the Windows32 API Library. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define NO_STAB_H + +#ifndef USG +#define USG 1 +#endif + +#ifndef ONLY_INT_FIELD +#define ONLY_INT_FIELDS 1 +#endif + +#ifndef USE_PROTOTYPES +#define USE_PROTOTYPES 1 +#endif + +#define NO_SYS_SIGLIST 1 +#define link(a,b) -1 +#define environ _environ + +/* Even though we support "/", allow "\" since everybody tests both. */ +#define DIR_SEPARATOR '\\' +#define EXECUTABLE_SUFFIX ".exe" + +#undef PATH_SEPARATOR +#define PATH_SEPARATOR ';' diff --git a/gnu/usr.bin/gcc/config/i386/xm-sco5.h b/gnu/usr.bin/gcc/config/i386/xm-sco5.h new file mode 100644 index 00000000000..99bc53c2bc5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-sco5.h @@ -0,0 +1,18 @@ +/* Configuration for GCC for Intel i386 running SCO. */ + +#include "i386/xm-sysv3.h" + +/* Big buffers improve performance. */ + +#define IO_BUFFER_SIZE (0x8000 - 1024) +/* OpenServer provides no sys_siglist, + but does offer the same data under another name. */ +#define sys_siglist _sys_siglist +#undef SYS_SIGLIST_DECLARED +#define SYS_SIGLIST_DECLARED + +/* If not compiled with GNU C, use the portable alloca. */ +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif + diff --git a/gnu/usr.bin/gcc/config/i960/rtems.h b/gnu/usr.bin/gcc/config/i960/rtems.h new file mode 100644 index 00000000000..714706859d9 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i960/rtems.h @@ -0,0 +1,28 @@ +/* Definitions for rtems targeting an Intel i960. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "i960/i960-coff.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di960 -Di80960 -DI960 -DI80960 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(i960) -Amachine(i960)" diff --git a/gnu/usr.bin/gcc/config/libgloss.h b/gnu/usr.bin/gcc/config/libgloss.h new file mode 100644 index 00000000000..2f2ba569f4f --- /dev/null +++ b/gnu/usr.bin/gcc/config/libgloss.h @@ -0,0 +1,35 @@ +/* libgloss.h -- operating system specific defines to be used when + targeting GCC for Libgloss supported targets. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* The libgloss standard for crt0.s has the name based on the command line + option. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{pg:pgcrt0%O%s}%{!pg:%{p:pcrt0%O%s}%{!p:crt0%O%s}}}" + +/* This file used to force LINK_SPEC to be the null string, but that is not + correct. LINK_SPEC is used to pass machine specific arguments to the + linker and hence can not be redefined here. LINK_SPEC is never used to + specify startup files or libraries, so it should never conflict with + libgloss. */ + +/* Don't set the target flags, this is done by the linker script */ +#undef LIB_SPEC +#define LIB_SPEC "" diff --git a/gnu/usr.bin/gcc/config/m32r/initfini.c b/gnu/usr.bin/gcc/config/m32r/initfini.c new file mode 100644 index 00000000000..34ef5da962f --- /dev/null +++ b/gnu/usr.bin/gcc/config/m32r/initfini.c @@ -0,0 +1,169 @@ +/* .init/.fini section handling + C++ global constructor/destructor handling. + This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm. + +Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this file 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. */ + +/* Declare a pointer to void function type. */ +typedef void (*func_ptr) (void); + +#ifdef CRT_INIT + +/* NOTE: In order to be able to support SVR4 shared libraries, we arrange + to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__, + __DTOR_END__ } per root executable and also one set of these symbols + per shared library. So in any given whole process image, we may have + multiple definitions of each of these symbols. In order to prevent + these definitions from conflicting with one another, and in order to + ensure that the proper lists are used for the initialization/finalization + of each individual shared library (respectively), we give these symbols + only internal (i.e. `static') linkage, and we also make it a point to + refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__ + symbol in crtinit.o, where they are defined. */ + +static func_ptr __CTOR_LIST__[1] + __attribute__ ((section (".ctors"))) + = { (func_ptr) (-1) }; + +static func_ptr __DTOR_LIST__[1] + __attribute__ ((section (".dtors"))) + = { (func_ptr) (-1) }; + +/* Run all the global destructors on exit from the program. */ + +/* Some systems place the number of pointers in the first word of the + table. On SVR4 however, that word is -1. In all cases, the table is + null-terminated. On SVR4, we start from the beginning of the list and + invoke each per-compilation-unit destructor routine in order + until we find that null. + + Note that this function MUST be static. There will be one of these + functions in each root executable and one in each shared library, but + although they all have the same code, each one is unique in that it + refers to one particular associated `__DTOR_LIST__' which belongs to the + same particular root executable or shared library file. */ + +static void __do_global_dtors () +asm ("__do_global_dtors") __attribute__ ((section (".text"))); + +static void +__do_global_dtors () +{ + func_ptr *p; + + for (p = __DTOR_LIST__ + 1; *p; p++) + (*p) (); +} + +/* .init section start. + This must appear at the start of the .init section. */ + +asm (" + .section .init,\"ax\",@progbits + .balign 4 + .global __init +__init: + push fp + push lr + mv fp,sp + ld24 r0,#__fini + bl atexit + .fillinsn +"); + +/* .fini section start. + This must appear at the start of the .init section. */ + +asm (" + .section .fini,\"ax\",@progbits + .balign 4 + .global __fini +__fini: + push fp + push lr + mv fp,sp + bl __do_global_dtors + .fillinsn +"); + +#endif /* CRT_INIT */ + +#ifdef CRT_FINI + +/* Put a word containing zero at the end of each of our two lists of function + addresses. Note that the words defined here go into the .ctors and .dtors + sections of the crtend.o file, and since that file is always linked in + last, these words naturally end up at the very ends of the two lists + contained in these two sections. */ + +static func_ptr __CTOR_END__[1] + __attribute__ ((section (".ctors"))) + = { (func_ptr) 0 }; + +static func_ptr __DTOR_END__[1] + __attribute__ ((section (".dtors"))) + = { (func_ptr) 0 }; + +/* Run all global constructors for the program. + Note that they are run in reverse order. */ + +static void __do_global_ctors () +asm ("__do_global_ctors") __attribute__ ((section (".text"))); + +static void +__do_global_ctors () +{ + func_ptr *p; + + for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) + (*p) (); +} + +/* .init section end. + This must live at the end of the .init section. */ + +asm (" + .section .init,\"ax\",@progbits + bl __do_global_ctors + mv sp,fp + pop lr + pop fp + jmp lr + .fillinsn +"); + +/* .fini section end. + This must live at the end of the .fini section. */ + +asm (" + .section .fini,\"ax\",@progbits + mv sp,fp + pop lr + pop fp + jmp lr + .fillinsn +"); + +#endif /* CRT_FINI */ diff --git a/gnu/usr.bin/gcc/config/m32r/m32r.c b/gnu/usr.bin/gcc/config/m32r/m32r.c new file mode 100644 index 00000000000..48504a06e14 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m32r/m32r.c @@ -0,0 +1,1835 @@ +/* Subroutines used for code generation on the Mitsubishi M32R cpu. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include <stdio.h> +#include "tree.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "expr.h" +#include "recog.h" + +/* Save the operands last given to a compare for use when we + generate a scc or bcc insn. */ +rtx m32r_compare_op0, m32r_compare_op1; + +/* Array of valid operand punctuation characters. */ +char m32r_punct_chars[256]; + +static void init_reg_tables (); + +/* Selected code model. */ +char *m32r_model_string = M32R_MODEL_DEFAULT; +enum m32r_model m32r_model; + +/* Selected SDA support. */ +char *m32r_sdata_string = M32R_SDATA_DEFAULT; +enum m32r_sdata m32r_sdata; + +/* Called by OVERRIDE_OPTIONS to initialize various things. */ + +void +m32r_init () +{ + init_reg_tables (); + + /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */ + memset (m32r_punct_chars, 0, sizeof (m32r_punct_chars)); + m32r_punct_chars['#'] = 1; + m32r_punct_chars['@'] = 1; /* ??? no longer used */ + + /* Provide default value if not specified. */ + if (!g_switch_set) + g_switch_value = SDATA_DEFAULT_SIZE; + + if (strcmp (m32r_model_string, "small") == 0) + m32r_model = M32R_MODEL_SMALL; + else if (strcmp (m32r_model_string, "medium") == 0) + m32r_model = M32R_MODEL_MEDIUM; + else if (strcmp (m32r_model_string, "large") == 0) + m32r_model = M32R_MODEL_LARGE; + else + error ("bad value (%s) for -mmodel switch", m32r_model_string); + + if (strcmp (m32r_sdata_string, "none") == 0) + m32r_sdata = M32R_SDATA_NONE; + else if (strcmp (m32r_sdata_string, "sdata") == 0) + m32r_sdata = M32R_SDATA_SDATA; + else if (strcmp (m32r_sdata_string, "use") == 0) + m32r_sdata = M32R_SDATA_USE; + else + error ("bad value (%s) for -msdata switch", m32r_sdata_string); +} + +/* Vectors to keep interesting information about registers where it can easily + be got. We use to use the actual mode value as the bit number, but there + is (or may be) more than 32 modes now. Instead we use two tables: one + indexed by hard register number, and one indexed by mode. */ + +/* The purpose of m32r_mode_class is to shrink the range of modes so that + they all fit (as bit numbers) in a 32 bit word (again). Each real mode is + mapped into one m32r_mode_class mode. */ + +enum m32r_mode_class { + C_MODE, + S_MODE, D_MODE, T_MODE, O_MODE, + SF_MODE, DF_MODE, TF_MODE, OF_MODE +}; + +/* Modes for condition codes. */ +#define C_MODES (1 << (int) C_MODE) + +/* Modes for single-word and smaller quantities. */ +#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE)) + +/* Modes for double-word and smaller quantities. */ +#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE)) + +/* Modes for quad-word and smaller quantities. */ +#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE)) + +/* Value is 1 if register/mode pair is acceptable on arc. */ + +unsigned int m32r_hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] = { + T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, + T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, S_MODES, S_MODES, S_MODES, + S_MODES, C_MODES +}; + +unsigned int m32r_mode_class [NUM_MACHINE_MODES]; + +enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER]; + +static void +init_reg_tables () +{ + int i; + + for (i = 0; i < NUM_MACHINE_MODES; i++) + { + switch (GET_MODE_CLASS (i)) + { + case MODE_INT: + case MODE_PARTIAL_INT: + case MODE_COMPLEX_INT: + if (GET_MODE_SIZE (i) <= 4) + m32r_mode_class[i] = 1 << (int) S_MODE; + else if (GET_MODE_SIZE (i) == 8) + m32r_mode_class[i] = 1 << (int) D_MODE; + else if (GET_MODE_SIZE (i) == 16) + m32r_mode_class[i] = 1 << (int) T_MODE; + else if (GET_MODE_SIZE (i) == 32) + m32r_mode_class[i] = 1 << (int) O_MODE; + else + m32r_mode_class[i] = 0; + break; + case MODE_FLOAT: + case MODE_COMPLEX_FLOAT: + if (GET_MODE_SIZE (i) <= 4) + m32r_mode_class[i] = 1 << (int) SF_MODE; + else if (GET_MODE_SIZE (i) == 8) + m32r_mode_class[i] = 1 << (int) DF_MODE; + else if (GET_MODE_SIZE (i) == 16) + m32r_mode_class[i] = 1 << (int) TF_MODE; + else if (GET_MODE_SIZE (i) == 32) + m32r_mode_class[i] = 1 << (int) OF_MODE; + else + m32r_mode_class[i] = 0; + break; + case MODE_CC: + default: + /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so + we must explicitly check for them here. */ + if (i == (int) CCmode) + m32r_mode_class[i] = 1 << (int) C_MODE; + else + m32r_mode_class[i] = 0; + break; + } + } + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (GPR_P (i)) + m32r_regno_reg_class[i] = GENERAL_REGS; + else if (i == ARG_POINTER_REGNUM) + m32r_regno_reg_class[i] = GENERAL_REGS; + else + m32r_regno_reg_class[i] = NO_REGS; + } +} + +/* M32R specific attribute support. + + interrupt - for interrupt functions + + model - select code model used to access object + + small: addresses use 24 bits, use bl to make calls + medium: addresses use 32 bits, use bl to make calls + large: addresses use 32 bits, use seth/add3/jl to make calls + + Grep for MODEL in m32r.h for more info. +*/ + +/* Return nonzero if IDENTIFIER is a valid decl attribute. */ + +int +m32r_valid_machine_decl_attribute (type, attributes, identifier, args) + tree type; + tree attributes; + tree identifier; + tree args; +{ + static tree interrupt_ident, model_ident; + static tree small_ident, medium_ident, large_ident; + + if (interrupt_ident == 0) + { + interrupt_ident = get_identifier ("__interrupt__"); + model_ident = get_identifier ("__model__"); + small_ident = get_identifier ("__small__"); + medium_ident = get_identifier ("__medium__"); + large_ident = get_identifier ("__large__"); + } + + if (identifier == interrupt_ident + && list_length (args) == 0) + return 1; + + if (identifier == model_ident + && list_length (args) == 1 + && (TREE_VALUE (args) == small_ident + || TREE_VALUE (args) == medium_ident + || TREE_VALUE (args) == large_ident)) + return 1; + + return 0; +} + +/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible, + and two if they are nearly compatible (which causes a warning to be + generated). */ + +int +m32r_comp_type_attributes (type1, type2) + tree type1, type2; +{ + return 1; +} + +/* Set the default attributes for TYPE. */ + +void +m32r_set_default_type_attributes (type) + tree type; +{ +} + +/* 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. */ + +void +m32r_select_section (decl, reloc) + tree decl; + int reloc; +{ + if (TREE_CODE (decl) == STRING_CST) + { + if (! flag_writable_strings) + const_section (); + else + data_section (); + } + else if (TREE_CODE (decl) == VAR_DECL) + { + if (SDATA_NAME_P (XSTR (XEXP (DECL_RTL (decl), 0), 0))) + sdata_section (); + else if ((flag_pic && reloc) + || !TREE_READONLY (decl) + || TREE_SIDE_EFFECTS (decl) + || !DECL_INITIAL (decl) + || (DECL_INITIAL (decl) != error_mark_node + && !TREE_CONSTANT (DECL_INITIAL (decl)))) + data_section (); + else + const_section (); + } + else + const_section (); +} + +/* Encode section information of DECL, which is either a VAR_DECL, + FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???. + + For the M32R we want to record: + + - whether the object lives in .sdata/.sbss. + objects living in .sdata/.sbss are prefixed with SDATA_FLAG_CHAR + + - what code model should be used to access the object + small: recorded with no flag - for space efficiency since they'll + be the most common + medium: prefixed with MEDIUM_FLAG_CHAR + large: prefixed with LARGE_FLAG_CHAR +*/ + +void +m32r_encode_section_info (decl) + tree decl; +{ + char prefix = 0; + tree model = 0; + + switch (TREE_CODE (decl)) + { + case VAR_DECL : + case FUNCTION_DECL : + model = lookup_attribute ("model", DECL_MACHINE_ATTRIBUTES (decl)); + break; + case STRING_CST : + case CONSTRUCTOR : + /* ??? document all others that can appear here */ + default : + return; + } + + /* Only mark the object as being small data area addressable if + it hasn't been explicitly marked with a code model. + + The user can explicitly put an object in the small data area with the + section attribute. If the object is in sdata/sbss and marked with a + code model do both [put the object in .sdata and mark it as being + addressed with a specific code model - don't mark it as being addressed + with an SDA reloc though]. This is ok and might be useful at times. If + the object doesn't fit the linker will give an error. */ + + if (! model) + { + if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd' + && DECL_SECTION_NAME (decl) != NULL_TREE) + { + char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); + if (! strcmp (name, ".sdata") || ! strcmp (name, ".sbss")) + { +#if 0 /* ??? There's no reason to disallow this, is there? */ + if (TREE_READONLY (decl)) + error_with_decl (decl, "const objects cannot go in .sdata/.sbss"); +#endif + prefix = SDATA_FLAG_CHAR; + } + } + else + { + if (TREE_CODE (decl) == VAR_DECL + && ! TREE_READONLY (decl) + && ! TARGET_SDATA_NONE) + { + int size = int_size_in_bytes (TREE_TYPE (decl)); + + if (size > 0 && size <= g_switch_value) + prefix = SDATA_FLAG_CHAR; + } + } + } + + /* If data area not decided yet, check for a code model. */ + if (prefix == 0) + { + if (model) + { + if (TREE_VALUE (TREE_VALUE (model)) == get_identifier ("__small__")) + ; /* don't mark the symbol specially */ + else if (TREE_VALUE (TREE_VALUE (model)) == get_identifier ("__medium__")) + prefix = MEDIUM_FLAG_CHAR; + else if (TREE_VALUE (TREE_VALUE (model)) == get_identifier ("__large__")) + prefix = LARGE_FLAG_CHAR; + else + abort (); /* shouldn't happen */ + } + else + { + if (TARGET_MODEL_SMALL) + ; /* don't mark the symbol specially */ + else if (TARGET_MODEL_MEDIUM) + prefix = MEDIUM_FLAG_CHAR; + else if (TARGET_MODEL_LARGE) + prefix = LARGE_FLAG_CHAR; + else + abort (); /* shouldn't happen */ + } + } + + if (prefix != 0) + { + rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' + ? TREE_CST_RTL (decl) : DECL_RTL (decl)); + char *str = XSTR (XEXP (rtl, 0), 0); + int len = strlen (str); + char *newstr = savealloc (len + 2); + strcpy (newstr + 1, str); + *newstr = prefix; + XSTR (XEXP (rtl, 0), 0) = newstr; + } +} + +/* Do anything needed before RTL is emitted for each function. */ + +void +m32r_init_expanders () +{ + /* ??? At one point there was code here. The function is left in + to make it easy to experiment. */ +} + +/* Acceptable arguments to the call insn. */ + +int +call_address_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (symbolic_operand (op, mode) + || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op)) + || (GET_CODE (op) == REG)); +} + +int +call_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM) + return 0; + op = XEXP (op, 0); + return call_address_operand (op, mode); +} + +/* Returns 1 if OP is a symbol reference. */ + +int +symbolic_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + case CONST : + return 1; + default: + return 0; + } +} + +/* Return truth value of statement that OP is a symbolic memory + operand of mode MODE. */ + +int +symbolic_memory_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + if (GET_CODE (op) != MEM) + return 0; + op = XEXP (op, 0); + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST + || GET_CODE (op) == LABEL_REF); +} + +/* Return 1 if OP is a reference to an object in .sdata/.sbss. */ + +int +small_data_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (! TARGET_SDATA_USE) + return 0; + + if (GET_CODE (op) == SYMBOL_REF) + return SDATA_NAME_P (XSTR (op, 0)); + + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT + && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1)))) + return SDATA_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0)); + + return 0; +} + +/* Return 1 if OP is a symbol that can use 24 bit addressing. */ + +int +addr24_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == LABEL_REF) + return TARGET_ADDR24; + + if (GET_CODE (op) == SYMBOL_REF) + return (SMALL_NAME_P (XSTR (op, 0)) + || (TARGET_ADDR24 + && (CONSTANT_POOL_ADDRESS_P (op) + || LIT_NAME_P (XSTR (op, 0))))); + + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT + && UINT24_P (INTVAL (XEXP (XEXP (op, 0), 1)))) + { + rtx sym = XEXP (XEXP (op, 0), 0); + return (SMALL_NAME_P (XSTR (sym, 0)) + || (TARGET_ADDR24 + && (CONSTANT_POOL_ADDRESS_P (op) + || LIT_NAME_P (XSTR (op, 0))))); + } + + return 0; +} + +/* Return 1 if OP is a symbol that needs 32 bit addressing. */ + +int +addr32_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == LABEL_REF) + return TARGET_ADDR32; + + if (GET_CODE (op) == SYMBOL_REF) + return (! addr24_operand (op) + && ! small_data_operand (op)); + + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) + { + return (! addr24_operand (op) + && ! small_data_operand (op)); + } + + return 0; +} + +/* Return 1 if OP is a function that can be called with the `bl' insn. */ + +int +call26_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == SYMBOL_REF) + return ! LARGE_NAME_P (XSTR (op, 0)); + + return TARGET_CALL26; +} + +/* Return 1 if OP is a function that must be called with 32 bit addressing. */ + +int +call32_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return ! call26_operand (op, mode); +} + +/* Returns 1 if OP is an acceptable operand for seth/add3. */ + +int +seth_add3_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == SYMBOL_REF + || GET_CODE (op) == LABEL_REF) + return 1; + + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT + && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1)))) + return 1; + + return 0; +} + +/* Return true if OP is a signed 8 bit immediate value. */ + +int +int8_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return INT8_P (INTVAL (op)); +} + +/* Return true if OP is a signed 16 bit immediate value. */ + +int +int16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return INT16_P (INTVAL (op)); +} + +/* Return true if OP is a signed 16 bit immediate value + useful in comparisons. */ + +int +cmp_int16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return CMP_INT16_P (INTVAL (op)); +} + +/* Return true if OP is an unsigned 16 bit immediate value. */ + +int +uint16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return UINT16_P (INTVAL (op)); +} + +/* Return true if OP is an unsigned 24 bit immediate value. */ + +int +uint24_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + return UINT24_P (INTVAL (op)); +} + +/* Return true if OP is a register or signed 8 bit value. */ + +int +reg_or_int8_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) + return register_operand (op, mode); + if (GET_CODE (op) != CONST_INT) + return 0; + return INT8_P (INTVAL (op)); +} + +/* Return true if OP is a register or signed 8 bit value. */ + +int +reg_or_int16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) + return register_operand (op, mode); + if (GET_CODE (op) != CONST_INT) + return 0; + return INT16_P (INTVAL (op)); +} + +/* Return true if OP is a register or signed 8 bit value. */ + +int +reg_or_uint16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) + return register_operand (op, mode); + if (GET_CODE (op) != CONST_INT) + return 0; + return UINT16_P (INTVAL (op)); +} + +/* Return true if OP is a register or signed 16 bit value for compares. */ + +int +reg_or_cmp_int16_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) + return register_operand (op, mode); + if (GET_CODE (op) != CONST_INT) + return 0; + return CMP_INT16_P (INTVAL (op)); +} + +/* Return true if OP is a const_int requiring two instructions to load. */ + +int +two_insn_const_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + if (INT16_P (INTVAL (op)) + || UINT24_P (INTVAL (op)) + || UPPER16_P (INTVAL (op))) + return 0; + return 1; +} + +/* Return true if OP is an acceptable argument for a single word + move source. */ + +int +move_src_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF : + case CONST : + return addr24_operand (op, mode); + case CONST_INT : + /* ??? We allow more cse opportunities if we only allow constants + loadable with one insn, and split the rest into two. The instances + where this would help should be rare and the current way is + simpler. */ + return INT32_P (INTVAL (op)); + case LABEL_REF : + return TARGET_ADDR24; + case CONST_DOUBLE : + if (mode == SFmode) + return 1; + else if (mode == SImode) + { + /* Large unsigned constants are represented as const_double's. */ + unsigned HOST_WIDE_INT low, high; + + low = CONST_DOUBLE_LOW (op); + high = CONST_DOUBLE_HIGH (op); + return high == 0 && low <= 0xffffffff; + } + else + return 0; + case REG : + return register_operand (op, mode); + case SUBREG : + /* (subreg (mem ...) ...) can occur here if the inner part was once a + pseudo-reg and is now a stack slot. */ + if (GET_CODE (SUBREG_REG (op)) == MEM) + return address_operand (XEXP (SUBREG_REG (op), 0), mode); + else + return register_operand (op, mode); + case MEM : + return address_operand (XEXP (op, 0), mode); + default : + return 0; + } +} + +/* Return true if OP is an acceptable argument for a double word + move source. */ + +int +move_double_src_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case CONST_INT : + case CONST_DOUBLE : + if (mode == DFmode) + return easy_df_const (op); + else + return easy_di_const (op); + case REG : + return register_operand (op, mode); + case SUBREG : + /* (subreg (mem ...) ...) can occur here if the inner part was once a + pseudo-reg and is now a stack slot. */ + if (GET_CODE (SUBREG_REG (op)) == MEM) + return move_double_src_operand (SUBREG_REG (op), mode); + else + return register_operand (op, mode); + case MEM : + /* Disallow auto inc/dec for now. */ + if (GET_CODE (XEXP (op, 0)) == PRE_DEC + || GET_CODE (XEXP (op, 0)) == PRE_INC) + return 0; + return address_operand (XEXP (op, 0), mode); + default : + return 0; + } +} + +/* Return true if OP is an acceptable argument for a move destination. */ + +int +move_dest_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case REG : + return register_operand (op, mode); + case SUBREG : + /* (subreg (mem ...) ...) can occur here if the inner part was once a + pseudo-reg and is now a stack slot. */ + if (GET_CODE (SUBREG_REG (op)) == MEM) + return address_operand (XEXP (SUBREG_REG (op), 0), mode); + else + return register_operand (op, mode); + case MEM : + return address_operand (XEXP (op, 0), mode); + default : + return 0; + } +} + +/* Return 1 if OP is a DImode const we want to handle inline. + This must match the code in the movdi pattern. + It is used by the 'G' CONST_DOUBLE_OK_FOR_LETTER. */ + +int +easy_di_const (op) + rtx op; +{ + rtx high_rtx, low_rtx; + HOST_WIDE_INT high, low; + + split_double (op, &high_rtx, &low_rtx); + high = INTVAL (high_rtx); + low = INTVAL (low_rtx); + /* Pick constants loadable with 2 16 bit `ldi' insns. */ + if (high >= -128 && high <= 127 + && low >= -128 && low <= 127) + return 1; + return 0; +} + +/* Return 1 if OP is a DFmode const we want to handle inline. + This must match the code in the movdf pattern. + It is used by the 'H' CONST_DOUBLE_OK_FOR_LETTER. */ + +int +easy_df_const (op) + rtx op; +{ + REAL_VALUE_TYPE r; + long l[2]; + + REAL_VALUE_FROM_CONST_DOUBLE (r, op); + REAL_VALUE_TO_TARGET_DOUBLE (r, l); + if (l[0] == 0 && l[1] == 0) + return 1; + if ((l[0] & 0xffff) == 0 && l[1] == 0) + return 1; + return 0; +} + +/* Return 1 if OP is an EQ or NE comparison operator. */ + +int +eqne_comparison_operator (op, mode) + rtx op; + enum machine_mode mode; +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != '<') + return 0; + return (code == EQ || code == NE); +} + +/* Return 1 if OP is a signed comparison operator. */ + +int +signed_comparison_operator (op, mode) + rtx op; + enum machine_mode mode; +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != '<') + return 0; + return (code == EQ || code == NE + || code == LT || code == LE || code == GT || code == GE); +} + +/* Return 1 if OP is (mem (reg ...)). + This is used in insn length calcs. */ + +int +memreg_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG; +} + +/* Comparisons. */ + +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, + return the mode to be used for the comparison. */ + +enum machine_mode +m32r_select_cc_mode (op, x, y) + enum rtx_code op; + rtx x, y; +{ + return CCmode; +} + +/* X and Y are two things to compare using CODE. Emit the compare insn and + return the rtx for compare [arg0 of the if_then_else]. */ + +rtx +gen_compare (code, x, y) + enum rtx_code code; + rtx x, y; +{ + enum machine_mode mode = SELECT_CC_MODE (code, x, y); + enum rtx_code compare_code, branch_code; + rtx cc_reg = gen_rtx (REG, mode, CARRY_REGNUM); + int swap_p = 0; + + switch (code) + { + case EQ: compare_code = EQ; branch_code = NE; break; + case NE: compare_code = EQ; branch_code = EQ; break; + case LT: compare_code = LT; branch_code = NE; break; + case LE: compare_code = LT; branch_code = EQ; swap_p = 1; break; + case GT: compare_code = LT; branch_code = NE; swap_p = 1; break; + case GE: compare_code = LT; branch_code = EQ; break; + case LTU: compare_code = LTU; branch_code = NE; break; + case LEU: compare_code = LTU; branch_code = EQ; swap_p = 1; break; + case GTU: compare_code = LTU; branch_code = NE; swap_p = 1; break; + case GEU: compare_code = LTU; branch_code = EQ; break; + } + + if (! TARGET_OLD_COMPARE) + { + /* reg/reg equal comparison */ + if (compare_code == EQ + && register_operand (y, SImode)) + return gen_rtx (code, mode, x, y); + /* reg/zero signed comparison */ + if ((compare_code == EQ || compare_code == LT) + && y == const0_rtx) + return gen_rtx (code, mode, x, y); + /* reg/smallconst equal comparison */ + if (compare_code == EQ + && GET_CODE (y) == CONST_INT + && CMP_INT16_P (INTVAL (y))) + { + rtx tmp = gen_reg_rtx (SImode); + emit_insn (gen_cmp_ne_small_const_insn (tmp, x, y)); + return gen_rtx (code, mode, tmp, const0_rtx); + } + /* reg/const equal comparison */ + if (compare_code == EQ + && CONSTANT_P (y)) + { + rtx tmp = force_reg (GET_MODE (x), y); + return gen_rtx (code, mode, x, tmp); + } + } + + if (swap_p && CONSTANT_P (y)) + y = force_reg (GET_MODE (x), y); + else if (CONSTANT_P (y)) + { + int ok_const_p = + (code == LTU || code == LEU || code == GTU || code == GEU) + ? uint16_operand (y, GET_MODE (y)) + : reg_or_cmp_int16_operand (y, GET_MODE (y)); + if (! ok_const_p) + y = force_reg (GET_MODE (x), y); + } + + switch (compare_code) + { + case EQ : + emit_insn (gen_cmp_eqsi_insn (swap_p ? y : x, swap_p ? x : y)); + break; + case LT : + emit_insn (gen_cmp_ltsi_insn (swap_p ? y : x, swap_p ? x : y)); + break; + case LTU : + emit_insn (gen_cmp_ltusi_insn (swap_p ? y : x, swap_p ? x : y)); + break; + } + + return gen_rtx (branch_code, VOIDmode, cc_reg, CONST0_RTX (mode)); +} + +/* Implements the FUNCTION_ARG_PARTIAL_NREGS macro. */ + +int +function_arg_partial_nregs (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + int ret; + int size = (((mode == BLKmode && type) + ? int_size_in_bytes (type) + : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; + + if (*cum >= M32R_MAX_PARM_REGS) + ret = 0; + else if (*cum + size > M32R_MAX_PARM_REGS) + ret = (*cum + size) - M32R_MAX_PARM_REGS; + else + ret = 0; + + return ret; +} + +/* Do any needed setup for a variadic function. For the M32R, we must + create a register parameter block, and then copy any anonymous arguments + in registers to memory. + + CUM has not been updated for the last named argument which has type TYPE + and mode MODE, and we rely on this fact. */ + +void +m32r_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int *pretend_size; + int no_rtl; +{ + int first_anon_arg; + + if (no_rtl) + return; + + /* All BLKmode values are passed by reference. */ + if (mode == BLKmode) + abort (); + + /* We must treat `__builtin_va_alist' as an anonymous arg. */ + if (current_function_varargs) + first_anon_arg = *cum; + else + first_anon_arg = (ROUND_ADVANCE_CUM (*cum, mode, type) + + ROUND_ADVANCE_ARG (mode, type)); + + if (first_anon_arg < M32R_MAX_PARM_REGS) + { + /* Note that first_reg_offset < M32R_MAX_PARM_REGS. */ + int first_reg_offset = first_anon_arg; + /* Size in words to "pretend" allocate. */ + int size = M32R_MAX_PARM_REGS - first_reg_offset; + rtx regblock; + + regblock = gen_rtx (MEM, BLKmode, + plus_constant (arg_pointer_rtx, + FIRST_PARM_OFFSET (0))); + move_block_from_reg (first_reg_offset, regblock, + size, size * UNITS_PER_WORD); + + *pretend_size = (size * UNITS_PER_WORD); + } +} + +/* Cost functions. */ + +/* Provide the costs of an addressing mode that contains ADDR. + If ADDR is not a valid address, its cost is irrelevant. + + This function is trivial at the moment. This code doesn't live + in m32r.h so it's easy to experiment. */ + +int +m32r_address_cost (addr) + rtx addr; +{ + return 1; +} + +/* Type of function DECL. + + The result is cached. To reset the cache at the end of a function, + call with DECL = NULL_TREE. */ + +enum m32r_function_type +m32r_compute_function_type (decl) + tree decl; +{ + /* Cached value. */ + static enum m32r_function_type fn_type = M32R_FUNCTION_UNKNOWN; + /* Last function we were called for. */ + static tree last_fn = NULL_TREE; + + /* Resetting the cached value? */ + if (decl == NULL_TREE) + { + fn_type = M32R_FUNCTION_UNKNOWN; + last_fn = NULL_TREE; + return fn_type; + } + + if (decl == last_fn && fn_type != M32R_FUNCTION_UNKNOWN) + return fn_type; + + /* Compute function type. */ + fn_type = (lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (current_function_decl)) != NULL_TREE + ? M32R_FUNCTION_INTERRUPT + : M32R_FUNCTION_NORMAL); + + last_fn = decl; + return fn_type; +} +/* Function prologue/epilogue handlers. */ + +/* M32R stack frames look like: + + Before call After call + +-----------------------+ +-----------------------+ + | | | | + high | local variables, | | local variables, | + mem | reg save area, etc. | | reg save area, etc. | + | | | | + +-----------------------+ +-----------------------+ + | | | | + | arguments on stack. | | arguments on stack. | + | | | | + SP+0->+-----------------------+ +-----------------------+ + | reg parm save area, | + | only created for | + | variable argument | + | functions | + +-----------------------+ + | previous frame ptr | + +-----------------------+ + | | + | register save area | + | | + +-----------------------+ + | return address | + +-----------------------+ + | | + | local variables | + | | + +-----------------------+ + | | + | alloca allocations | + | | + +-----------------------+ + | | + low | arguments on stack | + memory | | + SP+0->+-----------------------+ + +Notes: +1) The "reg parm save area" does not exist for non variable argument fns. +2) The "reg parm save area" can be eliminated completely if we saved regs + containing anonymous args separately but that complicates things too + much (so it's not done). +3) The return address is saved after the register save area so as to have as + many insns as possible between the restoration of `lr' and the `jmp lr'. +*/ + +/* Structure to be filled in by m32r_compute_frame_size with register + save masks, and offsets for the current function. */ +struct m32r_frame_info +{ + unsigned int total_size; /* # bytes that the entire frame takes up */ + unsigned int extra_size; /* # bytes of extra stuff */ + unsigned int pretend_size; /* # bytes we push and pretend caller did */ + unsigned int args_size; /* # bytes that outgoing arguments take up */ + unsigned int reg_size; /* # bytes needed to store regs */ + unsigned int var_size; /* # bytes that variables take up */ + unsigned int gmask; /* mask of saved gp registers */ + unsigned int save_fp; /* nonzero if fp must be saved */ + unsigned int save_lr; /* nonzero if lr (return addr) must be saved */ + int initialized; /* nonzero if frame size already calculated */ +}; + +/* Current frame information calculated by m32r_compute_frame_size. */ +static struct m32r_frame_info current_frame_info; + +/* Zero structure to initialize current_frame_info. */ +static struct m32r_frame_info zero_frame_info; + +#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) +#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) + +/* Tell prologue and epilogue if register REGNO should be saved / restored. + The return address and frame pointer are treated separately. + Don't consider them here. */ +#define MUST_SAVE_REGISTER(regno, interrupt_p) \ +((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \ + && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p))) + +#define MUST_SAVE_FRAME_POINTER (regs_ever_live[FRAME_POINTER_REGNUM]) +#define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM]) + +/* Return the bytes needed to compute the frame pointer from the current + stack pointer. + + SIZE is the size needed for local variables. */ + +unsigned int +m32r_compute_frame_size (size) + int size; /* # of var. bytes allocated. */ +{ + int regno; + unsigned int total_size, var_size, args_size, pretend_size, extra_size; + unsigned int reg_size; + unsigned int gmask; + enum m32r_function_type fn_type; + int interrupt_p; + + var_size = M32R_STACK_ALIGN (size); + args_size = M32R_STACK_ALIGN (current_function_outgoing_args_size); + pretend_size = current_function_pretend_args_size; + extra_size = FIRST_PARM_OFFSET (0); + total_size = extra_size + pretend_size + args_size + var_size; + reg_size = 0; + gmask = 0; + + /* See if this is an interrupt handler. Call used registers must be saved + for them too. */ + fn_type = m32r_compute_function_type (current_function_decl); + interrupt_p = M32R_INTERRUPT_P (fn_type); + + /* Calculate space needed for registers. */ + + for (regno = 0; regno < M32R_MAX_INT_REGS; regno++) + { + if (MUST_SAVE_REGISTER (regno, interrupt_p)) + { + reg_size += UNITS_PER_WORD; + gmask |= 1 << regno; + } + } + + current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER; + current_frame_info.save_lr = MUST_SAVE_RETURN_ADDR; + + reg_size += ((current_frame_info.save_fp + current_frame_info.save_lr) + * UNITS_PER_WORD); + total_size += reg_size; + + /* ??? Not sure this is necessary, and I don't think the epilogue + handler will do the right thing if this changes total_size. */ + total_size = M32R_STACK_ALIGN (total_size); + + /* Save computed information. */ + current_frame_info.total_size = total_size; + current_frame_info.extra_size = extra_size; + current_frame_info.pretend_size = pretend_size; + current_frame_info.var_size = var_size; + current_frame_info.args_size = args_size; + current_frame_info.reg_size = reg_size; + current_frame_info.gmask = gmask; + current_frame_info.initialized = reload_completed; + + /* Ok, we're done. */ + return total_size; +} + +/* Set up the stack and frame pointer (if desired) for the function. */ + +void +m32r_output_function_prologue (file, size) + FILE *file; + int size; +{ + int regno; + int total_size, frame_size; + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + char *fp_str = reg_names[FRAME_POINTER_REGNUM]; + unsigned int gmask = current_frame_info.gmask; + enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl); + + /* If this is an interrupt handler, mark it as such. */ + if (M32R_INTERRUPT_P (fn_type)) + { + fprintf (file, "\t%s interrupt handler\n", + ASM_COMMENT_START); + } + + /* This is only for the human reader. */ + fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n", + ASM_COMMENT_START, ASM_COMMENT_START, + current_frame_info.var_size, + current_frame_info.reg_size / 4, + current_frame_info.args_size, + current_frame_info.extra_size); + + total_size = (! current_frame_info.initialized + ? m32r_compute_frame_size (size) + : current_frame_info.total_size); + + /* These cases shouldn't happen. Catch them now. */ + if (total_size == 0 && gmask) + abort (); + +#if 1 + /* Allocate space for register arguments if this is a variadic function. */ + if (current_frame_info.pretend_size != 0) + fprintf (file, "\taddi %s,%s%d\n", + sp_str, IMMEDIATE_PREFIX, + -current_frame_info.pretend_size); +#else + /* If there are unnamed args in registers, save them. */ + if (current_function_stdarg || current_function_varargs) + { + int i; + fprintf (file, "\taddi %s,%s%d\n", + sp_str, IMMEDIATE_PREFIX, + - M32R_MAX_PARM_REGS * UNITS_PER_WORD); + for (i = 0; i < M32R_MAX_PARM_REGS; ++i) + fprintf (file, "\tst %s,@(sp,%d)\n", + reg_names[i], i * UNITS_PER_WORD); + } +#endif + + /* Save any registers we need to and set up fp. */ + + if (current_frame_info.save_fp) + fprintf (file, "\tpush %s\n", fp_str); + + gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK); + + /* Save any needed call-saved regs (and call-used if this is an + interrupt handler). */ + for (regno = 0; regno <= M32R_MAX_INT_REGS; ++regno) + { + if ((gmask & (1 << regno)) != 0) + fprintf (file, "\tpush %s\n", reg_names[regno]); + } + + if (current_frame_info.save_lr) + fprintf (file, "\tpush %s\n", reg_names[RETURN_ADDR_REGNUM]); + + /* Allocate the stack frame. */ + frame_size = total_size - (current_frame_info.pretend_size + + current_frame_info.reg_size); + if (frame_size == 0) + ; /* nothing to do */ + else if (frame_size <= 128) + fprintf (file, "\taddi %s,%s%d\n", + sp_str, IMMEDIATE_PREFIX, -frame_size); + else if (frame_size <= 32768) + fprintf (file, "\tadd3 %s,%s,%s%d\n", + sp_str, sp_str, IMMEDIATE_PREFIX, -frame_size); + else + fprintf (file, "\tld24 %s,%s%d\n\tsub %s,%s\n", + reg_names[PROLOGUE_TMP_REGNUM], + IMMEDIATE_PREFIX, frame_size, + sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + + if (frame_pointer_needed) + fprintf (file, "\tmv %s,%s\n", fp_str, sp_str); + + fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START); +} + +/* Do any necessary cleanup after a function to restore stack, frame, + and regs. */ + +void +m32r_output_function_epilogue (file, size) + FILE *file; + int size; +{ + int regno; + int noepilogue = FALSE; + int total_size; + enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl); + + /* This is only for the human reader. */ + fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START); + + if (!current_frame_info.initialized) + abort (); + total_size = current_frame_info.total_size; + + if (total_size == 0) + { + rtx insn = get_last_insn (); + + /* If the last insn was a BARRIER, we don't have to write any code + because a jump (aka return) was put there. */ + if (GET_CODE (insn) == NOTE) + insn = prev_nonnote_insn (insn); + if (insn && GET_CODE (insn) == BARRIER) + noepilogue = TRUE; + } + + if (!noepilogue) + { + unsigned int pretend_size = current_frame_info.pretend_size; + unsigned int frame_size = total_size - pretend_size; + unsigned int var_size = current_frame_info.var_size; + unsigned int args_size = current_frame_info.args_size; + unsigned int gmask = current_frame_info.gmask; + int can_trust_sp_p = !current_function_calls_alloca; + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + char *fp_str = reg_names[FRAME_POINTER_REGNUM]; + + /* The first thing to do is point the sp at the bottom of the register + save area. */ + if (can_trust_sp_p) + { + unsigned int reg_offset = var_size + args_size; + if (reg_offset == 0) + ; /* nothing to do */ + else if (reg_offset < 128) + fprintf (file, "\taddi %s,%s%d\n", + sp_str, IMMEDIATE_PREFIX, reg_offset); + else if (reg_offset < 32768) + fprintf (file, "\tadd3 %s,%s,%s%d\n", + sp_str, sp_str, IMMEDIATE_PREFIX, reg_offset); + else + fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n", + reg_names[PROLOGUE_TMP_REGNUM], + IMMEDIATE_PREFIX, reg_offset, + sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + } + else if (frame_pointer_needed) + { + unsigned int reg_offset = var_size + args_size; + if (reg_offset == 0) + fprintf (file, "\tmv %s,%s\n", sp_str, fp_str); + else if (reg_offset < 32768) + fprintf (file, "\tadd3 %s,%s,%s%d\n", + sp_str, fp_str, IMMEDIATE_PREFIX, reg_offset); + else + fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n", + reg_names[PROLOGUE_TMP_REGNUM], + IMMEDIATE_PREFIX, reg_offset, + sp_str, reg_names[PROLOGUE_TMP_REGNUM]); + } + else + abort (); + + if (current_frame_info.save_lr) + fprintf (file, "\tpop %s\n", reg_names[RETURN_ADDR_REGNUM]); + + /* Restore any saved registers, in reverse order of course. */ + gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK); + for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno) + { + if ((gmask & (1L << regno)) != 0) + fprintf (file, "\tpop %s\n", reg_names[regno]); + } + + if (current_frame_info.save_fp) + fprintf (file, "\tpop %s\n", fp_str); + + /* Remove varargs area if present. */ + if (current_frame_info.pretend_size != 0) + fprintf (file, "\taddi %s,%s%d\n", + sp_str, IMMEDIATE_PREFIX, current_frame_info.pretend_size); + + /* Emit the return instruction. */ + if (M32R_INTERRUPT_P (fn_type)) + fprintf (file, "\trte\n"); + else + fprintf (file, "\tjmp %s\n", reg_names[RETURN_ADDR_REGNUM]); + } + +#if 0 /* no longer needed */ + /* Ensure the function cleanly ends on a 32 bit boundary. */ + fprintf (file, "\t.fillinsn\n"); +#endif + + /* Reset state info for each function. */ + current_frame_info = zero_frame_info; + m32r_compute_function_type (NULL_TREE); +} + +/* PIC */ + +/* Emit special PIC prologues and epilogues. */ + +void +m32r_finalize_pic () +{ + /* nothing to do */ +} + +/* Nested function support. */ + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ + +void +m32r_initialize_trampoline (tramp, fnaddr, cxt) + rtx tramp, fnaddr, cxt; +{ +} + +/* Set the cpu type and print out other fancy things, + at the top of the file. */ + +void +m32r_asm_file_start (file) + FILE *file; +{ + if (flag_verbose_asm) + fprintf (file, "%s M32R/D special options: -G %d\n", + ASM_COMMENT_START, g_switch_value); +} + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ + +void +m32r_print_operand (file, x, code) + FILE *file; + rtx x; + int code; +{ + switch (code) + { + case 'R' : + /* Write second word of DImode or DFmode reference, + register or memory. */ + if (GET_CODE (x) == REG) + fputs (reg_names[REGNO (x)+1], file); + else if (GET_CODE (x) == MEM) + { + fprintf (file, "@("); + /* Handle possible auto-increment. Since it is pre-increment and + we have already done it, we can just use an offset of four. */ + /* ??? This is taken from rs6000.c I think. I don't think it is + currently necessary, but keep it around. */ + if (GET_CODE (XEXP (x, 0)) == PRE_INC + || GET_CODE (XEXP (x, 0)) == PRE_DEC) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4)); + else + output_address (plus_constant (XEXP (x, 0), 4)); + fputc (')', file); + } + else + output_operand_lossage ("invalid operand to %R code"); + return; + + case 'H' : /* High word */ + case 'L' : /* Low word */ + if (GET_CODE (x) == REG) + { + /* L = least significant word, H = most significant word */ + if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L')) + fputs (reg_names[REGNO (x)], file); + else + fputs (reg_names[REGNO (x)+1], file); + } + else if (GET_CODE (x) == CONST_INT + || GET_CODE (x) == CONST_DOUBLE) + { + rtx first, second; + + split_double (x, &first, &second); + fprintf (file, "0x%08lx", + code == 'L' ? INTVAL (first) : INTVAL (second)); + } + else + output_operand_lossage ("invalid operand to %H/%L code"); + return; + + case 'A' : + { + REAL_VALUE_TYPE d; + char str[30]; + + if (GET_CODE (x) != CONST_DOUBLE + || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT) + abort (); + REAL_VALUE_FROM_CONST_DOUBLE (d, x); + REAL_VALUE_TO_DECIMAL (d, "%.20e", str); + fprintf (file, "%s", str); + return; + } + + case 'B' : /* Bottom half */ + case 'T' : /* Top half */ + /* Output the argument to a `seth' insn (sets the Top half-word). + For constants output arguments to a seth/or3 pair to set Top and + Bottom halves. For symbols output arguments to a seth/add3 pair to + set Top and Bottom halves. The difference exists because for + constants seth/or3 is more readable but for symbols we need to use + the same scheme as `ld' and `st' insns (16 bit addend is signed). */ + switch (GET_CODE (x)) + { + case CONST_INT : + case CONST_DOUBLE : + { + rtx first, second; + + split_double (x, &first, &second); + x = WORDS_BIG_ENDIAN ? second : first; + fprintf (file, +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + "0x%x", +#else + "0x%lx", +#endif + (code == 'B' + ? INTVAL (x) & 0xffff + : (INTVAL (x) >> 16) & 0xffff)); + } + return; + case CONST : + case SYMBOL_REF : + if (code == 'B' + && small_data_operand (x, VOIDmode)) + { + fputs ("sda(", file); + output_addr_const (file, x); + fputc (')', file); + return; + } + /* fall through */ + case LABEL_REF : + fputs (code == 'T' ? "shigh(" : "low(", file); + output_addr_const (file, x); + fputc (')', file); + return; + default : + output_operand_lossage ("invalid operand to %T/%B code"); + return; + } + break; + + case 'U' : + /* ??? wip */ + /* Output a load/store with update indicator if appropriate. */ + if (GET_CODE (x) == MEM) + { + if (GET_CODE (XEXP (x, 0)) == PRE_INC + || GET_CODE (XEXP (x, 0)) == PRE_DEC) + fputs (".a", file); + } + else + output_operand_lossage ("invalid operand to %U code"); + return; + + case 'N' : + /* Print a constant value negated. */ + if (GET_CODE (x) == CONST_INT) + output_addr_const (file, GEN_INT (- INTVAL (x))); + else + output_operand_lossage ("invalid operand to %N code"); + return; + + case 'X' : + /* Print a const_int in hex. Used in comments. */ + if (GET_CODE (x) == CONST_INT) + fprintf (file, +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + "0x%x", +#else + "0x%lx", +#endif + INTVAL (x)); + return; + + case '#' : + fputs (IMMEDIATE_PREFIX, file); + return; + +#if 0 /* ??? no longer used */ + case '@' : + fputs (reg_names[SDA_REGNUM], file); + return; +#endif + + case 0 : + /* Do nothing special. */ + break; + + default : + /* Unknown flag. */ + output_operand_lossage ("invalid operand output code"); + } + + switch (GET_CODE (x)) + { + case REG : + fputs (reg_names[REGNO (x)], file); + break; + + case MEM : + fprintf (file, "@("); + if (GET_CODE (XEXP (x, 0)) == PRE_INC) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), + GET_MODE_SIZE (GET_MODE (x)))); + else if (GET_CODE (XEXP (x, 0)) == PRE_DEC) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), + - GET_MODE_SIZE (GET_MODE (x)))); + else + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case CONST_DOUBLE : + /* We handle SFmode constants here as output_addr_const doesn't. */ + if (GET_MODE (x) == SFmode) + { + REAL_VALUE_TYPE d; + long l; + + REAL_VALUE_FROM_CONST_DOUBLE (d, x); + REAL_VALUE_TO_TARGET_SINGLE (d, l); + fprintf (file, "0x%08lx", l); + break; + } + + /* Fall through. Let output_addr_const deal with it. */ + + default : + output_addr_const (file, x); + break; + } +} + +/* Print a memory address as an operand to reference that memory location. */ + +void +m32r_print_operand_address (file, addr) + FILE *file; + rtx addr; +{ + register rtx base, index = 0; + int offset = 0; + + switch (GET_CODE (addr)) + { + case REG : + fputs (reg_names[REGNO (addr)], file); + break; + + case PLUS : + if (GET_CODE (XEXP (addr, 0)) == CONST_INT) + offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1); + else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) + offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0); + else + base = XEXP (addr, 0), index = XEXP (addr, 1); + if (GET_CODE (base) == REG) + { + /* Print the offset first (if present) to conform to the manual. */ + if (index == 0) + { + if (offset != 0) + fprintf (file, "%d,", offset); + fputs (reg_names[REGNO (base)], file); + } + /* The chip doesn't support this, but left in for generality. */ + else if (GET_CODE (index) == REG) + fprintf (file, "%s,%s", + reg_names[REGNO (base)], reg_names[REGNO (index)]); + /* Not sure this can happen, but leave in for now. */ + else if (GET_CODE (index) == SYMBOL_REF) + { + output_addr_const (file, index); + fputc (',', file); + fputs (reg_names[REGNO (base)], file); + } + else + abort (); + } + else if (GET_CODE (base) == LO_SUM) + { + if (index != 0 + || GET_CODE (XEXP (base, 0)) != REG) + abort (); + if (small_data_operand (XEXP (base, 1), VOIDmode)) + fputs ("sda(", file); + else + fputs ("low(", file); + output_addr_const (file, plus_constant (XEXP (base, 1), offset)); + fputs ("),", file); + fputs (reg_names[REGNO (XEXP (base, 0))], file); + } + else + abort (); + break; + + case LO_SUM : + if (GET_CODE (XEXP (addr, 0)) != REG) + abort (); + if (small_data_operand (XEXP (addr, 1), VOIDmode)) + fputs ("sda(", file); + else + fputs ("low(", file); + output_addr_const (file, XEXP (addr, 1)); + fputs ("),", file); + fputs (reg_names[REGNO (XEXP (addr, 0))], file); + break; + + case PRE_INC : + case PRE_DEC : + /* We shouldn't get here as we've lost the mode of the memory object + (which says how much to inc/dec by). */ + abort (); + break; + + default : + output_addr_const (file, addr); + break; + } +} diff --git a/gnu/usr.bin/gcc/config/m32r/m32r.h b/gnu/usr.bin/gcc/config/m32r/m32r.h new file mode 100644 index 00000000000..99ab9c2281c --- /dev/null +++ b/gnu/usr.bin/gcc/config/m32r/m32r.h @@ -0,0 +1,1867 @@ +/* Definitions of target machine for GNU compiler, Mitsubishi M32R cpu. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Things to do: +- longlong.h? +*/ + +/* ??? Create elf.h and have svr4.h include it. */ +#include "svr4.h" + +#undef SWITCH_TAKES_ARG +#undef WORD_SWITCH_TAKES_ARG +#undef HANDLE_SYSV_PRAGMA +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE +#undef ASM_FILE_START +#undef ASM_OUTPUT_EXTERNAL_LIBCALL + +/* Print subsidiary information on the compiler version in use. */ +#define TARGET_VERSION fprintf (stderr, " (m32r)") + +/* Switch Recognition by gcc.c. Add -G xx support */ + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ +(DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') + +/* Names to predefine in the preprocessor for this target machine. */ +/* __M32R__ is defined by the existing compiler so we use that. */ +#define CPP_PREDEFINES "-Acpu(m32r) -Amachine(m32r) -D__M32R__" + +/* Additional flags for the preprocessor. */ +#define CPP_SPEC "" + +#define CC1_SPEC "%{G*}" + +#undef ASM_SPEC +#if 0 /* not supported yet */ +#define ASM_SPEC "%{v} %{mrelax:-relax}" +#else +#define ASM_SPEC "%{v}" +#endif + +#undef ASM_FINAL_SPEC + +#undef LINK_SPEC +#if 0 /* not supported yet */ +#define LINK_SPEC "%{v} %{mrelax:-relax}" +#else +#define LINK_SPEC "%{v}" +#endif + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:crt0.o%s crtsysc.o%s} crtinit.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtfini.o%s" + +#undef LIB_SPEC + +/* Run-time compilation parameters selecting different hardware subsets. */ + +extern int target_flags; + +/* If non-zero, tell the linker to do relaxing. + We don't do anything with the option, other than recognize it. + LINK_SPEC handles passing -relax to the linker. + This can cause incorrect debugging information as line numbers may + turn out wrong. This shouldn't be specified unless accompanied with -O2 + [where the user expects debugging information to be less accurate]. */ +#define TARGET_RELAX_MASK 1 + +/* For miscellaneous debugging purposes. */ +#define TARGET_DEBUG_MASK 2 +#define TARGET_DEBUG (target_flags & TARGET_DEBUG_MASK) + +/* Align loops to 32 byte boundaries (cache line size). */ +/* ??? This option is experimental and is not documented. */ +#define TARGET_ALIGN_LOOPS_MASK 4 +#define TARGET_ALIGN_LOOPS (target_flags & TARGET_ALIGN_LOOPS_MASK) + +/* Use old compare/branch support (kept around for awhile for + comparison and backoff purposes). */ +/* ??? This option is experimental and is not documented. + Eventually it will be deleted. */ +#define TARGET_OLD_COMPARE_MASK 8 +#define TARGET_OLD_COMPARE (target_flags & TARGET_OLD_COMPARE_MASK) + +/* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +#define TARGET_SWITCHES \ +{ \ +/* { "relax", TARGET_RELAX_MASK }, \ + { "no-relax", -TARGET_RELAX_MASK },*/ \ + { "debug", TARGET_DEBUG_MASK }, \ + { "align-loops", TARGET_ALIGN_LOOPS_MASK }, \ + { "no-align-loops", -TARGET_ALIGN_LOOPS_MASK }, \ + { "old-compare", TARGET_OLD_COMPARE_MASK }, \ + { "no-old-compare", -TARGET_OLD_COMPARE_MASK }, \ + SUBTARGET_SWITCHES \ + { "", TARGET_DEFAULT } \ +} + +#define TARGET_DEFAULT (0) + +#define SUBTARGET_SWITCHES + +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an + initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + fixed part of the option name, and the address of a variable. + The variable, type `char *', is set to the variable part of the + given option if the fixed part matches. The actual option name + is made by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the + given option is `-mshort-data-512', the variable `m88k_short_data' + will be set to the string `"512"'. + + extern char *m88k_short_data; + #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ + +extern char *m32r_model_string; +extern char *m32r_sdata_string; +#define TARGET_OPTIONS \ +{ \ + { "model=", &m32r_model_string }, \ + { "sdata=", &m32r_sdata_string }, \ +} + +/* Code Models + + Code models are used to select between two choices of two separate + possibilities (address space size, call insn to use): + + small: addresses use 24 bits, use bl to make calls + medium: addresses use 32 bits, use bl to make calls (*1) + large: addresses use 32 bits, use seth/add3/jl to make calls (*2) + + The fourth is "addresses use 24 bits, use seth/add3/jl to make calls" but + using this one doesn't make much sense. + + (*1) The linker may eventually be able to relax seth/add3 -> ld24. + (*2) The linker may eventually be able to relax seth/add3/jl -> bl. + + Internally these are recorded as TARGET_ADDR{24,32} and + TARGET_CALL{26,32}. + + The __model__ attribute can be used to select the code model to use when + accessing particular objects. */ + +enum m32r_model { M32R_MODEL_SMALL, M32R_MODEL_MEDIUM, M32R_MODEL_LARGE }; + +extern enum m32r_model m32r_model; +#define TARGET_MODEL_SMALL (m32r_model == M32R_MODEL_SMALL) +#define TARGET_MODEL_MEDIUM (m32r_model == M32R_MODEL_MEDIUM) +#define TARGET_MODEL_LARGE (m32r_model == M32R_MODEL_LARGE) +#define TARGET_ADDR24 (m32r_model == M32R_MODEL_SMALL) +#define TARGET_ADDR32 (! TARGET_ADDR24) +#define TARGET_CALL26 (! TARGET_CALL32) +#define TARGET_CALL32 (m32r_model == M32R_MODEL_LARGE) + +/* The default is the small model. */ +#define M32R_MODEL_DEFAULT "small" + +/* Small Data Area + + The SDA consists of sections .sdata, .sbss, and .scommon. + .scommon isn't a real section, symbols in it have their section index + set to SHN_M32R_SCOMMON, though support for it exists in the linker script. + + Two switches control the SDA: + + -G NNN - specifies the maximum size of variable to go in the SDA + + -msdata=foo - specifies how such variables are handled + + -msdata=none - small data area is disabled + + -msdata=sdata - small data goes in the SDA, special code isn't + generated to use it, and special relocs aren't + generated + + -msdata=use - small data goes in the SDA, special code is generated + to use the SDA and special relocs are generated + + The SDA is not multilib'd, it isn't necessary. + MULTILIB_EXTRA_OPTS is set in tmake_file to -msdata=sdata so multilib'd + libraries have small data in .sdata/SHN_M32R_SCOMMON so programs that use + -msdata=use will successfully link with them (references in header files + will cause the compiler to emit code that refers to library objects in + .data). ??? There can be a problem if the user passes a -G value greater + than the default and a library object in a header file is that size. + The default is 8 so this should be rare - if it occurs the user + is required to rebuild the libraries or use a smaller value for -G. +*/ + +/* Maximum size of variables that go in .sdata/.sbss. + The -msdata=foo switch also controls how small variables are handled. */ +#define SDATA_DEFAULT_SIZE 8 + +extern int g_switch_value; /* value of the -G xx switch */ +extern int g_switch_set; /* whether -G xx was passed. */ + +enum m32r_sdata { M32R_SDATA_NONE, M32R_SDATA_SDATA, M32R_SDATA_USE }; + +extern enum m32r_sdata m32r_sdata; +#define TARGET_SDATA_NONE (m32r_sdata == M32R_SDATA_NONE) +#define TARGET_SDATA_SDATA (m32r_sdata == M32R_SDATA_SDATA) +#define TARGET_SDATA_USE (m32r_sdata == M32R_SDATA_USE) + +/* Default is to disable the SDA + [for upward compatibility with previous toolchains]. */ +#define M32R_SDATA_DEFAULT "none" + +/* Define this macro as a C expression for the initializer of an array of + string to tell the driver program which options are defaults for this + target and thus do not need to be handled specially when using + `MULTILIB_OPTIONS'. */ +#define MULTILIB_DEFAULTS { "mmodel=small" } + +/* Sometimes certain combinations of command options do not make + sense on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + Don't use this macro to turn on various extra optimizations for + `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ + +extern void m32r_init (); + +#define OVERRIDE_OPTIONS \ +do { \ + /* These need to be done at start up. It's convenient to do them here. */ \ + m32r_init (); \ +} while (0) + +/* Define this macro if debugging can be performed even without a + frame pointer. If this macro is defined, GNU CC will turn on the + `-fomit-frame-pointer' option whenever `-O' is specified. */ +#define CAN_DEBUG_WITHOUT_FP + +/* Target machine storage layout. */ + +/* Define to use software floating point emulator for REAL_ARITHMETIC and + decimal <-> binary conversion. */ +#define REAL_ARITHMETIC + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. */ +#define BITS_BIG_ENDIAN 1 + +/* Define this if most significant byte of a word is the lowest numbered. */ +#define BYTES_BIG_ENDIAN 1 + +/* Define this if most significant word of a multiword number is the lowest + numbered. */ +#define WORDS_BIG_ENDIAN 1 + +/* Define this macro if WORDS_BIG_ENDIAN is not constant. This must + be a constant value with the same meaning as WORDS_BIG_ENDIAN, + which will be used only when compiling libgcc2.c. Typically the + value will be set based on preprocessor defines. */ +/*#define LIBGCC2_WORDS_BIG_ENDIAN 1*/ + +/* Number of bits in an addressable storage unit. */ +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ +#define BITS_PER_WORD 32 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD 4 + +/* Define this macro if it is advisable to hold scalars in registers + in a wider mode than that declared by the program. In such cases, + the value is constrained to be within the bounds of the declared + type, but kept valid in the wider mode. The signedness of the + extension may differ from that of the type. */ +#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ +if (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ +{ \ + (MODE) = SImode; \ +} + +/* Define this macro if the promotion described by `PROMOTE_MODE' + should also be done for outgoing function arguments. */ +/*#define PROMOTE_FUNCTION_ARGS*/ + +/* Likewise, if the function return value is promoted. + If defined, FUNCTION_VALUE must perform the same promotions done by + PROMOTE_MODE. */ +/*#define PROMOTE_FUNCTION_RETURN*/ + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ +#define POINTER_SIZE 32 + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY 32 + +/* Boundary (in *bits*) on which stack pointer should be aligned. */ +#define STACK_BOUNDARY 32 + +/* ALIGN FRAMES on word boundaries */ +#define M32R_STACK_ALIGN(LOC) (((LOC)+3) & ~3) + +/* Allocation boundary (in *bits*) for the code of a function. */ +#define FUNCTION_BOUNDARY 32 + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY 32 + +/* Every structure's size must be a multiple of this. */ +#define STRUCTURE_SIZE_BOUNDARY 8 + +/* A bitfield declared as `int' forces `int' alignment for the struct. */ +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* No data type wants to be aligned rounder than this. */ +#define BIGGEST_ALIGNMENT 32 + +/* The best alignment to use in cases where we have a choice. */ +#define FASTEST_ALIGNMENT 32 + +/* Make strings word-aligned so strcpy from constants will be faster. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST \ + && (ALIGN) < FASTEST_ALIGNMENT) \ + ? FASTEST_ALIGNMENT : (ALIGN)) + +/* Make arrays of chars word-aligned for the same reasons. */ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + (TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN)) + +/* Set this nonzero if move instructions will actually fail to work + when given unaligned data. */ +#define STRICT_ALIGNMENT 1 + +/* Layout of source language data types. */ + +#define SHORT_TYPE_SIZE 16 +#define INT_TYPE_SIZE 32 +#define LONG_TYPE_SIZE 32 +#define LONG_LONG_TYPE_SIZE 64 +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 64 +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* Define this as 1 if `char' should by default be signed; else as 0. */ +#define DEFAULT_SIGNED_CHAR 1 + +#define SIZE_TYPE "long unsigned int" +#define PTRDIFF_TYPE "long int" +#define WCHAR_TYPE "short unsigned int" +#define WCHAR_TYPE_SIZE 16 + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ +#define FIRST_PSEUDO_REGISTER 18 + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + + 0-3 - arguments/results + 4-5 - call used [4 is used as a tmp during prologue/epilogue generation] + 6 - call used, gptmp + 7 - call used, static chain pointer + 8-11 - call saved + 12 - call saved [reserved for global pointer] + 13 - frame pointer + 14 - subroutine link register + 15 - stack pointer + 16 - arg pointer + 17 - carry flag + + By default, the extension registers are not available. */ + +#define FIXED_REGISTERS \ +{ 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 1, \ + 1, 0 } + +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. */ + +#define CALL_USED_REGISTERS \ +{ 1, 1, 1, 1, 1, 1, 1, 1, \ + 0, 0, 0, 0, 0, 0, 1, 1, \ + 1, 1 } + +/* Zero or more C statements that may conditionally modify two variables + `fixed_regs' and `call_used_regs' (both of type `char []') after they + have been initialized from the two preceding macros. + + This is necessary in case the fixed or call-clobbered registers depend + on target flags. + + You need not define this macro if it has no work to do. */ + +/*#define CONDITIONAL_REGISTER_USAGE*/ + +/* If defined, an initializer for a vector of integers, containing the + numbers of hard registers in the order in which GNU CC should + prefer to use them (from most preferred to least). */ +#if 1 /* better for int code */ +#define REG_ALLOC_ORDER \ +{ 4, 5, 6, 7, 2, 3, 8, 9, 10, 11, 12, 13, 14, 0, 1, 15, 16, 17 } +#else /* better for fp code at expense of int code */ +#define REG_ALLOC_ORDER \ +{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 } +#endif + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. */ +#define HARD_REGNO_NREGS(REGNO, MODE) \ +((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ +extern unsigned int m32r_hard_regno_mode_ok[]; +extern unsigned int m32r_mode_class[]; +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ +((m32r_hard_regno_mode_ok[REGNO] & m32r_mode_class[MODE]) != 0) + +/* A C expression that is nonzero if it is desirable to choose + register allocation so as to avoid move instructions between a + value of mode MODE1 and a value of mode MODE2. + + If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, + MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, + MODE2)' must be zero. */ + +/* Tie QI/HI/SI modes together. */ +#define MODES_TIEABLE_P(MODE1, MODE2) \ +(GET_MODE_CLASS (MODE1) == MODE_INT \ + && GET_MODE_CLASS (MODE2) == MODE_INT \ + && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \ + && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD) + +/* Register classes and constants. */ + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. + + It is important that any condition codes have class NO_REGS. + See `register_operand'. */ + +enum reg_class { + NO_REGS, CARRY_REG, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ +#define REG_CLASS_NAMES \ +{ "NO_REGS", "CARRY_REG", "GENERAL_REGS", "ALL_REGS" } + +/* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS \ +{ {0}, {0x20000}, {0x1ffff}, {0x3ffff} } + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ +extern enum reg_class m32r_regno_reg_class[]; +#define REGNO_REG_CLASS(REGNO) \ +(m32r_regno_reg_class[REGNO]) + +/* The class value for index registers, and the one for base regs. */ +#define INDEX_REG_CLASS GENERAL_REGS +#define BASE_REG_CLASS GENERAL_REGS + +/* Get reg_class from a letter such as appears in the machine description. */ +#define REG_CLASS_FROM_LETTER(C) NO_REGS + +/* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ +#define REGNO_OK_FOR_BASE_P(REGNO) \ +((REGNO) < FIRST_PSEUDO_REGISTER \ + ? GPR_P (REGNO) || (REGNO) == ARG_POINTER_REGNUM \ + : GPR_P (reg_renumber[REGNO])) +#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) + +/* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. */ +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ +(CLASS) + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ +#define CLASS_MAX_NREGS(CLASS, MODE) \ +((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* The letters I, J, K, L, M, N, O, P in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ +/* 'I' is used for 8 bit signed immediates. + 'J' is used for 16 bit signed immediates. + 'K' is used for 16 bit unsigned immediates. + 'L' is used for 16 bit immediates left shifted by 16 (sign ???). + 'M' is used for 24 bit unsigned immediates. + 'N' is used for any 32 bit non-symbolic value. + 'O' is used for 5 bit unsigned immediates (shift count). + 'P' is used for 16 bit signed immediates for compares + (values in the range -32767 to +32768). */ + +/* local to this file */ +#define INT8_P(X) ((unsigned) ((X) + 0x80) < 0x100) +#define INT16_P(X) ((unsigned) ((X) + 0x8000) < 0x10000) +#define CMP_INT16_P(X) ((unsigned) ((X) - 1 + 0x8000) < 0x10000) +#define UINT16_P(X) ((unsigned) (X) < 0x10000) +#define UPPER16_P(X) (((X) & ~0xffff0000) == 0) +#define UINT24_P(X) ((unsigned) (X) < 0x1000000) +#define INT32_P(X) ((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \ + && (X) <= (unsigned HOST_WIDE_INT) 0xffffffff) +#define UINT5_P(X) ((unsigned) (X) < 32) + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ +((C) == 'I' ? INT8_P (VALUE) \ + : (C) == 'J' ? INT16_P (VALUE) \ + : (C) == 'K' ? UINT16_P (VALUE) \ + : (C) == 'L' ? UPPER16_P (VALUE) \ + : (C) == 'M' ? UINT24_P (VALUE) \ + : (C) == 'N' ? INT32_P (VALUE) \ + : (C) == 'O' ? UINT5_P (VALUE) \ + : (C) == 'P' ? CMP_INT16_P (VALUE) \ + : 0) + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. + For the m32r, handle a few constants inline. + ??? We needn't treat DI and DF modes differently, but for now we do. */ +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ +((C) == 'G' ? easy_di_const (VALUE) \ + : (C) == 'H' ? easy_df_const (VALUE) \ + : 0) + +/* A C expression that defines the optional machine-dependent constraint + letters that can be used to segregate specific types of operands, + usually memory references, for the target machine. It should return 1 if + VALUE corresponds to the operand type represented by the constraint letter + C. If C is not defined as an extra constraint, the value returned should + be 0 regardless of VALUE. */ +/* Q is for symbolic addresses loadable with ld24. + R is for symbolic addresses when ld24 can't be used. */ +#define EXTRA_CONSTRAINT(VALUE, C) \ +((C) == 'Q' \ + ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF) \ + || addr24_operand (VALUE, VOIDmode)) \ + : (C) == 'R' \ + ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF) \ + || addr32_operand (VALUE, VOIDmode)) \ + : 0) + +/* Stack layout and stack pointer usage. */ + +/* Define this macro if pushing a word onto the stack moves the stack + pointer to a smaller address. */ +#define STACK_GROWS_DOWNWARD + +/* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset from the frame pointer. */ +/*#define FRAME_GROWS_DOWNWARD*/ + +/* Offset from frame pointer to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ +/* The frame pointer points at the same place as the stack pointer, except if + alloca has been called. */ +#define STARTING_FRAME_OFFSET \ +M32R_STACK_ALIGN (current_function_outgoing_args_size) + +/* Offset from the stack pointer register to the first location at which + outgoing arguments are placed. */ +#define STACK_POINTER_OFFSET 0 + +/* Offset of first parameter from the argument pointer register value. */ +#define FIRST_PARM_OFFSET(FNDECL) 0 + +/* A C expression whose value is RTL representing the address in a + stack frame where the pointer to the caller's frame is stored. + Assume that FRAMEADDR is an RTL expression for the address of the + stack frame itself. + + If you don't define this macro, the default is to return the value + of FRAMEADDR--that is, the stack frame address is also the address + of the stack word that points to the previous frame. */ +/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/ + +/* A C expression whose value is RTL representing the value of the + return address for the frame COUNT steps up from the current frame. + FRAMEADDR is the frame pointer of the COUNT frame, or the frame + pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' + is defined. */ +/* The current return address is in r14. */ +#if 0 /* The default value should work. */ +#define RETURN_ADDR_RTX(COUNT, FRAME) \ +(((COUNT) == -1) \ + ? gen_rtx (REG, Pmode, 14) \ + : copy_to_reg (gen_rtx (MEM, Pmode, \ + memory_address (Pmode, plus_constant ((FRAME), UNITS_PER_WORD))))) +#endif + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 15 + +/* Base register for access to local variables of the function. */ +#define FRAME_POINTER_REGNUM 13 + +/* Base register for access to arguments of the function. */ +#define ARG_POINTER_REGNUM 16 + +/* The register number of the return address pointer register, which + is used to access the current function's return address from the + stack. On some machines, the return address is not at a fixed + offset from the frame pointer or stack pointer or argument + pointer. This register can be defined to point to the return + address on the stack, and then be converted by `ELIMINABLE_REGS' + into either the frame pointer or stack pointer. + + Do not define this macro unless there is no other way to get the + return address from the stack. */ +/* ??? revisit */ +/* #define RETURN_ADDRESS_POINTER_REGNUM */ + +/* Register in which static-chain is passed to a function. This must + not be a register used by the prologue. */ +#define STATIC_CHAIN_REGNUM 7 + +/* These aren't official macros. */ +#define PROLOGUE_TMP_REGNUM 4 +#define RETURN_ADDR_REGNUM 14 +/* #define GP_REGNUM 12 */ +#define CARRY_REGNUM 17 +#define M32R_MAX_INT_REGS 16 + +#define GPR_P(REGNO) ((unsigned) (REGNO) < M32R_MAX_INT_REGS) + +/* Eliminating the frame and arg pointers. */ + +/* A C expression which is nonzero if a function must have and use a + frame pointer. This expression is evaluated in the reload pass. + If its value is nonzero the function will have a frame pointer. */ +#define FRAME_POINTER_REQUIRED \ +(current_function_calls_alloca) + +#if 0 +/* C statement to store the difference between the frame pointer + and the stack pointer values immediately after the function prologue. + If `ELIMINABLE_REGS' is defined, this macro will be not be used and + need not be defined. */ +#define INITIAL_FRAME_POINTER_OFFSET(VAR) \ +((VAR) = m32r_compute_frame_size (get_frame_size ())) +#endif + +/* If defined, this macro specifies a table of register pairs used to + eliminate unneeded registers that point into the stack frame. If + it is not defined, the only elimination attempted by the compiler + is to replace references to the frame pointer with references to + the stack pointer. + + Note that the elimination of the argument pointer with the stack + pointer is specified first since that is the preferred elimination. */ + +#define ELIMINABLE_REGS \ +{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }} \ + +/* A C expression that returns non-zero if the compiler is allowed to + try to replace register number FROM-REG with register number + TO-REG. This macro need only be defined if `ELIMINABLE_REGS' is + defined, and will usually be the constant 1, since most of the + cases preventing register elimination are things that the compiler + already knows about. */ + +#define CAN_ELIMINATE(FROM, TO) \ +((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \ + ? ! frame_pointer_needed \ + : 1) + +/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It + specifies the initial difference between the specified pair of + registers. This macro must be defined if `ELIMINABLE_REGS' is + defined. */ + +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ +{ \ + int size = m32r_compute_frame_size (get_frame_size ()); \ + \ + if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = 0; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ + (OFFSET) = size - current_function_pretend_args_size; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = size - current_function_pretend_args_size; \ + else \ + abort (); \ +} + +/* Function argument passing. */ + +/* When a prototype says `char' or `short', really pass an `int'. */ +#define PROMOTE_PROTOTYPES + +/* If defined, the maximum amount of space required for outgoing + arguments will be computed and placed into the variable + `current_function_outgoing_args_size'. No space will be pushed + onto the stack for each call; instead, the function prologue should + increase the stack frame size by this amount. */ +#define ACCUMULATE_OUTGOING_ARGS + +/* Define this macro if functions should assume that stack space has + been allocated for arguments even when their values are passed in + registers. + + The value of this macro is the size, in bytes, of the area + reserved for arguments passed in registers for the function + represented by FNDECL. + + This space can be allocated by the caller, or be a part of the + machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says + which. */ +#if 0 +#define REG_PARM_STACK_SPACE(FNDECL) \ +(M32R_MAX_PARM_REGS * UNITS_PER_WORD) +#endif + +/* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + SIZE is the number of bytes of arguments passed on the stack. */ +#define RETURN_POPS_ARGS(DECL, FUNTYPE, SIZE) 0 + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. */ +#define CUMULATIVE_ARGS int + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ +((CUM) = 0) + +/* The number of registers used for parameter passing. Local to this file. */ +#define M32R_MAX_PARM_REGS 4 + +/* 1 if N is a possible register number for function argument passing. */ +#define FUNCTION_ARG_REGNO_P(N) \ +((unsigned) (N) < M32R_MAX_PARM_REGS) + +/* The ROUND_ADVANCE* macros are local to this file. */ +/* Round SIZE up to a word boundary. */ +#define ROUND_ADVANCE(SIZE) \ +(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Round arg MODE/TYPE up to the next word boundary. */ +#define ROUND_ADVANCE_ARG(MODE, TYPE) \ +((MODE) == BLKmode \ + ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ + : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) + +/* Round CUM up to the necessary point for argument MODE/TYPE. */ +#if 0 +#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \ +((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \ + > BITS_PER_WORD) \ + ? ((CUM) + 1 & ~1) \ + : (CUM)) +#else +#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) (CUM) +#endif + +/* Return boolean indicating arg of type TYPE and mode MODE will be passed in + a reg. This includes arguments that have to be passed by reference as the + pointer to them is passed in a reg if one is available (and that is what + we're given). + This macro is only used in this file. */ +#define PASS_IN_REG_P(CUM, MODE, TYPE, NAMED) \ +(ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) < M32R_MAX_PARM_REGS) + +/* Determine where to put an argument to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ +/* On the M32R the first M32R_MAX_PARM_REGS args are normally in registers + and the rest are pushed. */ +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +(PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED)) \ + ? gen_rtx (REG, (MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \ + : 0) + +/* ??? Quick hack to try to get varargs working the normal way. */ +#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ +(((! current_function_varargs || (NAMED)) \ + && PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED))) \ + ? gen_rtx (REG, (MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \ + : 0) + +/* A C expression for the number of words, at the beginning of an + argument, must be put in registers. The value must be zero for + arguments that are passed entirely in registers or that are entirely + pushed on the stack. + + On some machines, certain arguments must be passed partially in + registers and partially in memory. On these machines, typically the + first @var{n} words of arguments are passed in registers, and the rest + on the stack. If a multi-word argument (a @code{double} or a + structure) crosses that boundary, its first few words must be passed + in registers and the rest must be pushed. This macro tells the + compiler when this occurs, and how many of the words should go in + registers. */ +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ + function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED) + +/* A C expression that indicates when an argument must be passed by + reference. If nonzero for an argument, a copy of that argument is + made in memory and a pointer to the argument is passed instead of + the argument itself. The pointer is passed in whatever way is + appropriate for passing a pointer to that type. */ +/* All arguments greater than 8 bytes are passed this way. */ +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ +((TYPE) && int_size_in_bytes (TYPE) > 8) + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ +((CUM) = (ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \ + + ROUND_ADVANCE_ARG ((MODE), (TYPE)))) + +/* If defined, a C expression that gives the alignment boundary, in bits, + of an argument with the specified mode and type. If it is not defined, + PARM_BOUNDARY is used for all arguments. */ +#if 0 +/* We assume PARM_BOUNDARY == UNITS_PER_WORD here. */ +#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ +(((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ + ? PARM_BOUNDARY \ + : 2 * PARM_BOUNDARY) +#endif + +#if 0 +/* If defined, is a C expression that produces the machine-specific + code for a call to `__builtin_saveregs'. This code will be moved + to the very beginning of the function, before any parameter access + are made. The return value of this function should be an RTX that + contains the value to use as the return of `__builtin_saveregs'. + + The argument ARGS is a `tree_list' containing the arguments that + were passed to `__builtin_saveregs'. + + If this macro is not defined, the compiler will output an ordinary + call to the library function `__builtin_saveregs'. */ +extern struct rtx *m32r_expand_builtin_savergs (); +#define EXPAND_BUILTIN_SAVEREGS(ARGS) m32r_expand_builtin_saveregs (ARGS) +#endif + +/* This macro offers an alternative + to using `__builtin_saveregs' and defining the macro + `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register + arguments into the stack so that all the arguments appear to have + been passed consecutively on the stack. Once this is done, you + can use the standard implementation of varargs that works for + machines that pass all their arguments on the stack. + + The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, + containing the values that obtain after processing of the named + arguments. The arguments MODE and TYPE describe the last named + argument--its machine mode and its data type as a tree node. + + The macro implementation should do two things: first, push onto the + stack all the argument registers *not* used for the named + arguments, and second, store the size of the data thus pushed into + the `int'-valued variable whose name is supplied as the argument + PRETEND_SIZE. The value that you store here will serve as + additional offset for setting up the stack frame. + + If the argument NO_RTL is nonzero, it means that the + arguments of the function are being analyzed for the second time. + This happens for an inline function, which is not actually + compiled until the end of the source file. The macro + `SETUP_INCOMING_VARARGS' should not generate any instructions in + this case. */ + +#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_SIZE, NO_RTL) \ +m32r_setup_incoming_varargs (&ARGS_SO_FAR, MODE, TYPE, &PRETEND_SIZE, NO_RTL) + +/* Function results. */ + +/* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ +#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0) + +/* Define how to find the value returned by a library function + assuming the value has mode MODE. */ +#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + +/* 1 if N is a possible register number for a function value + as seen by the caller. */ +/* ??? What about r1 in DI/DF values. */ +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + +/* A C expression which can inhibit the returning of certain function + values in registers, based on the type of value. A nonzero value says + to return the function value in memory, just as large structures are + always returned. Here TYPE will be a C expression of type `tree', + representing the data type of the value. */ +#define RETURN_IN_MEMORY(TYPE) \ +(int_size_in_bytes (TYPE) > 8) + +/* Tell GCC to use RETURN_IN_MEMORY. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Register in which address to store a structure value + is passed to a function, or 0 to use `invisible' first argument. */ +#define STRUCT_VALUE 0 + +/* Function entry and exit. */ + +/* Initialize data used by insn expanders. This is called from + init_emit, once for each function, before code is generated. */ +#define INIT_EXPANDERS m32r_init_expanders () + +/* This macro generates the assembly code for function entry. + FILE is a stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. */ +#define FUNCTION_PROLOGUE(FILE, SIZE) \ +m32r_output_function_prologue (FILE, SIZE) + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ +#define EXIT_IGNORE_STACK 1 + +/* This macro generates the assembly code for function exit, + on machines that need it. If FUNCTION_EPILOGUE is not defined + then individual return instructions are generated for each + return statement. Args are same as for FUNCTION_PROLOGUE. + + The function epilogue should not depend on the current stack pointer! + It should use the frame pointer only. This is mandatory because + of alloca; we also take advantage of it to omit stack adjustments + before returning. */ +#define FUNCTION_EPILOGUE(FILE, SIZE) \ +m32r_output_function_epilogue (FILE, SIZE) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ +#define FUNCTION_PROFILER(FILE, LABELNO) + +/* Trampolines. */ + +/* On the M32R, the trampoline is + + ld24 r7,STATIC + ld24 r6,FUNCTION + jmp r6 + nop + + ??? Need addr32 support. +*/ + +/* Length in bytes of the trampoline for entering a nested function. */ +#define TRAMPOLINE_SIZE 12 + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +do { \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 0)), \ + plus_constant ((CXT), 0xe7000000)); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), \ + plus_constant ((FNADDR), 0xe6000000)); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 8)), \ + GEN_INT (0x1fc67000)); \ + emit_insn (gen_flush_icache (validize_mem (gen_rtx (MEM, SImode, TRAMP)))); \ +} while (0) + +/* Library calls. */ + +/* Generate calls to memcpy, memcmp and memset. */ +#define TARGET_MEM_FUNCTIONS + +/* Addressing modes, and classification of registers for them. */ + +/* Maximum number of registers that can appear in a valid memory address. */ +#define MAX_REGS_PER_ADDRESS 1 + +/* We have post-inc load and pre-dec,pre-inc store, + but only for 4 byte vals. */ +#if 0 +#define HAVE_PRE_DECREMENT +#define HAVE_PRE_INCREMENT +#define HAVE_POST_INCREMENT +#endif + +/* Recognize any constant value that is a valid address. */ +#define CONSTANT_ADDRESS_P(X) \ +(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST) + +/* Nonzero if the constant value X is a legitimate general operand. + We don't allow (plus symbol large-constant) as the relocations can't + describe it. INTVAL > 32767 handles both 16 bit and 24 bit relocations. + We allow all CONST_DOUBLE's as the md file patterns will force the + constant to memory if they can't handle them. */ + +#define LEGITIMATE_CONSTANT_P(X) \ +(! (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ + && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ + && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (X, 0), 1)) > 32767)) + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + +#ifdef REG_OK_STRICT + +/* Nonzero if X is a hard reg that can be used as a base reg. */ +#define REG_OK_FOR_BASE_P(X) GPR_P (REGNO (X)) +/* Nonzero if X is a hard reg that can be used as an index. */ +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) + +#else + +/* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ +#define REG_OK_FOR_BASE_P(X) \ +(GPR_P (REGNO (X)) \ + || (REGNO (X)) == ARG_POINTER_REGNUM \ + || REGNO (X) >= FIRST_PSEUDO_REGISTER) +/* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) + +#endif + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. */ + +/* local to this file */ +#define RTX_OK_FOR_BASE_P(X) \ +(REG_P (X) && REG_OK_FOR_BASE_P (X)) + +/* local to this file */ +#define RTX_OK_FOR_OFFSET_P(X) \ +(GET_CODE (X) == CONST_INT && INT16_P (INTVAL (X))) + +/* local to this file */ +#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \ +(GET_CODE (X) == PLUS \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ + && RTX_OK_FOR_OFFSET_P (XEXP (X, 1))) + +/* local to this file */ +#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \ +(GET_CODE (X) == LO_SUM \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ + && CONSTANT_P (XEXP (X, 1))) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ if (RTX_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \ + goto ADDR; \ + if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X))) \ + goto ADDR; \ +} + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. + + ??? Is there anything useful we can do here for the M32R? */ + +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) + +/* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. */ +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ +do { \ + if (GET_CODE (ADDR) == PRE_DEC) \ + goto LABEL; \ + if (GET_CODE (ADDR) == PRE_INC) \ + goto LABEL; \ + if (GET_CODE (ADDR) == POST_INC) \ + goto LABEL; \ +} while (0) + +/* Condition code usage. */ + +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, + return the mode to be used for the comparison. */ +extern enum machine_mode m32r_select_cc_mode (); +#define SELECT_CC_MODE(OP, X, Y) \ +m32r_select_cc_mode (OP, X, Y) + +/* Return non-zero if SELECT_CC_MODE will never return MODE for a + floating point inequality comparison. */ +#define REVERSIBLE_CC_MODE(MODE) 1 /*???*/ + +/* Costs. */ + +/* ??? I'm quite sure I don't understand enough of the subtleties involved + in choosing the right numbers to use here, but there doesn't seem to be + enough documentation on this. What I've done is define an insn to cost + 4 "units" and work from there. COSTS_N_INSNS (N) is defined as (N) * 4 - 2 + so that seems reasonable. Some values are supposed to be defined relative + to each other and thus aren't necessarily related to COSTS_N_INSNS. */ + +/* Compute the cost of computing a constant rtl expression RTX + whose rtx-code is CODE. The body of this macro is a portion + of a switch statement. If the code is computed here, + return it with a return statement. Otherwise, break from the switch. */ +/* Small integers are as cheap as registers. 4 byte values can be fetched + as immediate constants - let's give that the cost of an extra insn. */ +#define CONST_COSTS(X, CODE, OUTER_CODE) \ + case CONST_INT : \ + if (INT16_P (INTVAL (X))) \ + return 0; \ + /* fall through */ \ + case CONST : \ + case LABEL_REF : \ + case SYMBOL_REF : \ + return 4; \ + case CONST_DOUBLE : \ + { \ + rtx high, low; \ + split_double (X, &high, &low); \ + return 4 * (!INT16_P (INTVAL (high)) \ + + !INT16_P (INTVAL (low))); \ + } + +/* Compute the cost of an address. */ +#define ADDRESS_COST(ADDR) m32r_address_cost (ADDR) + +/* Compute extra cost of moving data between one register class + and another. */ +#define REGISTER_MOVE_COST(CLASS1, CLASS2) 2 + +/* Compute the cost of moving data between registers and memory. */ +/* Memory is 3 times as expensive as registers. + ??? Is that the right way to look at it? */ +#define MEMORY_MOVE_COST(MODE) \ +(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12) + +/* The cost of a branch insn. */ +/* A value of 2 here causes GCC to avoid using branches in comparisons like + while (a < N && a). Branches aren't that expensive on the M32R so + we define this as 1. Defining it as 2 had a heavy hit in fp-bit.c. */ +#define BRANCH_COST 1 + +/* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. The purpose for the cost of MULT is to encourage + `synth_mult' to find a synthetic multiply when reasonable. + + If we need more than 12 insns to do a multiply, then go out-of-line, + since the call overhead will be < 10% of the cost of the multiply. */ +#define RTX_COSTS(X, CODE, OUTER_CODE) \ + case MULT : \ + return COSTS_N_INSNS (3); \ + case DIV : \ + case UDIV : \ + case MOD : \ + case UMOD : \ + return COSTS_N_INSNS (10); \ + +/* Nonzero if access to memory by bytes is slow and undesirable. + For RISC chips, it means that access to memory by bytes is no + better than access by words when possible, so grab a whole word + and maybe make use of that. */ +#define SLOW_BYTE_ACCESS 1 + +/* Define this macro if it is as good or better to call a constant + function address than to call an address kept in a register. */ +#define NO_FUNCTION_CSE + +/* Define this macro if it is as good or better for a function to call + itself with an explicit address than to call an address kept in a + register. */ +#define NO_RECURSIVE_FUNCTION_CSE + +/* Enable the register move pass. + This is useful for machines with only 2 address instructions. + It's not currently enabled by default because on the stanford benchmarks + the improvement wasn't significant and in a couple of cases caused a + significant de-optimization. */ +/* #define ENABLE_REGMOVE_PASS */ + +/* Section selection. */ + +#define TEXT_SECTION_ASM_OP "\t.section .text" +#define DATA_SECTION_ASM_OP "\t.section .data" +#define RODATA_SECTION_ASM_OP "\t.section .rodata" +#define BSS_SECTION_ASM_OP "\t.section .bss" +#define SDATA_SECTION_ASM_OP "\t.section .sdata" +#define SBSS_SECTION_ASM_OP "\t.section .sbss" +/* This one is for svr4.h. */ +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP "\t.section .rodata" + +/* A list of names for sections other than the standard two, which are + `in_text' and `in_data'. You need not define this macro + on a system with no other sections (that GCC needs to use). */ +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_sdata, in_sbss, in_const, in_ctors, in_dtors + +/* One or more functions to be defined in "varasm.c". These + functions should do jobs analogous to those of `text_section' and + `data_section', for your additional sections. Do not define this + macro if you do not define `EXTRA_SECTIONS'. */ +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ +CONST_SECTION_FUNCTION \ +CTORS_SECTION_FUNCTION \ +DTORS_SECTION_FUNCTION \ +SDATA_SECTION_FUNCTION \ +SBSS_SECTION_FUNCTION + +#define SDATA_SECTION_FUNCTION \ +void \ +sdata_section () \ +{ \ + if (in_section != in_sdata) \ + { \ + fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \ + in_section = in_sdata; \ + } \ +} \ + +#define SBSS_SECTION_FUNCTION \ +void \ +sbss_section () \ +{ \ + if (in_section != in_sbss) \ + { \ + fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \ + in_section = in_sbss; \ + } \ +} \ + +/* A C statement or statements to switch to the appropriate section for + output of EXP. You can assume that EXP is either a `VAR_DECL' node + or a constant of some sort. RELOC indicates whether the initial value + of EXP requires link-time relocations. */ +extern void m32r_select_section (); +#undef SELECT_SECTION +#define SELECT_SECTION(EXP, RELOC) m32r_select_section ((EXP), (RELOC)) + +/* A C statement or statements to switch to the appropriate section for + output of RTX in mode MODE. You can assume that RTX + is some kind of constant in RTL. The argument MODE is redundant + except in the case of a `const_int' rtx. Select the section by + calling `text_section' or one of the alternatives for other + sections. + + Do not define this macro if you put all constants in the read-only + data section. */ + +#undef SELECT_RTX_SECTION + +/* Define this macro if jump tables (for tablejump insns) should be + output in the text section, along with the assembler instructions. + Otherwise, the readonly data section is used. + This macro is irrelevant if there is no separate readonly data section. */ +/*#define JUMP_TABLES_IN_TEXT_SECTION*/ + +/* Define this macro if references to a symbol must be treated + differently depending on something about the variable or + function named by the symbol (such as what section it is in). + + The macro definition, if any, is executed immediately after the + rtl for DECL or other node is created. + The value of the rtl will be a `mem' whose address is a + `symbol_ref'. + + The usual thing for this macro to do is to store a flag in the + `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified + name string in the `symbol_ref' (if one bit is not enough + information). */ + +#define SDATA_FLAG_CHAR '@' +/* Small objects are recorded with no prefix for space efficiency since + they'll be the most common. This isn't the case if the user passes + -mmodel={medium|large} and one could choose to not mark symbols that + are the default, but that complicates things. */ +/*#define SMALL_FLAG_CHAR '#'*/ +#define MEDIUM_FLAG_CHAR '%' +#define LARGE_FLAG_CHAR '&' + +#define SDATA_NAME_P(NAME) (*(NAME) == SDATA_FLAG_CHAR) +/*#define SMALL_NAME_P(NAME) (*(NAME) == SMALL_FLAG_CHAR)*/ +#define SMALL_NAME_P(NAME) (! ENCODED_NAME_P (NAME) && ! LIT_NAME_P (NAME)) +#define MEDIUM_NAME_P(NAME) (*(NAME) == MEDIUM_FLAG_CHAR) +#define LARGE_NAME_P(NAME) (*(NAME) == LARGE_FLAG_CHAR) +/* For string literals, etc. */ +#define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.') + +#define ENCODED_NAME_P(SYMBOL_NAME) \ +(SDATA_NAME_P (SYMBOL_NAME) \ + /*|| SMALL_NAME_P (SYMBOL_NAME)*/ \ + || MEDIUM_NAME_P (SYMBOL_NAME) \ + || LARGE_NAME_P (SYMBOL_NAME)) + +extern void m32r_encode_section_info (); +#define ENCODE_SECTION_INFO(DECL) m32r_encode_section_info (DECL) + +/* Decode SYM_NAME and store the real name part in VAR, sans + the characters that encode section info. Define this macro if + ENCODE_SECTION_INFO alters the symbol's name string. */ +/* Note that we have to handle symbols like "%*start". */ +#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \ +do { \ + (VAR) = (SYMBOL_NAME) + ENCODED_NAME_P (SYMBOL_NAME); \ + (VAR) += *(VAR) == '*'; \ +} while (0) + +/* PIC */ + +/* The register number of the register used to address a table of static + data addresses in memory. In some cases this register is defined by a + processor's ``application binary interface'' (ABI). When this macro + is defined, RTL is generated for this register once, as with the stack + pointer and frame pointer registers. If this macro is not defined, it + is up to the machine-dependent files to allocate such a register (if + necessary). */ +/*#define PIC_OFFSET_TABLE_REGNUM 12*/ + +/* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is + clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM + is not defined. */ +/* This register is call-saved on the M32R. */ +/*#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED*/ + +/* By generating position-independent code, when two different programs (A + and B) share a common library (libC.a), the text of the library can be + shared whether or not the library is linked at the same address for both + programs. In some of these environments, position-independent code + requires not only the use of different addressing modes, but also + special code to enable the use of these addressing modes. + + The FINALIZE_PIC macro serves as a hook to emit these special + codes once the function is being compiled into assembly code, but not + before. (It is not done before, because in the case of compiling an + inline function, it would lead to multiple PIC prologues being + included in functions which used inline functions and were compiled to + assembly language.) */ + +/*#define FINALIZE_PIC m32r_finalize_pic ()*/ + +/* A C expression that is nonzero if X is a legitimate immediate + operand on the target machine when generating position independent code. + You can assume that X satisfies CONSTANT_P, so you need not + check this. You can also assume `flag_pic' is true, so you need not + check it either. You need not define this macro if all constants + (including SYMBOL_REF) can be immediate operands when generating + position independent code. */ +/*#define LEGITIMATE_PIC_OPERAND_P(X)*/ + +/* Control the assembler format that we output. */ + +/* Output at beginning of assembler file. */ +extern void m32r_asm_file_start (); +#define ASM_FILE_START(FILE) m32r_asm_file_start (FILE) + +/* A C string constant describing how to begin a comment in the target + assembler language. The compiler assumes that the comment will + end at the end of the line. */ +#define ASM_COMMENT_START ";" + +/* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ +#define ASM_APP_ON "" + +/* Output to assembler file text saying following lines + no longer contain unusual constructs. */ +#define ASM_APP_OFF "" + +/* This is how to output an assembler line defining a `char' constant. */ +#define ASM_OUTPUT_CHAR(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.byte\t"); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an assembler line defining a `short' constant. */ +#define ASM_OUTPUT_SHORT(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.hword\t"); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an assembler line defining an `int' constant. + We also handle symbol output here. */ +#define ASM_OUTPUT_INT(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.word\t"); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an assembler line defining a `float' constant. */ +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ +do { \ + long t; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.word\t0x%lx %s %s\n", \ + t, ASM_COMMENT_START, str); \ +} while (0) + +/* This is how to output an assembler line defining a `double' constant. */ +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ +do { \ + long t[2]; \ + char str[30]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.word\t0x%lx %s %s\n\t.word\t0x%lx\n", \ + t[0], ASM_COMMENT_START, str, t[1]); \ +} while (0) + +/* This is how to output an assembler line for a numeric constant byte. */ +#define ASM_OUTPUT_BYTE(FILE, VALUE) \ + fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) + +/* The assembler's parentheses characters. */ +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ +/* On the M32R we need to ensure the next instruction starts on a 32 bit + boundary [the previous insn must either be 2 16 bit insns or 1 32 bit]. */ +#define ASM_OUTPUT_LABEL(FILE, NAME) \ +do { \ + assemble_name (FILE, NAME); \ + fputs (":\n", FILE); \ +} while (0) + +/* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ +#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ +do { \ + fputs ("\t.global\t", FILE); \ + assemble_name (FILE, NAME); \ + fputs ("\n", FILE); \ +} while (0) + +/* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. */ +#undef ASM_OUTPUT_LABELREF +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ +do { \ + char *real_name; \ + STRIP_NAME_ENCODING (real_name, (NAME)); \ + fprintf (FILE, "%s%s", USER_LABEL_PREFIX, real_name); \ +} while (0) + +/* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +do { \ + (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10); \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)); \ +} while (0) + +/* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ +#define REGISTER_NAMES \ +{ \ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "fp", "lr", "sp", \ + "ap", "cbit" \ +} + +/* If defined, a C initializer for an array of structures containing + a name and a register number. This macro defines additional names + for hard registers, thus allowing the `asm' option in declarations + to refer to registers using alternate names. */ +#define ADDITIONAL_REGISTER_NAMES \ +{ \ + /*{ "gp", GP_REGNUM },*/ \ + { "r13", FRAME_POINTER_REGNUM }, \ + { "r14", RETURN_ADDR_REGNUM }, \ + { "r15", STACK_POINTER_REGNUM }, \ +} + +/* A C expression which evaluates to true if CODE is a valid + punctuation character for use in the `PRINT_OPERAND' macro. */ +extern char m32r_punct_chars[]; +#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ +m32r_punct_chars[(unsigned char) (CHAR)] + +/* Print operand X (an rtx) in assembler syntax to file FILE. + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. + For `%' followed by punctuation, CODE is the punctuation and X is null. */ +#define PRINT_OPERAND(FILE, X, CODE) \ +m32r_print_operand (FILE, X, CODE) + +/* A C compound statement to output to stdio stream STREAM the + assembler syntax for an instruction operand that is a memory + reference whose address is ADDR. ADDR is an RTL expression. + + On some machines, the syntax for a symbolic address depends on + the section that the address refers to. On these machines, + define the macro `ENCODE_SECTION_INFO' to store the information + into the `symbol_ref', and then check for it here. */ +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ +m32r_print_operand_address (FILE, ADDR) + +/* If defined, C string expressions to be used for the `%R', `%L', + `%U', and `%I' options of `asm_fprintf' (see `final.c'). These + are useful when a single `md' file must support multiple assembler + formats. In that case, the various `tm.h' files can define these + macros differently. */ +#define REGISTER_PREFIX "" +#define LOCAL_LABEL_PREFIX ".L" +#define USER_LABEL_PREFIX "" +#define IMMEDIATE_PREFIX "#" + +/* This is how to output an element of a case-vector that is absolute. */ +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ +do { \ + char label[30]; \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ + fprintf (FILE, "\t.word\t"); \ + assemble_name (FILE, label); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an element of a case-vector that is relative. */ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +do { \ + char label[30]; \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ + fprintf (FILE, "\t.word\t"); \ + assemble_name (FILE, label); \ + fprintf (FILE, "-"); \ + ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \ + assemble_name (FILE, label); \ + fprintf (FILE, ")\n"); \ +} while (0) + +/* A C expression to output text to align the location counter in the way + that is desirable at the beginning of a loop. */ +/* On the M32R, align loops to 32 byte boundaries (cache line size) + if -malign-loops. */ +#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ +do { if (TARGET_ALIGN_LOOPS) ASM_OUTPUT_ALIGN (FILE, 5); } while (0) + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ +/* .balign is used to avoid confusion. */ +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ +do { if ((LOG) != 0) fprintf (FILE, "\t.balign %d\n", 1 << (LOG)); } while (0) + +/* Like `ASM_OUTPUT_COMMON' except takes the required alignment as a + separate, explicit argument. If you define this macro, it is used in + place of `ASM_OUTPUT_COMMON', and gives you more flexibility in + handling the required alignment of the variable. The alignment is + specified as the number of bits. */ + +#define SCOMMON_ASM_OP ".scomm" + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + if (! TARGET_SDATA_NONE \ + && (SIZE) > 0 && (SIZE) <= g_switch_value) \ + fprintf ((FILE), "\t%s\t", SCOMMON_ASM_OP); \ + else \ + fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ +} while (0) + +#if 0 /* not needed, delete later */ +/* Like `ASM_OUTPUT_LOCAL' except takes the required alignment as a + separate, explicit argument. If you define this macro, it is used in + place of `ASM_OUTPUT_LOCAL', and gives you more flexibility in + handling the required alignment of the variable. The alignment is + specified as the number of bits. */ + +extern void sbss_section (); + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + if ((SIZE) > 0 && (SIZE) <= g_switch_value) \ + { \ + sbss_section (); \ + ASM_OUTPUT_ALIGN (FILE, exact_log2 (ALIGN / BITS_PER_UNIT)); \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + ASM_OUTPUT_SKIP (FILE, SIZE); \ + if (!flag_inhibit_size_directive) \ + { \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", SIZE); \ + } \ + } \ + else \ + { \ + /* This is copied from svr4.h. */ \ + fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ + } \ +} while (0) +#endif + +/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a + separate, explicit argument. If you define this macro, it is used in + place of `ASM_OUTPUT_BSS', and gives you more flexibility in + handling the required alignment of the variable. The alignment is + specified as the number of bits. + + For the M32R we need sbss support. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ +do { \ + ASM_GLOBALIZE_LABEL (FILE, NAME); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +/* Debugging information. */ + +/* Generate DBX and DWARF debugging information. */ +#define DBX_DEBUGGING_INFO +#define DWARF_DEBUGGING_INFO + +/* Prefer STABS (for now). */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* How to renumber registers for dbx and gdb. */ +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* Turn off splitting of long stabs. */ +#define DBX_CONTIN_LENGTH 0 + +/* Miscellaneous. */ + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE Pmode + +/* Define this if the tablejump instruction expects the table + to contain offsets from the address of the table. + Do not define this if the table should contain absolute addresses. */ +/* It's not clear what PIC will look like or whether we want to use -fpic + for the embedded form currently being talked about. For now require -fpic + to get pc relative switch tables. */ +/*#define CASE_VECTOR_PC_RELATIVE*/ + +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD + will either zero-extend or sign-extend. The value of this macro should + be the code that says which one of the two operations is implicitly + done, NIL if none. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Specify the tree operation to be used to convert reals to integers. */ +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* This is the kind of divide that is easiest to do in the general case. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ +#define MOVE_MAX 4 + +/* Define this to be nonzero if shift instructions ignore all but the low-order + few bits. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* We assume that the store-condition-codes instructions store 0 for false + and some other value for true. This is the value stored for true. */ +#define STORE_FLAG_VALUE 1 + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +/* ??? The M32R doesn't have full 32 bit pointers, but making this PSImode has + it's own problems (you have to add extendpsisi2 and truncsipsi2). + Try to avoid it. */ +#define Pmode SImode + +/* A function address in a call instruction. */ +#define FUNCTION_MODE SImode + +/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS + is a valid machine specific attribute for DECL. + The attributes in ATTRIBUTES have previously been assigned to TYPE. */ +extern int m32r_valid_machine_attribute (); +#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ +m32r_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) + +/* A C expression that returns zero if the attributes on TYPE1 and TYPE2 are + incompatible, one if they are compatible, and two if they are + nearly compatible (which causes a warning to be generated). */ +extern int m32r_comp_type_attributes (); +#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \ +m32r_comp_type_attributes (TYPE1, TYPE2) + +/* Give newly defined TYPE some default attributes. */ +extern void m32r_set_default_type_attributes (); +#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \ +m32r_set_default_type_attributes (TYPE) + +/* Define the information needed to generate branch and scc insns. This is + stored from the compare operation. Note that we can't use "rtx" here + since it hasn't been defined! */ +extern struct rtx_def *m32r_compare_op0, *m32r_compare_op1; + +/* Define the function that build the compare insn for scc and bcc. */ +extern struct rtx_def *gen_compare (); + +/* M32R function types. */ +enum m32r_function_type { + M32R_FUNCTION_UNKNOWN, M32R_FUNCTION_NORMAL, M32R_FUNCTION_INTERRUPT +}; +#define M32R_INTERRUPT_P(TYPE) \ +((TYPE) == M32R_FUNCTION_INTERRUPT) +/* Compute the type of a function from its DECL. */ +enum m32r_function_type m32r_compute_function_type (); diff --git a/gnu/usr.bin/gcc/config/m32r/m32r.md b/gnu/usr.bin/gcc/config/m32r/m32r.md new file mode 100644 index 00000000000..4c8b2e54ffb --- /dev/null +++ b/gnu/usr.bin/gcc/config/m32r/m32r.md @@ -0,0 +1,1469 @@ +;; Machine description of the Mitsubishi M32R cpu for GNU C compiler +;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +;; This file is part of GNU CC. + +;; GNU CC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU CC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU CC; see the file COPYING. If not, write to +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;; See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; unspec usage +;; 0 - blockage +;; 1 - flush_icache +;; 2 - load_sda_base + +;; Insn type. Used to default other attribute values. +;; move4 = 4 byte move +(define_attr "type" + "move,move4,load,store,unary,binary,compare,shift,mul,div,uncond_branch,branch,call,multi,misc" + (const_string "misc")) + +;; Length in bytes. +(define_attr "length" "" + (cond [(eq_attr "type" "move,unary,shift,mul,div") + (const_int 2) + + (eq_attr "type" "binary") + (if_then_else (match_operand 2 "register_operand" "") + (const_int 2) (const_int 4)) + + (eq_attr "type" "compare") + (if_then_else (match_operand 1 "register_operand" "") + (const_int 2) (const_int 4)) + + (eq_attr "type" "load") + (if_then_else (match_operand 1 "memreg_operand" "") + (const_int 2) (const_int 4)) + + (eq_attr "type" "store") + (if_then_else (match_operand 0 "memreg_operand" "") + (const_int 2) (const_int 4)) + + (eq_attr "type" "multi") + (const_int 8) + + (eq_attr "type" "uncond_branch,branch,call") + (const_int 4)] + + (const_int 4))) + +;; The length here is the length of a single asm. Unfortunately it might be +;; 2 or 4 so we must allow for 4. That's ok though. +(define_asm_attributes + [(set_attr "length" "4") + (set_attr "type" "multi")]) + +;; Function units of the M32R +;; Units that take one cycle do not need to be specified. + +;; (define_function_unit {name} {num-units} {n-users} {test} +;; {ready-delay} {issue-delay} [{conflict-list}]) + +;; References to loaded registers should wait a cycle. +;; Memory with load-delay of 1 (i.e. 2 cycle load). +(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) + +;; Hack to get GCC to better pack the instructions. +;; We pretend there is a separate long function unit that conflicts with +;; both the left and right 16 bit insn slots. + +(define_function_unit "left" 1 1 + (eq_attr "length" "2") + 1 0 + [(not (eq_attr "length" "2"))]) + +(define_function_unit "right" 1 1 + (eq_attr "length" "1") + 1 0 + [(not (eq_attr "length" "2"))]) + +(define_function_unit "long" 1 1 + (not (eq_attr "length" "2")) + 1 0 + [(eq_attr "length" "2")]) + +;; Expand prologue as RTL +;; ??? Unfinished. + +;(define_expand "prologue" +; [(const_int 1)] +; "" +; " +;{ +;}") + +;; Move instructions. +;; +;; For QI and HI moves, the register must contain the full properly +;; sign-extended value. nonzero_bits assumes this [otherwise +;; SHORT_IMMEDIATES_SIGN_EXTEND must be used, but the comment for it +;; says it's a kludge and the .md files should be fixed instead]. + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. + Objects in the small data area are handled too. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (QImode, operands[1]); +}") + +(define_insn "*movqi_insn" + [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,m") + (match_operand:QI 1 "move_src_operand" "r,I,JQR,m,r"))] + "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)" + "@ + mv %0,%1 + ldi %0,%#%1 + ldi %0,%#%1 + ldub %0,%1 + stb %1,%0" + [(set_attr "type" "move,move,move4,load,store")]) + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (HImode, operands[1]); +}") + +(define_insn "*movhi_insn" + [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,m") + (match_operand:HI 1 "move_src_operand" "r,I,JQR,K,m,r"))] + "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)" + "@ + mv %0,%1 + ldi %0,%#%1 + ldi %0,%#%1 + ld24 %0,%#%1 + lduh %0,%1 + sth %1,%0" + [(set_attr "type" "move,move,move4,move4,load,store")]) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (SImode, operands[1]); + + /* Small Data Area reference? */ + if (small_data_operand (operands[1], SImode)) + { + emit_insn (gen_movsi_sda (operands[0], operands[1])); + DONE; + } + + /* If medium or large code model, symbols have to be loaded with + seth/add3. */ + if (addr32_operand (operands[1], SImode)) + { + emit_insn (gen_movsi_addr32 (operands[0], operands[1])); + DONE; + } +}") + +(define_insn "*movsi_insn" + [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,m") +;; ??? Do we need a const_double constraint here for large unsigned values? + (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,N,m,r"))] + "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" + "@ + mv %0,%1 + ldi %0,%#%1 ; %X1 + ldi %0,%#%1 ; %X1 + ld24 %0,%#%1 ; %X1 + seth %0,%#%T1 + seth %0,%#%T1\;or3 %0,%0,%#%B1 + ld %0,%1 + st %1,%0" + [(set_attr "type" "move,move,move4,move4,move4,multi,load,store")]) + +; Try to use a four byte / two byte pair for constants not loadable with +; ldi, ld24, seth. + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "two_insn_const_operand" ""))] + "" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))] + " +{ + unsigned HOST_WIDE_INT val = INTVAL (operands[1]); + unsigned HOST_WIDE_INT tmp; + int shift; + + /* In all cases we will emit two instructions. However we try to + use 2 byte instructions wherever possible. We can assume the + constant isn't loadable with any of ldi, ld24, or seth. */ + + /* See if we can load a 24 bit unsigned value and invert it. */ + if (UINT24_P (~ val)) + { + emit_insn (gen_movsi (operands[0], GEN_INT (~ val))); + emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); + DONE; + } + + /* See if we can load a 24 bit unsigned value and shift it into place. + 0x01fffffe is just beyond ld24's range. */ + for (shift = 1, tmp = 0x01fffffe; + shift < 8; + ++shift, tmp <<= 1) + { + if ((val & ~tmp) == 0) + { + emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift))); + emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift))); + DONE; + } + } + + /* Can't use any two byte insn, fall back to seth/or3. */ + operands[2] = GEN_INT ((val) & 0xffff0000); + operands[3] = GEN_INT ((val) & 0xffff); +}") + +;; Small data area support. +;; The address of _SDA_BASE_ is loaded into a register and all objects in +;; the small data area are indexed off that. This is done for each reference +;; but cse will clean things up for us. We let the compiler choose the +;; register to use so we needn't allocate (and maybe even fix) a special +;; register to use. Since the load and store insns have a 16 bit offset the +;; total size of the data area can be 64K. However, if the data area lives +;; above 16M (24 bits), _SDA_BASE_ will have to be loaded with seth/add3 which +;; would then yield 3 instructions to reference an object [though there would +;; be no net loss if two or more objects were referenced]. The 3 insns can be +;; reduced back to 2 if the size of the small data area were reduced to 32K +;; [then seth + ld/st would work for any object in the area]. Doing this +;; would require special handling of _SDA_BASE_ (its value would be +;; (.sdata + 32K) & 0xffff0000) and reloc computations would be different +;; [I think]. What to do about this is deferred until later and for now we +;; require .sdata to be in the first 16M. + +(define_expand "movsi_sda" + [(set (match_dup 2) + (unspec [(const_int 0)] 2)) + (set (match_operand:SI 0 "register_operand" "") + (lo_sum:SI (match_dup 2) + (match_operand:SI 1 "small_data_operand" "")))] + "" + " +{ + if (reload_in_progress || reload_completed) + operands[2] = operands[0]; + else + operands[2] = gen_reg_rtx (SImode); +}") + +(define_insn "*load_sda_base" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec [(const_int 0)] 2))] + "" + "ld24 %0,#_SDA_BASE_" + [(set_attr "type" "move4")]) + +;; 32 bit address support. + +(define_expand "movsi_addr32" + [(set (match_dup 2) + ; addr32_operand isn't used because it's too restrictive, + ; seth_add3_operand is more general and thus safer. + (high:SI (match_operand:SI 1 "seth_add3_operand" ""))) + (set (match_operand:SI 0 "register_operand" "") + (lo_sum:SI (match_dup 2) (match_dup 1)))] + "" + " +{ + if (reload_in_progress || reload_completed) + operands[2] = operands[0]; + else + operands[2] = gen_reg_rtx (SImode); +}") + +(define_insn "set_hi_si" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (match_operand 1 "symbolic_operand" "")))] + "" + "seth %0,%#shigh(%1)" + [(set_attr "type" "move4")]) + +(define_insn "lo_sum_si" + [(set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "in")))] + "" + "add3 %0,%1,%#%B2" + [(set_attr "length" "4")]) + +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (DImode, operands[1]); + + if (CONSTANT_P (operands[1]) + && ! easy_di_const (operands[1])) + { + rtx mem = force_const_mem (DImode, operands[1]); + rtx reg = ((reload_in_progress || reload_completed) + ? copy_to_suggested_reg (XEXP (mem, 0), + gen_rtx (REG, Pmode, REGNO (operands[0])), + Pmode) + : force_reg (Pmode, XEXP (mem, 0))); + operands[1] = change_address (mem, DImode, reg); + } +}") + +(define_insn "*movdi_insn" + [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m") + (match_operand:DI 1 "move_double_src_operand" "r,nG,m,r"))] + "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" + "* +{ + switch (which_alternative) + { + case 0 : + /* We normally copy the low-numbered register first. However, if + the first register operand 0 is the same as the second register of + operand 1, we must copy in the opposite order. */ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"mv %R0,%R1\;mv %0,%1\"; + else + return \"mv %0,%1\;mv %R0,%R1\"; + case 1 : + return \"#\"; + case 2 : + /* If the low-address word is used in the address, we must load it + last. Otherwise, load it first. Note that we cannot have + auto-increment in that case since the address register is known to be + dead. */ + if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, + operands [1], 0)) + { + return \"ld %R0,%R1\;ld %0,%1\"; + } + else + { + /* Try to use auto-inc addressing if we can. */ + if (GET_CODE (XEXP (operands[1], 0)) == REG + && dead_or_set_p (insn, XEXP (operands[1], 0))) + { + operands[1] = XEXP (operands[1], 0); + return \"ld %0,@%1+\;ld %R0,@%1\"; + } + return \"ld %0,%1\;ld %R0,%R1\"; + } + case 3 : + /* Try to use auto-inc addressing if we can. */ + if (GET_CODE (XEXP (operands[0], 0)) == REG + && dead_or_set_p (insn, XEXP (operands[0], 0))) + { + operands[0] = XEXP (operands[0], 0); + return \"st %1,@%0\;st %R1,@+%0\"; + } + return \"st %1,%0\;st %R1,%R0\"; + } +}" + [(set_attr "type" "multi,multi,multi,multi") + (set_attr "length" "4,4,6,6")]) + +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "const_double_operand" ""))] + "reload_completed" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] + " +{ + operands[2] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN == 0); + operands[3] = gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN != 0); + split_double (operands[1], operands + 4, operands + 5); +}") + +;; Floating point move insns. + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (SFmode, operands[1]); +}") + +(define_insn "*movsf_insn" + [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m") + (match_operand:SF 1 "move_src_operand" "r,F,m,r"))] + "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" + "* +{ + switch (which_alternative) + { + case 0 : + return \"mv %0,%1\"; + case 1 : + { + REAL_VALUE_TYPE r; + long l; + REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); + REAL_VALUE_TO_TARGET_SINGLE (r, l); + operands[1] = GEN_INT (l); + if (l == 0) + return \"ldi %0,%#0\"; + if ((l & 0xffff) == 0) + return \"seth %0,%#%T1\"; + else + return \"seth %0,%#%T1\;or3 %0,%0,%#%B1\"; + } + case 2 : + return \"ld %0,%1\"; + case 3 : + return \"st %1,%0\"; + } +}" + ;; ??? Length of alternative 1 is either 2, 4 or 8. + [(set_attr "type" "move,multi,load,store")]) + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " +{ + /* Everything except mem = const or mem = mem can be done easily. */ + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (DFmode, operands[1]); + + if (GET_CODE (operands[1]) == CONST_DOUBLE + && ! easy_df_const (operands[1])) + { + rtx mem = force_const_mem (DFmode, operands[1]); + rtx reg = ((reload_in_progress || reload_completed) + ? copy_to_suggested_reg (XEXP (mem, 0), + gen_rtx (REG, Pmode, REGNO (operands[0])), + Pmode) + : force_reg (Pmode, XEXP (mem, 0))); + operands[1] = change_address (mem, DFmode, reg); + } +}") + +(define_insn "*movdf_insn" + [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") + (match_operand:DF 1 "move_double_src_operand" "r,H,m,r"))] + "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" + "* +{ + switch (which_alternative) + { + case 0 : + /* We normally copy the low-numbered register first. However, if + the first register operand 0 is the same as the second register of + operand 1, we must copy in the opposite order. */ + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + return \"mv %R0,%R1\;mv %0,%1\"; + else + return \"mv %0,%1\;mv %R0,%R1\"; + case 1 : + { + REAL_VALUE_TYPE r; + long l[2]; + REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); + REAL_VALUE_TO_TARGET_DOUBLE (r, l); + operands[1] = GEN_INT (l[0]); + if (l[0] == 0 && l[1] == 0) + return \"ldi %0,%#0\;ldi %R0,%#0\"; + else if (l[1] != 0) + abort (); + else if ((l[0] & 0xffff) == 0) + return \"seth %0,%#%T1\;ldi %R0,%#0\"; + else + abort (); + } + case 2 : + /* If the low-address word is used in the address, we must load it + last. Otherwise, load it first. Note that we cannot have + auto-increment in that case since the address register is known to be + dead. */ + if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, + operands [1], 0)) + { + return \"ld %R0,%R1\;ld %0,%1\"; + } + else + { + /* Try to use auto-inc addressing if we can. */ + if (GET_CODE (XEXP (operands[1], 0)) == REG + && dead_or_set_p (insn, XEXP (operands[1], 0))) + { + operands[1] = XEXP (operands[1], 0); + return \"ld %0,@%1+\;ld %R0,@%1\"; + } + return \"ld %0,%1\;ld %R0,%R1\"; + } + case 3 : + /* Try to use auto-inc addressing if we can. */ + if (GET_CODE (XEXP (operands[0], 0)) == REG + && dead_or_set_p (insn, XEXP (operands[0], 0))) + { + operands[0] = XEXP (operands[0], 0); + return \"st %1,@%0\;st %R1,@+%0\"; + } + return \"st %1,%0\;st %R1,%R0\"; + } +}" + [(set_attr "type" "multi,multi,multi,multi") + (set_attr "length" "4,6,6,6")]) + +;; Zero extension instructions. + +(define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + "" + "@ + and3 %0,%1,%#255 + ldub %0,%1" + [(set_attr "type" "unary,load") + (set_attr "length" "4,*")]) + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + "" + "@ + and3 %0,%1,%#255 + ldub %0,%1" + [(set_attr "type" "unary,load") + (set_attr "length" "4,*")]) + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + "" + "@ + and3 %0,%1,%#65535 + lduh %0,%1" + [(set_attr "type" "unary,load") + (set_attr "length" "4,*")]) + +;; Sign extension instructions. +;; ??? See v850.md. + +;; These patterns originally accepted general_operands, however, slightly +;; better code is generated by only accepting register_operands, and then +;; letting combine generate the lds[hb] insns. +;; [This comment copied from sparc.md, I think.] + +(define_expand "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "") + (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); + int op1_subword = 0; + int op0_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + if (GET_CODE (operand0) == SUBREG) + { + op0_subword = SUBREG_WORD (operand0); + operand0 = XEXP (operand0, 0); + } + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), + shift_24)); + if (GET_MODE (operand0) != SImode) + operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword); + emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); + DONE; +}") + +(define_insn "*sign_extendqihi2_insn" + [(set (match_operand:HI 0 "register_operand" "=r") + (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] + "" + "ldb %0,%1" + [(set_attr "type" "load")]) + +(define_expand "extendqisi2" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), + shift_24)); + emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); + DONE; +}") + +(define_insn "*sign_extendqisi2_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] + "" + "ldb %0,%1" + [(set_attr "type" "load")]) + +(define_expand "extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] + "" + " +{ + rtx temp = gen_reg_rtx (SImode); + rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); + int op1_subword = 0; + + if (GET_CODE (operand1) == SUBREG) + { + op1_subword = SUBREG_WORD (operand1); + operand1 = XEXP (operand1, 0); + } + + emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1, + op1_subword), + shift_16)); + emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); + DONE; +}") + +(define_insn "*sign_extendhisi2_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] + "" + "ldh %0,%1" + [(set_attr "type" "load")]) + +;; Arithmetic instructions. + +; ??? Adding an alternative to split add3 of small constants into two +; insns yields better instruction packing but slower code. Adds of small +; values is done a lot. + +(define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,J")))] + "" + "@ + add %0,%2 + addi %0,%#%2 + add3 %0,%1,%#%2" + [(set_attr "type" "binary") + (set_attr "length" "2,2,4")]) + +;(define_split +; [(set (match_operand:SI 0 "register_operand" "") +; (plus:SI (match_operand:SI 1 "register_operand" "") +; (match_operand:SI 2 "int8_operand" "")))] +; "reload_completed +; && REGNO (operands[0]) != REGNO (operands[1]) +; && INT8_P (INTVAL (operands[2])) +; && INTVAL (operands[2]) != 0" +; [(set (match_dup 0) (match_dup 1)) +; (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] +; "") + +(define_insn "adddi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_operand:DI 1 "register_operand" "%0") + (match_operand:DI 2 "register_operand" "r"))) + (clobber (reg:CC 17))] + "" + "* +{ + /* ??? The cmp clears the condition bit. Can we speed up somehow? */ + return \"cmp %L0,%L0\;addx %L0,%L2\;addx %H0,%H2\"; +}" + [(set_attr "type" "binary") + (set_attr "length" "6")]) + +(define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "r")))] + "" + "sub %0,%2" + [(set_attr "type" "binary")]) + +(define_insn "subdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "register_operand" "r"))) + (clobber (reg:CC 17))] + "" + "* +{ + /* ??? The cmp clears the condition bit. Can we speed up somehow? */ + return \"cmp %L0,%L0\;subx %L0,%L2\;subx %H0,%H2\"; +}" + [(set_attr "type" "binary") + (set_attr "length" "6")]) + +; Multiply/Divide instructions. + +(define_insn "mulhisi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) + (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] + "" + "mullo %1,%2\;mvfacmi %0" + [(set_attr "type" "mul") + (set_attr "length" "4")]) + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "register_operand" "r")))] + "" + "mul %0,%2" + [(set_attr "type" "mul")]) + +(define_insn "divsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (div:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "r")))] + "" + "div %0,%2" + [(set_attr "type" "div")]) + +(define_insn "udivsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (udiv:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "r")))] + "" + "divu %0,%2" + [(set_attr "type" "div")]) + +(define_insn "modsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mod:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "r")))] + "" + "rem %0,%2" + [(set_attr "type" "div")]) + +(define_insn "umodsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (umod:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "register_operand" "r")))] + "" + "remu %0,%2" + [(set_attr "type" "div")]) + +;; Boolean instructions. +;; +;; We don't define the DImode versions as expand_binop does a good enough job. +;; And if it doesn't it should be fixed. + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (and:SI (match_operand:SI 1 "register_operand" "%0,r") + (match_operand:SI 2 "nonmemory_operand" "r,K")))] + "" + "@ + and %0,%2 + and3 %0,%1,%#%2 ; %X2" + [(set_attr "type" "binary")]) + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,r") + (match_operand:SI 2 "nonmemory_operand" "r,K")))] + "" + "@ + or %0,%2 + or3 %0,%1,%#%2 ; %X2" + [(set_attr "type" "binary")]) + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,r") + (match_operand:SI 2 "nonmemory_operand" "r,K")))] + "" + "@ + xor %0,%2 + xor3 %0,%1,%#%2 ; %X2" + [(set_attr "type" "binary")]) + +(define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "neg %0,%1" + [(set_attr "type" "unary")]) + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "not %0,%1" + [(set_attr "type" "unary")]) + +;; Shift instructions. + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r") + (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] + "" + "@ + sll %0,%2 + slli %0,%#%2 + sll3 %0,%1,%#%2" + [(set_attr "type" "shift") + (set_attr "length" "2,2,4")]) + +(define_insn "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") + (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] + "" + "@ + sra %0,%2 + srai %0,%#%2 + sra3 %0,%1,%#%2" + [(set_attr "type" "shift") + (set_attr "length" "2,2,4")]) + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") + (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] + "" + "@ + srl %0,%2 + srli %0,%#%2 + srl3 %0,%1,%#%2" + [(set_attr "type" "shift") + (set_attr "length" "2,2,4")]) + +;; Compare instructions. +;; This controls RTL generation and register allocation. + +;; We generate RTL for comparisons and branches by having the cmpxx +;; patterns store away the operands. Then the bcc patterns +;; emit RTL for both the compare and the branch. +;; +;; On the m32r it is more efficient to use the bxxz instructions and +;; thus merge the compare and branch into one instruction, so they are +;; preferred. + +(define_expand "cmpsi" + [(set (reg:CC 17) + (compare:CC (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "nonmemory_operand" "")))] + "" + " +{ + m32r_compare_op0 = operands[0]; + m32r_compare_op1 = operands[1]; + DONE; +}") + +;; The cmp_xxx_insn patterns set the condition bit to the result of the +;; comparison. There isn't a "compare equal" instruction so cmp_eqsi_insn +;; is quite inefficient. However, it is rarely used. + +(define_insn "cmp_eqsi_insn" + [(set (reg:CC 17) + (eq:CC (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P"))) + (clobber (match_scratch:SI 2 "=&r,&r"))] + "TARGET_OLD_COMPARE" + "@ + mv %2,%0\;sub %2,%1\;cmpui %2,#1 + add3 %2,%0,%#%N1\;cmpui %2,#1" + [(set_attr "type" "compare,compare") + (set_attr "length" "8,8")]) + +(define_insn "cmp_ltsi_insn" + [(set (reg:CC 17) + (lt:CC (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "reg_or_int16_operand" "r,J")))] + "" + "@ + cmp %0,%1 + cmpi %0,%#%1" + [(set_attr "type" "compare")]) + +(define_insn "cmp_ltusi_insn" + [(set (reg:CC 17) + (ltu:CC (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "reg_or_uint16_operand" "r,K")))] + "" + "@ + cmpu %0,%1 + cmpui %0,%#%1" + [(set_attr "type" "compare")]) + +;; reg == small constant comparisons are best handled by putting the result +;; of the comparison in a tmp reg and then using beqz/bnez. +;; ??? The result register doesn't contain 0/STORE_FLAG_VALUE, +;; it contains 0/non-zero. + +(define_insn "cmp_ne_small_const_insn" + [(set (match_operand:SI 0 "register_operand" "=r") + (ne:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "cmp_int16_operand" "P")))] + "" + "add3 %0,%1,%#%N2" + [(set_attr "type" "compare") + (set_attr "length" "4")]) + +;; These control RTL generation for conditional jump insns. + +(define_expand "beq" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bne" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bgt" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "ble" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bge" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "blt" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bgtu" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bleu" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bgeu" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1); +}") + +(define_expand "bltu" + [(set (pc) + (if_then_else (match_dup 1) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " +{ + operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1); +}") + +;; Now match both normal and inverted jump. + +(define_insn "*branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "eqne_comparison_operator" + [(reg 17) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + if (GET_CODE (operands[1]) == NE) + return \"bc %l0\"; + else + return \"bnc %l0\"; +}" + [(set_attr "type" "branch") + ; We use 400/800 instead of 512,1024 to account for inaccurate insn + ; lengths and insn alignments that are complex to track. + ; It's not important that we be hyper-precise here. It may be more + ; important blah blah blah when the chip supports parallel execution + ; blah blah blah but until then blah blah blah this is simple and + ; suffices. + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 400)) + (const_int 800)) + (const_int 2) + (const_int 4)))]) + +(define_insn "*rev_branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "eqne_comparison_operator" + [(reg 17) (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + ;"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" + "" + "* +{ + if (GET_CODE (operands[1]) == EQ) + return \"bc %l0\"; + else + return \"bnc %l0\"; +}" + [(set_attr "type" "branch") + ; We use 400/800 instead of 512,1024 to account for inaccurate insn + ; lengths and insn alignments that are complex to track. + ; It's not important that we be hyper-precise here. It may be more + ; important blah blah blah when the chip supports parallel execution + ; blah blah blah but until then blah blah blah this is simple and + ; suffices. + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 400)) + (const_int 800)) + (const_int 2) + (const_int 4)))]) + +; reg/reg compare and branch insns + +(define_insn "*reg_branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "eqne_comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + /* Is branch target reachable with beq/bne? */ + if (get_attr_length (insn) == 4) + { + if (GET_CODE (operands[1]) == EQ) + return \"beq %2,%3,%l0\"; + else + return \"bne %2,%3,%l0\"; + } + else + { + if (GET_CODE (operands[1]) == EQ) + return \"bne %2,%3,1f\;bra %l0\;1:\"; + else + return \"beq %2,%3,1f\;bra %l0\;1:\"; + } +}" + [(set_attr "type" "branch") + ; We use 25000/50000 instead of 32768/65536 to account for slot filling + ; which is complex to track and inaccurate length specs. + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 25000)) + (const_int 50000)) + (const_int 4) + (const_int 8)))]) + +(define_insn "*rev_reg_branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "eqne_comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r")]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* +{ + /* Is branch target reachable with beq/bne? */ + if (get_attr_length (insn) == 4) + { + if (GET_CODE (operands[1]) == NE) + return \"beq %2,%3,%l0\"; + else + return \"bne %2,%3,%l0\"; + } + else + { + if (GET_CODE (operands[1]) == NE) + return \"bne %2,%3,1f\;bra %l0\;1:\"; + else + return \"beq %2,%3,1f\;bra %l0\;1:\"; + } +}" + [(set_attr "type" "branch") + ; We use 25000/50000 instead of 32768/65536 to account for slot filling + ; which is complex to track and inaccurate length specs. + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 25000)) + (const_int 50000)) + (const_int 4) + (const_int 8)))]) + +; reg/zero compare and branch insns + +(define_insn "*zero_branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "signed_comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + char *br,*invbr; + char asmtext[40]; + + switch (GET_CODE (operands[1])) + { + case EQ : br = \"eq\"; invbr = \"ne\"; break; + case NE : br = \"ne\"; invbr = \"eq\"; break; + case LE : br = \"le\"; invbr = \"gt\"; break; + case GT : br = \"gt\"; invbr = \"le\"; break; + case LT : br = \"lt\"; invbr = \"ge\"; break; + case GE : br = \"ge\"; invbr = \"lt\"; break; + } + + /* Is branch target reachable with bxxz? */ + if (get_attr_length (insn) == 4) + { + sprintf (asmtext, \"b%sz %%2,%%l0\", br); + output_asm_insn (asmtext, operands); + } + else + { + sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", invbr); + output_asm_insn (asmtext, operands); + } + return \"\"; +}" + [(set_attr "type" "branch") + ; We use 25000/50000 instead of 32768/65536 to account for slot filling + ; which is complex to track and inaccurate length specs. + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 25000)) + (const_int 50000)) + (const_int 4) + (const_int 8)))]) + +(define_insn "*rev_zero_branch_insn" + [(set (pc) + (if_then_else (match_operator 1 "eqne_comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* +{ + char *br,*invbr; + char asmtext[40]; + + switch (GET_CODE (operands[1])) + { + case EQ : br = \"eq\"; invbr = \"ne\"; break; + case NE : br = \"ne\"; invbr = \"eq\"; break; + case LE : br = \"le\"; invbr = \"gt\"; break; + case GT : br = \"gt\"; invbr = \"le\"; break; + case LT : br = \"lt\"; invbr = \"ge\"; break; + case GE : br = \"ge\"; invbr = \"lt\"; break; + } + + /* Is branch target reachable with bxxz? */ + if (get_attr_length (insn) == 4) + { + sprintf (asmtext, \"b%sz %%2,%%l0\", invbr); + output_asm_insn (asmtext, operands); + } + else + { + sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", br); + output_asm_insn (asmtext, operands); + } + return \"\"; +}" + [(set_attr "type" "branch") + ; We use 25000/50000 instead of 32768/65536 to account for slot filling + ; which is complex to track and inaccurate length specs. + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 25000)) + (const_int 50000)) + (const_int 4) + (const_int 8)))]) + +;; Unconditional and other jump instructions. + +(define_insn "jump" + [(set (pc) (label_ref (match_operand 0 "" "")))] + "" + "bra %l0" + [(set_attr "type" "uncond_branch") + (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) + (const_int 400)) + (const_int 800)) + (const_int 2) + (const_int 4)))]) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "address_operand" "p"))] + "" + "jmp %a0" + [(set_attr "type" "uncond_branch") + (set_attr "length" "2")]) + +(define_insn "tablejump" + [(set (pc) (match_operand:SI 0 "address_operand" "p")) + (use (label_ref (match_operand 1 "" "")))] + "" + "jmp %a0" + [(set_attr "type" "uncond_branch") + (set_attr "length" "2")]) + +(define_expand "call" + ;; operands[1] is stack_size_rtx + ;; operands[2] is next_arg_register + [(parallel [(call (match_operand:SI 0 "call_operand" "") + (match_operand 1 "" "")) + (clobber (reg:SI 14))])] + "" + "") + +(define_insn "*call_via_reg" + [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "")) + (clobber (reg:SI 14))] + "" + "jl %0" + [(set_attr "type" "call") + (set_attr "length" "2")]) + +(define_insn "*call_via_label" + [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) + (match_operand 1 "" "")) + (clobber (reg:SI 14))] + "" + "* +{ + int call26_p = call26_operand (operands[0], FUNCTION_MODE); + + if (! call26_p) + { + /* We may not be able to reach with a `bl' insn so punt and leave it to + the linker. + We do this here, rather than doing a force_reg in the define_expand + so these insns won't be separated, say by scheduling, thus simplifying + the linker. */ + return \"seth r14,%T0\;add3 r14,r14,%B0\;jl r14\"; + } + else + return \"bl %0\"; +}" + [(set_attr "type" "call") + (set (attr "length") + (if_then_else (eq (symbol_ref "call26_operand (operands[0], FUNCTION_MODE)") + (const_int 0)) + (const_int 12) ; 10 + 2 for nop filler + ; The return address must be on a 4 byte boundary so + ; there's no point in using a value of 2 here. A 2 byte + ; insn may go in the left slot but we currently can't + ; use such knowledge. + (const_int 4)))]) + +(define_expand "call_value" + ;; operand 2 is stack_size_rtx + ;; operand 3 is next_arg_register + [(parallel [(set (match_operand 0 "register_operand" "=r") + (call (match_operand:SI 1 "call_operand" "") + (match_operand 2 "" ""))) + (clobber (reg:SI 14))])] + "" + "") + +(define_insn "*call_value_via_reg" + [(set (match_operand 0 "register_operand" "=r") + (call (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand 2 "" ""))) + (clobber (reg:SI 14))] + "" + "jl %1" + [(set_attr "type" "call") + (set_attr "length" "2")]) + +(define_insn "*call_value_via_label" + [(set (match_operand 0 "register_operand" "=r") + (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) + (match_operand 2 "" ""))) + (clobber (reg:SI 14))] + "" + "* +{ + int call26_p = call26_operand (operands[1], FUNCTION_MODE); + + if (! call26_p) + { + /* We may not be able to reach with a `bl' insn so punt and leave it to + the linker. + We do this here, rather than doing a force_reg in the define_expand + so these insns won't be separated, say by scheduling, thus simplifying + the linker. */ + return \"seth r14,%T1\;add3 r14,r14,%B1\;jl r14\"; + } + else + return \"bl %1\"; +}" + [(set_attr "type" "call") + (set (attr "length") + (if_then_else (eq (symbol_ref "call26_operand (operands[1], FUNCTION_MODE)") + (const_int 0)) + (const_int 12) ; 10 + 2 for nop filler + ; The return address must be on a 4 byte boundary so + ; there's no point in using a value of 2 here. A 2 byte + ; insn may go in the left slot but we currently can't + ; use such knowledge. + (const_int 4)))]) + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "type" "misc") + (set_attr "length" "2")]) + +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] + "" + "") + +;; Special pattern to flush the icache. + +(define_insn "flush_icache" + [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] + "" + "* return \"nop ; flush-icache\";" + [(set_attr "type" "misc")]) + +;; Split up troublesome insns for better scheduling. + +;; Peepholes go at the end. + +;; ??? Setting the type attribute may not be useful, but for completeness +;; we do it. + +(define_peephole + [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") + (const_int 4))) + (match_operand:SI 1 "register_operand" "r"))] + "dead_or_set_p (insn, operands[0])" + "st %1,@+%0" + [(set_attr "type" "store") + (set_attr "length" "2")]) diff --git a/gnu/usr.bin/gcc/config/m32r/t-m32r b/gnu/usr.bin/gcc/config/m32r/t-m32r new file mode 100644 index 00000000000..6005eb96db3 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m32r/t-m32r @@ -0,0 +1,57 @@ +# lib1funcs.asm is currently empty. +CROSS_LIBGCC1 = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +# Turn off the SDA while compiling libgcc2. There are no headers for it +# and we want maximal upward compatibility here. + +TARGET_LIBGCC2_CFLAGS = -G 0 + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +# We need to use -fpic when we are using gcc to compile the routines in +# initfini.c. This is only really needed when we are going to use gcc/g++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fpic when compiling the +# routines in initfini.c. +# -fpic currently isn't supported for the m32r. + +CRTSTUFF_T_CFLAGS = + +# .init/.fini section routines + +crtinit.o: $(srcdir)/config/m32r/initfini.c $(GCC_PASSES) $(CONFIG_H) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ + -DCRT_INIT -finhibit-size-directive -fno-inline-functions \ + -g0 -c $(srcdir)/config/m32r/initfini.c -o crtinit.o + +crtfini.o: $(srcdir)/config/m32r/initfini.c $(GCC_PASSES) $(CONFIG_H) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ + -DCRT_FINI -finhibit-size-directive -fno-inline-functions \ + -g0 -c $(srcdir)/config/m32r/initfini.c -o crtfini.o + +# -mmodel={small,medium} requires separate libraries. +# We don't build libraries for the large model, instead we use the medium +# libraries. The only difference is that the large model can handle jumps +# more than 26 signed bits away. + +MULTILIB_OPTIONS = mmodel=small/mmodel=medium +MULTILIB_DIRNAMES = small medium +MULTILIB_MATCHES = mmodel?medium=mmodel?large + +# Set MULTILIB_EXTRA_OPTS so shipped libraries have small data in .sdata and +# SHN_M32R_SCOMMON. +# This is important for objects referenced in system header files. +MULTILIB_EXTRA_OPTS = msdata=sdata + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/gnu/usr.bin/gcc/config/m32r/xm-m32r.h b/gnu/usr.bin/gcc/config/m32r/xm-m32r.h new file mode 100644 index 00000000000..57100c875cd --- /dev/null +++ b/gnu/usr.bin/gcc/config/m32r/xm-m32r.h @@ -0,0 +1,47 @@ +/* Configuration for GNU C-compiler for the M32R processor. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Doubles are stored in memory with the high order word first. This + matters when cross-compiling. */ +#define HOST_WORDS_BIG_ENDIAN 1 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ +#include "tm.h" + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* If compiled with Sun CC, the use of alloca requires this #include. */ +#ifndef __GNUC__ +#include "alloca.h" +#endif diff --git a/gnu/usr.bin/gcc/config/m68k/a-ux.h b/gnu/usr.bin/gcc/config/m68k/a-ux.h new file mode 100644 index 00000000000..74aaa4ea9ad --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/a-ux.h @@ -0,0 +1,206 @@ +/* Definitions for Motorola 680x0 running A/UX + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file was renamed from aux.h because of MSDOS: aux.anything + isn't usable. Sigh. */ + +/* Execution environment */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020) /* 68020, 68881 */ + +#define CPP_PREDEFINES "-Dunix -Dm68k -DAUX -DmacII \ +-Asystem(unix) -Asystem(AUX) -Acpu(m68k) -Amachine(m68k) -Amachine(macII)" + +#define CPP_SPEC \ +"%{!msoft-float:%{!ansi:-Dmc68881 }-D__HAVE_68881__ }\ +-Acpu(mc68000) -D__mc68000__ %{!ansi:-Dmc68000 }\ +%{!mc68000:%{!m68000:-Acpu(mc68020) -D__mc68020__ %{!ansi:-Dmc68020 }}}\ +%{m68030:-Acpu(mc68030) -D__mc68030__ %{!ansi:-Dmc68030 }}\ +%{m68040:-Acpu(mc68040) -D__mc68040__ %{!ansi:-Dmc68040 }}\ +%{!ansi:%{!traditional:-D__STDC__=2 }}\ +%{sbsd:-D_BSD_SOURCE -DBSD }%{ZB:-D_BSD_SOURCE -DBSD }\ +%{ssysv:-D_SYSV_SOURCE -DSYSV -DUSG }%{ZS:-D_SYSV_SOURCE -DSYSV -DUSG }\ +%{sposix:-D_POSIX_SOURCE -DPOSIX }%{ZP:-D_POSIX_SOURCE -DPOSIX }\ +%{sposix+:-D_POSIX_SOURCE -DPOSIX }\ +%{saux:-D_AUX_SOURCE }%{ZA:-D_AUX_SOURCE }\ +%{!sbsd:%{!ZB:%{!ssysv:%{!ZS:%{!sposix:%{!ZP:%{!snone:\ +-D_BSD_SOURCE -D_SYSV_SOURCE -D_AUX_SOURCE }}}}}}}" + +#define LIB_SPEC \ +"%{sbsd:-lbsd }%{ZB:-lbsd }\ +%{ssysv:-lsvid }%{ZS:-lsvid }\ +%{sposix:-lposix }%{ZP:-lposix }%{sposix+:-lposix }\ +%{!static:%{smac:-lmac_s -lat -lld -lmr }-lc_s }\ +%{static:%{smac:-lmac -lat -lld -lmr }-lc }" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ +"%{pg:mcrt0.o%s }%{!pg:%{p:mcrt1.o%s }\ +%{!p:%{smac:maccrt1.o%s low.o%s }%{!smac:crt1.o%s }}}\ +crt2.o%s " + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtn.o%s " + + +/*===================================================================*/ +/* Compilation environment -- mostly */ + +#define NO_SYS_SIGLIST + +/* We provide atexit(), A/UX does not have it */ +#define HAVE_ATEXIT + +/* Generate calls to memcpy, memcmp and memset, as opposed to bcopy, bcmp, + and bzero */ +#define TARGET_MEM_FUNCTIONS + +/* Resize standard types */ + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "unsigned int" + +/* Every structure or union's size must be a multiple of 2 bytes. */ +#define STRUCTURE_SIZE_BOUNDARY 16 + +/* Bits needed by collect */ + +#define OBJECT_FORMAT_COFF +#define MY_ISCOFF(m) ((m) == M68TVMAGIC || \ + (m) == M68MAGIC || \ + (m) == MC68TVMAGIC || \ + (m) == MC68MAGIC || \ + (m) == M68NSMAGIC) + + +#ifndef USE_COLLECT2 +/* For .ctor/.dtor sections for collecting constructors */ +/* We have special start/end files for defining [cd]tor lists */ +#define CTOR_LISTS_DEFINED_EXTERNALLY +#endif + + +/*======================================================================*/ +/* Calling convention and library support changes */ + +/* Define how to generate (in the callee) the output value of a function + and how to find (in the caller) the value returned by a function. VALTYPE + is the data type of the value (as a tree). If the precise function being + called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. + For A/UX generate the result in d0, a0, or fp0 as appropriate. */ + +#undef FUNCTION_VALUE +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 \ + ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \ + : (TREE_CODE (VALTYPE) == POINTER_TYPE \ + ? gen_rtx (REG, TYPE_MODE (VALTYPE), 8) \ + : gen_rtx (REG, TYPE_MODE (VALTYPE), 0))) + +#undef LIBCALL_VALUE +#define LIBCALL_VALUE(MODE) \ + gen_rtx (REG, (MODE), ((TARGET_68881 && \ + ((MODE) == SFmode || (MODE) == DFmode)) ? 16 : 0)) + +/* 1 if N is a possible register number for a function value. + For A/UX allow d0, a0, or fp0 as return registers, for integral, + pointer, or floating types, respectively. Reject fp0 if not using a + 68881 coprocessor. */ + +#undef FUNCTION_VALUE_REGNO_P +#define FUNCTION_VALUE_REGNO_P(N) \ + ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16)) + +/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for + more than one register. */ + +#undef NEEDS_UNTYPED_CALL +#define NEEDS_UNTYPED_CALL 1 + +/* For compatibility with the large body of existing code which does not + always properly declare external functions returning pointer types, the + A/UX convention is to copy the value returned for pointer functions + from a0 to d0 in the function epilogue, so that callers that have + neglected to properly declare the callee can still find the correct return + value. */ + +#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \ +{ \ + extern int current_function_returns_pointer; \ + if ((current_function_returns_pointer) && \ + ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \ + asm_fprintf (FILE, "\t%s %Ra0,%Rd0\n", ASM_MOV_INSN); \ +} + +/* How to call the function profiler */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ + asm_fprintf (FILE, "\t%Olea %LLP%d,%Ra0\n\t%Ojbsr %s\n", \ + (LABELNO), FUNCTION_PROFILER_SYMBOL) + +/* Finalize the trampoline by flushing the insn cache */ + +#undef FINALIZE_TRAMPOLINE +#define FINALIZE_TRAMPOLINE(TRAMP) \ + emit_library_call(gen_rtx(SYMBOL_REF, Pmode, "__clear_cache"), \ + 0, VOIDmode, 2, TRAMP, Pmode, \ + plus_constant(TRAMP, TRAMPOLINE_SIZE), Pmode); + +/* Clear the instruction cache from `beg' to `end'. This makes an + inline system call to SYS_sysm68k. The arguments are as follows: + + sysm68k(105, addr, scope, cache, len) + + 105 - the subfunction code to clear the cache + addr - the start address for the flush + scope - the scope of the flush (see the cpush insn) + cache - which cache to flush (see the cpush insn) + len - a factor relating to the number of flushes to perform : + len/16 lines, or len/4096 pages. + + While all this is only really relevant to 040's, the system call + will just return an error (which we ignore) on other systems. */ + +#define CLEAR_INSN_CACHE(beg, end) \ +{ \ + unsigned _beg = (unsigned)(beg), _end = (unsigned)(end); \ + unsigned _len = ((_end / 16) - (_beg / 16) + 1) * 16; \ + __asm __volatile( \ + ASM_MOV_INSN " %1, %-\n\t" /* nr lines */ \ + ASM_MOV_INSN " %#3, %-\n\t" /* insn+data caches */ \ + ASM_MOV_INSN " %#1, %-\n\t" /* clear lines */ \ + ASM_MOV_INSN " %0, %-\n\t" /* beginning of buffer */ \ + ASM_MOV_INSN " %#105, %-\n\t" /* cache sub-function nr */ \ + ASM_MOV_INSN " %#0, %-\n\t" /* dummy return address */ \ + ASM_MOV_INSN " %#38, %/d0\n\t" /* system call nr */ \ + "trap %#0\n\t" \ + "add%.l %#24, %/sp" \ + : /* no outputs */ \ + : "g"(_beg), "g"(_len) \ + : "%d0"); \ +} diff --git a/gnu/usr.bin/gcc/config/m68k/aux-crt1.c b/gnu/usr.bin/gcc/config/m68k/aux-crt1.c new file mode 100644 index 00000000000..9ee529b053d --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/aux-crt1.c @@ -0,0 +1,134 @@ +/* Startup code for A/UX + Copyright (C) 1996 Free Software Foundation, Inc. + +This file 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 this program; 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. */ + +/* This file is compiled three times to produce crt1.o, mcrt1.o, and + maccrt1.o. The final two are created by defining MCRT1 and MACCRT1 + respectively. */ + +#include <stdlib.h> +#ifdef MCRT1 +#include <unistd.h> +#include <mon.h> +#endif + +/* Extern function declarations */ + +extern void initfpu(void); +extern void __istart(void); +extern void __compatmode(void); +extern void _cleanup(void); +extern int main(int, char **, char **); +extern void exit(int) __attribute__((noreturn)); +extern void _exit(int) __attribute__((noreturn)); + +#ifdef MACCRT1 +extern void InitMac(void); +#endif +#ifdef MCRT1 +static void monitor_start(void); +#endif + +/* Global variables */ + +char **environ; +char *__splimit; /* address of top of stack */ + + +/* Initialize system and run */ + +void _start() __attribute__((noreturn)); +void _start() +{ + register int *fp __asm__("%a6"); + register char *d0 __asm__("%d0"); + char **argv; + int argc; + + __splimit = d0; + argc = fp[1]; + argv = (char **)&fp[2]; + environ = &argv[argc+1]; + + initfpu(); + __istart(); + __compatmode(); + + atexit(_cleanup); +#ifdef MCRT1 + monitor_start(); +#endif +#ifdef MACCRT1 + InitMac(); +#endif + + exit(main(argc, argv, environ)); +} + + +#ifdef MCRT1 +/* Start/Stop program monitor */ + +extern void monitor(void *, void *, WORD *, int, int); + +static WORD *monitor_buffer; + +static void monitor_cleanup(void) +{ + monitor(NULL, NULL, NULL, 0, 0); + free(monitor_buffer); +} + +static void monitor_start(void) +{ + extern int etext; + extern int stext __asm__(".text"); + + /* Choice of buffer size should be "no more than a few times + smaller than the program size" -- I don't believe that there + are any (useful) functions smaller than two insns (4 bytes) + so that is the scale factor used here */ + int len = (&etext - &stext + 1) / 4; + + monitor_buffer = (WORD *)calloc(len, sizeof(WORD)); + if (monitor_buffer == NULL) + { + static const char msg[] = "mcrt1: could not allocate monitor buffer\n"; + write(2, msg, sizeof(msg)-1); + _exit(-1); + } + + /* I'm not sure why the count cap at 600 -- but that is what A/UX does */ + monitor(&stext, &etext, monitor_buffer, len, 600); + + atexit(monitor_cleanup); +} +#endif /* MCRT1 */ diff --git a/gnu/usr.bin/gcc/config/m68k/aux-crt2.asm b/gnu/usr.bin/gcc/config/m68k/aux-crt2.asm new file mode 100644 index 00000000000..062c16ae8c2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/aux-crt2.asm @@ -0,0 +1,42 @@ +/* More startup code for A/UX */ + +#include "tm.h" + +#ifdef USE_BIN_AS + file "crt2.s" + +/* The init section is used to support shared libraries */ + init + global __istart + +__istart: + link %fp,&-4 +#else + .file "crt2.s" + +/* The init section is used to support shared libraries */ +.section .init, "x" +.even +.globl __istart + +__istart: + link %fp,#-4 + +#ifndef USE_COLLECT2 +/* The ctors and dtors sections are used to support COFF collection of + c++ constructors and destructors */ +.section .ctors, "d" +.even +.globl __CTOR_LIST__ + +__CTOR_LIST__: + .long -1 + +.section .dtors, "d" +.even +.globl __DTOR_LIST__ + +__DTOR_LIST__: + .long -1 +#endif /* USE_COLLECT2 */ +#endif /* USE_BIN_AS */ diff --git a/gnu/usr.bin/gcc/config/m68k/aux-crtn.asm b/gnu/usr.bin/gcc/config/m68k/aux-crtn.asm new file mode 100644 index 00000000000..ce63d7fead7 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/aux-crtn.asm @@ -0,0 +1,26 @@ +/* More startup code for A/UX */ + +#include "tm.h" + +#ifdef USE_BIN_AS + file "crtn.s" + + init + + unlk %fp + rts +#else + .file "crtn.s" + +.section .init, "x" + unlk %fp + rts + +#ifndef USE_COLLECT2 +.section .ctors, "d" + .long 0 + +.section .dtors, "d" + .long 0 +#endif /* USE_COLLECT2 */ +#endif /* USE_BIN_AS */ diff --git a/gnu/usr.bin/gcc/config/m68k/aux-exit.c b/gnu/usr.bin/gcc/config/m68k/aux-exit.c new file mode 100644 index 00000000000..fe06c77c406 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/aux-exit.c @@ -0,0 +1,99 @@ +/* Generic atexit() + Copyright (C) 1996 Free Software Foundation, Inc. + +This file 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 this program; 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. */ + +/* Rather than come up with some ugly hack to make mcrt1 work, it is + better to just go ahead and provide atexit(). */ + + +#include <stdlib.h> + + +void exit(int) __attribute__((noreturn)); +void _exit(int) __attribute__((noreturn)); +void _cleanup(void); + + +#define FNS_PER_BLOCK 32 + +struct atexit_fn_block +{ + struct atexit_fn_block *next; + void (*fns[FNS_PER_BLOCK])(void); + short used; +}; + + +/* staticly allocate the first block */ +static struct atexit_fn_block atexit_fns; +static struct atexit_fn_block *current_block = &atexit_fns; + + +int atexit(void (*fn)(void)) +{ + if (current_block->used >= FNS_PER_BLOCK) + { + struct atexit_fn_block *new_block = + (struct atexit_fn_block *)malloc(sizeof(struct atexit_fn_block)); + if (new_block == NULL) + return -1; + + new_block->used = 0; + new_block->next = current_block; + current_block = new_block; + } + + current_block->fns[current_block->used++] = fn; + + return 0; +} + + +void exit(int status) +{ + struct atexit_fn_block *block = current_block, *old_block; + short i; + + while (1) + { + for (i = block->used; --i >= 0 ;) + (*block->fns[i])(); + if (block == &atexit_fns) + break; + /* I know what you are thinking -- we are about to exit, why free? + Because it is friendly to memory leak detectors, that's why. */ + old_block = block; + block = block->next; + free(old_block); + } + + _exit(status); +} diff --git a/gnu/usr.bin/gcc/config/m68k/aux-low.gld b/gnu/usr.bin/gcc/config/m68k/aux-low.gld new file mode 100644 index 00000000000..d1bb2a99080 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/aux-low.gld @@ -0,0 +1,38 @@ +/* GLD link script for building mac-compatible executables */ + +OUTPUT_FORMAT("coff-m68k") + +SEARCH_DIR(@tooldir@/lib); +SEARCH_DIR(@libdir@); +SEARCH_DIR(/lib); +SEARCH_DIR(/usr/lib); +SEARCH_DIR(@local_prefix@/lib); + +ENTRY(_start) + +SECTIONS +{ + .lowmem 0 (DSECT) : { + /usr/lib/low.o (.data) + } + .text 0x10000000 : { + *(.text) + *(.init) + *(.fini) + etext = .; + _etext = .; + } + .data ALIGN(0x40000) : { + *(.data) + *(.ctors) + *(.dtors) + edata = .; + _edata = .; + } + .bss : { + *(.bss) + *(COMMON) + end = .; + _end = .; + } +} diff --git a/gnu/usr.bin/gcc/config/m68k/aux-mcount.c b/gnu/usr.bin/gcc/config/m68k/aux-mcount.c new file mode 100644 index 00000000000..1001c84762b --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/aux-mcount.c @@ -0,0 +1,69 @@ +/* Profiling support code for A/UX + Copyright (C) 1996 Free Software Foundation, Inc. + +This file 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 this program; 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. */ + +/* This routine is called at the beginning of functions compiled with -p + or -pg. The A/UX libraries call mcount%, but gas cannot generate + symbols with embedded percent signs. Previous ports of GCC to A/UX + have done things like (1) assemble a stub routine with the native + assembler, or (2) assemble a stub routine with gas and edit the object + file. This solution has the advantage that it can interoperate with + the A/UX version and can be used in an eventual port of glibc to A/UX. */ + +#ifndef __GNUC__ +#error This file uses GNU C extensions +#endif + +#include <mon.h> + +#ifdef IN_GCC +#include "tm.h" +#endif + +struct cnt *_countbase; + +#ifdef FUNCTION_PROFILER_SYMBOL +void __mcount() __asm__(FUNCTION_PROFILER_SYMBOL); +#endif + +void __mcount() +{ + register long **pfncnt __asm__("%a0"); + register long *fncnt = *pfncnt; + + if (!fncnt) + { + struct cnt *newcnt = _countbase++; + newcnt->fnpc = (char *)__builtin_return_address(0); + *pfncnt = fncnt = &newcnt->mcnt; + } + *fncnt += 1; +} diff --git a/gnu/usr.bin/gcc/config/m68k/auxas.h b/gnu/usr.bin/gcc/config/m68k/auxas.h new file mode 100644 index 00000000000..794df51558f --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/auxas.h @@ -0,0 +1,189 @@ +/* Definitions for Motorola 680x0 running A/UX using /bin/as + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define USE_BIN_AS + +#ifndef USE_COLLECT2 +#define USE_COLLECT2 +#endif + +#ifndef __ASSEMBLY__ + +#include "m68k/sgs.h" + +#define ASM_SPEC "%{m68030:-68030 }%{m68040:-68040 }" + +/* Modify AT&T SGS assembler syntax */ +/* A/UX's as doesn't do dots in pseudo-ops */ + +#define SDB_DEBUGGING_INFO + +#define NO_DOLLAR_IN_LABEL +#define NO_DOT_IN_LABEL + +#undef TEXT_SECTION_ASM_OP +#define TEXT_SECTION_ASM_OP "\ttext" + +#undef DATA_SECTION_ASM_OP +#define DATA_SECTION_ASM_OP "\tdata\t1" + +#undef BYTE_ASM_OP +#define BYTE_ASM_OP "byte" + +#undef WORD_ASM_OP +#define WORD_ASM_OP "short" + +#undef LONG_ASM_OP +#define LONG_ASM_OP "long" + +#undef SPACE_ASM_OP +#define SPACE_ASM_OP "space" + +#undef ALIGN_ASM_OP +#define ALIGN_ASM_OP "align" + +#undef GLOBAL_ASM_OP +#define GLOBAL_ASM_OP "\tglobal" + +#undef SWBEG_ASM_OP +#define SWBEG_ASM_OP "swbeg" + +#undef SET_ASM_OP +#define SET_ASM_OP "set" + +#undef ASM_PN_FORMAT +#define ASM_PN_FORMAT "%s%%%d" + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX "L%" + +#define ADDITIONAL_REGISTER_NAMES { "%a6", 14, "%a7", 15 } + +#undef ASM_OUTPUT_INT +#define ASM_OUTPUT_INT(FILE,VALUE) \ +( fprintf ((FILE), "\t%s ", LONG_ASM_OP), \ + output_addr_const ((FILE), (VALUE)), \ + fprintf ((FILE), "\n")) + +#undef ASM_OUTPUT_COMMON +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +( fputs ("\tcomm\t", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (ROUNDED))) + +#undef ASM_OUTPUT_LOCAL +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +( fputs ("\tlcomm\t", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (ROUNDED))) + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_directive ((FILE), main_input_filename) + +#undef ASM_OUTPUT_SOURCE_FILENAME +#define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) \ +( fputs ("\tfile\t", (FILE)), \ + output_quoted_string ((FILE), (NAME)), \ + fputc ('\n', (FILE)) ) + +#undef ASM_OUTPUT_CASE_FETCH +#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \ + asm_fprintf (file, "10(%Rpc,%s.", regname) + +#define SGS_NO_LI + +/* Random macros describing parts of SDB data. */ + +#define PUT_SDB_SCL(a) \ + fprintf(asm_out_file, "\tscl\t%d%s", (a), SDB_DELIM) + +#define PUT_SDB_INT_VAL(a) \ + fprintf (asm_out_file, "\tval\t%d%s", (a), SDB_DELIM) + +#define PUT_SDB_VAL(a) \ +( fputs ("\tval\t", asm_out_file), \ + output_addr_const (asm_out_file, (a)), \ + fprintf (asm_out_file, SDB_DELIM)) + +#define PUT_SDB_DEF(a) \ +do { fprintf (asm_out_file, "\tdef\t"); \ + ASM_OUTPUT_LABELREF (asm_out_file, a); \ + fprintf (asm_out_file, SDB_DELIM); } while (0) + +#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s%s", a, SDB_DELIM) + +#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file) + +#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o%s", a, SDB_DELIM) + +#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d%s", a, SDB_DELIM) + +#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t") + +#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a) + +#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM) + +#define PUT_SDB_TAG(a) \ +do { fprintf (asm_out_file, "\ttag\t"); \ + ASM_OUTPUT_LABELREF (asm_out_file, a); \ + fprintf (asm_out_file, SDB_DELIM); } while (0) + +#define PUT_SDB_BLOCK_START(LINE) \ + fprintf (asm_out_file, \ + "\tdef\t~bb%s\tval\t~%s\tscl\t100%s\tline\t%d%s\tendef\n", \ + SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) + +#define PUT_SDB_BLOCK_END(LINE) \ + fprintf (asm_out_file, \ + "\tdef\t~eb%s\tval\t~%s\tscl\t100%s\tline\t%d%s\tendef\n", \ + SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) + +#define PUT_SDB_FUNCTION_START(LINE) \ + fprintf (asm_out_file, \ + "\tdef\t~bf%s\tval\t~%s\tscl\t101%s\tline\t%d%s\tendef\n", \ + SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) + +#define PUT_SDB_FUNCTION_END(LINE) \ + fprintf (asm_out_file, \ + "\tdef\t~ef%s\tval\t~%s\tscl\t101%s\tline\t%d%s\tendef\n", \ + SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) + +#define PUT_SDB_EPILOGUE_END(NAME) \ +do { fprintf (asm_out_file, "\tdef\t"); \ + ASM_OUTPUT_LABELREF (asm_out_file, NAME); \ + fprintf (asm_out_file, \ + "%s\tval\t~%s\tscl\t-1%s\tendef\n", \ + SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0) + +#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \ + sprintf ((BUFFER), "~%dfake", (NUMBER)); + +#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \ + fprintf((FILE), "\tln\t%d\n", \ + (sdb_begin_function_line > 1 ? \ + last_linenum - sdb_begin_function_line : 1)) + +#define ASM_MOV_INSN "mov.l" + +#define FUNCTION_PROFILER_SYMBOL "mcount%" + +#endif /* !__ASSEMBLY__ */ diff --git a/gnu/usr.bin/gcc/config/m68k/auxgas.h b/gnu/usr.bin/gcc/config/m68k/auxgas.h new file mode 100644 index 00000000000..c2e0d567b45 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/auxgas.h @@ -0,0 +1,56 @@ +/* Definitions for Motorola 680x0 running A/UX using GAS + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define USE_GAS + +#ifndef __ASSEMBLY__ + +#include "m68k/m68k.h" +#include "m68k/coff.h" + +#define ASM_SPEC "%{m68000:-Am68000 }%{m68030:-Am68030 }%{m68040:-Am68040 }" + +/* Output #ident as a .ident. */ +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "\t.ident \"%s\"\n", NAME); + +#ifdef IDENTIFY_WITH_IDENT +/* Put the GCC identification somewhere nicer, I think. + Does the COFF GDB use the "gcc2_complied." symbol anyway? */ +#define ASM_IDENTIFY_GCC(FILE) /* nothing */ +#define ASM_IDENTIFY_LANGUAGE(FILE) \ + fprintf (FILE, "\t.ident \"GCC (%s) %s\"\n", lang_identify(), version_string) +#endif + +#ifdef USE_COLLECT2 +#undef ASM_OUTPUT_CONSTRUCTOR +#undef ASM_OUTPUT_DESTRUCTOR +/* for the sake of link-level compatibility with /bin/as version */ +#define NO_DOLLAR_IN_LABEL +#define NO_DOT_IN_LABEL +#endif + +#define ADDITIONAL_REGISTER_NAMES { "%fp", 14, "%a7", 15 } + +#define ASM_MOV_INSN "movel" + +#define FUNCTION_PROFILER_SYMBOL "__mcount" + +#endif /* !__ASSEMBLY__ */ diff --git a/gnu/usr.bin/gcc/config/m68k/auxgld.h b/gnu/usr.bin/gcc/config/m68k/auxgld.h new file mode 100644 index 00000000000..12c97afaead --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/auxgld.h @@ -0,0 +1,29 @@ +/* Definitions for Motorola 680x0 running A/UX using GLD + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define USE_GNU_LD + +#ifndef __ASSEMBLY__ + +#define LINK_SPEC \ +"%{p:-L/lib/libp -L/usr/lib/libp }%{pg:-L/lib/libp -L/usr/lib/libp }\ +%{smac:-T low.gld%s }" + +#endif /* !__ASSEMBLY__ */ diff --git a/gnu/usr.bin/gcc/config/m68k/auxld.h b/gnu/usr.bin/gcc/config/m68k/auxld.h new file mode 100644 index 00000000000..932dd6ab953 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/auxld.h @@ -0,0 +1,35 @@ +/* Definitions for Motorola 680x0 running A/UX using /bin/ld + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define USE_BIN_LD + +#ifndef USE_COLLECT2 +#define USE_COLLECT2 +#endif + +#ifndef __ASSEMBLY__ + +#define LINK_SPEC \ +"%{p:-L/lib/libp -L/usr/lib/libp }%{pg:-L/lib/libp -L/usr/lib/libp }\ +%{smac:low.ld%s }%{!smac:shlib.ld%s }" + +#define SWITCHES_NEED_SPACES "o" + +#endif /* !__ASSEMBLY__ */ diff --git a/gnu/usr.bin/gcc/config/m68k/m68k-psos.h b/gnu/usr.bin/gcc/config/m68k/m68k-psos.h new file mode 100644 index 00000000000..8e5b843397e --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/m68k-psos.h @@ -0,0 +1,67 @@ +/* Definitions of a target machine for the GNU compiler: + 68040 running pSOS, ELF object files, DBX debugging. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* Use MOTOROLA assembler syntax, as gas is configured that way and + glibc also seems to use it. Must come BEFORE m68k.h! */ + +#define MOTOROLA + +/* Get generic m68k definitions. */ + +#include "m68k/m68k.h" +#include "m68k/m68kemb.h" + +/* Default processor type is a (pure) 68040 with 68881 emulation using + the floating-point support package. */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_68040_ONLY|MASK_BITFIELD|MASK_68881|MASK_68020) + +/* Options passed to CPP, GAS, CC1 and CC1PLUS. We override + m68k-none.h for consistency with TARGET_DEFAULT. */ + +#undef CPP_SPEC +#define CPP_SPEC \ +"%{!mc68000:%{!m68000:%{!m68332:%{!msoft-float:-D__HAVE_68881__ }}}}\ +%{!ansi:-Dmc68000 %{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68040 }}}}}}}}}}}\ +-D__mc68000__ -D__mc68000 %{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68040__ -D__mc68040 }}}}}}}}}}" + +#undef ASM_SPEC +#define ASM_SPEC \ +"%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881 }\ +%{m68000}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040}%{m68302}%{m68332}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-mc68040}}}}}}}}}}" + +#undef CC1_SPEC +#define CC1_SPEC \ + "%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000}%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float}}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68040}}}}}}}}}}" + +#undef CC1PLUS_SPEC +#define CC1PLUS_SPEC \ + "%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000}%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float}}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68040}}}}}}}}}}" + + +/* Get processor-independent pSOS definitions. */ + +#include "psos.h" + + +/* end of m68k-psos.h */ diff --git a/gnu/usr.bin/gcc/config/m68k/mot3300-crt0.S b/gnu/usr.bin/gcc/config/m68k/mot3300-crt0.S new file mode 100644 index 00000000000..2a84b37716c --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/mot3300-crt0.S @@ -0,0 +1,98 @@ +/* The start module crt0.s for the SysV68 Motorola 3300 Delta Series. + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.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. */ + +#ifdef MOTOROLA +# define COMM comm +# define DATA data +# define EVEN even +# define FILE(n) file n +# define GLOBAL_SYM(s) global s +# define LOCAL_LABEL(l) L%##l +# define IDENT(s) ident s +# define TEXT text +#else /* Assume we are using GNU as. */ +# define COMM .comm +# define DATA .data +# define EVEN .even +# define FILE(name) .file name +# define GLOBAL_SYM(s) .globl s +# define LOCAL_LABEL(l) .L.##l +# define IDENT(s) .section .comment;.asciz s +# define TEXT .text +#endif + + FILE ("crt0.s") + TEXT + GLOBAL_SYM (_start) +_start: mov.l %d0,splimit% + subq.w &8,%sp + mov.l 8(%sp),(%sp) + lea 12(%sp),%a0 + mov.l %a0,4(%sp) + mov.l %a0,%a1 +LOCAL_LABEL(0): + tst.l (%a0)+ + bne.b LOCAL_LABEL(0) +#ifdef SGS_CMP_ORDER + cmpa.l %a0,(%a1) +#else + cmpa.l (%a1),%a0 +#endif + blt.b LOCAL_LABEL(1) + subq.w &4,%a0 +LOCAL_LABEL(1): + mov.l %a0,8(%sp) + mov.l %a0,environ + jsr initfpu + + subq.w &8,%sp + clr.l %d0 /* if (! isatty (fileno (stderr))) */ + mov.b _iob+27,%d0 + mov.l %d0,-(%sp) + jsr isatty + addq.w &4,%sp + tst.l %d0 + bne.b LOCAL_LABEL(isatty) + clr.l -(%sp) /* setbuf (stderr, NULL) */ + pea _iob+28 + jsr setbuf + addq.w &8,%sp +LOCAL_LABEL(isatty): + addq.w &8,%sp + + jsr main + mov.l %d0,(%sp) + jsr exit + moveq.l &1,%d0 + trap &0 + nop + + GLOBAL_SYM (__stop_monitor) +__stop_monitor: + rts + EVEN + + COMM splimit%,4 + COMM environ,4 + + IDENT ("$Id: mot3300-crt0.S,v 1.1 1998/02/14 19:18:52 niklas Exp $") + IDENT ("Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.de)") + IDENT ("Corrections by Philippe De Muyter (phdm@macqel.be)") diff --git a/gnu/usr.bin/gcc/config/m68k/mot3300Mcrt0.S b/gnu/usr.bin/gcc/config/m68k/mot3300Mcrt0.S new file mode 100644 index 00000000000..271c81c725a --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/mot3300Mcrt0.S @@ -0,0 +1,142 @@ +/* The start module mcrt0.s for the SysV68 Motorola 3300 Delta Series. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.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. */ + +#ifdef MOTOROLA +# define COMM comm +# define DATA data +# define EVEN even +# define FILE(n) file n +# define GLOBAL_SYM(s) global s +# define LOCAL_LABEL(l) L%##l +# define IDENT(s) ident s +# define TEXT text +#else /* Assume we are using GNU as. */ +# define COMM .comm +# define DATA .data +# define EVEN .even +# define FILE(name) .file name +# define GLOBAL_SYM(s) .globl s +# define LOCAL_LABEL(l) .L.##l +# define IDENT(s) .section .comment;.asciz s +# define TEXT .text +#endif + + FILE ("mcrt0.s") + TEXT + GLOBAL_SYM (_start) +_start: mov.l %d0,splimit% + subq.w &8,%sp + mov.l 8(%sp),(%sp) + lea 12(%sp),%a0 + mov.l %a0,___Argv + mov.l %a0,4(%sp) + mov.l %a0,%a1 +LOCAL_LABEL(0): + tst.l (%a0)+ + bne.b LOCAL_LABEL(0) +#ifdef SGS_CMP_ORDER + cmpa.l %a0,(%a1) +#else + cmpa.l (%a1),%a0 +#endif + blt.b LOCAL_LABEL(1) + subq.w &4,%a0 +LOCAL_LABEL(1): + mov.l %a0,8(%sp) + mov.l %a0,environ + jsr initfpu + + sub &8,%sp + clr.l %d0 /* if (! isatty (fileno (stderr))) */ + mov.b _iob+27,%d0 + mov.l %d0,-(%sp) + jsr isatty + addq.w &4,%sp + tst.l %d0 + bne.b LOCAL_LABEL(isatty) + clr.l -(%sp) /* setbuf (stderr, NULL) */ + pea _iob+28 + jsr setbuf + addq.w &8,%sp +LOCAL_LABEL(isatty): + addq.w &8,%sp + + mov.l &600,-(%sp) + mov.l &etext,%d1 + subi.l &LOCAL_LABEL(endofstart),%d1 + addq.l &1,%d1 + bclr &0,%d1 + addi.l &4812,%d1 + asr.l &1,%d1 + mov.l %d1,-(%sp) + add.l %d1,%d1 + mov.l %d1,-(%sp) + jsr sbrk + addq.w &4,%sp +#ifdef SGS_CMP_ORDER + cmpa.l %a0,&-1 +#else + cmpa.l &-1,%a0 +#endif + beq.b LOCAL_LABEL(3) + mov.l %a0,-(%sp) + add.l &12,%a0 + mov.l %a0,_countbase + mov.l &etext,-(%sp) + mov.l &LOCAL_LABEL(endofstart),-(%sp) + jsr monitor + lea 20(%sp),%sp + jsr main + mov.l %d0,(%sp) + jsr exit +_exit: moveq &1,%d0 + trap &0 + + GLOBAL_SYM (__stop_monitor) +__stop_monitor: + clr.l -(%sp) + jsr monitor + add.w &4,%sp + rts + +LOCAL_LABEL(errtxt): + byte 'N,'o,' ,'s,'p,'a,'c,'e,' ,'f,'o,'r,' ,'m,'o,'n + byte 'i,'t,'o,'r,' ,'b,'u,'f,'f,'e,'r,'\n +LOCAL_LABEL(errtxt_end): + + EVEN +LOCAL_LABEL(3): + pea LOCAL_LABEL(errtxt_end)-LOCAL_LABEL(errtxt) + pea LOCAL_LABEL(errtxt)(%pc) + pea 2 + jsr write + bra.b _exit +LOCAL_LABEL(endofstart): + + EVEN + + COMM splimit%,4 + COMM environ,4 + COMM _countbase,4 + + IDENT ("$Id: mot3300Mcrt0.S,v 1.1 1998/02/14 19:18:55 niklas Exp $") + IDENT ("Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.de)") + IDENT ("Corrections by Philippe De Muyter (phdm@macqel.be)") diff --git a/gnu/usr.bin/gcc/config/m68k/rtems.h b/gnu/usr.bin/gcc/config/m68k/rtems.h new file mode 100644 index 00000000000..77c02f8e9c8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/rtems.h @@ -0,0 +1,28 @@ +/* Definitions for rtems targeting a Motorola m68k using coff. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "m68k/m68k-coff.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dmc68000 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(mc68000) -Acpu(m68k) -Amachine(m68k)" diff --git a/gnu/usr.bin/gcc/config/m68k/t-aux b/gnu/usr.bin/gcc/config/m68k/t-aux new file mode 100644 index 00000000000..3d59d675ffd --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/t-aux @@ -0,0 +1,44 @@ +# Makefile additions for A/UX + +LIB2FUNCS_EXTRA=aux-mcount.c aux-exit.c + +FIXPROTO_DEFINES=-D_POSIX_SOURCE + +# Only really needed for collect2 +CLIB=-lld + +# Needed to support builds for multiple versions of A/UX +# LDFLAGS=-static + +# Make sure we get the right assembler by letting gcc choose +AS = $(GCC_FOR_TARGET) -xassembler-with-cpp -D__ASSEMBLY__ $(INCLUDES) -c + +aux-mcount.c: $(srcdir)/config/m68k/aux-mcount.c + cp $(srcdir)/config/m68k/aux-mcount.c aux-mcount.c + +aux-exit.c: $(srcdir)/config/m68k/aux-exit.c + cp $(srcdir)/config/m68k/aux-exit.c aux-exit.c + +crt1.o: $(srcdir)/config/m68k/aux-crt1.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -o crt1.o -c \ + -fno-omit-frame-pointer $(srcdir)/config/m68k/aux-crt1.c + +mcrt1.o: $(srcdir)/config/m68k/aux-crt1.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -o mcrt1.o -c \ + -fno-omit-frame-pointer -DMCRT1 $(srcdir)/config/m68k/aux-crt1.c + +maccrt1.o: $(srcdir)/config/m68k/aux-crt1.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -o maccrt1.o -c \ + -fno-omit-frame-pointer -DMACCRT1 $(srcdir)/config/m68k/aux-crt1.c + +crt2.o: $(srcdir)/config/m68k/aux-crt2.asm $(GCC_PASSES) + $(AS) -o crt2.o $(srcdir)/config/m68k/aux-crt2.asm + +crtn.o: $(srcdir)/config/m68k/aux-crtn.asm $(GCC_PASSES) + $(AS) -o crtn.o $(srcdir)/config/m68k/aux-crtn.asm + +low.gld: $(srcdir)/config/m68k/aux-low.gld + sed -e 's|@libdir@|$(libdir)|' -e 's|@tooldir@|$(tooldir)|' \ + -e 's|@local_prefix@|$(local_prefix)|' \ + $(srcdir)/config/m68k/aux-low.gld > tmp-low.gld + mv tmp-low.gld low.gld diff --git a/gnu/usr.bin/gcc/config/m68k/t-linux-aout b/gnu/usr.bin/gcc/config/m68k/t-linux-aout new file mode 100644 index 00000000000..4ef9e1acaed --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/t-linux-aout @@ -0,0 +1,5 @@ +# Don't make libgcc1.a +LIBGCC1 = +CROSS_LIBGCC1 = +# On GNU/Linux we can print long double +ENQUIRE_CFLAGS = -DNO_MEM -O0 diff --git a/gnu/usr.bin/gcc/config/m68k/t-mot3300 b/gnu/usr.bin/gcc/config/m68k/t-mot3300 new file mode 100644 index 00000000000..2fc11858d58 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/t-mot3300 @@ -0,0 +1,10 @@ +MULTILIB_OPTIONS=m68000/m68020 msoft-float +MULTILIB_DIRNAMES= +MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S +MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S +CRT0STUFF_T_CFLAGS = -DMOTOROLA -DSGS_CMP_ORDER diff --git a/gnu/usr.bin/gcc/config/m68k/t-mot3300-gald b/gnu/usr.bin/gcc/config/m68k/t-mot3300-gald new file mode 100644 index 00000000000..435afc49e65 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/t-mot3300-gald @@ -0,0 +1,13 @@ +T_CPPFLAGS = -DUSE_GAS -DUSE_GLD +TARGET_LIBGCC2_CFLAGS = -DUSE_GAS + +MULTILIB_OPTIONS=m68000/m68020 msoft-float +MULTILIB_DIRNAMES= +MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S +MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S +CRT0STUFF_T_CFLAGS = diff --git a/gnu/usr.bin/gcc/config/m68k/t-mot3300-gas b/gnu/usr.bin/gcc/config/m68k/t-mot3300-gas new file mode 100644 index 00000000000..525667452e2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/t-mot3300-gas @@ -0,0 +1,13 @@ +T_CPPFLAGS = -DUSE_GAS +TARGET_LIBGCC2_CFLAGS = -DUSE_GAS + +MULTILIB_OPTIONS=m68000/m68020 msoft-float +MULTILIB_DIRNAMES= +MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S +MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S +CRT0STUFF_T_CFLAGS = diff --git a/gnu/usr.bin/gcc/config/m68k/t-mot3300-gld b/gnu/usr.bin/gcc/config/m68k/t-mot3300-gld new file mode 100644 index 00000000000..8cc3ed6f250 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/t-mot3300-gld @@ -0,0 +1,12 @@ +T_CPPFLAGS = -DUSE_GLD + +MULTILIB_OPTIONS=m68000/m68020 msoft-float +MULTILIB_DIRNAMES= +MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040 + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S +MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S +CRT0STUFF_T_CFLAGS = -DMOTOROLA -DSGS_CMP_ORDER diff --git a/gnu/usr.bin/gcc/config/m68k/x-mot3300-gas b/gnu/usr.bin/gcc/config/m68k/x-mot3300-gas new file mode 100644 index 00000000000..cf2797773df --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/x-mot3300-gas @@ -0,0 +1,12 @@ +ALLOCA=alloca.o + +# This disables the long/short jump optimization. +# I use sysV68 R3V7.1 RM04 (phdm@info.ucl.ac.be) +# Since ss-950318, with jump optimization enabled, "as" issues a warning +# when assembling combine.s : +# aline nnnnn : Warning: Table overflow: some optimizations lost (SDIs) +# but later "ld" complains with +# ld: relocation entry found for non-relocatable symbol in combine.o +# and the produced "cc1" fails with SIGSEGV +# Another possible fix would be to split combine.c. +XCFLAGS=`if [ x$@ = xcombine.o -a "${CC}" = "${OLDCC}" ]; then echo -Wa,-j; fi` diff --git a/gnu/usr.bin/gcc/config/m68k/xm-aux.h b/gnu/usr.bin/gcc/config/m68k/xm-aux.h new file mode 100644 index 00000000000..5ac1f4654d8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m68k/xm-aux.h @@ -0,0 +1,9 @@ +#ifndef USG +#define USG +#endif + +#ifndef AUX +#define AUX +#endif + +#include "m68k/xm-m68k.h" diff --git a/gnu/usr.bin/gcc/config/m88k/t-dguxbcs b/gnu/usr.bin/gcc/config/m88k/t-dguxbcs new file mode 100644 index 00000000000..c42a9bf18d5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/m88k/t-dguxbcs @@ -0,0 +1,28 @@ +# Specify how to create the *.asm files + +MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ + moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ + moveDI96x.asm + +$(MOVE_ASM): $(srcdir)/config/m88k/m88k-move.sh + $(srcdir)/config/m88k/m88k-move.sh + +LIB2FUNCS_EXTRA = $(MOVE_ASM) +LIBGCC1 = libgcc1.null +CROSS_LIBGCC1 = libgcc1.null + +# In a coff environment, a link script is required for ctors and dtors. +m88kdgux.ld: $(srcdir)/config/m88k/dgux.ld + rm -f m88kdgux.ld; cp $(srcdir)/config/m88k/dgux.ld ./m88kdgux.ld + +# A bcs crtbegin.o is needed since bcs does not +# increment the stack pointer in the init section as elf does +bcscrtbegin.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -DCRT_BEGIN -DBCS \ + -finhibit-size-directive -fno-inline-functions \ + -g0 -c $(srcdir)/crtstuff.c -o bcscrtbegin.o + +# Build libgcc.a, crtbegin.o, and crtend.o as bcs objects +GCC_FOR_TARGET = PATH=/usr/sde/m88kbcs/usr/bin/:/usr/bin TARGET_BINARY_INTERFACE=m88kbcs ./xgcc -B./ -msvr3 -D_M88KBCS_TARGET -mno-ocs-debug-info + +T_CFLAGS = -O -D_M88KBCS_TARGET diff --git a/gnu/usr.bin/gcc/config/mips/r3900.h b/gnu/usr.bin/gcc/config/mips/r3900.h new file mode 100644 index 00000000000..c1867430129 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mips/r3900.h @@ -0,0 +1,71 @@ +/* Definitions of MIPS sub target machine for GNU compiler. + Toshiba r3900. You should include mips.h after this. + + Copyright (C) 1989, 90-6, 1997 Free Software Foundation, Inc. + Contributed by Gavin Koch (gavin@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. */ + +#define SUBTARGET_CPP_SPEC "\ +%{!mabi=32: %{!mabi=n32: %{!mabi=64: -D__mips_eabi}}} \ +%{!msingle-float:-D__mips_soft_float} \ +%{mhard-float:%e-mhard-float not supported.} \ +%{msingle-float:%{msoft-float: \ + %e-msingle-float and -msoft-float can not both be specified.}}" + +/* The following is needed because -mips3 and -mips4 set gp64 which in + combination with abi=eabi, causes long64 to be set. */ +#define SUBTARGET_CPP_SIZE_SPEC "\ +%{mips3:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \ +%{mips4:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \ +%{!mips3:%{!mips4:%{!m4650:\ + -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}}} " + +/* by default (if not mips-something-else) produce code for the r3900 */ +#define SUBTARGET_CC1_SPEC "\ +%{mhard-float:%e-mhard-float not supported.} \ +%{msingle-float:%{msoft-float: \ + %e-msingle-float and -msoft-float can not both be specified.}}" + +#define TARGET_DEFAULT (MASK_SOFT_FLOAT | MASK_MIPS3900) +#define MIPS_CPU_STRING_DEFAULT "R3900" +#define MIPS_ISA_DEFAULT 1 + +#define MULTILIB_DEFAULTS { "EB", "mips1", "msoft-float" } + +/* We use the MIPS EABI by default. */ +#define MIPS_ABI_DEFAULT ABI_EABI + + +/* Debugging */ + +#define DWARF2_DEBUGGING_INFO +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +/* For the 'preferred' cases ("gN" and "ggdbN") we need to tell the + gnu assembler "dwarf-2" */ + +#define SUBTARGET_ASM_DEBUGGING_SPEC "\ +%{!mmips-as: \ + %{g:-gdwarf-2} %{g0:-gdwarf-2} %{g1:-gdwarf-2} %{g2:-gdwarf-2} %{g3:-gdwarf-2} \ + %{ggdb:-gdwarf-2} %{ggdb0:-gdwarf-2} %{ggdb1:-gdwarf-2} %{ggdb2:-gdwarf-2} %{ggdb3:-gdwarf-2} \ + %{gdwarf-2*:-gdwarf-2}} \ +%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \ +%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \ +%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}" + diff --git a/gnu/usr.bin/gcc/config/mips/rtems64.h b/gnu/usr.bin/gcc/config/mips/rtems64.h new file mode 100644 index 00000000000..6433ed56498 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mips/rtems64.h @@ -0,0 +1,28 @@ +/* Definitions for rtems targeting a MIPS ORION using ecoff. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "mips/elforion.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dmips -DMIPSEB -DR4000 -D_mips -D_MIPSEB -D_R4000 \ + -Drtems -D__rtems__ -Asystem(rtems)" diff --git a/gnu/usr.bin/gcc/config/mips/sni-gas.h b/gnu/usr.bin/gcc/config/mips/sni-gas.h new file mode 100644 index 00000000000..752866536b8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mips/sni-gas.h @@ -0,0 +1,43 @@ +#include "mips/sni-svr4.h" + +/* Enable debugging. */ +#define DBX_DEBUGGING_INFO +#define SDB_DEBUGGING_INFO +#define MIPS_DEBUGGING_INFO + +#define DWARF_DEBUGGING_INFO +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG + +/* We need to use .esize and .etype instead of .size and .type to + avoid conflicting with ELF directives. These are only recognized + by gas, anyhow, not the native assembler. */ +#undef PUT_SDB_SIZE +#define PUT_SDB_SIZE(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.esize\t%d;", (a)); \ +} while (0) + +#undef PUT_SDB_TYPE +#define PUT_SDB_TYPE(a) \ +do { \ + extern FILE *asm_out_text_file; \ + fprintf (asm_out_text_file, "\t.etype\t0x%x;", (a)); \ +} while (0) + + +/* This is how to equate one symbol to another symbol. The syntax used is + `SYM1=SYM2'. Note that this is different from the way equates are done + with most svr4 assemblers, where the syntax is `.set SYM1,SYM2'. */ + +#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \ + do { fprintf ((FILE), "\t"); \ + assemble_name (FILE, LABEL1); \ + fprintf (FILE, " = "); \ + assemble_name (FILE, LABEL2); \ + fprintf (FILE, "\n"); \ + } while (0) + + + diff --git a/gnu/usr.bin/gcc/config/mips/sni-svr4.h b/gnu/usr.bin/gcc/config/mips/sni-svr4.h new file mode 100644 index 00000000000..f42a882fb82 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mips/sni-svr4.h @@ -0,0 +1,97 @@ +/* Definitions of target machine for GNU compiler. SNI SINIX version. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Marco Walther (Marco.Walther@mch.sni.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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#define MIPS_SVR4 + +#define CPP_PREDEFINES "\ +-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SVR4 \ +-D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_SVR4 \ +-Asystem(unix) -Asystem(svr4) -Acpu(mips) -Amachine(mips)" + +#define SUBTARGET_CPP_SIZE_SPEC "\ +-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int" + +#define LINK_SPEC "\ +%{G*} \ +%{!mgas: \ + %{dy} %{dn}}" + +#define LIB_SPEC "\ + %{p:-lprof1} \ + %{!p:%{pg:-lprof1} \ + %{!pg:-L/usr/ccs/lib/ -lc /usr/ccs/lib/crtn.o%s}}" + +#define STARTFILE_SPEC "\ + %{pg:gcrt0.o%s} \ + %{!pg:%{p:mcrt0.o%s} \ + %{!p:/usr/ccs/lib/crt1.o /usr/ccs/lib/crti.o /usr/ccs/lib/values-Xt.o%s}}" + +/* Mips System V.4 doesn't have a getpagesize() function needed by the + trampoline code, so use the POSIX sysconf function to get it. + This is only done when compiling the trampoline code. */ + +#ifdef L_trampoline +#include <unistd.h> + +#define getpagesize() sysconf(_SC_PAGE_SIZE) +#endif /* L_trampoline */ + +/* Use atexit for static constructors/destructors, instead of defining + our own exit function. */ +#define HAVE_ATEXIT + +/* Generate calls to memcpy, etc., not bcopy, etc. */ +#define TARGET_MEM_FUNCTIONS + +#define OBJECT_FORMAT_ELF + +#define TARGET_DEFAULT MASK_ABICALLS +#define ABICALLS_ASM_OP ".option pic2" + +#define MACHINE_TYPE "SNI running SINIX 5.42" + +#define MIPS_DEFAULT_GVALUE 0 + +#define NM_FLAGS "-p" + +/* wir haben ein Problem, wenn in einem Assembler-File keine .text-section + erzeugt wird. Dann landen diese Pseudo-Labels in irgendeiner anderen + section, z.B. .reginfo. Das macht den ld sehr ungluecklich. */ + +#define ASM_IDENTIFY_GCC(mw_stream) \ + fprintf(mw_stream, "\t.ident \"gcc2_compiled.\"\n"); + +#define ASM_IDENTIFY_LANGUAGE(STREAM) + +#define ASM_LONG ".word\t" +#define ASM_GLOBAL ".rdata\n\t\t.globl\t" + +#include "mips/mips.h" + +/* We do not want to run mips-tfile! */ +#undef ASM_FINAL_SPEC + +#undef OBJECT_FORMAT_COFF + +/* We don't support debugging info for now. */ +#undef DBX_DEBUGGING_INFO +#undef SDB_DEBUGGING_INFO +#undef MIPS_DEBUGGING_INFO +#undef PREFERRED_DEBUGGING_TYPE diff --git a/gnu/usr.bin/gcc/config/mips/x-sni-svr4 b/gnu/usr.bin/gcc/config/mips/x-sni-svr4 new file mode 100644 index 00000000000..f986f88162f --- /dev/null +++ b/gnu/usr.bin/gcc/config/mips/x-sni-svr4 @@ -0,0 +1,18 @@ +# Define CC and OLDCC as the same, so that the tests: +# if [ x"$(OLDCC)" = x"$(CC)" ] ... +# +# will succeed (if OLDCC != CC, it is assumed that GCC is +# being used in secondary stage builds). +# -Olimit is so the user can use -O2. Down with fixed +# size tables! + +CC = $(OLDCC) +OPT = +OLDCC = cc -Olimit 3000 $(OPT) + +X_CFLAGS = -DNO_SYS_SIGLIST + +# Show we need to use the C version of ALLOCA +# The SVR3 configurations have it, but the SVR4 configurations don't. +# For now, just try using it for all SVR* configurations. +ALLOCA = alloca.o diff --git a/gnu/usr.bin/gcc/config/mn10200/divmod.c b/gnu/usr.bin/gcc/config/mn10200/divmod.c new file mode 100644 index 00000000000..6faa09102b5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/divmod.c @@ -0,0 +1,50 @@ +long udivmodsi4 (); + +long +__divsi3 (long a, long b) +{ + int neg = 0; + long res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodsi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + +long +__modsi3 (long a, long b) +{ + int neg = 0; + long res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} diff --git a/gnu/usr.bin/gcc/config/mn10200/lib1funcs.asm b/gnu/usr.bin/gcc/config/mn10200/lib1funcs.asm new file mode 100644 index 00000000000..ff98fcc0ca2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/lib1funcs.asm @@ -0,0 +1,609 @@ +/* libgcc1 routines for Matsushita mn10200. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 this program; 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. */ + +#ifdef L_divhi3 + /* Derive signed division/modulo from unsigned "divu" instruction. */ + .text + .globl ___divhi3 + .type ___divhi3,@function +___divhi3: + + /* We're going to need some scratch registers, so save d2/d3 + into the stack. */ + add -8,a3 + movx d2,(0,a3) + movx d3,(4,a3) + + /* Loading zeros into registers now allows us to use them + in the compare instructions, which saves a total of + two bytes (egad). */ + sub d3,d3 + sub d2,d2 + sub a0,a0 + + /* If first operand is negative, then make it positive. + It will be contained in d2 just before .L1. + + a0 tells us if the first operand was negated. */ + cmp d2,d0 + bge .L0 + sub d0,d2 + mov 1,a0 + bra .L1 +.L0: + mov d0,d2 +.L1: + /* If the second operand is negative, then make it positive. + It will be contained in d3 just before .L3. + + d0 tells us if the second operand was negated. */ + cmp d3,d1 + bge .L2 + sub d1,d3 + mov 1,d0 + bra .L3 +.L2: + sub d0,d0 + mov d1,d3 +.L3: + /* Loading d1 with zero here allows us to save one byte + in the comparison below. */ + + sub d1,d1 + + /* Make sure to clear the mdr register, then do the unsigned + division. Result will be in d2/mdr. */ + mov d1,mdr + divu d3,d2 + + /* Negate the remainder based on the first argument negation + flag only. */ + cmp d1,a0 + beq .L4 + mov mdr,d3 + sub d3,d1 + bra .L5 +.L4: + mov mdr,d1 + +.L5: + /* Negate the result if either, but not both of the inputs + were negated. */ + mov a0,d3 + xor d3,d0 + beq .L6 + sub d0,d0 + sub d2,d0 + bra .L7 +.L6: + mov d2,d0 +.L7: + + /* Restore our scratch registers, deallocate our stack and return. */ + movx (0,a3),d2 + movx (4,a3),d3 + add 8,a3 + rts + .size ___divhi3,.-___divhi3 +#endif + +#ifdef L_modhi3 + .text + .globl ___modhi3 + .type ___modhi3,@function +___modhi3: + jsr ___divhi3 + mov d1,d0 + rts + .size ___modhi3,.-___modhi3 +#endif + +#ifdef L_addsi3 + .text + .globl ___addsi3 + .type ___addsi3,@function +___addsi3: + add -4,a3 + movx d2,(0,a3) + mov (8,a3),d2 + add d2,d0 + mov (10,a3),d2 + addc d2,d1 + movx (0,a3),d2 + add 4,a3 + rts + + .size ___addsi3,.-___addsi3 +#endif + +#ifdef L_subsi3 + .text + .globl ___subsi3 + .type ___subsi3,@function +___subsi3: + add -4,a3 + movx d2,(0,a3) + mov (8,a3),d2 + sub d2,d0 + mov (10,a3),d2 + subc d2,d1 + movx (0,a3),d2 + add 4,a3 + rts + + .size ___subsi3,.-___subsi3 +#endif + +#ifdef L_mulsi3 + .text + .globl ___mulsi3 + .type ___mulsi3,@function +___mulsi3: + add -4,a3 + mov a1,(0,a3) + mov d0,a0 + /* Multiply arg0 msb with arg1 lsb. + arg0 msb is in register d1, + arg1 lsb is in memory. */ + mov (8,a3),d0 + mulu d0,d1 + mov d1,a1 + + /* Multiply arg0 lsb with arg1 msb. + arg0 msb is in register a0, + arg1 lsb is in memory. */ + mov a0,d0 + mov (10,a3),d1 + mulu d0,d1 + + /* Add the cross products. */ + add d1,a1 + + /* Now multiply arg0 lsb with arg1 lsb. */ + mov (8,a3),d1 + mulu d1,d0 + + /* Add in the upper 16 bits to the cross product sum. */ + mov mdr,d1 + add a1,d1 + mov (0,a3),a1 + add 4,a3 + rts + + .size ___mulsi3,.-___mulsi3 +#endif + +#ifdef L_ashlsi3 + .text + .globl ___ashlsi3 + .type ___ashlsi3,@function +___ashlsi3: + mov (4,a3),a0 + cmp 0,a0 + beq .L0 +.L1: + add d0,d0 + addc d1,d1 + add -1,a0 + bne .L1 +.L0: + rts + + .size ___ashlsi3,.-___ashlsi3 +#endif + +#ifdef L_lshrsi3 + .text + .globl ___lshrsi3 + .type ___lshrsi3,@function +___lshrsi3: + mov (4,a3),a0 + cmp 0,a0 + beq .L0 +.L1: + lsr d1 + ror d0 + add -1,a0 + bne .L1 +.L0: + rts + + .size ___lshrsi3,.-___lshrsi3 +#endif + +#ifdef L_ashrsi3 + .text + .globl ___ashrsi3 + .type ___ashrsi3,@function +___ashrsi3: + mov (4,a3),a0 + cmp 0,a0 + beq .L0 +.L1: + asr d1 + ror d0 + add -1,a0 + bne .L1 +.L0: + rts + + .size ___ashrsi3,.-___ashrsi3 +#endif + +/* All functions beyond this point pass their arguments in registers! */ +#ifdef L_negsi2_d0 + .text + .globl ___negsi2_d0 + .type ___negsi2_d0,@function +___negsi2_d0: + add -8,a3 + movx d3,(0,a3) + movx d2,(4,a3) + mov d0,d2 + mov d1,d3 + sub d0,d0 + sub d1,d1 + sub d2,d0 + subc d3,d1 + movx (0,a3),d3 + movx (4,a3),d2 + add 8,a3 + rts + + .size ___negsi2_d0,.-___negsi2_d0 +#endif + +#ifdef L_negsi2_d2 + .text + .globl ___negsi2_d2 + .type ___negsi2_d2,@function +___negsi2_d2: + add -8,a3 + movx d1,(0,a3) + movx d0,(4,a3) + mov d2,d0 + mov d3,d1 + sub d2,d2 + sub d3,d3 + sub d0,d2 + subc d1,d3 + movx (0,a3),d1 + movx (4,a3),d0 + add 8,a3 + rts + + .size ___negsi2_d2,.-___negsi2_d2 +#endif + +#ifdef L_zero_extendpsisi2_d0 + .text + .globl ___zero_extendpsisi2_d0 + .type ___zero_extendpsisi2_d0,@function +___zero_extendpsisi2_d0: + add -4,a3 + movx d0,(0,a3) + movbu (2,a3),d1 + add 4,a3 + rts + + .size ___zero_extendpsisi2_d0,.-___zero_extendpsisi2_d0 +#endif + +#ifdef L_zero_extendpsisi2_d2 + .text + .globl ___zero_extendpsisi2_d2 + .type ___zero_extendpsisi2_d2,@function +___zero_extendpsisi2_d2: + add -4,a3 + movx d2,(0,a3) + movbu (2,a3),d3 + add 4,a3 + rts + + .size ___zero_extendpsisi2_d2,.-___zero_extendpsisi2_d2 +#endif + +#ifdef L_sign_extendpsisi2_d0 + .text + .globl ___sign_extendpsisi2_d0 + .type ___sign_extendpsisi2_d0,@function +___sign_extendpsisi2_d0: + add -4,a3 + movx d0,(0,a3) + movb (2,a3),d1 + add 4,a3 + rts + + .size ___sign_extendpsisi2_d0,.-___sign_extendpsisi2_d0 +#endif + +#ifdef L_sign_extendpsisi2_d2 + .text + .globl ___sign_extendpsisi2_d2 + .type ___sign_extendpsisi2_d2,@function +___sign_extendpsisi2_d2: + add -4,a3 + movx d2,(0,a3) + movb (2,a3),d3 + add 4,a3 + rts + + .size ___sign_extendpsisi2_d2,.-___sign_extendpsisi2_d2 +#endif + +#ifdef L_truncsipsi2_d0_d0 + .text + .globl ___truncsipsi2_d0_d0 + .type ___truncsipsi2_d0_d0,@function +___truncsipsi2_d0_d0: + add -4,a3 + mov d0,(a3) + mov d1,(2,a3) + movx (0,a3),d0 + add 4,a3 + rts + + .size ___truncsipsi2_d0_d0,.-___truncsipsi2_d0_d0 +#endif + +#ifdef L_truncsipsi2_d0_d1 + .text + .globl ___truncsipsi2_d0_d1 + .type ___truncsipsi2_d0_d1,@function +___truncsipsi2_d0_d1: + add -4,a3 + mov d0,(a3) + mov d1,(2,a3) + movx (0,a3),d1 + add 4,a3 + rts + + .size ___truncsipsi2_d0_d1,.-___truncsipsi2_d0_d1 +#endif + +#ifdef L_truncsipsi2_d0_d2 + .text + .globl ___truncsipsi2_d0_d2 + .type ___truncsipsi2_d0_d2,@function +___truncsipsi2_d0_d2: + add -4,a3 + mov d0,(a3) + mov d1,(2,a3) + movx (0,a3),d2 + add 4,a3 + rts + + .size ___truncsipsi2_d0_d2,.-___truncsipsi2_d0_d2 +#endif + +#ifdef L_truncsipsi2_d0_d3 + .text + .globl ___truncsipsi2_d0_d3 + .type ___truncsipsi2_d0_d3,@function +___truncsipsi2_d0_d3: + add -4,a3 + mov d0,(a3) + mov d1,(2,a3) + movx (0,a3),d3 + add 4,a3 + rts + + .size ___truncsipsi2_d0_d3,.-___truncsipsi2_d0_d3 +#endif + +#ifdef L_truncsipsi2_d2_d0 + .text + .globl ___truncsipsi2_d2_d0 + .type ___truncsipsi2_d2_d0,@function +___truncsipsi2_d2_d0: + add -4,a3 + mov d2,(a3) + mov d3,(2,a3) + movx (0,a3),d0 + add 4,a3 + rts + + .size ___truncsipsi2_d2_d0,.-___truncsipsi2_d2_d0 +#endif + +#ifdef L_truncsipsi2_d2_d1 + .text + .globl ___truncsipsi2_d2_d1 + .type ___truncsipsi2_d2_d1,@function +___truncsipsi2_d2_d1: + add -4,a3 + mov d2,(a3) + mov d3,(2,a3) + movx (0,a3),d1 + add 4,a3 + rts + + .size ___truncsipsi2_d2_d1,.-___truncsipsi2_d2_d1 +#endif + +#ifdef L_truncsipsi2_d2_d2 + .text + .globl ___truncsipsi2_d2_d2 + .type ___truncsipsi2_d2_d2,@function +___truncsipsi2_d2_d2: + add -4,a3 + mov d2,(a3) + mov d3,(2,a3) + movx (0,a3),d2 + add 4,a3 + rts + + .size ___truncsipsi2_d2_d2,.-___truncsipsi2_d2_d2 +#endif + +#ifdef L_truncsipsi2_d2_d3 + .text + .globl ___truncsipsi2_d2_d3 + .type ___truncsipsi2_d2_d3,@function +___truncsipsi2_d2_d3: + add -4,a3 + mov d2,(a3) + mov d3,(2,a3) + movx (0,a3),d3 + add 4,a3 + rts + + .size ___truncsipsi2_d2_d3,.-___truncsipsi2_d2_d3 +#endif + + +#ifdef L_cmpsi2 + .text + .globl ___cmpsi2 + .type ___cmpsi2,@function +___cmpsi2: + add -4,a3 + mov a1,(0,a3) + mov (10,a3),a1 + mov (8,a3),a0 + cmp a1,d1 + blt .L9 + bgt .L6 + cmp a0,d0 + bcc .L5 +.L9: + sub d0,d0 + jmp .L8 +.L5: + cmp a0,d0 + bhi .L6 + mov 1,d0 + jmp .L8 +.L6: + mov 2,d0 +.L8: + mov (0,a3),a1 + add 4,a3 + rts + .size ___cmpsi2,.-___cmpsi2 +#endif + +#ifdef L_ucmpsi2 + .text + .globl ___ucmpsi2 + .type ___ucmpsi2,@function +___ucmpsi2: + add -4,a3 + mov a1,(0,a3) + mov (10,a3),a1 + mov (8,a3),a0 + cmp a1,d1 + bcs .L9 + bhi .L6 + cmp a0,d0 + bcc .L5 +.L9: + sub d0,d0 + jmp .L8 +.L5: + cmp a0,d0 + bhi .L6 + mov 1,d0 + jmp .L8 +.L6: + mov 2,d0 +.L8: + mov (0,a3),a1 + add 4,a3 + rts + .size ___ucmpsi2,.-___ucmpsi2 +#endif + + +#ifdef L_prologue + .text + .globl ___prologue + .type ___prologue,@function +___prologue: + mov (0,a3),a0 + add -16,a3 + movx d2,(4,a3) + movx d3,(8,a3) + mov a1,(12,a3) + mov a2,(16,a3) + mov a0,(0,a3) + rts + .size ___prologue,.-___prologue +#endif + +#ifdef L_epilogue_a0 + .text + .globl ___epilogue_a0 + .type ___epilogue_a0,@function +___epilogue_a0: + mov (0,a3),a0 + movx (4,a3),d2 + movx (8,a3),d3 + mov (12,a3),a1 + mov (16,a3),a2 + add 16,a3 + mov a0,(0,a3) + rts + .size ___epilogue_a0,.-___epilogue_a0 +#endif + +#ifdef L_epilogue_d0 + .text + .globl ___epilogue_d0 + .type ___epilogue_d0,@function +___epilogue_d0: + movx (0,a3),d0 + movx (4,a3),d2 + movx (8,a3),d3 + mov (12,a3),a1 + mov (16,a3),a2 + add 16,a3 + movx d0,(0,a3) + rts + .size ___epilogue_d0,.-___epilogue_d0 +#endif + +#ifdef L_epilogue_noreturn + .text + .globl ___epilogue_noreturn + .type ___epilogue_noreturn,@function +___epilogue_noreturn: + movx (0,a3),d2 + movx (4,a3),d3 + mov (8,a3),a1 + mov (12,a3),a2 + add 16,a3 + rts + .size ___epilogue_noreturn,.-___epilogue_noreturn +#endif diff --git a/gnu/usr.bin/gcc/config/mn10200/mn10200.c b/gnu/usr.bin/gcc/config/mn10200/mn10200.c new file mode 100644 index 00000000000..5435f773c8d --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/mn10200.c @@ -0,0 +1,1532 @@ +/* Subroutines for insn-output.c for Matsushita MN10200 series + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Jeff Law (law@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. */ + +#include "config.h" +#include <stdio.h> +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "recog.h" +#include "expr.h" +#include "tree.h" +#include "obstack.h" + +/* Global registers known to hold the value zero. + + Normally we'd depend on CSE and combine to put zero into a + register and re-use it. + + However, on the mn10x00 processors we implicitly use the constant + zero in tst instructions, so we might be able to do better by + loading the value into a register in the prologue, then re-useing + that register throughout the function. + + We could perform similar optimizations for other constants, but with + gcse due soon, it doesn't seem worth the effort. + + These variables hold a rtx for a register known to hold the value + zero throughout the entire function, or NULL if no register of + the appropriate class has such a value throughout the life of the + function. */ +rtx zero_dreg; +rtx zero_areg; + +/* Note whether or not we need an out of line epilogue. */ +static int out_of_line_epilogue; + +/* Indicate this file was compiled by gcc and what optimization + level was used. */ +void +asm_file_start (file) + FILE *file; +{ + fprintf (file, "#\tGCC For the Matsushita MN10200\n"); + if (optimize) + fprintf (file, "# -O%d\n", optimize); + else + fprintf (file, "\n\n"); + output_file_directive (file, main_input_filename); +} + +/* Print operand X using operand code CODE to assembly language output file + FILE. */ + +void +print_operand (file, x, code) + FILE *file; + rtx x; + int code; +{ + switch (code) + { + case 'b': + case 'B': + /* These are normal and reversed branches. */ + switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x))) + { + case NE: + fprintf (file, "ne"); + break; + case EQ: + fprintf (file, "eq"); + break; + case GE: + fprintf (file, "ge"); + break; + case GT: + fprintf (file, "gt"); + break; + case LE: + fprintf (file, "le"); + break; + case LT: + fprintf (file, "lt"); + break; + case GEU: + fprintf (file, "cc"); + break; + case GTU: + fprintf (file, "hi"); + break; + case LEU: + fprintf (file, "ls"); + break; + case LTU: + fprintf (file, "cs"); + break; + default: + abort (); + } + break; + case 'C': + /* This is used for the operand to a call instruction; + if it's a REG, enclose it in parens, else output + the operand normally. */ + if (GET_CODE (x) == REG) + { + fputc ('(', file); + print_operand (file, x, 0); + fputc (')', file); + } + else + print_operand (file, x, 0); + break; + + /* These are the least significant word in a 32bit value. + 'o' allows us to sign extend a constant if doing so + makes for more compact code. */ + case 'L': + case 'o': + switch (GET_CODE (x)) + { + case MEM: + fputc ('(', file); + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case REG: + fprintf (file, "%s", reg_names[REGNO (x)]); + break; + + case SUBREG: + fprintf (file, "%s", + reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]); + break; + + case CONST_DOUBLE: + if (code == 'L') + { + long val; + REAL_VALUE_TYPE rv; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, val); + print_operand_address (file, GEN_INT (val & 0xffff)); + } + else + { + long val; + REAL_VALUE_TYPE rv; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, val); + + val &= 0xffff; + val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000; + print_operand_address (file, GEN_INT (val)); + } + break; + + case CONST_INT: + if (code == 'L') + print_operand_address (file, GEN_INT ((INTVAL (x) & 0xffff))); + else + { + unsigned int val = INTVAL (x) & 0xffff; + val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000; + print_operand_address (file, GEN_INT (val)); + } + break; + default: + abort (); + } + break; + + /* Similarly, but for the most significant word. */ + case 'H': + case 'h': + switch (GET_CODE (x)) + { + case MEM: + fputc ('(', file); + x = adj_offsettable_operand (x, 2); + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case REG: + fprintf (file, "%s", reg_names[REGNO (x) + 1]); + break; + + case SUBREG: + fprintf (file, "%s", + reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1); + break; + + case CONST_DOUBLE: + if (code == 'H') + { + long val; + REAL_VALUE_TYPE rv; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, val); + + print_operand_address (file, GEN_INT ((val >> 16) & 0xffff)); + } + else + { + long val; + REAL_VALUE_TYPE rv; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, val); + + val = (val >> 16) & 0xffff; + val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000; + + print_operand_address (file, GEN_INT (val)); + } + break; + + case CONST_INT: + if (code == 'H') + print_operand_address (file, + GEN_INT ((INTVAL (x) >> 16) & 0xffff)); + else + { + unsigned int val = (INTVAL (x) >> 16) & 0xffff; + val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000; + + print_operand_address (file, GEN_INT (val)); + } + break; + default: + abort (); + } + break; + + /* Output ~CONST_INT. */ + case 'N': + if (GET_CODE (x) != CONST_INT) + abort (); + fprintf (file, "%d", ~INTVAL (x)); + break; + + /* An address which can not be register indirect, if it is + register indirect, then turn it into reg + disp. */ + case 'A': + if (GET_CODE (x) != MEM) + abort (); + if (GET_CODE (XEXP (x, 0)) == REG) + x = gen_rtx (PLUS, PSImode, XEXP (x, 0), GEN_INT (0)); + else + x = XEXP (x, 0); + fputc ('(', file); + output_address (x); + fputc (')', file); + break; + + case 'Z': + print_operand (file, XEXP (x, 1), 0); + break; + + /* More cases where we can sign-extend a CONST_INT if it + results in more compact code. */ + case 's': + case 'S': + if (GET_CODE (x) == CONST_INT) + { + int val = INTVAL (x); + + if (code == 's') + x = GEN_INT (((val & 0xffff) ^ (~0x7fff)) + 0x8000); + else + x = GEN_INT (((val & 0xff) ^ (~0x7f)) + 0x80); + } + /* FALL THROUGH */ + default: + switch (GET_CODE (x)) + { + case MEM: + fputc ('(', file); + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case REG: + fprintf (file, "%s", reg_names[REGNO (x)]); + break; + + case SUBREG: + fprintf (file, "%s", + reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]); + break; + + case CONST_INT: + case CONST_DOUBLE: + case SYMBOL_REF: + case CONST: + case LABEL_REF: + case CODE_LABEL: + print_operand_address (file, x); + break; + default: + abort (); + } + break; + } +} + +/* Output assembly language output for the address ADDR to FILE. */ + +void +print_operand_address (file, addr) + FILE *file; + rtx addr; +{ + switch (GET_CODE (addr)) + { + case REG: + print_operand (file, addr, 0); + break; + case PLUS: + { + rtx base, index; + /* The base and index could be in any order, so we have + to figure out which is the base and which is the index. + Uses the same code as GO_IF_LEGITIMATE_ADDRESS. */ + if (REG_P (XEXP (addr, 0)) + && REG_OK_FOR_BASE_P (XEXP (addr, 0))) + base = XEXP (addr, 0), index = XEXP (addr, 1); + else if (REG_P (XEXP (addr, 1)) + && REG_OK_FOR_BASE_P (XEXP (addr, 1))) + base = XEXP (addr, 1), index = XEXP (addr, 0); + else + abort (); + print_operand (file, index, 0); + fputc (',', file); + print_operand (file, base, 0);; + break; + } + case SYMBOL_REF: + output_addr_const (file, addr); + break; + default: + output_addr_const (file, addr); + break; + } +} + +/* Count the number of tst insns which compare an address register + with zero. */ +static void +count_tst_insns (areg_countp) + int *areg_countp; +{ + rtx insn; + + /* Assume no tst insns exist. */ + *areg_countp = 0; + + /* If not optimizing, then quit now. */ + if (!optimize) + return; + + /* Walk through all the insns. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + rtx pat; + + /* Ignore anything that is not a normal INSN. */ + if (GET_CODE (insn) != INSN) + continue; + + /* Ignore anything that isn't a SET. */ + pat = PATTERN (insn); + if (GET_CODE (pat) != SET) + continue; + + /* Check for a tst insn. */ + if (SET_DEST (pat) == cc0_rtx + && GET_CODE (SET_SRC (pat)) == REG + && REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS) + (*areg_countp)++; + } +} + +/* Return the total size (in bytes) of the current function's frame. + This is the size of the register save area + the size of locals, + spills, etc. */ +int +total_frame_size () +{ + unsigned int size = get_frame_size (); + unsigned int outgoing_args_size = current_function_outgoing_args_size; + int i; + + /* First figure out if we're going to use an out of line + prologue, if so we have to make space for all the + registers, even if we don't use them. */ + if (optimize && !current_function_needs_context && !frame_pointer_needed) + { + int inline_count, outline_count; + + /* Compute how many bytes an inline prologue would take. + + Each address register store takes two bytes, each data register + store takes three bytes. */ + inline_count = 0; + if (regs_ever_live[5]) + inline_count += 2; + if (regs_ever_live[6]) + inline_count += 2; + if (regs_ever_live[2]) + inline_count += 3; + if (regs_ever_live[3]) + inline_count += 3; + + /* If this function has any stack, then the stack adjustment + will take two (or more) bytes. */ + if (size || outgoing_args_size + || regs_ever_live[5] || regs_ever_live[6] + || regs_ever_live[2] || regs_ever_live[3]) + inline_count += 2; + + /* Multiply the current count by two and add one to account for the + epilogue insns. */ + inline_count = inline_count * 2 + 1; + + /* Now compute how many bytes an out of line sequence would take. */ + /* A relaxed jsr will be three bytes. */ + outline_count = 3; + + /* If there are outgoing arguments, then we will need a stack + pointer adjustment after the call to the prologue, two + more bytes. */ + outline_count += (outgoing_args_size == 0 ? 0 : 2); + + /* If there is some local frame to allocate, it will need to be + done before the call to the prologue, two more bytes. */ + if (get_frame_size () != 0) + outline_count += 2; + + /* Now account for the epilogue, multiply the base count by two, + then deal with optimizing away the rts instruction. */ + outline_count = outline_count * 2 + 1; + + if (get_frame_size () == 0 && outgoing_args_size == 0) + outline_count -= 1; + + /* If an out of line prologue is smaller, use it. */ + if (inline_count > outline_count) + return size + outgoing_args_size + 16; + } + + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i] + || (i == FRAME_POINTER_REGNUM && frame_pointer_needed)) + size += 4; + } + + return (size + outgoing_args_size); +} + +/* Expand the prologue into RTL. */ +void +expand_prologue () +{ + unsigned int size = total_frame_size (); + unsigned int outgoing_args_size = current_function_outgoing_args_size; + int offset, i; + + zero_areg = NULL_RTX; + zero_dreg = NULL_RTX; + + /* If optimizing, see if we should do an out of line prologue/epilogue + sequence. + + We don't support out of line prologues if the current function + needs a context or frame pointer. */ + if (optimize && !current_function_needs_context && !frame_pointer_needed) + { + int inline_count, outline_count, areg_count; + + /* We need to end the current sequence so that count_tst_insns can + look at all the insns in this function. Normally this would be + unsafe, but it's OK in the prologue/epilogue expanders. */ + end_sequence (); + + /* Get a count of the number of tst insns which use address + registers (it's not profitable to try and improve tst insns + which use data registers). */ + count_tst_insns (&areg_count); + + /* Now start a new sequence. */ + start_sequence (); + + /* Compute how many bytes an inline prologue would take. + + Each address register store takes two bytes, each data register + store takes three bytes. */ + inline_count = 0; + if (regs_ever_live[5]) + inline_count += 2; + if (regs_ever_live[6]) + inline_count += 2; + if (regs_ever_live[2]) + inline_count += 3; + if (regs_ever_live[3]) + inline_count += 3; + + /* If this function has any stack, then the stack adjustment + will take two (or more) bytes. */ + if (size || outgoing_args_size + || regs_ever_live[5] || regs_ever_live[6] + || regs_ever_live[2] || regs_ever_live[3]) + inline_count += 2; + + /* Multiply the current count by two and add one to account for the + epilogue insns. */ + inline_count = inline_count * 2 + 1; + + /* Now compute how many bytes an out of line sequence would take. */ + /* A relaxed jsr will be three bytes. */ + outline_count = 3; + + /* If there are outgoing arguments, then we will need a stack + pointer adjustment after the call to the prologue, two + more bytes. */ + outline_count += (outgoing_args_size == 0 ? 0 : 2); + + /* If there is some local frame to allocate, it will need to be + done before the call to the prologue, two more bytes. */ + if (get_frame_size () != 0) + outline_count += 2; + + /* Now account for the epilogue, multiply the base count by two, + then deal with optimizing away the rts instruction. */ + outline_count = outline_count * 2 + 1; + + if (get_frame_size () == 0 && outgoing_args_size == 0) + outline_count -= 1; + + /* If an out of line prologue is smaller, use it. */ + if (inline_count > outline_count) + { + if (get_frame_size () != 0) + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-size + outgoing_args_size + 16))); + emit_insn (gen_outline_prologue_call ()); + + if (outgoing_args_size) + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-outgoing_args_size))); + + out_of_line_epilogue = 1; + + /* Determine if it is profitable to put the value zero into a register + for the entire function. If so, set ZERO_DREG and ZERO_AREG. */ + + /* First see if we could load the value into a data register + since that's the most efficient way. */ + if (areg_count > 1 + && (!regs_ever_live[2] || !regs_ever_live[3])) + { + if (!regs_ever_live[2]) + { + regs_ever_live[2] = 1; + zero_dreg = gen_rtx (REG, HImode, 2); + } + if (!regs_ever_live[3]) + { + regs_ever_live[3] = 1; + zero_dreg = gen_rtx (REG, HImode, 3); + } + } + + /* Now see if we could load the value into a address register. */ + if (zero_dreg == NULL_RTX + && areg_count > 2 + && (!regs_ever_live[5] || !regs_ever_live[6])) + { + if (!regs_ever_live[5]) + { + regs_ever_live[5] = 1; + zero_areg = gen_rtx (REG, HImode, 5); + } + if (!regs_ever_live[6]) + { + regs_ever_live[6] = 1; + zero_areg = gen_rtx (REG, HImode, 6); + } + } + + if (zero_dreg) + emit_move_insn (zero_dreg, const0_rtx); + + if (zero_areg) + emit_move_insn (zero_areg, const0_rtx); + + return; + } + } + + out_of_line_epilogue = 0; + + /* Temporarily stuff the static chain onto the stack so we can + use a0 as a scratch register during the prologue. */ + if (current_function_needs_context) + { + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-4))); + emit_move_insn (gen_rtx (MEM, PSImode, stack_pointer_rtx), + gen_rtx (REG, PSImode, STATIC_CHAIN_REGNUM)); + } + + if (frame_pointer_needed) + { + /* Store a2 into a0 temporarily. */ + emit_move_insn (gen_rtx (REG, PSImode, 4), frame_pointer_rtx); + + /* Set up the frame pointer. */ + emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + } + + /* Make any necessary space for the saved registers and local frame. */ + if (size) + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-size))); + + /* Save the callee saved registers. They're saved into the top + of the frame, using the stack pointer. */ + for (i = 0, offset = outgoing_args_size; + i < FIRST_PSEUDO_REGISTER; i++) + { + if (regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i] + || (i == FRAME_POINTER_REGNUM && frame_pointer_needed)) + { + int regno; + + /* If we're saving the frame pointer, then it will be found in + register 4 (a0). */ + regno = (i == FRAME_POINTER_REGNUM && frame_pointer_needed) ? 4 : i; + + emit_move_insn (gen_rtx (MEM, PSImode, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (offset))), + gen_rtx (REG, PSImode, regno)); + offset += 4; + } + } + + /* Now put the static chain back where the rest of the function + expects to find it. */ + if (current_function_needs_context) + { + emit_move_insn (gen_rtx (REG, PSImode, STATIC_CHAIN_REGNUM), + gen_rtx (MEM, PSImode, + gen_rtx (PLUS, PSImode, stack_pointer_rtx, + GEN_INT (size)))); + } +} + +/* Expand the epilogue into RTL. */ +void +expand_epilogue () +{ + unsigned int size; + unsigned int outgoing_args_size = current_function_outgoing_args_size; + int offset, i, temp_regno; + rtx basereg; + + size = total_frame_size (); + + if (DECL_RESULT (current_function_decl) + && DECL_RTL (DECL_RESULT (current_function_decl)) + && REG_P (DECL_RTL (DECL_RESULT (current_function_decl)))) + temp_regno = (REGNO (DECL_RTL (DECL_RESULT (current_function_decl))) == 4 + ? 0 : 4); + else + temp_regno = 4; + + /* Emit an out of line epilogue sequence if it's profitable to do so. */ + if (out_of_line_epilogue) + { + /* If there were no outgoing arguments and no local frame, then + we will be able to omit the rts at the end of this function, + so just jump to the epilogue_noreturn routine. */ + if (get_frame_size () == 0 && outgoing_args_size == 0) + { + emit_jump_insn (gen_outline_epilogue_jump ()); + return; + } + + if (outgoing_args_size) + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (outgoing_args_size))); + + if (temp_regno == 0) + emit_insn (gen_outline_epilogue_call_d0 ()); + else if (temp_regno == 4) + emit_insn (gen_outline_epilogue_call_a0 ()); + + if (get_frame_size () != 0) + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (size - outgoing_args_size - 16))); + emit_jump_insn (gen_return_internal ()); + return; + } + + /* Registers are restored from the frame pointer if we have one, + else they're restored from the stack pointer. Figure out + the appropriate offset to the register save area for both cases. */ + if (frame_pointer_needed) + { + basereg = frame_pointer_rtx; + offset = -(size - outgoing_args_size); + } + else + { + basereg = stack_pointer_rtx; + offset = outgoing_args_size; + } + + /* Restore each register. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i] + || (i == FRAME_POINTER_REGNUM && frame_pointer_needed)) + { + int regno; + + /* Restore the frame pointer (if it exists) into a temporary + register. */ + regno = ((i == FRAME_POINTER_REGNUM && frame_pointer_needed) + ? temp_regno : i); + + emit_move_insn (gen_rtx (REG, PSImode, regno), + gen_rtx (MEM, PSImode, + gen_rtx (PLUS, Pmode, + basereg, + GEN_INT (offset)))); + offset += 4; + } + } + + if (frame_pointer_needed) + { + /* Deallocate this frame's stack. */ + emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); + /* Restore the old frame pointer. */ + emit_move_insn (frame_pointer_rtx, gen_rtx (REG, PSImode, temp_regno)); + } + else if (size) + { + /* Deallocate this function's stack. */ + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (size))); + } + + /* If we had to allocate a slot to save the context pointer, + then it must be deallocated here. */ + if (current_function_needs_context) + emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (4))); + + /* Emit the return insn, if this function had no stack, then we + can use the standard return (which allows more optimizations), + else we have to use the special one which inhibits optimizations. */ + if (size == 0 && !current_function_needs_context) + emit_jump_insn (gen_return ()); + else + emit_jump_insn (gen_return_internal ()); +} + +/* Update the condition code from the insn. */ + +void +notice_update_cc (body, insn) + rtx body; + rtx insn; +{ + switch (get_attr_cc (insn)) + { + case CC_NONE: + /* Insn does not affect CC at all. */ + break; + + case CC_NONE_0HIT: + /* Insn does not change CC, but the 0'th operand has been changed. */ + if (cc_status.value1 != 0 + && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1)) + cc_status.value1 = 0; + break; + + case CC_SET_ZN: + /* Insn sets the Z,N flags of CC to recog_operand[0]. + V,C is in an unusable state. */ + CC_STATUS_INIT; + cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY; + cc_status.value1 = recog_operand[0]; + break; + + case CC_SET_ZNV: + /* Insn sets the Z,N,V flags of CC to recog_operand[0]. + C is in an unusable state. */ + CC_STATUS_INIT; + cc_status.flags |= CC_NO_CARRY; + cc_status.value1 = recog_operand[0]; + break; + + case CC_COMPARE: + /* The insn is a compare instruction. */ + CC_STATUS_INIT; + cc_status.value1 = SET_SRC (body); + break; + + case CC_CLOBBER: + /* Insn doesn't leave CC in a usable state. */ + CC_STATUS_INIT; + break; + + default: + CC_STATUS_INIT; + break; + } +} + +/* Return true if OP is a valid call operand. Valid call operands + are SYMBOL_REFs and REGs. */ +int +call_address_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG); +} + +/* Return true if OP is a memory operand with a constant address. + A special PSImode move pattern uses this predicate. */ +int +constant_memory_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return GET_CODE (op) == MEM && CONSTANT_ADDRESS_P (XEXP (op, 0)); +} + +/* What (if any) secondary registers are needed to move IN with mode + MODE into a register from in register class CLASS. + + We might be able to simplify this. */ +enum reg_class +secondary_reload_class (class, mode, in, input) + enum reg_class class; + enum machine_mode mode; + rtx in; + int input; +{ + int regno; + + /* Memory loads less than a full word wide can't have an + address or stack pointer destination. They must use + a data register as an intermediate register. */ + if (input + && GET_CODE (in) == MEM + && (mode == QImode) + && class == ADDRESS_REGS) + return DATA_REGS; + + /* Address register stores which are not PSImode need a scratch register. */ + if (! input + && GET_CODE (in) == MEM + && (mode != PSImode) + && class == ADDRESS_REGS) + return DATA_REGS; + + /* Otherwise assume no secondary reloads are needed. */ + return NO_REGS; +} + + +/* Shifts. + + We devote a fair bit of code to getting efficient shifts since we can only + shift one bit at a time, and each single bit shift may take multiple + instructions. + + The basic shift methods: + + * loop shifts -- emit a loop using one (or two on H8/S) bit shifts; + this is the default. SHIFT_LOOP + + * inlined shifts -- emit straight line code for the shift; this is + used when a straight line shift is about the same size or smaller + than a loop. We allow the inline version to be slightly longer in + some cases as it saves a register. SHIFT_INLINE + + * There other oddballs. Not worth explaining. SHIFT_SPECIAL + + + HImode shifts: + + 1-4 do them inline + + 5-7 If ashift, then multiply, else loop. + + 8-14 - If ashift, then multiply, if lshiftrt, then divide, else loop. + 15 - rotate the bit we want into the carry, clear the destination, + (use mov 0,dst, not sub as sub will clobber the carry), then + move bit into place. + + Don't Panic, it's not nearly as bad as the H8 shifting code!!! */ + +int +nshift_operator (x, mode) + rtx x; + enum machine_mode mode; +{ + switch (GET_CODE (x)) + { + case ASHIFTRT: + case LSHIFTRT: + case ASHIFT: + return 1; + + default: + return 0; + } +} + +/* Called from the .md file to emit code to do shifts. + Returns a boolean indicating success + (currently this is always TRUE). */ + +int +expand_a_shift (mode, code, operands) + enum machine_mode mode; + int code; + rtx operands[]; +{ + emit_move_insn (operands[0], operands[1]); + + /* need a loop to get all the bits we want - we generate the + code at emit time, but need to allocate a scratch reg now */ + + emit_insn (gen_rtx + (PARALLEL, VOIDmode, + gen_rtvec (2, + gen_rtx (SET, VOIDmode, operands[0], + gen_rtx (code, mode, + operands[0], operands[2])), + gen_rtx (CLOBBER, VOIDmode, + gen_rtx (SCRATCH, HImode, 0))))); + + return 1; +} + +/* Shift algorithm determination. + + There are various ways of doing a shift: + SHIFT_INLINE: If the amount is small enough, just generate as many one-bit + shifts as we need. + SHIFT_SPECIAL: Hand crafted assembler. + SHIFT_LOOP: If the above methods fail, just loop. */ + +enum shift_alg +{ + SHIFT_INLINE, + SHIFT_SPECIAL, + SHIFT_LOOP, + SHIFT_MAX +}; + +/* Symbols of the various shifts which can be used as indices. */ + +enum shift_type + { + SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT + }; + +/* Symbols of the various modes which can be used as indices. */ + +enum shift_mode + { + HIshift, + }; + +/* For single bit shift insns, record assembler and what bits of the + condition code are valid afterwards (represented as various CC_FOO + bits, 0 means CC isn't left in a usable state). */ + +struct shift_insn +{ + char *assembler; + int cc_valid; +}; + +/* Assembler instruction shift table. + + These tables are used to look up the basic shifts. + They are indexed by cpu, shift_type, and mode. +*/ + +static const struct shift_insn shift_one[3][3] = +{ + { +/* SHIFT_ASHIFT */ + { "add\t%0,%0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, + }, +/* SHIFT_LSHIFTRT */ + { + { "lsr\t%0", CC_NO_CARRY }, + }, +/* SHIFT_ASHIFTRT */ + { + { "asr\t%0", CC_NO_CARRY }, + }, +}; + +/* Given CPU, MODE, SHIFT_TYPE, and shift count COUNT, determine the best + algorithm for doing the shift. The assembler code is stored in ASSEMBLER. + We don't achieve maximum efficiency in all cases, but the hooks are here + to do so. + + For now we just use lots of switch statements. Since we don't even come + close to supporting all the cases, this is simplest. If this function ever + gets too big, perhaps resort to a more table based lookup. Of course, + at this point you may just wish to do it all in rtl. */ + +static enum shift_alg +get_shift_alg (shift_type, mode, count, assembler_p, cc_valid_p) + enum shift_type shift_type; + enum machine_mode mode; + int count; + const char **assembler_p; + int *cc_valid_p; +{ + /* The default is to loop. */ + enum shift_alg alg = SHIFT_LOOP; + enum shift_mode shift_mode; + + /* We don't handle negative shifts or shifts greater than the word size, + they should have been handled already. */ + + if (count < 0 || count > GET_MODE_BITSIZE (mode)) + abort (); + + switch (mode) + { + case HImode: + shift_mode = HIshift; + break; + default: + abort (); + } + + /* Assume either SHIFT_LOOP or SHIFT_INLINE. + It is up to the caller to know that looping clobbers cc. */ + *assembler_p = shift_one[shift_type][shift_mode].assembler; + *cc_valid_p = shift_one[shift_type][shift_mode].cc_valid; + + /* Now look for cases we want to optimize. */ + + switch (shift_mode) + { + case HIshift: + if (count <= 4) + return SHIFT_INLINE; + else if (count < 15 && shift_type != SHIFT_ASHIFTRT) + { + switch (count) + { + case 5: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 32,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 32,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 6: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 64,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 64,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 7: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 128,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 128,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 8: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 256,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 256,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 9: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 512,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 512,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 10: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 1024,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 1024,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 11: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 2048,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 2048,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 12: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 4096,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 4096,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 13: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 8192,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 8192,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + case 14: + if (shift_type == SHIFT_ASHIFT) + *assembler_p = "mov 16384,%4\n\tmul %4,%0"; + else if (shift_type == SHIFT_LSHIFTRT) + *assembler_p + = "sub %4,%4\n\tmov %4,mdr\n\tmov 16384,%4\n\tdivu %4,%0"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + } + } + else if (count == 15) + { + if (shift_type == SHIFT_ASHIFTRT) + { + *assembler_p = "add\t%0,%0\n\tsubc\t%0,%0\n"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + } + if (shift_type == SHIFT_LSHIFTRT) + { + *assembler_p = "add\t%0,%0\n\tmov 0,%0\n\trol %0\n"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + } + if (shift_type == SHIFT_ASHIFT) + { + *assembler_p = "ror\t%0\n\tmov 0,%0\n\tror %0\n"; + *cc_valid_p = CC_NO_CARRY; + return SHIFT_SPECIAL; + } + } + break; + + default: + abort (); + } + + return alg; +} + +/* Emit the assembler code for doing shifts. */ + +char * +emit_a_shift (insn, operands) + rtx insn; + rtx *operands; +{ + static int loopend_lab; + char *assembler; + int cc_valid; + rtx inside = PATTERN (insn); + rtx shift = operands[3]; + enum machine_mode mode = GET_MODE (shift); + enum rtx_code code = GET_CODE (shift); + enum shift_type shift_type; + enum shift_mode shift_mode; + + loopend_lab++; + + switch (mode) + { + case HImode: + shift_mode = HIshift; + break; + default: + abort (); + } + + switch (code) + { + case ASHIFTRT: + shift_type = SHIFT_ASHIFTRT; + break; + case LSHIFTRT: + shift_type = SHIFT_LSHIFTRT; + break; + case ASHIFT: + shift_type = SHIFT_ASHIFT; + break; + default: + abort (); + } + + if (GET_CODE (operands[2]) != CONST_INT) + { + /* Indexing by reg, so have to loop and test at top */ + output_asm_insn ("mov %2,%4", operands); + output_asm_insn ("cmp 0,%4", operands); + fprintf (asm_out_file, "\tble .Lle%d\n", loopend_lab); + + /* Get the assembler code to do one shift. */ + get_shift_alg (shift_type, mode, 1, &assembler, &cc_valid); + } + else + { + int n = INTVAL (operands[2]); + enum shift_alg alg; + + /* If the count is negative, make it 0. */ + if (n < 0) + n = 0; + /* If the count is too big, truncate it. + ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to + do the intuitive thing. */ + else if (n > GET_MODE_BITSIZE (mode)) + n = GET_MODE_BITSIZE (mode); + + alg = get_shift_alg (shift_type, mode, n, &assembler, &cc_valid); + + + switch (alg) + { + case SHIFT_INLINE: + /* Emit one bit shifts. */ + while (n > 0) + { + output_asm_insn (assembler, operands); + n -= 1; + } + + /* Keep track of CC. */ + if (cc_valid) + { + cc_status.value1 = operands[0]; + cc_status.flags |= cc_valid; + } + return ""; + + case SHIFT_SPECIAL: + output_asm_insn (assembler, operands); + + /* Keep track of CC. */ + if (cc_valid) + { + cc_status.value1 = operands[0]; + cc_status.flags |= cc_valid; + } + return ""; + } + + { + fprintf (asm_out_file, "\tmov %d,%s\n", n, + reg_names[REGNO (operands[4])]); + fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); + output_asm_insn (assembler, operands); + output_asm_insn ("add -1,%4", operands); + fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); + return ""; + } + } + + fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); + output_asm_insn (assembler, operands); + output_asm_insn ("add -1,%4", operands); + fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); + fprintf (asm_out_file, ".Lle%d:\n", loopend_lab); + + return ""; +} + +/* Return an RTX to represent where a value with mode MODE will be returned + from a function. If the result is 0, the argument is pushed. */ + +rtx +function_arg (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + rtx result = 0; + int size, align; + + /* We only support using 2 data registers as argument registers. */ + int nregs = 2; + + /* Only pass named arguments in registers. */ + if (!named) + return NULL_RTX; + + /* Figure out the size of the object to be passed. We lie and claim + PSImode values are only two bytes since they fit in a single + register. */ + if (mode == BLKmode) + size = int_size_in_bytes (type); + else if (mode == PSImode) + size = 2; + else + size = GET_MODE_SIZE (mode); + + /* Figure out the alignment of the object to be passed. */ + align = size; + + cum->nbytes = (cum->nbytes + 1) & ~1; + + /* Don't pass this arg via a register if all the argument registers + are used up. */ + if (cum->nbytes + size > nregs * UNITS_PER_WORD) + return 0; + + switch (cum->nbytes / UNITS_PER_WORD) + { + case 0: + result = gen_rtx (REG, mode, 0); + break; + case 1: + result = gen_rtx (REG, mode, 1); + break; + default: + result = 0; + } + + return result; +} + +/* Return the number of registers to use for an argument passed partially + in registers and partially in memory. */ + +int +function_arg_partial_nregs (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + int size, align; + + /* We only support using 2 data registers as argument registers. */ + int nregs = 2; + + return 0; + /* Only pass named arguments in registers. */ + if (!named) + return 0; + + /* Figure out the size of the object to be passed. */ + if (mode == BLKmode) + size = int_size_in_bytes (type); + else if (mode == PSImode) + size = 2; + else + size = GET_MODE_SIZE (mode); + + /* Figure out the alignment of the object to be passed. */ + align = size; + + cum->nbytes = (cum->nbytes + 1) & ~1; + + /* Don't pass this arg via a register if all the argument registers + are used up. */ + if (cum->nbytes > nregs * UNITS_PER_WORD) + return 0; + + if (cum->nbytes + size <= nregs * UNITS_PER_WORD) + return 0; + + /* Don't pass this arg via a register if it would be split between + registers and memory. */ + if (type == NULL_TREE + && cum->nbytes + size > nregs * UNITS_PER_WORD) + return 0; + + return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD; +} + +char * +output_tst (operand, insn) + rtx operand, insn; +{ + + rtx temp; + int past_call = 0; + + /* Only tst insns using address registers can be optimized. */ + if (REGNO_REG_CLASS (REGNO (operand)) != ADDRESS_REGS) + return "cmp 0,%0"; + + /* If testing an address register against zero, we can do better if + we know there's a register already holding the value zero. First + see if a global register has been set to zero, else we do a search + for a register holding zero, if both of those fail, then we use a + compare against zero. */ + if (zero_dreg || zero_areg) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = zero_dreg ? zero_dreg : zero_areg; + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + + /* We can save a byte if we can find a register which has the value + zero in it. */ + temp = PREV_INSN (insn); + while (temp) + { + rtx set; + + /* We allow the search to go through call insns. We record + the fact that we've past a CALL_INSN and reject matches which + use call clobbered registers. */ + if (GET_CODE (temp) == CODE_LABEL + || GET_CODE (temp) == JUMP_INSN + || GET_CODE (temp) == BARRIER) + break; + + if (GET_CODE (temp) == CALL_INSN) + past_call = 1; + + if (GET_CODE (temp) == NOTE) + { + temp = PREV_INSN (temp); + continue; + } + + /* It must be an insn, see if it is a simple set. */ + set = single_set (temp); + if (!set) + { + temp = PREV_INSN (temp); + continue; + } + + /* Are we setting a register to zero? + + If it's a call clobbered register, have we past a call? */ + if (REG_P (SET_DEST (set)) + && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set))) + && !reg_set_between_p (SET_DEST (set), temp, insn) + && (!past_call + || !call_used_regs[REGNO (SET_DEST (set))])) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = SET_DEST (set); + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + temp = PREV_INSN (temp); + } + return "cmp 0,%0"; +} + +/* Return nonzero if OP is a valid operand for a {zero,sign}_extendpsisi + instruction. + + It accepts anything that is a general operand or the sum of the + stack pointer and a general operand. */ +extendpsi_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (general_operand (op, mode) + || (GET_CODE (op) == PLUS + && XEXP (op, 0) == stack_pointer_rtx + && general_operand (XEXP (op, 1), VOIDmode))); +} diff --git a/gnu/usr.bin/gcc/config/mn10200/mn10200.h b/gnu/usr.bin/gcc/config/mn10200/mn10200.h new file mode 100644 index 00000000000..7eb26dd7c0d --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/mn10200.h @@ -0,0 +1,1078 @@ +/* Definitions of target machine for GNU compiler. Matsushita MN10200 series + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Jeff Law (law@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. */ + +#include "svr4.h" + +/* Get rid of svr4.h stuff we don't want/need. */ +#undef ASM_SPEC +#undef ASM_FINAL_SPEC +#undef LIB_SPEC +#undef ENDFILE_SPEC +#undef LINK_SPEC +#undef STARTFILE_SPEC + +/* Names to predefine in the preprocessor for this target machine. */ + +#define CPP_PREDEFINES "-D__mn10200__ -D__MN10200__ -D__LONG_MAX__=2147483647L -D__LONG_LONG_MAX__=2147483647L -D__INT_MAX__=32767" + +/* Run-time compilation parameters selecting different hardware subsets. */ + +/* We don't have any switched on the mn10200. Though there are some things + that might be worth a switch: + + -mspace to optimize even more for space. + + -mrelax to enable the relaxing linker. */ + +extern int target_flags; + +/* Macros used in the machine description to test the flags. */ + +/* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +#define TARGET_SWITCHES \ + {{ "", TARGET_DEFAULT}} + +#ifndef TARGET_DEFAULT +#define TARGET_DEFAULT 0 +#endif + +/* Print subsidiary information on the compiler version in use. */ + +#define TARGET_VERSION fprintf (stderr, " (MN10200)"); + + +/* Target machine storage layout */ + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. + This is not true on the Matsushita MN10300. */ +#define BITS_BIG_ENDIAN 0 + +/* Define this if most significant byte of a word is the lowest numbered. */ +/* This is not true on the Matsushita MN10200. */ +#define BYTES_BIG_ENDIAN 0 + +/* Define this if most significant word of a multiword number is lowest + numbered. + This is not true on the Matsushita MN10200. */ +#define WORDS_BIG_ENDIAN 0 + +/* Number of bits in an addressable storage unit */ +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. + + This is a white lie. Registers are really 24bits, but most operations + only operate on 16 bits. GCC chokes badly if we set this to a value + that is not a power of two. */ +#define BITS_PER_WORD 16 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD 2 + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. + + This differs from Pmode because we need to allocate 32bits of space + to hold the 24bit pointers on this machine. */ +#define POINTER_SIZE 32 + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY 16 + +/* The stack goes in 16 bit lumps. */ +#define STACK_BOUNDARY 16 + +/* Allocation boundary (in *bits*) for the code of a function. + 8 is the minimum boundary; it's unclear if bigger alignments + would improve performance. */ +#define FUNCTION_BOUNDARY 8 + +/* No data type wants to be aligned rounder than this. */ +#define BIGGEST_ALIGNMENT 16 + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY 16 + +/* Seems to be how the Matsushita compiler does things, and there's + no real reason to be different. */ +#define STRUCTURE_SIZE_BOUNDARY 16 +#undef PCC_BITFIELD_TYPE_MATTERS + +/* Define this if move instructions will actually fail to work + when given unaligned data. */ +#define STRICT_ALIGNMENT 1 + +/* Define this as 1 if `char' should by default be signed; else as 0. */ +#define DEFAULT_SIGNED_CHAR 0 + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. + + XXX Long term we should probably expose the MDR register, we use + it for division, multiplication, and some extension operations. */ + +#define FIRST_PSEUDO_REGISTER 8 + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. */ + +#define FIXED_REGISTERS \ + { 0, 0, 0, 0, 0, 0, 0, 1} + +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you + like. */ + +#define CALL_USED_REGISTERS \ + { 1, 1, 0, 0, 1, 0, 0, 1} + +#define REG_ALLOC_ORDER \ + { 0, 1, 4, 2, 3, 5, 6, 7} + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. */ + +#define HARD_REGNO_NREGS(REGNO, MODE) \ + ((MODE) == PSImode ? 1 : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ + / UNITS_PER_WORD)) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode + MODE. + + We allow any register to hold a PSImode value. We allow any register + to hold values <= 16 bits. For values > 16 bits we require aligned + register pairs. */ +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((MODE) == PSImode ? 1 : ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) <= 2) + +/* Value is 1 if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ +#define MODES_TIEABLE_P(MODE1, MODE2) \ + (MODE1 == MODE2 || (GET_MODE_SIZE (MODE1) <= 2 && GET_MODE_SIZE (MODE2) <= 2)) + +/* 4 data, and effectively 2 address registers is small as far as I'm + concerned. Especially since we use 2 data registers for argument + passing and return values. + + We used to define CLASS_LIKELY_SPILLED_P as true for DATA_REGS too, + but we've made improvements to the port which greatly reduce register + pressure. As a result we no longer need to define CLASS_LIKELY_SPILLED_P + for DATA_REGS (and by not defining it we get significantly better code). */ +#define SMALL_REGISTER_CLASSES 1 +#define CLASS_LIKELY_SPILLED_P(CLASS) (CLASS == ADDRESS_REGS) + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + +enum reg_class { + NO_REGS, DATA_REGS, ADDRESS_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ + +#define REG_CLASS_NAMES \ +{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \ + "GENERAL_REGS", "ALL_REGS", "LIM_REGS" } + +/* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS \ +{ 0, /* No regs */ \ + 0x0f, /* DATA_REGS */ \ + 0xf0, /* ADDRESS_REGS */ \ + 0xff, /* GENERAL_REGS */ \ + 0xff, /* ALL_REGS */ \ +} + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) < 4 ? DATA_REGS : ADDRESS_REGS) + +/* The class value for index registers, and the one for base regs. */ + +#define INDEX_REG_CLASS DATA_REGS +#define BASE_REG_CLASS ADDRESS_REGS + +/* Get reg_class from a letter such as appears in the machine description. */ + +#define REG_CLASS_FROM_LETTER(C) \ + ((C) == 'd' ? DATA_REGS : \ + (C) == 'a' ? ADDRESS_REGS : NO_REGS) + +/* Macros to check register numbers against specific register classes. */ + +/* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ + +#define REGNO_OK_FOR_BASE_P(regno) \ + (((regno) > 3 && regno < FIRST_PSEUDO_REGISTER) \ + || (reg_renumber[regno] > 3 && reg_renumber[regno] < FIRST_PSEUDO_REGISTER)) + +#define REGNO_OK_FOR_INDEX_P(regno) \ + (((regno) >= 0 && regno < 4) \ + || (reg_renumber[regno] >= 0 && reg_renumber[regno] < 4)) + + +/* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. */ + +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ + ((GET_MODE (X) != PSImode) ? DATA_REGS : CLASS) + +/* We want to use DATA_REGS for anything that is not PSImode. */ +#define LIMIT_RELOAD_CLASS(MODE, CLASS) \ + ((MODE != PSImode) ? DATA_REGS : CLASS) + +/* We have/need secondary reloads on the mn10200. Mostly to deal + with problems using address registers. */ +#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN) \ + secondary_reload_class(CLASS,MODE,IN, 1) + +#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,IN) \ + secondary_reload_class(CLASS,MODE,IN, 0) + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ + +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((MODE) == PSImode ? 1 : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* The letters I, J, K, L, M, N, O, P in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ + +#define INT_8_BITS(VALUE) ((unsigned) (VALUE) + 0x80 < 0x100) +#define INT_16_BITS(VALUE) ((unsigned) (VALUE) + 0x8000 < 0x10000) + +#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0) +#define CONST_OK_FOR_J(VALUE) ((VALUE) >= 1 && (VALUE) <= 3) +#define CONST_OK_FOR_K(VALUE) ((VALUE) >= 1 && (VALUE) <= 4) +#define CONST_OK_FOR_L(VALUE) ((VALUE) == 15) +#define CONST_OK_FOR_M(VALUE) ((VALUE) == 255) + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \ + (C) == 'J' ? CONST_OK_FOR_J (VALUE) : \ + (C) == 'K' ? CONST_OK_FOR_K (VALUE) : \ + (C) == 'L' ? CONST_OK_FOR_L (VALUE) : \ + (C) == 'M' ? CONST_OK_FOR_M (VALUE) : 0) + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. + + `G' is a floating-point zero. */ + +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ + && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \ + : 0) + + + +/* Stack layout; function entry, exit and calling. */ + +/* Define this if pushing a word on the stack + makes the stack pointer a smaller address. */ + +#define STACK_GROWS_DOWNWARD + +/* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ + +#define FRAME_GROWS_DOWNWARD + +/* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ + +#define STARTING_FRAME_OFFSET 0 + +/* Offset of first parameter from the argument pointer register value. */ +/* Is equal to the size of the saved fp + pc, even if an fp isn't + saved since the value is used before we know. */ + +#define FIRST_PARM_OFFSET(FNDECL) (current_function_needs_context ? 8 : 4) + +/* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 7 + +/* Base register for access to local variables of the function. */ +#define FRAME_POINTER_REGNUM 6 + +/* Base register for access to arguments of the function. */ +#define ARG_POINTER_REGNUM 6 + +/* Register in which static-chain is passed to a function. */ +#define STATIC_CHAIN_REGNUM 4 + +/* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms + may be accessed via the stack pointer) in functions that seem suitable. + This is computed in `reload', in reload1.c. + + We allow frame pointers to be eliminated when not having one will + not interfere with debugging. */ +#define ACCUMULATE_OUTGOING_ARGS +#define FRAME_POINTER_REQUIRED 0 +#define CAN_DEBUG_WITHOUT_FP + +/* Store in the variable DEPTH the initial difference between the + frame pointer reg contents and the stack pointer reg contents, + as of the start of the function body. This depends on the layout + of the fixed parts of the stack frame and on how registers are saved. */ + +#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = total_frame_size() + +/* Various type size information. + + The mn10200 has a limited number of small registers. Sizes of basic + data types are adjusted accordingly. */ +#define SHORT_TYPE_SIZE 16 +#define INT_TYPE_SIZE 16 +#define LONG_TYPE_SIZE 32 +#define LONG_LONG_TYPE_SIZE 32 +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 32 +#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE + +/* Any size less than 64bits will work; but a smarter definition + can make G++ code smaller and faster. Most operations on the + mn10200 occur on 16bit hunks, so the best size for a boolean + is 16bits. */ +#define BOOL_TYPE_SIZE 16 + +/* The difference of two pointers must be at least 24bits since pointers + are 24bits; however, no basic data type is 24bits, so we have to round + up to a 32bits for the difference of pointers. */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#define SIZE_TYPE "long unsigned int" +#define PTRDIFF_TYPE "long unsigned int" + +/* Note sizeof (WCHAR_TYPE) must be equal to the value of WCHAR_TYPE_SIZE! */ +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#define MAX_FIXED_MODE_SIZE 32 + +/* A guess for the MN10200. */ +#define PROMOTE_PROTOTYPES 1 + +/* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + SIZE is the number of bytes of arguments passed on the stack. */ + +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 + +/* 1 if N is a possible register number for function argument passing. */ + +#define FUNCTION_ARG_REGNO_P(N) ((N) <= 1) + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. */ + +#define CUMULATIVE_ARGS struct cum_arg +struct cum_arg { int nbytes; }; + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. + + On the MN10200, the offset starts at 0. */ + +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ + ((CUM).nbytes = 0) + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM).nbytes += ((MODE) != BLKmode \ + ? (MODE) == PSImode ? 2 : \ + (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD \ + : (int_size_in_bytes (TYPE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD)) + +/* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + +extern struct rtx_def *function_arg(); +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ + function_arg (&CUM, MODE, TYPE, NAMED) + + +/* For "large" items, we pass them by invisible reference, and the + callee is responsible for copying the data item if it might be + modified. */ +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ + ((TYPE) && int_size_in_bytes (TYPE) > 8) + +#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ + ((TYPE) && int_size_in_bytes (TYPE) > 8) + +/* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), TYPE_MODE (VALTYPE) == PSImode ? 4 : 0) + +/* Define how to find the value returned by a library function + assuming the value has mode MODE. */ + +#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, (MODE) == PSImode ? 4 : 0) + +/* 1 if N is a possible register number for a function value. */ + +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 4) + +/* Return values > 8 bytes in length in memory. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 +#define RETURN_IN_MEMORY(TYPE) \ + (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode) + +/* Register in which address to store a structure value + is passed to a function. On the MN10200 it's passed as + the first parameter. */ + +#define STRUCT_VALUE 0 + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ + +#define EXIT_IGNORE_STACK 1 + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. + + ?!? Profiling is not currently supported. */ + +#define FUNCTION_PROFILER(FILE, LABELNO) ; + +/* Yes, we actually support trampolines on this machine, even though + nobody is likely to ever use them. */ +#define TRAMPOLINE_TEMPLATE(FILE) \ + do { \ + fprintf (FILE, "\t.byte 0xfd\n"); \ + fprintf (FILE, "\t.byte 0x00\n"); \ + fprintf (FILE, "\t.byte 0x00\n"); \ + fprintf (FILE, "\tmov (a3),a0\n"); \ + fprintf (FILE, "\tadd -4,a3\n"); \ + fprintf (FILE, "\tmov a0,(0,a3)\n"); \ + fprintf (FILE, "\tmov (21,a0),a0\n"); \ + fprintf (FILE, "\tmov a0,(4,a3)\n"); \ + fprintf (FILE, "\tmov (0,a3),a0\n"); \ + fprintf (FILE, "\tmov (17,a0),a0\n"); \ + fprintf (FILE, "\tadd 4,a3\n"); \ + fprintf (FILE, "\trts\n"); \ + fprintf (FILE, "\t.long 0\n"); \ + fprintf (FILE, "\t.long 0\n"); \ + } while (0) + +/* Length in units of the trampoline for entering a nested function. */ + +#define TRAMPOLINE_SIZE 0x1c + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ + +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +{ \ + emit_move_insn (gen_rtx (MEM, PSImode, plus_constant ((TRAMP), 20)), \ + (CXT)); \ + emit_move_insn (gen_rtx (MEM, PSImode, plus_constant ((TRAMP), 24)), \ + (FNADDR)); \ +} + +/* A C expression whose value is RTL representing the value of the return + address for the frame COUNT steps up from the current frame. */ + +#define RETURN_ADDR_RTX(COUNT, FRAME) \ + ((COUNT == 0) \ + ? gen_rtx (MEM, Pmode, frame_pointer_rtx) \ + : (rtx) 0) + + +/* Addressing modes, and classification of registers for them. */ + + +/* 1 if X is an rtx for a constant that is a valid address. */ + +#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) + +/* Extra constraints. */ +#define OK_FOR_R(OP) \ + (GET_CODE (OP) == MEM \ + && GET_MODE (OP) == QImode \ + && REG_P (XEXP (OP, 0))) + +/* Q is used for sp + <something> in the {zero,sign}_extendpsisi2 patterns. */ +#define EXTRA_CONSTRAINT(OP, C) \ + ((C) == 'R' ? OK_FOR_R (OP) : \ + (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF : \ + (C) == 'Q' ? GET_CODE (OP) == PLUS : 0) + +/* Maximum number of registers that can appear in a valid memory address. */ + +#define MAX_REGS_PER_ADDRESS 2 + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + +#ifndef REG_OK_STRICT +/* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ +#define REG_OK_FOR_INDEX_P(X) \ + (GET_MODE (X) == PSImode \ + && ((REGNO (X) >= 0 && REGNO(X) <= 3) || REGNO (X) >= FIRST_PSEUDO_REGISTER)) +/* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ +#define REG_OK_FOR_BASE_P(X) \ + (GET_MODE (X) == PSImode \ + && ((REGNO (X) >= 4 && REGNO(X) <= 8) || REGNO (X) >= FIRST_PSEUDO_REGISTER)) +#else +/* Nonzero if X is a hard reg that can be used as an index. */ +#define REG_OK_FOR_INDEX_P(X) \ + (GET_MODE (X) == PSImode) && REGNO_OK_FOR_INDEX_P (REGNO (X)) +/* Nonzero if X is a hard reg that can be used as a base reg. */ +#define REG_OK_FOR_BASE_P(X) \ + (GET_MODE (X) == PSImode) && REGNO_OK_FOR_BASE_P (REGNO (X)) +#endif + + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + We used to allow reg+reg addresses for QImode and HImode; however, + they tended to cause the register allocator to run out of registers. + Basically, an indexed load/store always keeps 2 data and one address + register live, which is just too many for this machine. + + The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS, + except for CONSTANT_ADDRESS_P which is actually machine-independent. */ + +/* Accept either REG or SUBREG where a register is valid. */ + +#define RTX_OK_FOR_BASE_P(X) \ + ((REG_P (X) && REG_OK_FOR_BASE_P (X)) \ + || (GET_CODE (X) == SUBREG && REG_P (SUBREG_REG (X)) \ + && REG_OK_FOR_BASE_P (SUBREG_REG (X)))) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ \ + if ((MODE != PSImode) && CONSTANT_ADDRESS_P (X)) \ + goto ADDR; \ + if (RTX_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (GET_CODE (X) == PLUS) \ + { \ + rtx base = 0, index = 0; \ + if (REG_P (XEXP (X, 0)) \ + && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ + base = XEXP (X, 0), index = XEXP (X, 1); \ + if (REG_P (XEXP (X, 1)) \ + && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ + base = XEXP (X, 1), index = XEXP (X, 0); \ + if (base != 0 && index != 0) \ + { \ + if (GET_CODE (index) == CONST_INT) \ + goto ADDR; \ + } \ + } \ +} + + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. */ + +#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} + +/* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. */ + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} + +/* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + +#define LEGITIMATE_CONSTANT_P(X) 1 + + +/* Tell final.c how to eliminate redundant test instructions. */ + +/* Here we define machine-dependent flags and fields in cc_status + (see `conditions.h'). No extra ones are needed for the vax. */ + +/* Store in cc_status the expressions + that the condition codes will describe + after execution of an instruction whose pattern is EXP. + Do not alter them if the instruction would not alter the cc's. */ + +#define CC_OVERFLOW_UNUSABLE 0x200 +#define CC_NO_CARRY CC_NO_OVERFLOW +#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN) + +/* The mn10200 has a limited number of registers, so CSE of function + addresses generally makes code worse due to register pressure. */ +#define NO_FUNCTION_CSE + +/* Compute the cost of computing a constant rtl expression RTX + whose rtx-code is CODE. The body of this macro is a portion + of a switch statement. If the code is computed here, + return it with a return statement. Otherwise, break from the switch. */ + +#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ + case CONST_INT: \ + /* Zeros are extremely cheap. */ \ + if (INTVAL (RTX) == 0) \ + return 0; \ + /* If it fits in 8 bits, then it's still relatively cheap. */ \ + if (INT_8_BITS (INTVAL (RTX))) \ + return 1; \ + /* This is the "base" cost, includes constants where either the \ + upper or lower 16bits are all zeros. */ \ + if (INT_16_BITS (INTVAL (RTX)) \ + || (INTVAL (RTX) & 0xffff) == 0 \ + || (INTVAL (RTX) & 0xffff0000) == 0) \ + return 2; \ + return 4; \ + /* These are more costly than a CONST_INT, but we can relax them, \ + so they're less costly than a CONST_DOUBLE. */ \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 6; \ + /* We don't optimize CONST_DOUBLEs well nor do we relax them well, \ + so their cost is very high. */ \ + case CONST_DOUBLE: \ + return 8; + +/* Make moves between different classes more expensive than moves + within the same class. */ +#define REGISTER_MOVE_COST(CLASS1, CLASS2) (CLASS1 != CLASS2 ? 4 : 2) + +/* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. + + ?!? This probably needs more work. The definitions below were first + taken from the H8 port, then tweaked slightly to improve code density + on various sample codes. */ + +#define RTX_COSTS(RTX,CODE,OUTER_CODE) \ + case MOD: \ + case DIV: \ + return 8; \ + case MULT: \ + return (GET_MODE (RTX) == SImode ? 20 : 8); + +/* Nonzero if access to memory by bytes or half words is no faster + than accessing full words. */ +#define SLOW_BYTE_ACCESS 1 + +/* According expr.c, a value of around 6 should minimize code size, and + for the MN10200 series, code size our primary concern. */ +#define MOVE_RATIO 6 + +#define TEXT_SECTION_ASM_OP "\t.section .text" +#define DATA_SECTION_ASM_OP "\t.section .data" +#define BSS_SECTION_ASM_OP "\t.section .bss" + +/* Output at beginning/end of assembler file. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) asm_file_start(FILE) + +#define ASM_COMMENT_START "#" + +/* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ + +#define ASM_APP_ON "#APP\n" + +/* Output to assembler file text saying following lines + no longer contain unusual constructs. */ + +#define ASM_APP_OFF "#NO_APP\n" + +/* This is how to output an assembler line defining a `double' constant. + It is .dfloat or .gfloat, depending. */ + +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf (FILE, "\t.double %s\n", dstr); \ + } while (0) + + +/* This is how to output an assembler line defining a `float' constant. */ +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf (FILE, "\t.float %s\n", dstr); \ + } while (0) + +/* This is how to output an assembler line defining an `int' constant. */ + +#define ASM_OUTPUT_INT(FILE, VALUE) \ +( fprintf (FILE, "\t.long "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* Likewise for `char' and `short' constants. */ + +#define ASM_OUTPUT_SHORT(FILE, VALUE) \ +( fprintf (FILE, "\t.hword "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +#define ASM_OUTPUT_CHAR(FILE, VALUE) \ +( fprintf (FILE, "\t.byte "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line for a numeric constant byte. */ +#define ASM_OUTPUT_BYTE(FILE, VALUE) \ + fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) + +/* Define the parentheses used to group arithmetic operations + in assembler code. */ + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* This says how to output the assembler to define a global + uninitialized but not common symbol. + Try to use asm_output_bss to implement this macro. */ + +#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \ + asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)) + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ + +#define ASM_OUTPUT_LABEL(FILE, NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + +/* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ + +#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ + do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + +/* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. */ + +#undef ASM_OUTPUT_LABELREF +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ + do { \ + char* real_name; \ + STRIP_NAME_ENCODING (real_name, (NAME)); \ + fprintf (FILE, "_%s", real_name); \ + } while (0) + +/* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) + +/* This is how we tell the assembler that two symbols have the same value. */ + +#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \ + do { assemble_name(FILE, NAME1); \ + fputs(" = ", FILE); \ + assemble_name(FILE, NAME2); \ + fputc('\n', FILE); } while (0) + + +/* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ + +#define REGISTER_NAMES \ +{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3"} + +/* Print an instruction operand X on file FILE. + look in mn10200.c for details */ + +#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE) + +/* Print a memory operand whose address is X, on file FILE. + This uses a function in output-vax.c. */ + +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) + +#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) +#define ASM_OUTPUT_REG_POP(FILE,REGNO) + +/* This is how to output an element of a case-vector that is absolute. */ + +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + asm_fprintf (FILE, "\t%s .L%d\n", ".long", VALUE) + +/* This is how to output an element of a case-vector that is relative. */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL) + +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG) != 0) \ + fprintf (FILE, "\t.align %d\n", (LOG)) + +/* We don't have to worry about dbx compatibility for the mn10200. */ +#define DEFAULT_GDB_EXTENSIONS 1 + +/* Use stabs debugging info by default. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#define DBX_REGISTER_NUMBER(REGNO) REGNO + +/* GDB always assumes the current function's frame begins at the value + of the stack pointer upon entry to the current function. Accessing + local variables and parameters passed on the stack is done using the + base of the frame + an offset provided by GCC. + + For functions which have frame pointers this method works fine; + the (frame pointer) == (stack pointer at function entry) and GCC provides + an offset relative to the frame pointer. + + This loses for functions without a frame pointer; GCC provides an offset + which is relative to the stack pointer after adjusting for the function's + frame size. GDB would prefer the offset to be relative to the value of + the stack pointer at the function's entry. Yuk! */ +#define DEBUGGER_AUTO_OFFSET(X) \ + ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) \ + + (frame_pointer_needed ? 0 : -total_frame_size ())) + +#define DEBUGGER_ARG_OFFSET(OFFSET, X) \ + ((GET_CODE (X) == PLUS ? OFFSET : 0) \ + + (frame_pointer_needed ? 0 : -total_frame_size ())) + +/* Define to use software floating point emulator for REAL_ARITHMETIC and + decimal <-> binary conversion. */ +#define REAL_ARITHMETIC + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE Pmode + +/* Define this if the case instruction drops through after the table + when the index is out of range. Don't define it if the case insn + jumps to the default label instead. */ +#define CASE_DROPS_THROUGH + +/* Dispatch tables on the mn10200 are extremely expensive in terms of code + and readonly data size. So we crank up the case threshold value to + encourage a series of if/else comparisons to implement many small switch + statements. In theory, this value could be increased much more if we + were solely optimizing for space, but we keep it "reasonable" to avoid + serious code efficiency lossage. */ +#define CASE_VALUES_THRESHOLD 8 + +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +/* We could define this either way. Using ZERO_EXTEND for QImode makes slightly + fast and more compact code. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Specify the tree operation to be used to convert reals to integers. */ +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* This flag, if defined, says the same insns that convert to a signed fixnum + also convert validly to an unsigned one. */ +#define FIXUNS_TRUNC_LIKE_FIX_TRUNC + +/* This is the kind of divide that is easiest to do in the general case. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ +#define MOVE_MAX 2 + +/* Define if shifts truncate the shift count + which implies one can omit a sign-extension or zero-extension + of a shift count. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) (OUTPREC != 32) + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +#define Pmode PSImode + +/* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ +#define FUNCTION_MODE QImode + +/* Perform target dependent optabs initialization. */ +#define MODHI3_LIBCALL "__modhi3" +#define DIVHI3_LIBCALL "__divhi3" + +#define INIT_TARGET_OPTABS \ + do { \ + sdiv_optab->handlers[(int) HImode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, DIVHI3_LIBCALL); \ + smod_optab->handlers[(int) HImode].libfunc \ + = gen_rtx (SYMBOL_REF, Pmode, MODHI3_LIBCALL); \ + } while (0) + +/* The assembler op to get a word. */ + +#define FILE_ASM_OP "\t.file\n" + +extern void asm_file_start (); +extern void print_operand (); +extern void print_operand_address (); +extern void expand_prologue (); +extern void expand_epilogue (); +extern void notice_update_cc (); +extern int call_address_operand (); +extern enum reg_class secondary_reload_class (); +extern char *emit_a_shift (); +extern int current_function_needs_context; +extern char *output_tst (); +extern int extendpsi_operand (); +extern int rtx_equal_function_value_matters; +extern struct rtx_def *zero_dreg; +extern struct rtx_def *zero_areg; diff --git a/gnu/usr.bin/gcc/config/mn10200/mn10200.md b/gnu/usr.bin/gcc/config/mn10200/mn10200.md new file mode 100644 index 00000000000..9dc753c3023 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/mn10200.md @@ -0,0 +1,1978 @@ +;; GCC machine description for Matsushita MN10200 +;; Copyright (C) 1997 Free Software Foundation, Inc. + +;; Contributed by Jeff Law (law@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. + +;; The original PO technology requires these to be ordered by speed, +;; so that assigner will pick the fastest. + +;; See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; Condition code settings. +;; none - insn does not affect cc +;; none_0hit - insn does not affect cc but it does modify operand 0 +;; This attribute is used to keep track of when operand 0 changes. +;; See the description of NOTICE_UPDATE_CC for more info. +;; set_znv - sets z,n,v to usable values; c is unknown. +;; set_zn - sets z,n to usable values; v,c is unknown. +;; compare - compare instruction +;; clobber - value of cc is unknown +(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber" + (const_string "clobber")) + +;; ---------------------------------------------------------------------- +;; MOVE INSTRUCTIONS +;; ---------------------------------------------------------------------- +;; +;; Some general notes on move instructions. +;; +;; The hardware can't encode nop moves involving data registers, so +;; we catch them and emit a nop instead. +;; +;; Loads/stores to/from address registers must be 16bit aligned, +;; thus we avoid them for QImode. +;; +;; Stores from address registers always store 24bits, so avoid +;; stores from address registers in HImode, SImode, and SFmode. +;; +;; As a result of the various problems using address registers in +;; QImode, HImode, SImode, and SFmode, we discourage their use via +;; '*' in their constraints. They're still allowed, but they're never +;; the preferred class for for insns with those modes. + +;; movqi + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand0, QImode) + && !register_operand (operand1, QImode)) + operands[1] = copy_to_mode_reg (QImode, operand1); +}") + +;; We avoid memory operations involving address registers because we +;; can't be sure they'll be suitably aligned. +;; +;; We also discourage holding QImode values in address registers. +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=d,d,*a,d,d,m,d,*a,*a") + (match_operand:QI 1 "general_operand" "0,I,I,di,m,d,*a,d,i*a"))] + "register_operand (operands[0], QImode) + || register_operand (operands[1], QImode)" + "@ + nop + sub %0,%0 + sub %0,%0 + mov %S1,%0 + movbu %1,%0 + movb %1,%0 + mov %1,%0 + mov %1,%0 + mov %1,%0" + [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +;; movhi + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, HImode) + && !register_operand (operand0, HImode)) + operands[1] = copy_to_mode_reg (HImode, operand1); +}") + +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=d,d,*a,d,d,m,d,*a,*a,*a") + (match_operand:HI 1 "general_operand" "0,I,I,di,m,d,*a,d,i*a,m"))] + "register_operand (operands[0], HImode) + || register_operand (operands[1], HImode)" + "@ + nop + sub %0,%0 + sub %0,%0 + mov %s1,%0 + mov %1,%0 + mov %1,%0 + mov %1,%0 + mov %1,%0 + mov %1,%0 + mov %A1,%0" + [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +;; movpsi and helpers + +(define_expand "movpsi" + [(set (match_operand:PSI 0 "general_operand" "") + (match_operand:PSI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, PSImode) + && !register_operand (operand0, PSImode)) + operands[1] = copy_to_mode_reg (PSImode, operand1); +}") + + +;; Constant and indexed addresses are not valid addresses for PSImode, +;; therefore they won't be matched by the general movpsi pattern below. +;; ??? We had patterns to handle indexed addresses, but they kept making +;; us run out of regs, so they were eliminated. + +(define_insn "" + [(set (match_operand:PSI 0 "register_operand" "=a") + (match_operand:PSI 1 "constant_memory_operand" ""))] + "" + "mov %A1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:PSI 0 "constant_memory_operand" "=X") + (match_operand:PSI 1 "register_operand" "a"))] + "" + "mov %1,%A0" + [(set_attr "cc" "none_0hit")]) + +;; We want to prefer address registers here because 24bit moves to/from +;; memory are shorter and faster when done via address registers. +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,a?d,?da,a,m,?d,m") + (match_operand:PSI 1 "general_operand" "0,I,?dai,m,a,m,?d"))] + "register_operand (operands[0], PSImode) + || register_operand (operands[1], PSImode)" + "@ + nop + sub %0,%0 + mov %1,%0 + mov %A1,%0 + mov %1,%A0 + movx %A1,%0 + movx %1,%A0" + [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, SImode) + && !register_operand (operand0, SImode)) + operands[1] = copy_to_mode_reg (SImode, operand1); +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d,d,*a,dm,d,d,*a,*a,*a") + (match_operand:SI 1 "general_operand" "0,I,I,d,dim,*a,d,*a,i"))] + "register_operand (operands[0], SImode) + || register_operand (operands[1], SImode)" + "* +{ + switch (which_alternative) + { + case 0: + return \"nop\"; + case 1: + case 2: + return \"sub %H0,%H0\;sub %L0,%L0\"; + case 3: + case 5: + case 6: + case 7: + return \"mov %H1,%H0\;mov %L1,%L0\"; + + /* The next two cases try to optimize cases where one half + of the constant is all zeros, or when the two halves are + the same. */ + case 4: + case 8: + if (REG_P (operands[0]) + && GET_CODE (operands[1]) == CONST_INT + && (INTVAL (operands[1]) & 0xffff0000) == 0) + output_asm_insn (\"sub %H0,%H0\", operands); + else + output_asm_insn (\"mov %h1,%H0\", operands); + + if (GET_CODE (operands[1]) == CONST_INT + && ((INTVAL (operands[1]) & 0xffff) + == ((INTVAL (operands[1]) >> 16) & 0xffff))) + output_asm_insn (\"mov %H0,%L0\", operands); + else if (GET_CODE (operands[1]) == CONST_INT + && (INTVAL (operands[1]) & 0xffff) == 0) + output_asm_insn (\"sub %L0,%L0\", operands); + else + output_asm_insn (\"mov %o1,%L0\", operands); + return \"\"; + } +}" + [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, SFmode) + && !register_operand (operand0, SFmode)) + operands[1] = copy_to_mode_reg (SFmode, operand1); +}") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=d,d,*a,dm,d,d,*a,*a,*a") + (match_operand:SF 1 "general_operand" "0,G,G,d,dim,*a,d,*a,i"))] + "register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode)" + "* +{ + switch (which_alternative) + { + case 0: + return \"nop\"; + + case 1: + case 2: + return \"sub %H0,%H0\;sub %L0,%L0\"; + + default: + { + long val; + REAL_VALUE_TYPE rv; + + if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); + REAL_VALUE_TO_TARGET_SINGLE (rv, val); + } + + if (GET_CODE (operands[1]) == CONST_INT) + val = INTVAL (operands[1]); + + if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && (val & 0xffff0000) == 0) + output_asm_insn (\"sub %H0,%H0\", operands); + else + output_asm_insn (\"mov %h1,%H0\", operands); + + if (GET_CODE (operands[1]) == CONST_INT + && ((INTVAL (operands[1]) & 0xffff) + == ((INTVAL (operands[1]) >> 16) & 0xffff))) + output_asm_insn (\"mov %H0,%L0\", operands); + else if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && (val & 0x0000ffff) == 0) + output_asm_insn (\"sub %L0,%L0\", operands); + else + output_asm_insn (\"mov %o1,%L0\", operands); + return \"\"; + } + } +}" + [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + + +;; ---------------------------------------------------------------------- +;; TEST INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Go ahead and define tsthi and tstpsi so we can eliminate redundant tst insns +;; when we start trying to optimize this port. +(define_insn "tsthi" + [(set (cc0) (match_operand:HI 0 "general_operand" "da"))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + +(define_insn "tstpsi" + [(set (cc0) (match_operand:PSI 0 "general_operand" "da"))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) (zero_extend:HI (match_operand:QI 0 "memory_operand" "d")))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) (zero_extend:PSI (match_operand:QI 0 "memory_operand" "d")))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + +(define_insn "cmphi" + [(set (cc0) + (compare:HI (match_operand:HI 0 "general_operand" "da") + (match_operand:HI 1 "general_operand" "dai")))] + "" + "cmp %1,%0" + [(set_attr "cc" "compare")]) + +(define_insn "cmppsi" + [(set (cc0) + (compare:PSI (match_operand:PSI 0 "general_operand" "da") + (match_operand:PSI 1 "general_operand" "dai")))] + "" + "cmp %1,%0" + [(set_attr "cc" "compare")]) + +;; ---------------------------------------------------------------------- +;; ADD INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "addhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (plus:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "dai")))] + "" + "add %2,%0" + [(set_attr "cc" "set_zn")]) + +(define_insn "addpsi3" + [(set (match_operand:PSI 0 "general_operand" "=da") + (plus:PSI (match_operand:PSI 1 "general_operand" "%0") + (match_operand:PSI 2 "general_operand" "dai")))] + "" + "add %2,%0" + [(set_attr "cc" "set_zn")]) + +;; We want to avoid using explicit registers; reload won't tell us +;; if it has to spill them and may generate incorrect code in such +;; cases. +;; +;; So we call out to a library routine to perform 32bit add or +;; subtract operations. +(define_expand "addsi3" + [(set (match_operand:SI 0 "general_operand" "") + (plus:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" "")))] + "" + " +{ + /* If adding a CONST_INT, we are better off generating code ourselves. + + During RTL generation we call out to library routines. + + After RTL generation we can not call the library routines as + they need to push arguments via virtual_outgoing_args_rtx which + has already been instantiated. So, after RTL generation we just + FAIL and open code the operation. */ + if (GET_CODE (operands[2]) == CONST_INT) + { + if (!rtx_equal_p (operands[0], operands[1])) + emit_move_insn (operands[0], operands[1]); + emit_insn (gen_addsi3_const (operands[0], operands[0], operands[2])); + DONE; + } + else if (rtx_equal_function_value_matters) + { + rtx ret, insns; + extern rtx emit_library_call_value (); + + start_sequence (); + ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__addsi3\"), + NULL_RTX, 1, SImode, 2, operands[1], + SImode, operands[2], SImode); + insns = get_insns (); + end_sequence (); + emit_libcall_block (insns, operands[0], ret, + gen_rtx (ASHIFT, SImode, operands[1], operands[2])); + DONE; + } + else + FAIL; +}") + +(define_insn "addsi3_const" + [(set (match_operand:SI 0 "general_operand" "=d") + (plus:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "const_int_operand" "i"))) + (clobber (match_scratch:SI 3 "=&d"))] + "" + "* +{ + unsigned long value = INTVAL (operands[2]); + + /* If only the high bits are set in the constant, then we only + need a single add operation. It might be better to catch this + at RTL expansion time. */ + if ((value & 0xffff) == 0) + return \"add %h2,%H0\"; + + value >>= 16; + value &= 0xffff; + + if (value == 0) + return \"sub %3,%3\;add %o2,%L0\;addc %3,%H0\"; + else + return \"mov %h2,%3\;add %o2,%L0\;addc %3,%H0\"; +}" + [(set_attr "cc" "clobber")]) + +;; ---------------------------------------------------------------------- +;; SUBTRACT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "subhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (minus:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dai")))] + "" + "sub %2,%0" + [(set_attr "cc" "set_zn")]) + +(define_insn "subpsi3" + [(set (match_operand:PSI 0 "general_operand" "=da") + (minus:PSI (match_operand:PSI 1 "general_operand" "0") + (match_operand:PSI 2 "general_operand" "dai")))] + "" + "sub %2,%0" + [(set_attr "cc" "set_zn")]) + +(define_expand "subsi3" + [(set (match_operand:SI 0 "general_operand" "") + (minus:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" "")))] + "" + " +{ + /* During RTL generation we call out to library routines. + + After RTL generation we can not call the library routines as + they need to push arguments via virtual_outgoing_args_rtx which + has already been instantiated. So, after RTL generation we just + FAIL and open code the operation. */ + if (rtx_equal_function_value_matters) + { + rtx ret, insns; + extern rtx emit_library_call_value (); + + start_sequence (); + ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__subsi3\"), + NULL_RTX, 1, SImode, 2, operands[1], + SImode, operands[2], SImode); + insns = get_insns (); + end_sequence (); + emit_libcall_block (insns, operands[0], ret, + gen_rtx (ASHIFT, SImode, operands[1], operands[2])); + DONE; + } + else + FAIL; +}") + +;; There isn't a negate instruction, so we fake it. +;; +;; We used to expand this into patterns, but a single pattern +;; actually generates better overall code. +;; +;; We could do HImode negations with a "not;add" sequence, but +;; generally it's generated slightly worse code. +;; +;; The second alternative is not strictly necesasry, but helps +;; when the register allocators start running short of registers. +(define_insn "neghi2" + [(set (match_operand:HI 0 "general_operand" "=&d,d") + (neg:HI (match_operand:HI 1 "general_operand" "d,0")))] + "" + "@ + sub %0,%0\;sub %1,%0 + not %0\;add 1,%0" + [(set_attr "cc" "set_zn")]) + +;; The not/and sequence won't work here. It's not clear if we'll +;; ever need to provide an alternate sequence since this should +;; be used much less frequently than neghi2. +(define_insn "negpsi2" + [(set (match_operand:PSI 0 "general_operand" "=&d") + (neg:PSI (match_operand:PSI 1 "general_operand" "d")))] + "" + "sub %0,%0\;sub %1,%0" + [(set_attr "cc" "set_zn")]) + +;; Using a magic libcall that accepts its arguments in any +;; data register pair has proven to be the most efficient +;; and most compact way to represent negsi2. +(define_insn "negsi2" + [(set (match_operand:SI 0 "general_operand" "=d") + (neg:SI (match_operand:SI 1 "general_operand" "0")))] + "" + "jsr ___negsi2_%0" + [(set_attr "cc" "clobber")]) + +;; ---------------------------------------------------------------------- +;; MULTIPLY INSTRUCTIONS +;; ---------------------------------------------------------------------- +;; +;; The mn10200 has HIxHI->SI widening multiply, but we get _severe_ +;; code density regressions if we enable such a pattern. + +(define_insn "mulhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (mult:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "d")))] + "" + "mul %2,%0" + [(set_attr "cc" "set_zn")]) + +(define_insn "udivmodhi4" + [(set (match_operand:HI 0 "general_operand" "=d") + (udiv:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "d"))) + (set (match_operand:HI 3 "general_operand" "=&d") + (umod:HI (match_dup 1) (match_dup 2)))] + "" + "* +{ + if (zero_dreg) + output_asm_insn (\"mov %0,mdr\", &zero_dreg); + else + output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands); + + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return \"divu %2,%0\"; + else + return \"divu %2,%0\;mov mdr,%3\"; +}" + [(set_attr "cc" "set_zn")]) + + +;; ---------------------------------------------------------------------- +;; AND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "andhi3" + [(set (match_operand:HI 0 "general_operand" "=d,d") + (and:HI (match_operand:HI 1 "general_operand" "%0,0") + (match_operand:HI 2 "general_operand" "M,di")))] + "" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xff) + return \"extxbu %0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x7fff) + return \"add %0,%0\;lsr %0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffe) + return \"lsr %0\;add %0,%0\"; + return \"and %2,%0\"; +}" + [(set_attr "cc" "none_0hit,set_znv")]) + +;; This expander + pattern exist only to allow trampolines to be aligned +;; in the stack. +(define_expand "andpsi3" + [(set (match_operand:PSI 0 "general_operand" "") + (and:PSI (match_operand:PSI 1 "general_operand" "") + (match_operand:PSI 2 "const_int_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT + || (INTVAL (operands[2]) & 0xff0000) != 0xff0000) + FAIL; +}") + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d") + (and:PSI (match_operand:PSI 1 "general_operand" "%0") + (match_operand:PSI 2 "const_int_operand" "i")))] + "GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) & 0xff0000) == 0xff0000" + "and %2,%0" + [(set_attr "cc" "clobber")]) + +;; ---------------------------------------------------------------------- +;; OR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "iorhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (ior:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "di")))] + "" + "or %2,%0" + [(set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; XOR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "xorhi3" + [(set (match_operand:HI 0 "general_operand" "=d") + (xor:HI (match_operand:HI 1 "general_operand" "%0") + (match_operand:HI 2 "general_operand" "di")))] + "" + "xor %2,%0" + [(set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; NOT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "one_cmplhi2" + [(set (match_operand:HI 0 "general_operand" "=d") + (not:HI (match_operand:HI 1 "general_operand" "0")))] + "" + "not %0" + [(set_attr "cc" "set_znv")]) + + +;; ----------------------------------------------------------------- +;; BIT INSTRUCTIONS +;; ----------------------------------------------------------------- + +;; These clears a constant set of bits in memory or in a register. +;; We must support register destinations to make reload happy. +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "R,d") + (subreg:QI + (and:HI (subreg:HI (match_dup 0) 0) + (match_operand 1 "const_int_operand" "")) 0)) + (clobber (match_scratch:HI 2 "=&d,X"))] + "" + "@ + mov %N1,%2\;bclr %2,%0 + and %1,%0" + [(set_attr "cc" "clobber")]) + +;; This clears a variable set of bits in memory or in a register. +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "R,d") + (subreg:QI + (and:HI (subreg:HI (match_dup 0) 0) + (not:HI (match_operand:HI 1 "general_operand" "d,d"))) 0)) + (clobber (match_scratch:HI 2 "=X,&d"))] + "" + "@ + bclr %1,%0 + mov %1,%2\;not %2\;and %2,%0" + [(set_attr "cc" "clobber")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "R,d") + (subreg:QI + (and:HI (not:HI (match_operand:HI 1 "general_operand" "d,d")) + (subreg:HI (match_dup 0) 0)) 0)) + (clobber (match_scratch:HI 2 "=X,&d"))] + "" + "@ + bclr %1,%0 + mov %1,%2\;not %2\;and %2,%0" + [(set_attr "cc" "clobber")]) + +;; These set bits in memory. +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "R,d") + (subreg:QI + (ior:HI (subreg:HI (match_dup 0) 0) + (match_operand:HI 1 "general_operand" "d,d")) 0))] + "" + "@ + bset %1,%0 + or %1,%0" + [(set_attr "cc" "clobber")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "R,d") + (subreg:QI + (ior:HI (match_operand:HI 1 "general_operand" "d,d") + (subreg:HI (match_dup 0) 0)) 0))] + "" + "@ + bset %1,%0 + or %1,%0" + [(set_attr "cc" "clobber")]) + +;; Not any shorter/faster than using cmp, but it might save a +;; register if the result of the AND isn't ever used. + +(define_insn "" + [(set (cc0) + (zero_extract:HI (match_operand:HI 0 "general_operand" "d") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")))] + "" + "* +{ + int len = INTVAL (operands[1]); + int bit = INTVAL (operands[2]); + int mask = 0; + rtx xoperands[2]; + + while (len > 0) + { + mask |= (1 << bit); + bit++; + len--; + } + + xoperands[0] = operands[0]; + xoperands[1] = GEN_INT (mask); + output_asm_insn (\"btst %1,%0\", xoperands); + return \"\"; +}" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "d") + (match_operand:HI 1 "const_int_operand" "i")))] + "" + "btst %1,%0" + [(set_attr "cc" "set_znv")]) + + +;; ---------------------------------------------------------------------- +;; JUMP INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Conditional jump instructions + +(define_expand "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_insn "" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + return 0; + + if (GET_MODE (SET_SRC (PATTERN (PREV_INSN (insn)))) == PSImode) + return \"b%b1x %0\"; + else + return \"b%b1 %0\"; +}" + [(set_attr "cc" "none")]) + +(define_insn "" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + return 0; + + if (GET_MODE (SET_SRC (PATTERN (PREV_INSN (insn)))) == PSImode) + return \"b%B1x %0\"; + else + return \"b%B1 %0\"; +}" + [(set_attr "cc" "none")]) + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jmp %l0" + [(set_attr "cc" "none")]) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:PSI 0 "general_operand" "a"))] + "" + "jmp (%0)" + [(set_attr "cc" "none")]) + +(define_insn "tablejump" + [(set (pc) (match_operand:PSI 0 "general_operand" "a")) + (use (label_ref (match_operand 1 "" "")))] + "" + "jmp (%0)" + [(set_attr "cc" "none")]) + +;; Call subroutine with no return value. + +(define_expand "call" + [(call (match_operand:QI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + if (! call_address_operand (XEXP (operands[0], 0))) + XEXP (operands[0], 0) = force_reg (PSImode, XEXP (operands[0], 0)); + emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1])); + DONE; +}") + +(define_insn "call_internal" + [(call (mem:QI (match_operand:PSI 0 "call_address_operand" "aS")) + (match_operand:HI 1 "general_operand" "g"))] + "" + "jsr %C0" + [(set_attr "cc" "clobber")]) + +;; Call subroutine, returning value in operand 0 +;; (which must be a hard register). + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + if (! call_address_operand (XEXP (operands[1], 0))) + XEXP (operands[1], 0) = force_reg (PSImode, XEXP (operands[1], 0)); + emit_call_insn (gen_call_value_internal (operands[0], + XEXP (operands[1], 0), + operands[2])); + DONE; +}") + +(define_insn "call_value_internal" + [(set (match_operand 0 "" "=da") + (call (mem:QI (match_operand:PSI 1 "call_address_operand" "aS")) + (match_operand:HI 2 "general_operand" "g")))] + "" + "jsr %C1" + [(set_attr "cc" "clobber")]) + +(define_expand "untyped_call" + [(parallel [(call (match_operand 0 "" "") + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] + "" + " +{ + int i; + + emit_call_insn (gen_call (operands[0], const0_rtx)); + + for (i = 0; i < XVECLEN (operands[2], 0); i++) + { + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); + } + DONE; +}") + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "cc" "none")]) + +;; ---------------------------------------------------------------------- +;; EXTEND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=d,d,d") + (zero_extend:HI + (match_operand:QI 1 "general_operand" "0,di,m")))] + "" + "@ + extxbu %0 + mov %1,%0\;extxbu %0 + movbu %1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "zero_extendqipsi2" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (zero_extend:PSI + (match_operand:QI 1 "general_operand" "0,di,m")))] + "" + "@ + extxbu %0 + mov %1,%0\;extxbu %0 + movbu %1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d,d") + (zero_extend:SI + (match_operand:QI 1 "general_operand" "0,di,m")))] + "" + "@ + extxbu %L0\;sub %H0,%H0 + mov %1,%L0\;extxbu %L0\;sub %H0,%H0 + movbu %1,%L0\;sub %H0,%H0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "zero_extendhipsi2" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (zero_extend:PSI + (match_operand:HI 1 "general_operand" "0,di,m")))] + "" + "@ + extxu %0 + mov %1,%0\;extxu %0 + mov %1,%0\;extxu %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d") + (zero_extend:SI + (match_operand:HI 1 "general_operand" "0,dim")))] + "" + "@ + sub %H0,%H0 + mov %1,%L0\;sub %H0,%H0" + [(set_attr "cc" "none_0hit")]) + +;; The last alternative is necessary because the second operand might +;; have been the frame pointer. The frame pointer would get replaced +;; by (plus (stack_pointer) (const_int)). +;; +;; Reload would think that it only needed a PSImode register in +;; push_reload and at the start of allocate_reload_regs. However, +;; at the end of allocate_reload_reg it would realize that the +;; reload register must also be valid for SImode, and if it was +;; not valid reload would abort. +(define_insn "zero_extendpsisi2" + [(set (match_operand:SI 0 "register_operand" "=d,?d,?*d,?*d") + (zero_extend:SI (match_operand:PSI 1 "extendpsi_operand" + "m,?0,?*dai,Q")))] + "" + "@ + mov %L1,%L0\;movbu %H1,%H0 + jsr ___zero_extendpsisi2_%0 + mov %1,%L0\;jsr ___zero_extendpsisi2_%0 + mov a3,%L0\;add %Z1,%L0\;jsr ___zero_extendpsisi2_%0" + [(set_attr "cc" "clobber")]) + +;;- sign extension instructions + +(define_insn "extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=d,d,d") + (sign_extend:HI + (match_operand:QI 1 "general_operand" "0,di,m")))] + "" + "* +{ + if (which_alternative == 0) + return \"extxb %0\"; + else if (which_alternative == 1) + return \"mov %1,%0\;extxb %0\"; + else if (GET_CODE (XEXP (operands[1], 0)) == REG) + return \"movbu %1,%0\;extxb %0\"; + else + return \"movb %1,%0\"; +}" + [(set_attr "cc" "none_0hit")]) + +(define_insn "extendqipsi2" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (sign_extend:PSI + (match_operand:QI 1 "general_operand" "0,di,m")))] + "" + "* +{ + if (which_alternative == 0) + return \"extxb %0\"; + else if (which_alternative == 1) + return \"mov %1,%0\;extxb %0\"; + else if (GET_CODE (XEXP (operands[1], 0)) == REG) + return \"movbu %1,%0\;extxb %0\"; + else + return \"movb %1,%0\"; +}" + [(set_attr "cc" "none_0hit")]) + +(define_insn "extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d,d") + (sign_extend:SI + (match_operand:QI 1 "general_operand" "0,di,m")))] + "" + "* +{ + if (which_alternative == 0) + return \"extxb %L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\"; + else if (which_alternative == 1) + return \"mov %1,%L0\;extxb %L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\"; + else if (GET_CODE (XEXP (operands[1], 0)) == REG) + return \"movbu %1,%L0\;extxb %L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\"; + else + return \"movb %1,%L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\"; +}" + [(set_attr "cc" "none_0hit")]) + +(define_insn "extendhipsi2" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (sign_extend:PSI + (match_operand:HI 1 "general_operand" "0,di,m")))] + "" + "@ + extx %0 + mov %1,%0\;extx %0 + mov %1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d,d") + (sign_extend:SI + (match_operand:HI 1 "general_operand" "0,di,m")))] + "" + "@ + mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0 + mov %1,%L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0 + mov %1,%L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0" + [(set_attr "cc" "none_0hit")]) + +;; The last alternative is necessary because the second operand might +;; have been the frame pointer. The frame pointer would get replaced +;; by (plus (stack_pointer) (const_int)). +;; +;; Reload would think that it only needed a PSImode register in +;; push_reload and at the start of allocate_reload_regs. However, +;; at the end of allocate_reload_reg it would realize that the +;; reload register must also be valid for SImode, and if it was +;; not valid reload would abort. +(define_insn "extendpsisi2" + [(set (match_operand:SI 0 "general_operand" "=d,?d,?*d,?*d") + (sign_extend:SI (match_operand:PSI 1 "extendpsi_operand" + "m,?0,?*dai,Q")))] + "" + "@ + mov %L1,%L0\;movb %H1,%H0 + jsr ___sign_extendpsisi2_%0 + mov %1,%L0\;jsr ___sign_extendpsisi2_%0 + mov a3,%L0\;add %Z1,%L0\;jsr ___sign_extendpsisi2_%0" + [(set_attr "cc" "clobber")]) + +(define_insn "truncsipsi2" + [(set (match_operand:PSI 0 "general_operand" "=a,?d,?*d,da") + (truncate:PSI (match_operand:SI 1 "general_operand" "m,?m,?*d,i")))] + "" + "@ + mov %1,%0 + movx %A1,%0 + jsr ___truncsipsi2_%1_%0 + mov %1,%0" + [(set_attr "cc" "clobber")]) + + +;; Combine should be simplifying this stuff, but isn't. +;; +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d,d,d") + (sign_extend:SI + (zero_extend:HI (match_operand:QI 1 "general_operand" "0,di,m"))))] + "" + "@ + extxbu %L0\;sub %H0,%H0 + mov %1,%L0\;extxbu %L0\;sub %H0,%H0 + movbu %1,%L0\;sub %H0,%H0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (sign_extend:SI (match_operand:QI 1 "general_operand" "0,di,m"))))] + "" + "* +{ + if (which_alternative == 0) + return \"extxb %0\"; + else if (which_alternative == 1) + return \"mov %1,%0\;extxb %0\"; + else if (GET_CODE (XEXP (operands[1], 0)) == REG) + return \"movbu %1,%0\;extxb %0\"; + else + return \"movb %1,%0\"; +}" + [(set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (sign_extend:SI (match_operand:HI 1 "general_operand" "0,di,m"))))] + "" + "@ + extx %0 + mov %1,%0\;extx %0 + mov %1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (sign_extend:SI + (zero_extend:HI (match_operand:QI 1 "general_operand" "0,di,m")))))] + "" + "@ + extxbu %0 + mov %1,%0\;extxbu %0 + movbu %1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (zero_extend:SI (match_operand:HI 1 "general_operand" "0,di,m"))))] + "" + "@ + extxu %0 + mov %1,%0\;extxu %0 + mov %1,%0\;extxu %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (zero_extend:SI (match_operand:QI 1 "general_operand" "0,di,m"))))] + "" + "@ + extxbu %0 + mov %1,%0\;extxbu %0 + movbu %1,%0" + [(set_attr "cc" "none_0hit")]) + +;; ---------------------------------------------------------------------- +;; SHIFTS +;; ---------------------------------------------------------------------- + +;; If the shift count is small, we expand it into several single bit +;; shift insns. Otherwise we expand into a generic shift insn which +;; handles larger shift counts, shift by variable amounts, etc. +(define_expand "ashlhi3" + [(set (match_operand:HI 0 "general_operand" "") + (ashift:HI (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* This is an experiment to see if exposing more of the underlying + operations results in better code. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) <= 4) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, HImode, operands[0], + gen_rtx (ASHIFT, HImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else + { + expand_a_shift (HImode, ASHIFT, operands); + DONE; + } +}") + +;; ASHIFT one bit. +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=d") + (ashift:HI (match_operand:HI 1 "general_operand" "0") + (const_int 1)))] + "" + "add %0,%0" + [(set_attr "cc" "set_zn")]) + +(define_expand "lshrhi3" + [(set (match_operand:HI 0 "general_operand" "") + (lshiftrt:HI (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* This is an experiment to see if exposing more of the underlying + operations results in better code. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) <= 4) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, HImode, operands[0], + gen_rtx (LSHIFTRT, HImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else + { + expand_a_shift (HImode, LSHIFTRT, operands); + DONE; + } +}") + +;; LSHIFTRT one bit. +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=d") + (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") + (const_int 1)))] + "" + "lsr %0" + [(set_attr "cc" "set_znv")]) + +(define_expand "ashrhi3" + [(set (match_operand:HI 0 "general_operand" "") + (ashiftrt:HI (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* This is an experiment to see if exposing more of the underlying + operations results in better code. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) <= 4) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, HImode, operands[0], + gen_rtx (ASHIFTRT, HImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else + { + expand_a_shift (HImode, ASHIFTRT, operands); + DONE; + } +}") + +;; ASHIFTRT one bit. +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=d") + (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") + (const_int 1)))] + "" + "asr %0" + [(set_attr "cc" "set_znv")]) + +;; And the general HImode shift pattern. Handles both shift by constants +;; and shift by variable counts. +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=d,d") + (match_operator:HI 3 "nshift_operator" + [ (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "KL,dan")])) + (clobber (match_scratch:HI 4 "=X,&d"))] + "" + "* return emit_a_shift (insn, operands);" + [(set_attr "cc" "clobber")]) + +;; We expect only ASHIFT with constant shift counts to be common for +;; PSImode, so we optimize just that case. For all other cases we +;; extend the value to SImode and perform the shift in SImode. +(define_expand "ashlpsi3" + [(set (match_operand:PSI 0 "general_operand" "") + (ashift:PSI (match_operand:PSI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* This is an experiment to see if exposing more of the underlying + operations results in better code. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) <= 7) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, PSImode, operands[0], + gen_rtx (ASHIFT, PSImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else + { + expand_a_shift (PSImode, ASHIFT, operands); + DONE; + } +}") + +;; ASHIFT one bit. +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d") + (ashift:PSI (match_operand:PSI 1 "general_operand" "0") + (const_int 1)))] + "" + "add %0,%0" + [(set_attr "cc" "set_zn")]) + +(define_expand "lshrpsi3" + [(set (match_operand:PSI 0 "general_operand" "") + (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_zero_extendpsisi2 (reg, operands[1])); + reg = expand_binop (SImode, lshr_optab, reg, + operands[2], reg, 1, OPTAB_WIDEN); + emit_insn (gen_truncsipsi2 (operands[0], reg)); + DONE; +}") + +(define_expand "ashrpsi3" + [(set (match_operand:PSI 0 "general_operand" "") + (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_extendpsisi2 (reg, operands[1])); + reg = expand_binop (SImode, ashr_optab, reg, + operands[2], reg, 0, OPTAB_WIDEN); + emit_insn (gen_truncsipsi2 (operands[0], reg)); + DONE; +}") + +(define_expand "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ashift:SI (match_operand:SI 1 "nonmemory_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* For small shifts, just emit a series of single bit shifts inline. + + For other constant shift counts smaller than a word or non-constant + shift counts we call out to a library call during RTL generation time; + after RTL generation time we allow optabs.c to open code the operation. + See comments in addsi3/subsi3 expanders. + + Otherwise we allow optabs.c to open code the operation. */ + if (GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) <= 3)) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, SImode, operands[0], + gen_rtx (ASHIFT, SImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else if (rtx_equal_function_value_matters + && (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) <= 15)) + { + rtx ret, insns; + extern rtx emit_library_call_value (); + + start_sequence (); + ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__ashlsi3\"), + NULL_RTX, 1, SImode, 2, operands[1], + SImode, operands[2], HImode); + insns = get_insns (); + end_sequence (); + emit_libcall_block (insns, operands[0], ret, + gen_rtx (ASHIFT, SImode, operands[1], operands[2])); + DONE; + } + else + FAIL; +}") + +;; ASHIFT one bit. +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (ashift:SI (match_operand:SI 1 "general_operand" "0") + (const_int 1)))] + "" + "add %L0,%L0\;addc %H0,%H0" + [(set_attr "cc" "clobber")]) + +(define_expand "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "") + (lshiftrt:SI (match_operand:SI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* For small shifts, just emit a series of single bit shifts inline. + + For other constant shift counts smaller than a word or non-constant + shift counts we call out to a library call during RTL generation time; + after RTL generation time we allow optabs.c to open code the operation. + See comments in addsi3/subsi3 expanders. + + Otherwise we allow optabs.c to open code the operation. */ + if (GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) <= 2)) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, SImode, operands[0], + gen_rtx (LSHIFTRT, SImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else if (rtx_equal_function_value_matters + && (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) <= 15)) + { + rtx ret, insns; + extern rtx emit_library_call_value (); + + start_sequence (); + ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__lshrsi3\"), + NULL_RTX, 1, SImode, 2, operands[1], + SImode, operands[2], HImode); + insns = get_insns (); + end_sequence (); + emit_libcall_block (insns, operands[0], ret, + gen_rtx (LSHIFTRT, SImode, operands[1], operands[2])); + DONE; + } + else + FAIL; +}") + +;; LSHIFTRT one bit. +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") + (const_int 1)))] + "" + "lsr %H0\;ror %L0" + [(set_attr "cc" "clobber")]) + +(define_expand "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + /* For small shifts, just emit a series of single bit shifts inline. + + For other constant shift counts smaller than a word or non-constant + shift counts we call out to a library call during RTL generation time; + after RTL generation time we allow optabs.c to open code the operation. + See comments in addsi3/subsi3 expanders. + + Otherwise we allow optabs.c to open code the operation. */ + if (GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) <= 2)) + { + int count = INTVAL (operands[2]); + emit_move_insn (operands[0], operands[1]); + while (count > 0) + { + emit_insn (gen_rtx (SET, SImode, operands[0], + gen_rtx (ASHIFTRT, SImode, + operands[0], GEN_INT (1)))); + count--; + } + DONE; + } + else if (rtx_equal_function_value_matters + && (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) <= 15)) + { + rtx ret, insns; + extern rtx emit_library_call_value (); + + start_sequence (); + ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"__ashrsi3\"), + NULL_RTX, 1, SImode, 2, operands[1], + SImode, operands[2], HImode); + insns = get_insns (); + end_sequence (); + emit_libcall_block (insns, operands[0], ret, + gen_rtx (ASHIFTRT, SImode, operands[1], operands[2])); + DONE; + } + else + FAIL; +}") + +;; ASHIFTRT one bit. +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=d") + (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") + (const_int 1)))] + "" + "asr %H0\;ror %L0" + [(set_attr "cc" "clobber")]) + +;; ---------------------------------------------------------------------- +;; PROLOGUE/EPILOGUE +;; ---------------------------------------------------------------------- +(define_expand "prologue" + [(const_int 0)] + "" + "expand_prologue (); DONE;") + +(define_insn "outline_prologue_call" + [(const_int 1)] + "" + "jsr ___prologue" + [(set_attr "cc" "clobber")]) + +(define_expand "epilogue" + [(return)] + "" + " +{ + expand_epilogue (); + DONE; +}") + +(define_insn "outline_epilogue_call_a0" + [(const_int 2)] + "" + "jsr ___epilogue_a0" + [(set_attr "cc" "clobber")]) + +(define_insn "outline_epilogue_call_d0" + [(const_int 3)] + "" + "jsr ___epilogue_d0" + [(set_attr "cc" "clobber")]) + +(define_insn "outline_epilogue_jump" + [(const_int 4)] + "" + "jmp ___epilogue_noreturn" + [(set_attr "cc" "clobber")]) + +(define_insn "return" + [(return)] + "reload_completed && total_frame_size () == 0 + && !current_function_needs_context" + "* +{ + rtx next = next_active_insn (insn); + + if (next + && GET_CODE (next) == JUMP_INSN + && GET_CODE (PATTERN (next)) == RETURN) + return \"\"; + return \"rts\"; +}" + [(set_attr "cc" "clobber")]) + +(define_insn "return_internal" + [(const_int 0) + (return)] + "" + "rts" + [(set_attr "cc" "clobber")]) + +;; These are special combiner patterns to improve array/pointer accesses. +;; +;; A typical sequence involves extending an integer/char, shifting it left +;; a few times, then truncating the value to PSImode. +;; +;; This first pattern combines the shifting & truncation operations, by +;; itself it is a win because the shifts end up occurring in PSImode instead +;; of SImode. However, it has the secondary effect of giving us the +;; opportunity to match patterns which allow us to remove the initial +;; extension completely, which is a big win. +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,a") + (truncate:PSI + (ashift:SI (match_operand:SI 1 "general_operand" "d,m,m") + (match_operand:HI 2 "const_int_operand" "i,i,i"))))] + "" + "* +{ + int count = INTVAL (operands[2]); + if (which_alternative == 0) + output_asm_insn (\"jsr ___truncsipsi2_%1_%0\", operands); + else if (which_alternative == 1) + output_asm_insn (\"movx %A1,%0\", operands); + else + output_asm_insn (\" mov %1,%0\", operands); + + while (count) + { + output_asm_insn (\"add %0,%0\", operands); + count--; + } + return \"\"; +}" + [(set_attr "cc" "clobber")]) + +;; Similarly, except that we also have zero/sign extension of the +;; original operand. */ +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d") + (truncate:PSI + (ashift:SI + (zero_extend:SI (match_operand:HI 1 "general_operand" "0,dim")) + (match_operand:HI 2 "const_int_operand" "i,i"))))] + "" + "* +{ + int count = INTVAL (operands[2]); + + /* First extend operand 1 to PSImode. */ + if (which_alternative == 0) + output_asm_insn (\"extxu %0\", operands); + else + output_asm_insn (\"mov %1,%0\;extxu %0\", operands); + + /* Now do the shifting. */ + while (count) + { + output_asm_insn (\"add %0,%0\", operands); + count--; + } + return \"\"; +}" + [(set_attr "cc" "clobber")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (ashift:SI + (sign_extend:SI (match_operand:HI 1 "general_operand" "0,di,m")) + (match_operand:HI 2 "const_int_operand" "i,i,i"))))] + "" + "* +{ + int count = INTVAL (operands[2]); + + /* First extend operand 1 to PSImode. */ + if (which_alternative == 0) + output_asm_insn (\"extx %0\", operands); + else if (which_alternative == 1) + output_asm_insn (\"mov %1,%0\;extx %0\", operands); + else + output_asm_insn (\"mov %1,%0\", operands); + + /* Now do the shifting. */ + while (count) + { + output_asm_insn (\"add %0,%0\", operands); + count--; + } + return \"\"; +}" + [(set_attr "cc" "clobber")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (ashift:SI + (sign_extend:SI + (zero_extend:HI (match_operand:QI 1 "general_operand" "0,di,m"))) + (match_operand:HI 2 "const_int_operand" "i,i,i"))))] + "" + "* +{ + int count = INTVAL (operands[2]); + + /* First extend operand 1 to PSImode. */ + if (which_alternative == 0) + output_asm_insn (\"extxbu %0\", operands); + else if (which_alternative == 1) + output_asm_insn (\"mov %1,%0\;extxbu %0\", operands); + else + output_asm_insn (\"movbu %1,%0\", operands); + + /* Now do the shifting. */ + while (count) + { + output_asm_insn (\"add %0,%0\", operands); + count--; + } + return \"\"; +}" + [(set_attr "cc" "clobber")]) + +(define_insn "" + [(set (match_operand:PSI 0 "general_operand" "=d,d,d") + (truncate:PSI + (ashift:SI + (sign_extend:SI + (match_operand:QI 1 "general_operand" "0,di,m")) + (match_operand:HI 2 "const_int_operand" "i,i,i"))))] + "" + "* +{ + int count = INTVAL (operands[2]); + + /* First extend operand 1 to PSImode. */ + if (which_alternative == 0) + output_asm_insn (\"extxb %0\", operands); + else if (which_alternative == 1) + output_asm_insn (\"mov %1,%0\;extxb %0\", operands); + else if (GET_CODE (XEXP (operands[1], 0)) == REG) + output_asm_insn (\"movbu %1,%0\;extxb %0\", operands); + else + output_asm_insn (\"movb %1,%0\", operands); + + /* Now do the shifting. */ + while (count) + { + output_asm_insn (\"add %0,%0\", operands); + count--; + } + return \"\"; +}" + [(set_attr "cc" "clobber")]) + +;; Try to combine consecutive updates of the stack pointer (or any +;; other register for that matter). +(define_peephole + [(set (match_operand:PSI 0 "register_operand" "=da") + (plus:PSI (match_dup 0) + (match_operand 1 "const_int_operand" ""))) + (set (match_dup 0) + (plus:PSI (match_dup 0) + (match_operand 2 "const_int_operand" "")))] + "" + "* +{ + operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1])); + return \"add %1,%0\"; +}" + [(set_attr "cc" "clobber")]) + +;; +;; We had patterns to check eq/ne, but the they don't work because +;; 0x80000000 + 0x80000000 = 0x0 with a carry out. +;; +;; The Z flag and C flag would be set, and we have no way to +;; check for the Z flag set and C flag clear. +;; +;; This will work on the mn10200 because we can check the ZX flag +;; if the comparison is in HImode. +(define_peephole + [(set (cc0) (match_operand:HI 0 "register_operand" "d")) + (set (pc) (if_then_else (ge (cc0) (const_int 0)) + (match_operand 1 "" "") + (pc)))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcc %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:HI 0 "register_operand" "d")) + (set (pc) (if_then_else (lt (cc0) (const_int 0)) + (match_operand 1 "" "") + (pc)))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcs %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:HI 0 "register_operand" "d")) + (set (pc) (if_then_else (ge (cc0) (const_int 0)) + (pc) + (match_operand 1 "" "")))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcs %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:HI 0 "register_operand" "d")) + (set (pc) (if_then_else (lt (cc0) (const_int 0)) + (pc) + (match_operand 1 "" "")))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcc %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:PSI 0 "register_operand" "d")) + (set (pc) (if_then_else (ge (cc0) (const_int 0)) + (match_operand 1 "" "") + (pc)))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bccx %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:PSI 0 "register_operand" "d")) + (set (pc) (if_then_else (lt (cc0) (const_int 0)) + (match_operand 1 "" "") + (pc)))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcsx %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:PSI 0 "register_operand" "d")) + (set (pc) (if_then_else (ge (cc0) (const_int 0)) + (pc) + (match_operand 1 "" "")))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcsx %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:PSI 0 "register_operand" "d")) + (set (pc) (if_then_else (lt (cc0) (const_int 0)) + (pc) + (match_operand 1 "" "")))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bccx %1" + [(set_attr "cc" "clobber")]) + +;; We call out to library routines to perform 32bit addition and subtraction +;; operations (see addsi3/subsi3 expanders for why). These peepholes catch +;; the trivial case where the operation could be done with an add;addc or +;; sub;subc sequence. +(define_peephole + [(set (mem:SI (reg:PSI 7)) (reg:SI 2)) + (set (reg:SI 0) (call (match_operand:QI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF + && strcmp (XSTR (XEXP (operands[1], 0), 0), \"__addsi3\") == 0" + "add d2,d0\;addc d3,d1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (mem:SI (reg:PSI 7)) (reg:SI 2)) + (set (reg:SI 0) (call (match_operand:QI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF + && strcmp (XSTR (XEXP (operands[1], 0), 0), \"__subsi3\") == 0" + "sub d2,d0\;subc d3,d1" + [(set_attr "cc" "clobber")]) diff --git a/gnu/usr.bin/gcc/config/mn10200/t-mn10200 b/gnu/usr.bin/gcc/config/mn10200/t-mn10200 new file mode 100644 index 00000000000..9486837cd9a --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/t-mn10200 @@ -0,0 +1,50 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = mn10200/lib1funcs.asm +LIB1ASMFUNCS = _divhi3 \ + _modhi3 \ + _addsi3 \ + _subsi3 \ + _mulsi3 \ + _ashlsi3 \ + _lshrsi3 \ + _ashrsi3 \ + _negsi2_d0 \ + _negsi2_d2 \ + _zero_extendpsisi2_d0 \ + _zero_extendpsisi2_d2 \ + _sign_extendpsisi2_d0 \ + _sign_extendpsisi2_d2 \ + _truncsipsi2_d0_d0 \ + _truncsipsi2_d0_d1 \ + _truncsipsi2_d0_d2 \ + _truncsipsi2_d0_d3 \ + _truncsipsi2_d2_d0 \ + _truncsipsi2_d2_d1 \ + _truncsipsi2_d2_d2 \ + _truncsipsi2_d2_d3 \ + _cmpsi2 \ + _ucmpsi2 \ + _prologue \ + _epilogue_a0 \ + _epilogue_d0 \ + _epilogue_noreturn + + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +# We do not have DF or DI types, so fake out the libgcc2 compilation. +TARGET_LIBGCC2_CFLAGS=-DDF=SF -DDI=SI +LIB2FUNCS_EXTRA = fp-bit.c $(srcdir)/config/mn10200/udivmodsi4.c \ + $(srcdir)/config/mn10200/divmod.c $(srcdir)/config/mn10200/udivmod.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + echo '#define FLOAT_ONLY' >> fp-bit.c + echo '#define SMALL_MACHINE' >> fp-bit.c + echo '#define CMPtype HItype' >> fp-bit.c + echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c + echo '#endif' >> fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c diff --git a/gnu/usr.bin/gcc/config/mn10200/udivmod.c b/gnu/usr.bin/gcc/config/mn10200/udivmod.c new file mode 100644 index 00000000000..1395e9cc940 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/udivmod.c @@ -0,0 +1,14 @@ +long udivmodsi4 (); + +long +__udivsi3 (long a, long b) +{ + return udivmodsi4 (a, b, 0); +} + +long +__umodsi3 (long a, long b) +{ + return udivmodsi4 (a, b, 1); +} + diff --git a/gnu/usr.bin/gcc/config/mn10200/udivmodsi4.c b/gnu/usr.bin/gcc/config/mn10200/udivmodsi4.c new file mode 100644 index 00000000000..83c2340c2f8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/udivmodsi4.c @@ -0,0 +1,24 @@ +unsigned long +udivmodsi4(unsigned long num, unsigned long den, int modwanted) +{ + unsigned long bit = 1; + unsigned long res = 0; + + while (den < num && bit && !(den & (1L<<31))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) return num; + return res; +} diff --git a/gnu/usr.bin/gcc/config/mn10200/xm-mn10200.h b/gnu/usr.bin/gcc/config/mn10200/xm-mn10200.h new file mode 100644 index 00000000000..7ebac70ed3f --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10200/xm-mn10200.h @@ -0,0 +1,47 @@ +/* Configuration for Matsushita MN10200. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +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. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 16 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + +#include "tm.h" + +#ifndef __STDC__ +extern char *malloc (), *realloc (), *calloc (); +#else +extern void *malloc (), *realloc (), *calloc (); +#endif +extern void free (); diff --git a/gnu/usr.bin/gcc/config/mn10300/mn10300.c b/gnu/usr.bin/gcc/config/mn10300/mn10300.c new file mode 100644 index 00000000000..f46e4232083 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10300/mn10300.c @@ -0,0 +1,1065 @@ +/* Subroutines for insn-output.c for Matsushita MN10300 series + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Jeff Law (law@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. */ + +#include "config.h" +#include <stdio.h> +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "recog.h" +#include "expr.h" +#include "tree.h" +#include "obstack.h" + +/* Global registers known to hold the value zero. + + Normally we'd depend on CSE and combine to put zero into a + register and re-use it. + + However, on the mn10x00 processors we implicitly use the constant + zero in tst instructions, so we might be able to do better by + loading the value into a register in the prologue, then re-useing + that register throughout the function. + + We could perform similar optimizations for other constants, but with + gcse due soon, it doesn't seem worth the effort. + + These variables hold a rtx for a register known to hold the value + zero throughout the entire function, or NULL if no register of + the appropriate class has such a value throughout the life of the + function. */ +rtx zero_dreg; +rtx zero_areg; + +void +asm_file_start (file) + FILE *file; +{ + fprintf (file, "#\tGCC For the Matsushita MN10300\n"); + if (optimize) + fprintf (file, "# -O%d\n", optimize); + else + fprintf (file, "\n\n"); + output_file_directive (file, main_input_filename); +} + + +/* Print operand X using operand code CODE to assembly language output file + FILE. */ + +void +print_operand (file, x, code) + FILE *file; + rtx x; + int code; +{ + switch (code) + { + case 'b': + case 'B': + /* These are normal and reversed branches. */ + switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x))) + { + case NE: + fprintf (file, "ne"); + break; + case EQ: + fprintf (file, "eq"); + break; + case GE: + fprintf (file, "ge"); + break; + case GT: + fprintf (file, "gt"); + break; + case LE: + fprintf (file, "le"); + break; + case LT: + fprintf (file, "lt"); + break; + case GEU: + fprintf (file, "cc"); + break; + case GTU: + fprintf (file, "hi"); + break; + case LEU: + fprintf (file, "ls"); + break; + case LTU: + fprintf (file, "cs"); + break; + default: + abort (); + } + break; + case 'C': + /* This is used for the operand to a call instruction; + if it's a REG, enclose it in parens, else output + the operand normally. */ + if (GET_CODE (x) == REG) + { + fputc ('(', file); + print_operand (file, x, 0); + fputc (')', file); + } + else + print_operand (file, x, 0); + break; + + /* These are the least significant word in a 64bit value. */ + case 'L': + switch (GET_CODE (x)) + { + case MEM: + fputc ('(', file); + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case REG: + fprintf (file, "%s", reg_names[REGNO (x)]); + break; + + case SUBREG: + fprintf (file, "%s", + reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]); + break; + + case CONST_DOUBLE: + { + long val[2]; + REAL_VALUE_TYPE rv; + + switch (GET_MODE (x)) + { + case DFmode: + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_DOUBLE (rv, val); + print_operand_address (file, GEN_INT (val[0])); + break;; + case SFmode: + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]); + print_operand_address (file, GEN_INT (val[0])); + break;; + case VOIDmode: + case DImode: + print_operand_address (file, + GEN_INT (CONST_DOUBLE_LOW (x))); + break; + } + break; + } + + case CONST_INT: + print_operand_address (file, x); + break; + + default: + abort (); + } + break; + + /* Similarly, but for the most significant word. */ + case 'H': + switch (GET_CODE (x)) + { + case MEM: + fputc ('(', file); + x = adj_offsettable_operand (x, 4); + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case REG: + fprintf (file, "%s", reg_names[REGNO (x) + 1]); + break; + + case SUBREG: + fprintf (file, "%s", + reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1); + break; + + case CONST_DOUBLE: + { + long val[2]; + REAL_VALUE_TYPE rv; + + switch (GET_MODE (x)) + { + case DFmode: + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_DOUBLE (rv, val); + print_operand_address (file, GEN_INT (val[1])); + break;; + case SFmode: + abort (); + case VOIDmode: + case DImode: + print_operand_address (file, + GEN_INT (CONST_DOUBLE_HIGH (x))); + break; + } + break; + } + + case CONST_INT: + if (INTVAL (x) < 0) + print_operand_address (file, GEN_INT (-1)); + else + print_operand_address (file, GEN_INT (0)); + break; + default: + abort (); + } + break; + + case 'A': + fputc ('(', file); + if (GET_CODE (XEXP (x, 0)) == REG) + output_address (gen_rtx (PLUS, SImode, XEXP (x, 0), GEN_INT (0))); + else + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case 'N': + output_address (GEN_INT ((~INTVAL (x)) & 0xff)); + break; + + /* For shift counts. The hardware ignores the upper bits of + any immediate, but the assembler will flag an out of range + shift count as an error. So we mask off the high bits + of the immediate here. */ + case 'S': + if (GET_CODE (x) == CONST_INT) + { + fprintf (file, "%d", INTVAL (x) & 0x1f); + break; + } + /* FALL THROUGH */ + + default: + switch (GET_CODE (x)) + { + case MEM: + fputc ('(', file); + output_address (XEXP (x, 0)); + fputc (')', file); + break; + + case PLUS: + output_address (x); + break; + + case REG: + fprintf (file, "%s", reg_names[REGNO (x)]); + break; + + case SUBREG: + fprintf (file, "%s", + reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]); + break; + + /* This will only be single precision.... */ + case CONST_DOUBLE: + { + unsigned long val; + REAL_VALUE_TYPE rv; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, val); + print_operand_address (file, GEN_INT (val)); + break; + } + + case CONST_INT: + case SYMBOL_REF: + case CONST: + case LABEL_REF: + case CODE_LABEL: + print_operand_address (file, x); + break; + default: + abort (); + } + break; + } +} + +/* Output assembly language output for the address ADDR to FILE. */ + +void +print_operand_address (file, addr) + FILE *file; + rtx addr; +{ + switch (GET_CODE (addr)) + { + case REG: + if (addr == stack_pointer_rtx) + print_operand_address (file, gen_rtx (PLUS, SImode, + stack_pointer_rtx, + GEN_INT (0))); + else + print_operand (file, addr, 0); + break; + case PLUS: + { + rtx base, index; + if (REG_P (XEXP (addr, 0)) + && REG_OK_FOR_BASE_P (XEXP (addr, 0))) + base = XEXP (addr, 0), index = XEXP (addr, 1); + else if (REG_P (XEXP (addr, 1)) + && REG_OK_FOR_BASE_P (XEXP (addr, 1))) + base = XEXP (addr, 1), index = XEXP (addr, 0); + else + abort (); + print_operand (file, index, 0); + fputc (',', file); + print_operand (file, base, 0);; + break; + } + case SYMBOL_REF: + output_addr_const (file, addr); + break; + default: + output_addr_const (file, addr); + break; + } +} + +int +can_use_return_insn () +{ + /* size includes the fixed stack space needed for function calls. */ + int size = get_frame_size () + current_function_outgoing_args_size; + + /* And space for the return pointer. */ + size += current_function_outgoing_args_size ? 4 : 0; + + return (reload_completed + && size == 0 + && !regs_ever_live[2] + && !regs_ever_live[3] + && !regs_ever_live[6] + && !regs_ever_live[7] + && !frame_pointer_needed); +} + +/* Count the number of tst insns which compare a data or address + register with zero. */ +static void +count_tst_insns (dreg_countp, areg_countp) + int *dreg_countp; + int *areg_countp; +{ + rtx insn; + + /* Assume no tst insns exist. */ + *dreg_countp = 0; + *areg_countp = 0; + + /* If not optimizing, then quit now. */ + if (!optimize) + return; + + /* Walk through all the insns. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + rtx pat; + + /* Ignore anything that is not a normal INSN. */ + if (GET_CODE (insn) != INSN) + continue; + + /* Ignore anything that isn't a SET. */ + pat = PATTERN (insn); + if (GET_CODE (pat) != SET) + continue; + + /* Check for a tst insn. */ + if (SET_DEST (pat) == cc0_rtx + && GET_CODE (SET_SRC (pat)) == REG) + { + if (REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == DATA_REGS) + (*dreg_countp)++; + + if (REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS) + (*areg_countp)++; + } + + /* Setting an address register to zero can also be optimized, + so count it just like a tst insn. */ + if (GET_CODE (SET_DEST (pat)) == REG + && GET_CODE (SET_SRC (pat)) == CONST_INT + && INTVAL (SET_SRC (pat)) == 0 + && REGNO_REG_CLASS (REGNO (SET_DEST (pat))) == ADDRESS_REGS) + (*areg_countp)++; + } +} + +void +expand_prologue () +{ + unsigned int size; + + /* We need to end the current sequence so that count_tst_insns can + look at all the insns in this function. Normally this would be + unsafe, but it's OK in the prologue/epilogue expanders. */ + end_sequence (); + + /* Determine if it is profitable to put the value zero into a register + for the entire function. If so, set ZERO_DREG and ZERO_AREG. */ + if (regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7] + || frame_pointer_needed) + { + int dreg_count, areg_count; + + /* Get a count of the number of tst insns which use address and + data registers. */ + count_tst_insns (&dreg_count, &areg_count); + + /* If there's more than one tst insn using a data register, then + this optimization is a win. */ + if (dreg_count > 1 + && (!regs_ever_live[2] || !regs_ever_live[3])) + { + if (!regs_ever_live[2]) + { + regs_ever_live[2] = 1; + zero_dreg = gen_rtx (REG, SImode, 2); + } + else + { + regs_ever_live[3] = 1; + zero_dreg = gen_rtx (REG, SImode, 3); + } + } + else + zero_dreg = NULL_RTX; + + /* If there's more than two tst insns using an address register, + then this optimization is a win. */ + if (areg_count > 2 + && (!regs_ever_live[6] || !regs_ever_live[7])) + { + if (!regs_ever_live[6]) + { + regs_ever_live[6] = 1; + zero_areg = gen_rtx (REG, SImode, 6); + } + else + { + regs_ever_live[7] = 1; + zero_areg = gen_rtx (REG, SImode, 7); + } + } + else + zero_areg = NULL_RTX; + } + else + { + zero_dreg = NULL_RTX; + zero_areg = NULL_RTX; + } + + /* Start a new sequence. */ + start_sequence (); + + /* SIZE includes the fixed stack space needed for function calls. */ + size = get_frame_size () + current_function_outgoing_args_size; + size += (current_function_outgoing_args_size ? 4 : 0); + + /* If this is an old-style varargs function, then its arguments + need to be flushed back to the stack. */ + if (current_function_varargs) + { + emit_move_insn (gen_rtx (MEM, SImode, + gen_rtx (PLUS, Pmode, stack_pointer_rtx, + GEN_INT (4))), + gen_rtx (REG, SImode, 0)); + emit_move_insn (gen_rtx (MEM, SImode, + gen_rtx (PLUS, Pmode, stack_pointer_rtx, + GEN_INT (8))), + gen_rtx (REG, SImode, 1)); + } + + /* And now store all the registers onto the stack with a + single two byte instruction. */ + if (regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7] + || frame_pointer_needed) + emit_insn (gen_store_movm ()); + + /* Now put the frame pointer into the frame pointer register. */ + if (frame_pointer_needed) + emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + + /* Allocate stack for this frame. */ + if (size) + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (-size))); + + /* Load zeros into registers as needed. */ + if (zero_dreg) + emit_move_insn (zero_dreg, const0_rtx); + + if (zero_areg) + emit_move_insn (zero_areg, const0_rtx); +} + +void +expand_epilogue () +{ + unsigned int size; + + /* SIZE includes the fixed stack space needed for function calls. */ + size = get_frame_size () + current_function_outgoing_args_size; + size += (current_function_outgoing_args_size ? 4 : 0); + + /* Maybe cut back the stack, except for the register save area. + + If the frame pointer exists, then use the frame pointer to + cut back the stack. + + If the stack size + register save area is more than 255 bytes, + then the stack must be cut back here since the size + register + save size is too big for a ret/retf instruction. + + Else leave it alone, it will be cut back as part of the + ret/retf instruction, or there wasn't any stack to begin with. + + Under no circumstances should the register save area be + deallocated here, that would leave a window where an interrupt + could occur and trash the register save area. */ + if (frame_pointer_needed) + { + emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); + size = 0; + } + else if ((regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7]) + && size + 16 > 255) + { + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (size))); + size = 0; + } + + /* For simplicity, we just movm all the callee saved registers to + the stack with one instruction. + + ?!? Only save registers which are actually used. Reduces + stack requirements and is faster. */ + if (regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7] + || frame_pointer_needed) + emit_jump_insn (gen_return_internal_regs (GEN_INT (size + 16))); + else + { + if (size) + { + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (size))); + emit_jump_insn (gen_return_internal ()); + } + else + { + emit_jump_insn (gen_return ()); + } + } +} + +/* Update the condition code from the insn. */ + +void +notice_update_cc (body, insn) + rtx body; + rtx insn; +{ + switch (get_attr_cc (insn)) + { + case CC_NONE: + /* Insn does not affect CC at all. */ + break; + + case CC_NONE_0HIT: + /* Insn does not change CC, but the 0'th operand has been changed. */ + if (cc_status.value1 != 0 + && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1)) + cc_status.value1 = 0; + break; + + case CC_SET_ZN: + /* Insn sets the Z,N flags of CC to recog_operand[0]. + V,C are unusable. */ + CC_STATUS_INIT; + cc_status.flags |= CC_NO_CARRY | CC_OVERFLOW_UNUSABLE; + cc_status.value1 = recog_operand[0]; + break; + + case CC_SET_ZNV: + /* Insn sets the Z,N,V flags of CC to recog_operand[0]. + C is unusable. */ + CC_STATUS_INIT; + cc_status.flags |= CC_NO_CARRY; + cc_status.value1 = recog_operand[0]; + break; + + case CC_COMPARE: + /* The insn is a compare instruction. */ + CC_STATUS_INIT; + cc_status.value1 = SET_SRC (body); + break; + + case CC_INVERT: + /* The insn is a compare instruction. */ + CC_STATUS_INIT; + cc_status.value1 = SET_SRC (body); + cc_status.flags |= CC_INVERTED; + break; + + case CC_CLOBBER: + /* Insn doesn't leave CC in a usable state. */ + CC_STATUS_INIT; + break; + + default: + abort (); + } +} + +/* Return true if OP is a valid call operand. */ + +int +call_address_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG); +} + +/* What (if any) secondary registers are needed to move IN with mode + MODE into a register from in register class CLASS. + + We might be able to simplify this. */ +enum reg_class +secondary_reload_class (class, mode, in) + enum reg_class class; + enum machine_mode mode; + rtx in; +{ + int regno; + + /* Memory loads less than a full word wide can't have an + address or stack pointer destination. They must use + a data register as an intermediate register. */ + if (GET_CODE (in) == MEM + && (mode == QImode || mode == HImode) + && (class == ADDRESS_REGS || class == SP_REGS)) + return DATA_REGS; + + /* We can't directly load sp + const_int into a data register; + we must use an address register as an intermediate. */ + if (class != SP_REGS + && class != ADDRESS_REGS + && class != SP_OR_ADDRESS_REGS + && (in == stack_pointer_rtx + || (GET_CODE (in) == PLUS + && (XEXP (in, 0) == stack_pointer_rtx + || XEXP (in, 1) == stack_pointer_rtx)))) + return ADDRESS_REGS; + + if (GET_CODE (in) == PLUS + && (XEXP (in, 0) == stack_pointer_rtx + || XEXP (in, 1) == stack_pointer_rtx)) + return DATA_REGS; + + + /* Otherwise assume no secondary reloads are needed. */ + return NO_REGS; +} + +int +initial_offset (from, to) + int from, to; +{ + /* The difference between the argument pointer and the frame pointer + is the size of the callee register save area. */ + if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) + { + if (regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7] + || frame_pointer_needed) + return 16; + else + return 0; + } + + /* The difference between the argument pointer and the stack pointer is + the sum of the size of this function's frame, the callee register save + area, and the fixed stack space needed for function calls (if any). */ + if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + { + if (regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7] + || frame_pointer_needed) + return (get_frame_size () + 16 + + (current_function_outgoing_args_size + ? current_function_outgoing_args_size + 4 : 0)); + else + return (get_frame_size () + + (current_function_outgoing_args_size + ? current_function_outgoing_args_size + 4 : 0)); + } + + /* The difference between the frame pointer and stack pointer is the sum + of the size of this function's frame and the fixed stack space needed + for function calls (if any). */ + if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + return (get_frame_size () + + (current_function_outgoing_args_size + ? current_function_outgoing_args_size + 4 : 0)); + + abort (); +} + +/* Flush the argument registers to the stack for a stdarg function; + return the new argument pointer. */ +rtx +mn10300_builtin_saveregs (arglist) + tree arglist; +{ + rtx offset; + tree fntype = TREE_TYPE (current_function_decl); + int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0 + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) + != void_type_node))) + ? UNITS_PER_WORD : 0); + + if (argadj) + offset = plus_constant (current_function_arg_offset_rtx, argadj); + else + offset = current_function_arg_offset_rtx; + + emit_move_insn (gen_rtx (MEM, SImode, current_function_internal_arg_pointer), + gen_rtx (REG, SImode, 0)); + emit_move_insn (gen_rtx (MEM, SImode, + plus_constant + (current_function_internal_arg_pointer, 4)), + gen_rtx (REG, SImode, 1)); + return copy_to_reg (expand_binop (Pmode, add_optab, + current_function_internal_arg_pointer, + offset, 0, 0, OPTAB_LIB_WIDEN)); +} + +/* Return an RTX to represent where a value with mode MODE will be returned + from a function. If the result is 0, the argument is pushed. */ + +rtx +function_arg (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + rtx result = 0; + int size, align; + + /* We only support using 2 data registers as argument registers. */ + int nregs = 2; + + /* Figure out the size of the object to be passed. */ + if (mode == BLKmode) + size = int_size_in_bytes (type); + else + size = GET_MODE_SIZE (mode); + + /* Figure out the alignment of the object to be passed. */ + align = size; + + cum->nbytes = (cum->nbytes + 3) & ~3; + + /* Don't pass this arg via a register if all the argument registers + are used up. */ + if (cum->nbytes > nregs * UNITS_PER_WORD) + return 0; + + /* Don't pass this arg via a register if it would be split between + registers and memory. */ + if (type == NULL_TREE + && cum->nbytes + size > nregs * UNITS_PER_WORD) + return 0; + + switch (cum->nbytes / UNITS_PER_WORD) + { + case 0: + result = gen_rtx (REG, mode, 0); + break; + case 1: + result = gen_rtx (REG, mode, 1); + break; + default: + result = 0; + } + + return result; +} + +/* Return the number of registers to use for an argument passed partially + in registers and partially in memory. */ + +int +function_arg_partial_nregs (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + int size, align; + + /* We only support using 2 data registers as argument registers. */ + int nregs = 2; + + /* Figure out the size of the object to be passed. */ + if (mode == BLKmode) + size = int_size_in_bytes (type); + else + size = GET_MODE_SIZE (mode); + + /* Figure out the alignment of the object to be passed. */ + align = size; + + cum->nbytes = (cum->nbytes + 3) & ~3; + + /* Don't pass this arg via a register if all the argument registers + are used up. */ + if (cum->nbytes > nregs * UNITS_PER_WORD) + return 0; + + if (cum->nbytes + size <= nregs * UNITS_PER_WORD) + return 0; + + /* Don't pass this arg via a register if it would be split between + registers and memory. */ + if (type == NULL_TREE + && cum->nbytes + size > nregs * UNITS_PER_WORD) + return 0; + + return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD; +} + +/* Output a tst insn. */ +char * +output_tst (operand, insn) + rtx operand, insn; +{ + rtx temp; + int past_call = 0; + + /* If we have a data register which is known to be zero throughout + the function, then use it instead of doing a search. */ + if (zero_dreg && REGNO_REG_CLASS (REGNO (operand)) == DATA_REGS) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = zero_dreg; + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + + /* Similarly for address registers. */ + if (zero_areg && REGNO_REG_CLASS (REGNO (operand)) == ADDRESS_REGS) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = zero_areg; + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + + /* We can save a byte if we can find a register which has the value + zero in it. */ + temp = PREV_INSN (insn); + while (optimize && temp) + { + rtx set; + + /* We allow the search to go through call insns. We record + the fact that we've past a CALL_INSN and reject matches which + use call clobbered registers. */ + if (GET_CODE (temp) == CODE_LABEL + || GET_CODE (temp) == JUMP_INSN + || GET_CODE (temp) == BARRIER) + break; + + if (GET_CODE (temp) == CALL_INSN) + past_call = 1; + + if (GET_CODE (temp) == NOTE) + { + temp = PREV_INSN (temp); + continue; + } + + /* It must be an insn, see if it is a simple set. */ + set = single_set (temp); + if (!set) + { + temp = PREV_INSN (temp); + continue; + } + + /* Are we setting a data register to zero (this does not win for + address registers)? + + If it's a call clobbered register, have we past a call? + + Make sure the register we find isn't the same as ourself; + the mn10300 can't encode that. */ + if (REG_P (SET_DEST (set)) + && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set))) + && !reg_set_between_p (SET_DEST (set), temp, insn) + && (REGNO_REG_CLASS (REGNO (SET_DEST (set))) + == REGNO_REG_CLASS (REGNO (operand))) + && REGNO (SET_DEST (set)) != REGNO (operand) + && (!past_call + || !call_used_regs[REGNO (SET_DEST (set))])) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = SET_DEST (set); + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + temp = PREV_INSN (temp); + } + return "cmp 0,%0"; +} + +int +impossible_plus_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + extern rtx *reg_equiv_mem; + rtx reg1, reg2; + + if (GET_CODE (op) != PLUS) + return 0; + + if (XEXP (op, 0) == stack_pointer_rtx + || XEXP (op, 1) == stack_pointer_rtx) + return 1; + + return 0; +} + +/* Return 1 if X contains a symbolic expression. We know these + expressions will have one of a few well defined forms, so + we need only check those forms. */ +int +symbolic_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + case LABEL_REF: + return 1; + case CONST: + op = XEXP (op, 0); + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF + || GET_CODE (XEXP (op, 0)) == LABEL_REF) + && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: + return 0; + } +} + +/* Try machine dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + Normally it is always safe for this macro to do nothing. It exists to + recognize opportunities to optimize the output. + + But on a few ports with segmented architectures and indexed addressing + (mn10300, hppa) it is used to rewrite certain problematical addresses. */ +rtx +legitimize_address (x, oldx, mode) + rtx x; + rtx oldx; + enum machine_mode mode; +{ + /* Uh-oh. We might have an address for x[n-100000]. This needs + special handling to avoid creating an indexed memory address + with x-100000 as the base. */ + if (GET_CODE (x) == PLUS + && symbolic_operand (XEXP (x, 1), VOIDmode)) + { + /* Ugly. We modify things here so that the address offset specified + by the index expression is computed first, then added to x to form + the entire address. */ + + rtx regx1, regx2, regy1, regy2, y; + + /* Strip off any CONST. */ + y = XEXP (x, 1); + if (GET_CODE (y) == CONST) + y = XEXP (y, 0); + + if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS) + { + regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0)); + regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0)); + regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0)); + regx1 = force_reg (Pmode, + gen_rtx (GET_CODE (y), Pmode, regx1, regy2)); + return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1)); + } + } + return x; +} diff --git a/gnu/usr.bin/gcc/config/mn10300/mn10300.h b/gnu/usr.bin/gcc/config/mn10300/mn10300.h new file mode 100644 index 00000000000..9ebcec147c1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10300/mn10300.h @@ -0,0 +1,1016 @@ +/* Definitions of target machine for GNU compiler. Matsushita MN10300 series + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Jeff Law (law@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. */ + +#include "svr4.h" + +#undef ASM_SPEC +#undef ASM_FINAL_SPEC +#undef LIB_SPEC +#undef ENDFILE_SPEC +#undef LINK_SPEC +#undef STARTFILE_SPEC + +/* Names to predefine in the preprocessor for this target machine. */ + +#define CPP_PREDEFINES "-D__mn10300__ -D__MN10300__" + +/* Run-time compilation parameters selecting different hardware subsets. */ + +extern int target_flags; + +/* Global registers known to hold the value zero. */ +extern struct rtx_def *zero_dreg; +extern struct rtx_def *zero_areg; + +/* Macros used in the machine description to test the flags. */ + +/* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +/* Generate code to work around mul/mulq bugs on the mn10300. */ +#define TARGET_MULT_BUG (target_flags & 0x1) +#define TARGET_SWITCHES \ + {{ "mult-bug", 0x1}, \ + { "no-mult-bug", -0x1}, \ + { "", TARGET_DEFAULT}} + +#ifndef TARGET_DEFAULT +#define TARGET_DEFAULT 0x1 +#endif + +/* Print subsidiary information on the compiler version in use. */ + +#define TARGET_VERSION fprintf (stderr, " (MN10300)"); + + +/* Target machine storage layout */ + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. + This is not true on the Matsushita MN1003. */ +#define BITS_BIG_ENDIAN 0 + +/* Define this if most significant byte of a word is the lowest numbered. */ +/* This is not true on the Matsushita MN10300. */ +#define BYTES_BIG_ENDIAN 0 + +/* Define this if most significant word of a multiword number is lowest + numbered. + This is not true on the Matsushita MN10300. */ +#define WORDS_BIG_ENDIAN 0 + +/* Number of bits in an addressable storage unit */ +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ +#define BITS_PER_WORD 32 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD 4 + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ +#define POINTER_SIZE 32 + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY 32 + +/* The stack goes in 32 bit lumps. */ +#define STACK_BOUNDARY 32 + +/* Allocation boundary (in *bits*) for the code of a function. + 8 is the minimum boundary; it's unclear if bigger alignments + would improve performance. */ +#define FUNCTION_BOUNDARY 8 + +/* No data type wants to be aligned rounder than this. */ +#define BIGGEST_ALIGNMENT 32 + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY 32 + +/* Define this if move instructions will actually fail to work + when given unaligned data. */ +#define STRICT_ALIGNMENT 1 + +/* Define this as 1 if `char' should by default be signed; else as 0. */ +#define DEFAULT_SIGNED_CHAR 0 + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ + +#define FIRST_PSEUDO_REGISTER 10 + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. */ + +#define FIXED_REGISTERS \ + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1} + +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you + like. */ + +#define CALL_USED_REGISTERS \ + { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1} + +#define REG_ALLOC_ORDER \ + { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9} + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. */ + +#define HARD_REGNO_NREGS(REGNO, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode + MODE. */ + +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + (REGNO_REG_CLASS (REGNO) == DATA_REGS \ + ? ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) <= 4 \ + : ((REGNO) & 1) == 0 || GET_MODE_SIZE (MODE) == 4) + +/* Value is 1 if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ +#define MODES_TIEABLE_P(MODE1, MODE2) \ + (MODE1 == MODE2 || GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4) + +/* 4 data, and effectively 3 address registers is small as far as I'm + concerned. */ +#define SMALL_REGISTER_CLASSES 1 + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + +enum reg_class { + NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ + +#define REG_CLASS_NAMES \ +{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \ + "SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS", \ + "GENERAL_REGS", "ALL_REGS", "LIM_REGS" } + +/* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS \ +{ 0, /* No regs */ \ + 0x00f, /* DATA_REGS */ \ + 0x1f0, /* ADDRESS_REGS */ \ + 0x200, /* SP_REGS */ \ + 0x1ff, /* DATA_OR_ADDRESS_REGS */\ + 0x1f0, /* SP_OR_ADDRESS_REGS */\ + 0x1ff, /* GENERAL_REGS */ \ + 0x3ff, /* ALL_REGS */ \ +} + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) < 4 ? DATA_REGS : \ + (REGNO) < 9 ? ADDRESS_REGS : \ + (REGNO) == 9 ? SP_REGS: 0) + +/* The class value for index registers, and the one for base regs. */ + +#define INDEX_REG_CLASS DATA_REGS +#define BASE_REG_CLASS SP_OR_ADDRESS_REGS + +/* Get reg_class from a letter such as appears in the machine description. */ + +#define REG_CLASS_FROM_LETTER(C) \ + ((C) == 'd' ? DATA_REGS : \ + (C) == 'a' ? ADDRESS_REGS : \ + (C) == 'x' ? SP_REGS : NO_REGS) + +/* Macros to check register numbers against specific register classes. */ + +/* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ + +#define REGNO_OK_FOR_BASE_P(regno) \ + (((regno) > 3 && regno < FIRST_PSEUDO_REGISTER) \ + || (reg_renumber[regno] > 3 && reg_renumber[regno] < FIRST_PSEUDO_REGISTER)) + +#define REGNO_OK_FOR_INDEX_P(regno) \ + (((regno) >= 0 && regno < 4) \ + || (reg_renumber[regno] >= 0 && reg_renumber[regno] < 4)) + + +/* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. */ + +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ + (X == stack_pointer_rtx && CLASS != SP_REGS ? ADDRESS_REGS : CLASS) + +#define PREFERRED_OUTPUT_RELOAD_CLASS(X,CLASS) \ + (X == stack_pointer_rtx && CLASS != SP_REGS ? ADDRESS_REGS : CLASS) + +#define LIMIT_RELOAD_CLASS(MODE, CLASS) \ + ((MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS) + +#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \ + secondary_reload_class(CLASS,MODE,IN) + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ + +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* The letters I, J, K, L, M, N, O, P in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ + +#define INT_8_BITS(VALUE) ((unsigned) (VALUE) + 0x80 < 0x100) +#define INT_16_BITS(VALUE) ((unsigned) (VALUE) + 0x8000 < 0x10000) + +#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0) +#define CONST_OK_FOR_J(VALUE) ((VALUE) == 1) +#define CONST_OK_FOR_K(VALUE) ((VALUE) == 2) +#define CONST_OK_FOR_L(VALUE) ((VALUE) == 4) +#define CONST_OK_FOR_M(VALUE) ((VALUE) == 3) +#define CONST_OK_FOR_N(VALUE) ((VALUE) == 255 || (VALUE) == 65535) + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \ + (C) == 'J' ? CONST_OK_FOR_J (VALUE) : \ + (C) == 'K' ? CONST_OK_FOR_K (VALUE) : \ + (C) == 'L' ? CONST_OK_FOR_L (VALUE) : \ + (C) == 'M' ? CONST_OK_FOR_M (VALUE) : \ + (C) == 'N' ? CONST_OK_FOR_N (VALUE) : 0) + + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. + + `G' is a floating-point zero. */ + +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ + && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) : 0) + + +/* Stack layout; function entry, exit and calling. */ + +/* Define this if pushing a word on the stack + makes the stack pointer a smaller address. */ + +#define STACK_GROWS_DOWNWARD + +/* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ + +#define FRAME_GROWS_DOWNWARD + +/* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ + +#define STARTING_FRAME_OFFSET 0 + +/* Offset of first parameter from the argument pointer register value. */ +/* Is equal to the size of the saved fp + pc, even if an fp isn't + saved since the value is used before we know. */ + +#define FIRST_PARM_OFFSET(FNDECL) 4 + +/* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 9 + +/* Base register for access to local variables of the function. */ +#define FRAME_POINTER_REGNUM 7 + +/* Base register for access to arguments of the function. This + is a fake register and will be eliminated into either the frame + pointer or stack pointer. */ +#define ARG_POINTER_REGNUM 8 + +/* Register in which static-chain is passed to a function. */ +#define STATIC_CHAIN_REGNUM 5 + +#define ELIMINABLE_REGS \ +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} + +#define CAN_ELIMINATE(FROM, TO) 1 + +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + OFFSET = initial_offset (FROM, TO) + +/* We can debug without frame pointers on the mn10300, so eliminate + them whenever possible. */ +#define FRAME_POINTER_REQUIRED 0 +#define CAN_DEBUG_WITHOUT_FP + +/* A guess for the MN10300. */ +#define PROMOTE_PROTOTYPES 1 + +/* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + SIZE is the number of bytes of arguments passed on the stack. */ + +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 + +/* We use d0/d1 for passing parameters, so allocate 8 bytes of space + for a register flushback area. */ +#define REG_PARM_STACK_SPACE(DECL) 8 +#define OUTGOING_REG_PARM_STACK_SPACE +#define ACCUMULATE_OUTGOING_ARGS + +/* So we can allocate space for return pointers once for the function + instead of around every call. */ +#define STACK_POINTER_OFFSET 4 + +/* 1 if N is a possible register number for function argument passing. + On the MN10300, no registers are used in this way. */ + +#define FUNCTION_ARG_REGNO_P(N) ((N) <= 1) + + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. + + On the MN10300, this is a single integer, which is a number of bytes + of arguments scanned so far. */ + +#define CUMULATIVE_ARGS struct cum_arg +struct cum_arg {int nbytes; }; + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. + + On the MN10300, the offset starts at 0. */ + +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ + ((CUM).nbytes = 0) + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM).nbytes += ((MODE) != BLKmode \ + ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ + : (int_size_in_bytes (TYPE) + 3) & ~3)) + +/* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + +/* On the MN10300 all args are pushed. */ + +extern struct rtx_def *function_arg (); +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ + function_arg (&CUM, MODE, TYPE, NAMED) + +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ + function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED) + + +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ + ((TYPE) && int_size_in_bytes (TYPE) > 8) + +#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ + ((TYPE) && int_size_in_bytes (TYPE) > 8) + +/* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), POINTER_TYPE_P (VALTYPE) ? 4 : 0) + +/* Define how to find the value returned by a library function + assuming the value has mode MODE. */ + +#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + +/* 1 if N is a possible register number for a function value. */ + +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 4) + +/* Return values > 8 bytes in length in memory. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 +#define RETURN_IN_MEMORY(TYPE) \ + (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode) + +/* Register in which address to store a structure value + is passed to a function. On the MN10300 it's passed as + the first parameter. */ + +#define STRUCT_VALUE 0 + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ + +#define EXIT_IGNORE_STACK 1 + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + +#define FUNCTION_PROFILER(FILE, LABELNO) ; + +#define TRAMPOLINE_TEMPLATE(FILE) \ + do { \ + fprintf (FILE, "\tadd -4,sp\n"); \ + fprintf (FILE, "\t.long 0x0004fffa\n"); \ + fprintf (FILE, "\tmov (0,sp),a0\n"); \ + fprintf (FILE, "\tadd 4,sp\n"); \ + fprintf (FILE, "\tmov (13,a0),a1\n"); \ + fprintf (FILE, "\tmov (17,a0),a0\n"); \ + fprintf (FILE, "\tjmp (a0)\n"); \ + fprintf (FILE, "\t.long 0\n"); \ + fprintf (FILE, "\t.long 0\n"); \ + } while (0) + +/* Length in units of the trampoline for entering a nested function. */ + +#define TRAMPOLINE_SIZE 0x1b + +#define TRAMPOLINE_ALIGNMENT 32 + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ + +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +{ \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 0x14)), \ + (CXT)); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 0x18)), \ + (FNADDR)); \ +} +/* A C expression whose value is RTL representing the value of the return + address for the frame COUNT steps up from the current frame. + + On the mn10300, the return address is not at a constant location + due to the frame layout. Luckily, it is at a constant offset from + the argument pointer, so we define RETURN_ADDR_RTX to return a + MEM using arg_pointer_rtx. Reload will replace arg_pointer_rtx + with a reference to the stack/frame pointer + an appropriate offset. */ + +#define RETURN_ADDR_RTX(COUNT, FRAME) \ + ((COUNT == 0) \ + ? gen_rtx (MEM, Pmode, arg_pointer_rtx) \ + : (rtx) 0) + +/* Emit code for a call to builtin_saveregs. We must emit USE insns which + reference the 2 integer arg registers. + Ordinarily they are not call used registers, but they are for + _builtin_saveregs, so we must make this explicit. */ + +extern struct rtx_def *mn10300_builtin_saveregs (); +#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) mn10300_builtin_saveregs (ARGLIST) + +/* Addressing modes, and classification of registers for them. */ + + +/* 1 if X is an rtx for a constant that is a valid address. */ + +#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) + +/* Extra constraints. */ + +#define OK_FOR_R(OP) \ + (GET_CODE (OP) == MEM \ + && GET_MODE (OP) == QImode \ + && (CONSTANT_ADDRESS_P (XEXP (OP, 0)) \ + || (GET_CODE (XEXP (OP, 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (OP, 0)) \ + && XEXP (OP, 0) != stack_pointer_rtx) \ + || (GET_CODE (XEXP (OP, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (XEXP (OP, 0), 0)) \ + && XEXP (XEXP (OP, 0), 0) != stack_pointer_rtx \ + && GET_CODE (XEXP (XEXP (OP, 0), 1)) == CONST_INT \ + && INT_8_BITS (INTVAL (XEXP (XEXP (OP, 0), 1)))))) + +#define EXTRA_CONSTRAINT(OP, C) \ + ((C) == 'R' ? OK_FOR_R (OP) : (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF : 0) + +/* Maximum number of registers that can appear in a valid memory address. */ + +#define MAX_REGS_PER_ADDRESS 2 + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + +#ifndef REG_OK_STRICT +/* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ +#define REG_OK_FOR_INDEX_P(X) \ + ((REGNO (X) >= 0 && REGNO(X) <= 3) || REGNO (X) >= FIRST_PSEUDO_REGISTER) +/* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ +#define REG_OK_FOR_BASE_P(X) \ + ((REGNO (X) >= 4 && REGNO(X) <= 9) || REGNO (X) >= FIRST_PSEUDO_REGISTER) +#else +/* Nonzero if X is a hard reg that can be used as an index. */ +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) +/* Nonzero if X is a hard reg that can be used as a base reg. */ +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#endif + + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS, + except for CONSTANT_ADDRESS_P which is actually + machine-independent. + + On the mn10300, the value in the address register must be + in the same memory space/segment as the effective address. + + This is problematical for reload since it does not understand + that base+index != index+base in a memory reference. + + Note it is still possible to use reg+reg addressing modes, + it's just much more difficult. For a discussion of a possible + workaround and solution, see the comments in pa.c before the + function record_unscaled_index_insn_codes. */ + +/* Accept either REG or SUBREG where a register is valid. */ + +#define RTX_OK_FOR_BASE_P(X) \ + ((REG_P (X) && REG_OK_FOR_BASE_P (X)) \ + || (GET_CODE (X) == SUBREG && REG_P (SUBREG_REG (X)) \ + && REG_OK_FOR_BASE_P (SUBREG_REG (X)))) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ \ + if (CONSTANT_ADDRESS_P (X)) \ + goto ADDR; \ + if (RTX_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (GET_CODE (X) == PLUS) \ + { \ + rtx base = 0, index = 0; \ + if (REG_P (XEXP (X, 0)) \ + && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ + base = XEXP (X, 0), index = XEXP (X, 1); \ + if (REG_P (XEXP (X, 1)) \ + && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ + base = XEXP (X, 1), index = XEXP (X, 0); \ + if (base != 0 && index != 0) \ + { \ + if (GET_CODE (index) == CONST_INT) \ + goto ADDR; \ + } \ + } \ +} + + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. */ + +extern struct rtx_def *legitimize_address (); +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ +{ rtx orig_x = (X); \ + (X) = legitimize_address (X, OLDX, MODE); \ + if ((X) != orig_x && memory_address_p (MODE, X)) \ + goto WIN; } + +/* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. */ + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} + +/* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + +#define LEGITIMATE_CONSTANT_P(X) 1 + + +/* Tell final.c how to eliminate redundant test instructions. */ + +/* Here we define machine-dependent flags and fields in cc_status + (see `conditions.h'). No extra ones are needed for the vax. */ + +/* Store in cc_status the expressions + that the condition codes will describe + after execution of an instruction whose pattern is EXP. + Do not alter them if the instruction would not alter the cc's. */ + +#define CC_OVERFLOW_UNUSABLE 0x200 +#define CC_NO_CARRY CC_NO_OVERFLOW +#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN) + +/* Compute the cost of computing a constant rtl expression RTX + whose rtx-code is CODE. The body of this macro is a portion + of a switch statement. If the code is computed here, + return it with a return statement. Otherwise, break from the switch. */ + +#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ + case CONST_INT: \ + /* Zeros are extremely cheap. */ \ + if (INTVAL (RTX) == 0 && OUTER_CODE == SET) \ + return 0; \ + /* If it fits in 8 bits, then it's still relatively cheap. */ \ + if (INT_8_BITS (INTVAL (RTX))) \ + return 1; \ + /* This is the "base" cost, includes constants where either the \ + upper or lower 16bits are all zeros. */ \ + if (INT_16_BITS (INTVAL (RTX)) \ + || (INTVAL (RTX) & 0xffff) == 0 \ + || (INTVAL (RTX) & 0xffff0000) == 0) \ + return 2; \ + return 4; \ + /* These are more costly than a CONST_INT, but we can relax them, \ + so they're less costly than a CONST_DOUBLE. */ \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 6; \ + /* We don't optimize CONST_DOUBLEs well nor do we relax them well, \ + so their cost is very high. */ \ + case CONST_DOUBLE: \ + return 8; + + +#define REGISTER_MOVE_COST(CLASS1, CLASS2) (CLASS1 != CLASS2 ? 4 : 2) + +/* A crude cut at RTX_COSTS for the MN10300. */ + +/* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. */ +#define RTX_COSTS(RTX,CODE,OUTER_CODE) \ + case MOD: \ + case DIV: \ + return 8; \ + case MULT: \ + return 8; + +/* Nonzero if access to memory by bytes or half words is no faster + than accessing full words. */ +#define SLOW_BYTE_ACCESS 1 + +/* Dispatch tables on the mn10300 are extremely expensive in terms of code + and readonly data size. So we crank up the case threshold value to + encourage a series of if/else comparisons to implement many small switch + statements. In theory, this value could be increased much more if we + were solely optimizing for space, but we keep it "reasonable" to avoid + serious code efficiency lossage. */ +#define CASE_VALUES_THRESHOLD 6 + +#define NO_FUNCTION_CSE + +/* According expr.c, a value of around 6 should minimize code size, and + for the MN10300 series, that's our primary concern. */ +#define MOVE_RATIO 6 + +#define TEXT_SECTION_ASM_OP "\t.section .text" +#define DATA_SECTION_ASM_OP "\t.section .data" +#define BSS_SECTION_ASM_OP "\t.section .bss" + +/* Output at beginning/end of assembler file. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) asm_file_start(FILE) + +#define ASM_COMMENT_START "#" + +/* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ + +#define ASM_APP_ON "#APP\n" + +/* Output to assembler file text saying following lines + no longer contain unusual constructs. */ + +#define ASM_APP_OFF "#NO_APP\n" + +/* This is how to output an assembler line defining a `double' constant. + It is .dfloat or .gfloat, depending. */ + +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf (FILE, "\t.double %s\n", dstr); \ + } while (0) + + +/* This is how to output an assembler line defining a `float' constant. */ +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf (FILE, "\t.float %s\n", dstr); \ + } while (0) + +/* This is how to output an assembler line defining an `int' constant. */ + +#define ASM_OUTPUT_INT(FILE, VALUE) \ +( fprintf (FILE, "\t.long "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* Likewise for `char' and `short' constants. */ + +#define ASM_OUTPUT_SHORT(FILE, VALUE) \ +( fprintf (FILE, "\t.hword "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +#define ASM_OUTPUT_CHAR(FILE, VALUE) \ +( fprintf (FILE, "\t.byte "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line for a numeric constant byte. */ +#define ASM_OUTPUT_BYTE(FILE, VALUE) \ + fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) + +/* Define the parentheses used to group arithmetic operations + in assembler code. */ + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* This says how to output the assembler to define a global + uninitialized but not common symbol. + Try to use asm_output_bss to implement this macro. */ + +#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \ + asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)) + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ + +#define ASM_OUTPUT_LABEL(FILE, NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + +/* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ + +#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ + do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + +/* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. */ + +#undef ASM_OUTPUT_LABELREF +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ + do { \ + char* real_name; \ + STRIP_NAME_ENCODING (real_name, (NAME)); \ + fprintf (FILE, "_%s", real_name); \ + } while (0) + +/* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) + +/* This is how we tell the assembler that two symbols have the same value. */ + +#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \ + do { assemble_name(FILE, NAME1); \ + fputs(" = ", FILE); \ + assemble_name(FILE, NAME2); \ + fputc('\n', FILE); } while (0) + + +/* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ + +#define REGISTER_NAMES \ +{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp" } + +/* Print an instruction operand X on file FILE. + look in mn10300.c for details */ + +#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE) + +/* Print a memory operand whose address is X, on file FILE. + This uses a function in output-vax.c. */ + +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) + +#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) +#define ASM_OUTPUT_REG_POP(FILE,REGNO) + +/* This is how to output an element of a case-vector that is absolute. */ + +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + asm_fprintf (FILE, "\t%s .L%d\n", ".long", VALUE) + +/* This is how to output an element of a case-vector that is relative. */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL) + +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG) != 0) \ + fprintf (FILE, "\t.align %d\n", (LOG)) + +/* We don't have to worry about dbx compatibility for the mn10300. */ +#define DEFAULT_GDB_EXTENSIONS 1 + +/* Use stabs debugging info by default. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#define DBX_REGISTER_NUMBER(REGNO) REGNO + +/* Define to use software floating point emulator for REAL_ARITHMETIC and + decimal <-> binary conversion. */ +#define REAL_ARITHMETIC + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE Pmode + +/* Define this if the case instruction drops through after the table + when the index is out of range. Don't define it if the case insn + jumps to the default label instead. */ +#define CASE_DROPS_THROUGH + +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS + +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Specify the tree operation to be used to convert reals to integers. */ +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* This flag, if defined, says the same insns that convert to a signed fixnum + also convert validly to an unsigned one. */ +#define FIXUNS_TRUNC_LIKE_FIX_TRUNC + +/* This is the kind of divide that is easiest to do in the general case. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ +#define MOVE_MAX 4 + +/* Define if shifts truncate the shift count + which implies one can omit a sign-extension or zero-extension + of a shift count. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +#define Pmode SImode + +/* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ +#define FUNCTION_MODE QImode + +/* The assembler op to get a word. */ + +#define FILE_ASM_OP "\t.file\n" + +extern void asm_file_start (); +extern int const_costs (); +extern void print_operand (); +extern void print_operand_address (); +extern void expand_prologue (); +extern void expand_epilogue (); +extern void notice_update_cc (); +extern int call_address_operand (); +extern int impossible_plus_operand (); +extern enum reg_class secondary_reload_class (); +extern int initial_offset (); +extern char *output_tst (); +int symbolic_operand (); diff --git a/gnu/usr.bin/gcc/config/mn10300/mn10300.md b/gnu/usr.bin/gcc/config/mn10300/mn10300.md new file mode 100644 index 00000000000..2ff8a8162ea --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10300/mn10300.md @@ -0,0 +1,1415 @@ +;; GCC machine description for Matsushita MN10300 +;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +;; Contributed by Jeff Law (law@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. + +;; The original PO technology requires these to be ordered by speed, +;; so that assigner will pick the fastest. + +;; See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; Condition code settings. +;; none - insn does not affect cc +;; none_0hit - insn does not affect cc but it does modify operand 0 +;; This attribute is used to keep track of when operand 0 changes. +;; See the description of NOTICE_UPDATE_CC for more info. +;; set_znv - insn sets z,n,v to usable values; c is unusable. +;; set_zn - insn sets z,n to usable values; v,c are unusable. +;; compare - compare instruction +;; invert -- like compare, but flags are inverted. +;; clobber - value of cc is unknown +(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber,invert" + (const_string "clobber")) + +;; ---------------------------------------------------------------------- +;; MOVE INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; movqi + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand0, QImode) + && !register_operand (operand1, QImode)) + operands[1] = copy_to_mode_reg (QImode, operand1); +}") + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=d,*a,d,*a,d,*a,d,*a,d,m") + (match_operand:QI 1 "general_operand" "0,0,I,I,a,d,di,ia,m,d"))] + "register_operand (operands[0], QImode) + || register_operand (operands[1], QImode)" + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + case 6: + case 7: + return \"mov %1,%0\"; + case 8: + case 9: + return \"movbu %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +;; movhi + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, HImode) + && !register_operand (operand0, HImode)) + operands[1] = copy_to_mode_reg (HImode, operand1); +}") + +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=d,*a,d,*a,d,*a,d,*a,d,m") + (match_operand:HI 1 "general_operand" "0,0,I,I,a,d,di,ia,m,d"))] + "register_operand (operands[0], HImode) + || register_operand (operands[1], HImode)" + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + case 6: + case 7: + return \"mov %1,%0\"; + case 8: + case 9: + return \"movhu %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +;; movsi and helpers + +;; We use this to handle addition of two values when one operand is the +;; stack pointer and the other is a memory reference of some kind. Reload +;; does not handle them correctly without this expander. +(define_expand "reload_insi" + [(set (match_operand:SI 0 "register_operand" "=a") + (match_operand:SI 1 "impossible_plus_operand" "")) + (clobber (match_operand:SI 2 "register_operand" "=&r"))] + "" + " +{ + if (XEXP (operands[1], 0) == stack_pointer_rtx) + { + emit_move_insn (operands[0], XEXP (operands[1], 0)); + if (GET_CODE (XEXP (operands[1], 1)) == SUBREG + && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 1))) + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 1)))))) + emit_move_insn (operands[2], + gen_rtx (ZERO_EXTEND, GET_MODE (XEXP (operands[1], 1)), + SUBREG_REG (XEXP (operands[1], 1)))); + else + emit_move_insn (operands[2], XEXP (operands[1], 1)); + } + else + { + emit_move_insn (operands[0], XEXP (operands[1], 1)); + if (GET_CODE (XEXP (operands[1], 0)) == SUBREG + && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 0))) + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 0)))))) + emit_move_insn (operands[2], + gen_rtx (ZERO_EXTEND, GET_MODE (XEXP (operands[1], 0)), + SUBREG_REG (XEXP (operands[1], 0)))); + else + emit_move_insn (operands[2], XEXP (operands[1], 0)); + } + emit_insn (gen_addsi3 (operands[0], operands[0], operands[2])); + DONE; +}") + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, SImode) + && !register_operand (operand0, SImode)) + operands[1] = copy_to_mode_reg (SImode, operand1); +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" + "=d,a,d,a,dm,dm,am,am,d,d,a,a,aR,x") + (match_operand:SI 1 "general_operand" + "0,0,I,I,d,a,d,a,dim,aim,dim,aim,x,aR"))] + "register_operand (operands[0], SImode) + || register_operand (operands[1], SImode)" + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + return \"mov %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, SFmode) + && !register_operand (operand0, SFmode)) + operands[1] = copy_to_mode_reg (SFmode, operand1); +}") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=d,a,d,a,dam,da") + (match_operand:SF 1 "general_operand" "0,0,G,G,da,daim"))] + "register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode)" + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + return \"mov %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit")]) + +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, DImode) + && !register_operand (operand0, DImode)) + operands[1] = copy_to_mode_reg (DImode, operand1); +}") + +(define_insn "" + [(set (match_operand:DI 0 "general_operand" + "=d,a,d,a,dm,dm,am,am,d,d,a,a") + (match_operand:DI 1 "general_operand" + "0,0,I,I,d,a,d,a,dim,aim,dim,aim"))] + "register_operand (operands[0], DImode) + || register_operand (operands[1], DImode)" + "* +{ + long val[2]; + REAL_VALUE_TYPE rv; + + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + + case 2: + return \"clr %L0\;clr %H0\"; + + case 3: + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg ? zero_areg : operands[1]; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L1,%L0\;mov %L0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\;mov %L0,%H0\", xoperands); + return \"\"; + } + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + if (GET_CODE (operands[1]) == CONST_INT) + { + val[0] = INTVAL (operands[1]); + val[1] = val[0] < 0 ? -1 : 0; + } + if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + if (GET_MODE (operands[1]) == DFmode) + { + REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); + REAL_VALUE_TO_TARGET_DOUBLE (rv, val); + } + else if (GET_MODE (operands[1]) == VOIDmode + || GET_MODE (operands[1]) == DImode) + { + val[0] = CONST_DOUBLE_LOW (operands[1]); + val[1] = CONST_DOUBLE_HIGH (operands[1]); + } + } + + if (GET_CODE (operands[1]) == MEM + && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) + { + rtx temp = operands[0]; + + while (GET_CODE (temp) == SUBREG) + temp = SUBREG_REG (temp); + + if (GET_CODE (temp) != REG) + abort (); + + if (reg_overlap_mentioned_p (gen_rtx (REG, SImode, REGNO (temp)), + XEXP (operands[1], 0))) + return \"mov %H1,%H0\;mov %L1,%L0\"; + else + return \"mov %L1,%L0\;mov %H1,%H0\"; + + } + else if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) + && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = XEXP (operands[1], 0); + + output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\", + xoperands); + return \"\"; + } + else + { + if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[0] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %L0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L0,%L0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\", xoperands); + } + else + output_asm_insn (\"mov %L1,%L0\", operands); + } + else + output_asm_insn (\"mov %L1,%L0\", operands); + + if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[1] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %H0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %H0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%H0\", xoperands); + } + else + output_asm_insn (\"mov %H1,%H0\", operands); + } + else if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[0] == val[1]) + output_asm_insn (\"mov %L0,%H0\", operands); + else + output_asm_insn (\"mov %H1,%H0\", operands); + return \"\"; + } + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register */ + if (!register_operand (operand1, DFmode) + && !register_operand (operand0, DFmode)) + operands[1] = copy_to_mode_reg (DFmode, operand1); +}") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" + "=d,a,d,a,dm,dm,am,am,d,d,a,a") + (match_operand:DF 1 "general_operand" + "0,0,G,G,d,a,d,a,dim,aim,dim,aim"))] + "register_operand (operands[0], DFmode) + || register_operand (operands[1], DFmode)" + "* +{ + long val[2]; + REAL_VALUE_TYPE rv; + + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + + case 2: + return \"clr %L0\;clr %H0\"; + + case 3: + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg ? zero_areg : operands[1]; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L1,%L0\;mov %L0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\;mov %L0,%H0\", xoperands); + return \"\"; + } + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + if (GET_CODE (operands[1]) == CONST_INT) + { + val[0] = INTVAL (operands[1]); + val[1] = val[0] < 0 ? -1 : 0; + } + if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + if (GET_MODE (operands[1]) == DFmode) + { + REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); + REAL_VALUE_TO_TARGET_DOUBLE (rv, val); + } + else if (GET_MODE (operands[1]) == VOIDmode + || GET_MODE (operands[1]) == DImode) + { + val[0] = CONST_DOUBLE_LOW (operands[1]); + val[1] = CONST_DOUBLE_HIGH (operands[1]); + } + } + + if (GET_CODE (operands[1]) == MEM + && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) + { + rtx temp = operands[0]; + + while (GET_CODE (temp) == SUBREG) + temp = SUBREG_REG (temp); + + if (GET_CODE (temp) != REG) + abort (); + + if (reg_overlap_mentioned_p (gen_rtx (REG, SImode, REGNO (temp)), + XEXP (operands[1], 0))) + return \"mov %H1,%H0\;mov %L1,%L0\"; + else + return \"mov %L1,%L0\;mov %H1,%H0\"; + + } + else if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) + && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = XEXP (operands[1], 0); + + output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\", + xoperands); + return \"\"; + } + else + { + if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[0] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %L0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L0,%L0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\", xoperands); + } + else + output_asm_insn (\"mov %L1,%L0\", operands); + } + else + output_asm_insn (\"mov %L1,%L0\", operands); + + if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[1] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %H0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %H0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%H0\", xoperands); + } + else + output_asm_insn (\"mov %H1,%H0\", operands); + } + else if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[0] == val[1]) + output_asm_insn (\"mov %L0,%H0\", operands); + else + output_asm_insn (\"mov %H1,%H0\", operands); + return \"\"; + } + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + + + +;; ---------------------------------------------------------------------- +;; TEST INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Go ahead and define tstsi so we can eliminate redundant tst insns +;; when we start trying to optimize this port. +(define_insn "tstsi" + [(set (cc0) (match_operand:SI 0 "register_operand" "da"))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "d")))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "d")))] + "" + "* return output_tst (operands[0], insn);" + [(set_attr "cc" "set_znv")]) + + +(define_insn "cmpsi" + [(set (cc0) + (compare (match_operand:SI 0 "register_operand" "!*d*a,da") + (match_operand:SI 1 "nonmemory_operand" "!*0,dai")))] + "" + "@ + add 0,%0 + cmp %1,%0" + [(set_attr "cc" "invert,compare")]) + +;; ---------------------------------------------------------------------- +;; ADD INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "addsi3" + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")))] + "" + " +{ + /* We can't add a variable amount directly to the stack pointer; + so do so via a temporary register. */ + if (operands[0] == stack_pointer_rtx + && GET_CODE (operands[1]) != CONST_INT + && GET_CODE (operands[2]) != CONST_INT) + { + rtx temp = gen_reg_rtx (SImode); + emit_move_insn (temp, gen_rtx (PLUS, SImode, operands[1], operands[2])); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d,a,a,da,x,&!da") + (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,da") + (match_operand:SI 2 "nonmemory_operand" "J,J,L,dai,i,da")))] + "" + "@ + inc %0 + inc %0 + inc4 %0 + add %2,%0 + add %2,%0 + mov %2,%0\;add %1,%0" + [(set_attr "cc" "set_zn,none_0hit,none_0hit,set_zn,none_0hit,set_zn")]) + +;; ---------------------------------------------------------------------- +;; SUBTRACT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=da") + (minus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "nonmemory_operand" "dai")))] + "" + "sub %2,%0" + [(set_attr "cc" "set_zn")]) + +(define_expand "negsi2" + [(set (match_operand:SI 0 "register_operand" "") + (neg:SI (match_operand:SI 1 "register_operand" "")))] + "" + " +{ + rtx target = gen_reg_rtx (SImode); + + emit_move_insn (target, GEN_INT (0)); + emit_insn (gen_subsi3 (target, target, operands[1])); + emit_move_insn (operands[0], target); + DONE; +}") + +;; ---------------------------------------------------------------------- +;; MULTIPLY INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (mult:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "register_operand" "d")))] + "" + "* +{ + if (TARGET_MULT_BUG) + return \"nop\;nop\;mul %2,%0\"; + else + return \"mul %2,%0\"; +}" + [(set_attr "cc" "set_zn")]) + +(define_insn "udivmodsi4" + [(set (match_operand:SI 0 "general_operand" "=d") + (udiv:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "d"))) + (set (match_operand:SI 3 "general_operand" "=&d") + (umod:SI (match_dup 1) (match_dup 2)))] + "" + "* +{ + if (zero_dreg) + output_asm_insn (\"mov %0,mdr\", &zero_dreg); + else + output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands); + + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return \"divu %2,%0\"; + else + return \"divu %2,%0\;mov mdr,%3\"; +}" + [(set_attr "cc" "set_zn")]) + +(define_insn "divmodsi4" + [(set (match_operand:SI 0 "general_operand" "=d") + (div:SI (match_operand:SI 1 "general_operand" "0") + (match_operand:SI 2 "general_operand" "d"))) + (set (match_operand:SI 3 "general_operand" "=d") + (mod:SI (match_dup 1) (match_dup 2)))] + "" + "* +{ + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return \"ext %0\;div %2,%0\"; + else + return \"ext %0\;div %2,%0\;mov mdr,%3\"; +}" + [(set_attr "cc" "set_zn")]) + + +;; ---------------------------------------------------------------------- +;; AND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (and:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "nonmemory_operand" "N,di")))] + "" + "* +{ + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xff) + return \"extbu %0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xffff) + return \"exthu %0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x7fffffff) + return \"add %0,%0\;lsr 1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x3fffffff) + return \"asl2 %0\;lsr 2,%0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x1fffffff) + return \"add %0,%0\;asl2 %0\;lsr 3,%0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x0fffffff) + return \"asl2 %0,%0\;asl2 %0\;lsr 4,%0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffffe) + return \"lsr 1,%0\;add %0,%0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffffc) + return \"lsr 2,%0\;asl2 %0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffff8) + return \"lsr 3,%0\;add %0,%0\;asl2 %0\"; + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffffff0) + return \"lsr 4,%0\;asl2 %0\;asl2 %0\"; + return \"and %2,%0\"; +}" + [(set_attr "cc" "none_0hit,set_znv")]) + +;; ---------------------------------------------------------------------- +;; OR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (ior:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "or %2,%0" + [(set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; XOR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (xor:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "nonmemory_operand" "di")))] + "" + "xor %2,%0" + [(set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; NOT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=d") + (not:SI (match_operand:SI 1 "register_operand" "0")))] + "" + "not %0" + [(set_attr "cc" "set_znv")]) + +;; ----------------------------------------------------------------- +;; BIT FIELDS +;; ----------------------------------------------------------------- + + +;; These set/clear memory in byte sized chunks. +;; +;; They are no smaller/faster than loading the value into a register +;; and storing the register, but they don't need a scratch register +;; which may allow for better code generation. +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=R,d") (const_int 0))] + "" + "@ + bclr 255,%A0 + clr %0" + [(set_attr "cc" "clobber")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=R,d") (const_int -1))] + "" + "@ + bset 255,%A0 + mov -1,%0" + [(set_attr "cc" "clobber,none_0hit")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=R,d") + (subreg:QI + (and:SI (subreg:SI (match_dup 0) 0) + (match_operand:SI 1 "const_int_operand" "i,i")) 0))] + "" + "@ + bclr %N1,%A0 + and %1,%0" + [(set_attr "cc" "clobber,set_znv")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=R,d") + (subreg:QI + (ior:SI (subreg:SI (match_dup 0) 0) + (match_operand:SI 1 "const_int_operand" "i,i")) 0))] + "" + "@ + bset %1,%A0 + or %1,%0" + [(set_attr "cc" "clobber,set_znv")]) + +(define_insn "" + [(set (cc0) + (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")))] + "" + "* +{ + int len = INTVAL (operands[1]); + int bit = INTVAL (operands[2]); + int mask = 0; + rtx xoperands[2]; + + while (len > 0) + { + mask |= (1 << bit); + bit++; + len--; + } + + xoperands[0] = operands[0]; + xoperands[1] = GEN_INT (mask); + output_asm_insn (\"btst %1,%0\", xoperands); + return \"\"; +}" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) + (zero_extract:SI (match_operand:QI 0 "general_operand" "R,d") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")))] + "INTVAL (operands[1]) <= 8 && INTVAL (operands[2]) <= 7" + "* +{ + int len = INTVAL (operands[1]); + int bit = INTVAL (operands[2]); + int mask = 0; + rtx xoperands[2]; + + while (len > 0) + { + mask |= (1 << bit); + bit++; + len--; + } + + xoperands[0] = operands[0]; + xoperands[1] = GEN_INT (mask); + if (GET_CODE (operands[0]) == REG) + output_asm_insn (\"btst %1,%0\", xoperands); + else + output_asm_insn (\"btst %1,%A0\", xoperands); + return \"\"; +}" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) (and:SI (match_operand:SI 0 "register_operand" "d") + (match_operand:SI 1 "const_int_operand" "")))] + "" + "btst %1,%0" + [(set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (cc0) + (and:SI + (subreg:SI (match_operand:QI 0 "general_operand" "R,d") 0) + (match_operand:SI 1 "const_int_operand" "")))] + "" + "@ + btst %1,%A0 + btst %1,%0" + [(set_attr "cc" "set_znv")]) + + +;; ---------------------------------------------------------------------- +;; JUMP INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Conditional jump instructions + +(define_expand "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_insn "" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + return 0; + return \"b%b1 %0\"; +}" + [(set_attr "cc" "none")]) + +(define_insn "" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + return 0; + return \"b%B1 %0\"; +}" + [(set_attr "cc" "none")]) + +;; Unconditional and other jump instructions. + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jmp %l0" + [(set_attr "cc" "none")]) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "register_operand" "a"))] + "" + "jmp (%0)" + [(set_attr "cc" "none")]) + +(define_insn "tablejump" + [(set (pc) (match_operand:SI 0 "register_operand" "a")) + (use (label_ref (match_operand 1 "" "")))] + "" + "jmp (%0)" + [(set_attr "cc" "none")]) + +;; Call subroutine with no return value. + +(define_expand "call" + [(call (match_operand:QI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + if (! call_address_operand (XEXP (operands[0], 0))) + XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); + emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1])); + DONE; +}") + +(define_insn "call_internal" + [(call (mem:QI (match_operand:SI 0 "call_address_operand" "aS")) + (match_operand:SI 1 "general_operand" "g"))] + "" + "* +{ + if (REG_P (operands[0])) + return \"calls %C0\"; + else + return \"call %C0,[],0\"; +}" + [(set_attr "cc" "clobber")]) + +;; Call subroutine, returning value in operand 0 +;; (which must be a hard register). + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" "")))] + "" + " +{ + if (! call_address_operand (XEXP (operands[1], 0))) + XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); + emit_call_insn (gen_call_value_internal (operands[0], + XEXP (operands[1], 0), + operands[2])); + DONE; +}") + +(define_insn "call_value_internal" + [(set (match_operand 0 "" "=da") + (call (mem:QI (match_operand:SI 1 "call_address_operand" "aS")) + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (REG_P (operands[1])) + return \"calls %C1\"; + else + return \"call %C1,[],0\"; +}" + [(set_attr "cc" "clobber")]) + +(define_expand "untyped_call" + [(parallel [(call (match_operand 0 "" "") + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] + "" + " +{ + int i; + + emit_call_insn (gen_call (operands[0], const0_rtx)); + + for (i = 0; i < XVECLEN (operands[2], 0); i++) + { + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); + } + DONE; +}") + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "cc" "none")]) + +;; ---------------------------------------------------------------------- +;; EXTEND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d,d") + (zero_extend:SI + (match_operand:QI 1 "general_operand" "0,d,m")))] + "" + "@ + extbu %0 + mov %1,%0\;extbu %0 + movbu %1,%0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d,d") + (zero_extend:SI + (match_operand:HI 1 "general_operand" "0,d,m")))] + "" + "@ + exthu %0 + mov %1,%0\;exthu %0 + movhu %1,%0" + [(set_attr "cc" "none_0hit")]) + +;;- sign extension instructions + +(define_insn "extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d") + (sign_extend:SI + (match_operand:QI 1 "general_operand" "0,d")))] + "" + "@ + extb %0 + mov %1,%0\;extb %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=d,d") + (sign_extend:SI + (match_operand:HI 1 "general_operand" "0,d")))] + "" + "@ + exth %0 + mov %1,%0\;exth %0" + [(set_attr "cc" "none_0hit")]) + +;; ---------------------------------------------------------------------- +;; SHIFTS +;; ---------------------------------------------------------------------- + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=da,d,d,d,d") + (ashift:SI + (match_operand:SI 1 "register_operand" "0,0,0,0,0") + (match_operand:QI 2 "nonmemory_operand" "J,K,M,L,di")))] + "" + "@ + add %0,%0 + asl2 %0 + asl2 %0\;add %0,%0 + asl2 %0\;asl2 %0 + asl %S2,%0" + [(set_attr "cc" "set_zn")]) + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (lshiftrt:SI + (match_operand:SI 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "di")))] + "" + "lsr %S2,%0" + [(set_attr "cc" "set_zn")]) + +(define_insn "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=d") + (ashiftrt:SI + (match_operand:SI 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "di")))] + "" + "asr %S2,%0" + [(set_attr "cc" "set_zn")]) + +;; ---------------------------------------------------------------------- +;; PROLOGUE/EPILOGUE +;; ---------------------------------------------------------------------- +(define_expand "prologue" + [(const_int 0)] + "" + "expand_prologue (); DONE;") + +(define_expand "epilogue" + [(return)] + "" + " +{ + expand_epilogue (); + DONE; +}") + +(define_insn "return_internal" + [(const_int 2)] + "" + "rets" + [(set_attr "cc" "clobber")]) + +;; This insn restores the callee saved registers and does a return, it +;; can also deallocate stack space. +(define_insn "return_internal_regs" + [(const_int 0) + (match_operand:SI 0 "const_int_operand" "i") + (return)] + "" + "ret [d2,d3,a2,a3],%0" + [(set_attr "cc" "clobber")]) + +(define_insn "store_movm" + [(const_int 1)] + "" + "movm [d2,d3,a2,a3],(sp)" + [(set_attr "cc" "clobber")]) + +(define_insn "return" + [(return)] + "can_use_return_insn ()" + "* +{ + rtx next = next_active_insn (insn); + + if (next + && GET_CODE (next) == JUMP_INSN + && GET_CODE (PATTERN (next)) == RETURN) + return \"\"; + else + return \"rets\"; +}" + [(set_attr "cc" "clobber")]) + +;; Try to combine consecutive updates of the stack pointer (or any +;; other register for that matter). +(define_peephole + [(set (match_operand:SI 0 "register_operand" "=dax") + (plus:SI (match_dup 0) + (match_operand 1 "const_int_operand" ""))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (match_operand 2 "const_int_operand" "")))] + "" + "* +{ + operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1])); + return \"add %1,%0\"; +}" + [(set_attr "cc" "clobber")]) + +;; +;; We had patterns to check eq/ne, but the they don't work because +;; 0x80000000 + 0x80000000 = 0x0 with a carry out. +;; +;; The Z flag and C flag would be set, and we have no way to +;; check for the Z flag set and C flag clear. +;; +;; This will work on the mn10200 because we can check the ZX flag +;; if the comparison is in HImode. +(define_peephole + [(set (cc0) (match_operand:SI 0 "register_operand" "d")) + (set (pc) (if_then_else (ge (cc0) (const_int 0)) + (match_operand 1 "" "") + (pc)))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcc %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:SI 0 "register_operand" "d")) + (set (pc) (if_then_else (lt (cc0) (const_int 0)) + (match_operand 1 "" "") + (pc)))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcs %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:SI 0 "register_operand" "d")) + (set (pc) (if_then_else (ge (cc0) (const_int 0)) + (pc) + (match_operand 1 "" "")))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcs %1" + [(set_attr "cc" "clobber")]) + +(define_peephole + [(set (cc0) (match_operand:SI 0 "register_operand" "d")) + (set (pc) (if_then_else (lt (cc0) (const_int 0)) + (pc) + (match_operand 1 "" "")))] + "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" + "add %0,%0\;bcc %1" + [(set_attr "cc" "clobber")]) + diff --git a/gnu/usr.bin/gcc/config/mn10300/t-mn10300 b/gnu/usr.bin/gcc/config/mn10300/t-mn10300 new file mode 100644 index 00000000000..379b90fca7f --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10300/t-mn10300 @@ -0,0 +1,20 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1=libgcc1.null + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + echo '#ifdef __LITTLE_ENDIAN__' > dp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >>dp-bit.c + echo '#endif' >> dp-bit.c + cat $(srcdir)/config/fp-bit.c >> dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c + echo '#endif' >> fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c diff --git a/gnu/usr.bin/gcc/config/mn10300/xm-mn10300.h b/gnu/usr.bin/gcc/config/mn10300/xm-mn10300.h new file mode 100644 index 00000000000..63d61c276c2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/mn10300/xm-mn10300.h @@ -0,0 +1,47 @@ +/* Configuration for Matsushita MN10300. + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +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. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + +#include "tm.h" + +#ifndef __STDC__ +extern char *malloc (), *realloc (), *calloc (); +#else +extern void *malloc (), *realloc (), *calloc (); +#endif +extern void free (); diff --git a/gnu/usr.bin/gcc/config/pa/ee.asm b/gnu/usr.bin/gcc/config/pa/ee.asm new file mode 100644 index 00000000000..787bda75c0d --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/ee.asm @@ -0,0 +1,261 @@ +; Subroutines for out of line prologues and epilogues on for the HPPA +; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +; This file is part of GNU CC. + +; GNU CC is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. + +; GNU CC is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +; You should have received a copy of the GNU General Public License +; along with GNU CC; see the file COPYING. If not, write to +; the Free Software Foundation, 59 Temple Place - Suite 330, +; Boston, MA 02111-1307, USA. + + .SPACE $PRIVATE$ + .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 + .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 + .SPACE $TEXT$ + .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 + .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY + .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8 + +; This is an out-of-line prologue. +; +; It performs the following operations: +; +; * Saves the return pointer at sp - 20 +; +; * Creates a new stack frame (sp'), size of the frame is passed in %r21 +; +; * The old stack pointer is saved at sp (frame pointer version only). +; +; * Saves grs (passed in low 16 bits of %r22 into the stack frame +; at sp' + local_fsize (passed in %r19). +; +; * Saves frs (passed in high 16 bits of %r22) into the stack +; frame at sp' + local_fsize (passed in %r19). +; +; * Sets up a frame pointer (in %r3) (frame pointer version only). +; +; * Returns to the instruction _immediately_ after the call to +; this function. + + .SPACE $TEXT$ + .SUBSPA $MILLICODE$ + .EXPORT __outline_prologue,MILLICODE + .align 32 +__outline_prologue + .PROC + .CALLINFO FRAME=0,NO_CALLS + .ENTRY + copy %r30,%r20 + + ; Subtract 4 from our return pointer so that we return to + ; the right location. + ldo -4(%r31),%r31 + + ; Save off %r2 + stw %r2,-20(0,%r30) + + ; Make our new frame. + add %r21,%r30,%r30 + + ; Add in local_fsize to our frame pointer so we do register + ; saves into the right place + add %r20,%r19,%r20 + + ; %r22 tells us what registers we need to save. The upper half + ; is for fp registers, the lower half for integer registers. + ; We put the lower half in %r1 and the upper half into %r22 + ; for later use. + extru %r22,31,16,%r1 + extrs %r22,15,16,%r22 + + ; %r1 now olds a value 0-18 which corresponds to the number + ; of grs we need to save. We need to reverse that value so + ; we can just into the table and straight-line execute to the + ; end of the gr saves. + comb,= %r0,%r1,L$0000 + subi 18,%r1,%r1 + blr,n %r1,%r0 + b,n L$0000 + stws,ma %r18,4(0,%r20) + nop + stws,ma %r17,4(0,%r20) + nop + stws,ma %r16,4(0,%r20) + nop + stws,ma %r15,4(0,%r20) + nop + stws,ma %r14,4(0,%r20) + nop + stws,ma %r13,4(0,%r20) + nop + stws,ma %r12,4(0,%r20) + nop + stws,ma %r11,4(0,%r20) + nop + stws,ma %r10,4(0,%r20) + nop + stws,ma %r9,4(0,%r20) + nop + stws,ma %r8,4(0,%r20) + nop + stws,ma %r7,4(0,%r20) + nop + stws,ma %r6,4(0,%r20) + nop + stws,ma %r5,4(0,%r20) + nop + stws,ma %r4,4(0,%r20) + nop + stws,ma %r3,4(0,%r20) + nop +L$0000 + ; All gr saves are done. Align the temporary frame pointer and + ; do the fr saves. + ldo 7(%r20),%r20 + depi 0,31,3,%r20 + + comb,= %r0,%r22,L$0001 + subi 21,%r22,%r22 + blr,n %r22,%r0 + b,n L$0001 + fstws,ma %fr21,8(0,%r20) + nop + fstws,ma %fr20,8(0,%r20) + nop + fstws,ma %fr19,8(0,%r20) + nop + fstws,ma %fr18,8(0,%r20) + nop + fstws,ma %fr17,8(0,%r20) + nop + fstws,ma %fr16,8(0,%r20) + nop + fstws,ma %fr15,8(0,%r20) + nop + fstws,ma %fr14,8(0,%r20) + nop + fstws,ma %fr13,8(0,%r20) + nop + fstws,ma %fr12,8(0,%r20) + nop +L$0001 + ; Return + bv,n 0(%r31) + .EXIT + .PROCEND + + + + .EXPORT __outline_epilogue,MILLICODE + .align 32 +__outline_epilogue + .PROC + .CALLINFO FRAME=0,NO_CALLS + .ENTRY + ; Get our original stack pointer and put it in %r20 + sub %r30,%r21,%r20 + + ; Subtract 4 from our return pointer so that we return to + ; the right location. + ldo -4(%r31),%r31 + + ; Reload %r2 + ldw -20(0,%r20),%r2 + + ; Add in local_fsize (%r19) to the frame pointer to find + ; the saved registers. + add %r20,%r19,%r20 + + ; %r22 tells us what registers we need to restore. The upper half + ; is for fp registers, the lower half for integer registers. + ; We put the lower half in %r1 and the upper half into %r22 + ; for later use. + extru %r22,31,16,%r1 + extrs %r22,15,16,%r22 + + ; %r1 now olds a value 0-18 which corresponds to the number + ; of grs we need to restore. We need to reverse that value so + ; we can just into the table and straight-line execute to the + ; end of the gr restore. + comb,= %r0,%r1,L$0004 + subi 18,%r1,%r1 + blr,n %r1,%r0 + b,n L$0004 + ldws,ma 4(0,%r20),%r18 + nop + ldws,ma 4(0,%r20),%r17 + nop + ldws,ma 4(0,%r20),%r16 + nop + ldws,ma 4(0,%r20),%r15 + nop + ldws,ma 4(0,%r20),%r14 + nop + ldws,ma 4(0,%r20),%r13 + nop + ldws,ma 4(0,%r20),%r12 + nop + ldws,ma 4(0,%r20),%r11 + nop + ldws,ma 4(0,%r20),%r10 + nop + ldws,ma 4(0,%r20),%r9 + nop + ldws,ma 4(0,%r20),%r8 + nop + ldws,ma 4(0,%r20),%r7 + nop + ldws,ma 4(0,%r20),%r6 + nop + ldws,ma 4(0,%r20),%r5 + nop + ldws,ma 4(0,%r20),%r4 + nop + ldws,ma 4(0,%r20),%r3 + nop +L$0004 + ; All gr restore are done. Align the temporary frame pointer and + ; do the fr restore. + ldo 7(%r20),%r20 + depi 0,31,3,%r20 + + comb,= %r0,%r22,L$0005 + subi 21,%r22,%r22 + blr,n %r22,%r0 + b,n L$0005 + fldws,ma 8(0,%r20),%fr21 + nop + fldws,ma 8(0,%r20),%fr20 + nop + fldws,ma 8(0,%r20),%fr19 + nop + fldws,ma 8(0,%r20),%fr18 + nop + fldws,ma 8(0,%r20),%fr17 + nop + fldws,ma 8(0,%r20),%fr16 + nop + fldws,ma 8(0,%r20),%fr15 + nop + fldws,ma 8(0,%r20),%fr14 + nop + fldws,ma 8(0,%r20),%fr13 + nop + fldws,ma 8(0,%r20),%fr12 + nop +L$0005 + ; Return and deallocate our frame. + bv 0(%r31) + sub %r30,%r21,%r30 + .EXIT + .PROCEND diff --git a/gnu/usr.bin/gcc/config/pa/ee_fp.asm b/gnu/usr.bin/gcc/config/pa/ee_fp.asm new file mode 100644 index 00000000000..ef040cf7dad --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/ee_fp.asm @@ -0,0 +1,274 @@ +; Subroutines for out of line prologues and epilogues on for the HPPA +; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +; This file is part of GNU CC. + +; GNU CC is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. + +; GNU CC is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. + +; You should have received a copy of the GNU General Public License +; along with GNU CC; see the file COPYING. If not, write to +; the Free Software Foundation, 59 Temple Place - Suite 330, +; Boston, MA 02111-1307, USA. + + .SPACE $PRIVATE$ + .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 + .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 + .SPACE $TEXT$ + .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 + .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY + .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8 + + +; This is an out-of-line prologue. +; +; It performs the following operations: +; +; * Saves the return pointer at sp - 20 +; +; * Creates a new stack frame (sp'), size of the frame is passed in %r21 +; +; * The old stack pointer is saved at sp (frame pointer version only). +; +; * Saves grs (passed in low 16 bits of %r22 into the stack frame +; at sp' + local_fsize (passed in %r19). +; +; * Saves frs (passed in high 16 bits of %r22) into the stack +; frame at sp' + local_fsize (passed in %r19). +; +; * Sets up a frame pointer (in %r3) (frame pointer version only). +; +; * Returns to the instruction _immediately_ after the call to +; this function. + + .SPACE $TEXT$ + .SUBSPA $MILLICODE$ + .EXPORT __outline_prologue_fp,MILLICODE + .align 32 +__outline_prologue_fp + .PROC + .CALLINFO FRAME=0,NO_CALLS + .ENTRY + copy %r30,%r20 + + ; Subtract 4 from our return pointer so that we return to + ; the right location. + ldo -4(%r31),%r31 + + ; Save off %r2 + stw %r2,-20(0,%r30) + + ; Make our new frame. + add %r21,%r30,%r30 + + ; Save our old stack pointer. + stw %r20,0(0,%r20) + + ; Add in local_fsize to our frame pointer so we do register + ; saves into the right place + add %r20,%r19,%r20 + + ; %r22 tells us what registers we need to save. The upper half + ; is for fp registers, the lower half for integer registers. + ; We put the lower half in %r1 and the upper half into %r22 + ; for later use. + extru %r22,31,16,%r1 + extrs %r22,15,16,%r22 + + ; %r1 now olds a value 0-18 which corresponds to the number + ; of grs we need to save. We need to reverse that value so + ; we can just into the table and straight-line execute to the + ; end of the gr saves. + comb,= %r0,%r1,L$0002 + subi 18,%r1,%r1 + blr,n %r1,%r0 + b,n L$0002 + stws,ma %r18,4(0,%r20) + nop + stws,ma %r17,4(0,%r20) + nop + stws,ma %r16,4(0,%r20) + nop + stws,ma %r15,4(0,%r20) + nop + stws,ma %r14,4(0,%r20) + nop + stws,ma %r13,4(0,%r20) + nop + stws,ma %r12,4(0,%r20) + nop + stws,ma %r11,4(0,%r20) + nop + stws,ma %r10,4(0,%r20) + nop + stws,ma %r9,4(0,%r20) + nop + stws,ma %r8,4(0,%r20) + nop + stws,ma %r7,4(0,%r20) + nop + stws,ma %r6,4(0,%r20) + nop + stws,ma %r5,4(0,%r20) + nop + stws,ma %r4,4(0,%r20) + nop + stws,ma %r3,4(0,%r20) + nop +L$0002 + ; All gr saves are done. Align the temporary frame pointer and + ; do the fr saves. + ldo 7(%r20),%r20 + depi 0,31,3,%r20 + + comb,= %r0,%r22,L$0003 + subi 21,%r22,%r22 + blr,n %r22,%r0 + b,n L$0003 + fstws,ma %fr21,8(0,%r20) + nop + fstws,ma %fr20,8(0,%r20) + nop + fstws,ma %fr19,8(0,%r20) + nop + fstws,ma %fr18,8(0,%r20) + nop + fstws,ma %fr17,8(0,%r20) + nop + fstws,ma %fr16,8(0,%r20) + nop + fstws,ma %fr15,8(0,%r20) + nop + fstws,ma %fr14,8(0,%r20) + nop + fstws,ma %fr13,8(0,%r20) + nop + fstws,ma %fr12,8(0,%r20) + nop +L$0003 + ; Return, setting up a frame pointer in the delay slot + bv 0(%r31) + sub %r30,%r21,%r3 + .EXIT + .PROCEND + + +; This is an out-of-line epilogue. It's operation is basically the reverse +; of the out-of-line prologue. + + .EXPORT __outline_epilogue_fp,MILLICODE + .align 32 +__outline_epilogue_fp + .PROC + .CALLINFO FRAME=0,NO_CALLS + .ENTRY + ; Make a copy of our frame pointer into %r20 + copy %r3,%r20 + + ; Subtract 4 from our return pointer so that we return to + ; the right location. + ldo -4(%r31),%r31 + + ; Reload %r2 + ; First save off %r2 + ldw -20(0,%r20),%r2 + + ; Load our old stack pointer, save it in %r21. + ldw 0(0,%r20),%r21 + + ; Add in local_fsize (%r19) to the frame pointer to find + ; the saved registers. + add %r20,%r19,%r20 + + ; %r22 tells us what registers we need to restore. The upper half + ; is for fp registers, the lower half for integer registers. + ; We put the lower half in %r1 and the upper half into %r22 + ; for later use. + extru %r22,31,16,%r1 + extrs %r22,15,16,%r22 + + ; %r1 now olds a value 0-18 which corresponds to the number + ; of grs we need to restore. We need to reverse that value so + ; we can just into the table and straight-line execute to the + ; end of the gr restore. + comb,= %r0,%r1,L$0006 + subi 18,%r1,%r1 + blr,n %r1,%r0 + b,n L$0006 + ldws,ma 4(0,%r20),%r18 + nop + ldws,ma 4(0,%r20),%r17 + nop + ldws,ma 4(0,%r20),%r16 + nop + ldws,ma 4(0,%r20),%r15 + nop + ldws,ma 4(0,%r20),%r14 + nop + ldws,ma 4(0,%r20),%r13 + nop + ldws,ma 4(0,%r20),%r12 + nop + ldws,ma 4(0,%r20),%r11 + nop + ldws,ma 4(0,%r20),%r10 + nop + ldws,ma 4(0,%r20),%r9 + nop + ldws,ma 4(0,%r20),%r8 + nop + ldws,ma 4(0,%r20),%r7 + nop + ldws,ma 4(0,%r20),%r6 + nop + ldws,ma 4(0,%r20),%r5 + nop + ldws,ma 4(0,%r20),%r4 + nop + ldws,ma 4(0,%r20),%r3 + nop +L$0006 + ; All gr restore are done. Align the temporary frame pointer and + ; do the fr restore. + ldo 7(%r20),%r20 + depi 0,31,3,%r20 + + comb,= %r0,%r22,L$0007 + subi 21,%r22,%r22 + blr,n %r22,%r0 + b,n L$0007 + fldws,ma 8(0,%r20),%fr21 + nop + fldws,ma 8(0,%r20),%fr20 + nop + fldws,ma 8(0,%r20),%fr19 + nop + fldws,ma 8(0,%r20),%fr18 + nop + fldws,ma 8(0,%r20),%fr17 + nop + fldws,ma 8(0,%r20),%fr16 + nop + fldws,ma 8(0,%r20),%fr15 + nop + fldws,ma 8(0,%r20),%fr14 + nop + fldws,ma 8(0,%r20),%fr13 + nop + fldws,ma 8(0,%r20),%fr12 + nop +L$0007 + ; Return and deallocate our frame. + bv 0(%r31) + copy %r21,%r30 + .EXIT + .PROCEND + + diff --git a/gnu/usr.bin/gcc/config/pa/lib1funcs.asm b/gnu/usr.bin/gcc/config/pa/lib1funcs.asm new file mode 100644 index 00000000000..95eb75e1398 --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/lib1funcs.asm @@ -0,0 +1,1146 @@ +; Low level integer divide, multiply, remainder, etc routines for the HPPA. +; Copyright (C) 1995 Free Software Foundation, Inc. + +; This file is part of GNU CC. + +; GNU CC is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. + +; In addition to the permissions in the GNU General Public License, the +; Free Software Foundation gives you unlimited permission to link the +; compiled version of this file with other programs, and to distribute +; those programs without any restriction coming from the use of this +; file. (The General Public License restrictions do apply in other +; respects; for example, they cover modification of the file, and +; distribution when not linked into another program.) + +; 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. + +#ifdef L_dyncall + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .export $$dyncall +$$dyncall + .proc + .callinfo frame=0,no_calls + .entry + bb,>=,n %r22,30,L$1 ; branch if not plabel address + depi 0,31,2,%r22 ; clear the two least significant bits + ldw 4(%sr0,%r22),%r19 ; load new LTP value + ldw 0(%sr0,%r22),%r22 ; load address of target +L$1 ldsid (%sr0,%r22),%r1 ; get the "space ident" selected by r22 + mtsp %r1,%sr0 ; move that space identifier into sr0 + be 0(%sr0,%r22) ; branch to the real target + stw %r2,-24(%sr0,%r30) ; save return address into frame marker + .exit + .procend +#endif + + +#ifdef L_multiply +#define op0 %r26 +#define op1 %r25 +#define res %r29 +#define ret %r31 +#define tmp %r1 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$mulU + .export $$mulI +$$mulU +$$mulI + .proc + .callinfo frame=0,no_calls + .entry + addi,tr 0,%r0,res ; clear out res, skip next insn +L$loop zdep op1,26,27,op1 ; shift up op1 by 5 +L$lo zdep op0,30,5,tmp ; extract next 5 bits and shift up + blr tmp,%r0 + extru op0,26,27,op0 ; shift down op0 by 5 +L$0 comib,<> 0,op0,L$lo + zdep op1,26,27,op1 ; shift up op1 by 5 + bv %r0(ret) + nop +L$1 b L$loop + addl op1,res,res + nop + nop +L$2 b L$loop + sh1addl op1,res,res + nop + nop +L$3 sh1addl op1,op1,tmp ; 3x + b L$loop + addl tmp,res,res + nop +L$4 b L$loop + sh2addl op1,res,res + nop + nop +L$5 sh2addl op1,op1,tmp ; 5x + b L$loop + addl tmp,res,res + nop +L$6 sh1addl op1,op1,tmp ; 3x + b L$loop + sh1addl tmp,res,res + nop +L$7 zdep op1,28,29,tmp ; 8x + sub tmp,op1,tmp ; 7x + b L$loop + addl tmp,res,res +L$8 b L$loop + sh3addl op1,res,res + nop + nop +L$9 sh3addl op1,op1,tmp ; 9x + b L$loop + addl tmp,res,res + nop +L$10 sh2addl op1,op1,tmp ; 5x + b L$loop + sh1addl tmp,res,res + nop +L$11 sh2addl op1,op1,tmp ; 5x + sh1addl tmp,op1,tmp ; 11x + b L$loop + addl tmp,res,res +L$12 sh1addl op1,op1,tmp ; 3x + b L$loop + sh2addl tmp,res,res + nop +L$13 sh1addl op1,op1,tmp ; 3x + sh2addl tmp,op1,tmp ; 13x + b L$loop + addl tmp,res,res +L$14 zdep op1,28,29,tmp ; 8x + sub tmp,op1,tmp ; 7x + b L$loop + sh1addl tmp,res,res +L$15 zdep op1,27,28,tmp ; 16x + sub tmp,op1,tmp ; 15x + b L$loop + addl tmp,res,res +L$16 zdep op1,27,28,tmp ; 16x + b L$loop + addl tmp,res,res + nop +L$17 zdep op1,27,28,tmp ; 16x + addl tmp,op1,tmp ; 17x + b L$loop + addl tmp,res,res +L$18 sh3addl op1,op1,tmp ; 9x + b L$loop + sh1addl tmp,res,res + nop +L$19 sh3addl op1,op1,tmp ; 9x + sh1addl tmp,op1,tmp ; 19x + b L$loop + addl tmp,res,res +L$20 sh2addl op1,op1,tmp ; 5x + b L$loop + sh2addl tmp,res,res + nop +L$21 sh2addl op1,op1,tmp ; 5x + sh2addl tmp,op1,tmp ; 21x + b L$loop + addl tmp,res,res +L$22 sh2addl op1,op1,tmp ; 5x + sh1addl tmp,op1,tmp ; 11x + b L$loop + sh1addl tmp,res,res +L$23 sh1addl op1,op1,tmp ; 3x + sh3addl tmp,res,res ; += 8x3 + b L$loop + sub res,op1,res ; -= x +L$24 sh1addl op1,op1,tmp ; 3x + b L$loop + sh3addl tmp,res,res ; += 8x3 + nop +L$25 sh2addl op1,op1,tmp ; 5x + sh2addl tmp,tmp,tmp ; 25x + b L$loop + addl tmp,res,res +L$26 sh1addl op1,op1,tmp ; 3x + sh2addl tmp,op1,tmp ; 13x + b L$loop + sh1addl tmp,res,res ; += 2x13 +L$27 sh1addl op1,op1,tmp ; 3x + sh3addl tmp,tmp,tmp ; 27x + b L$loop + addl tmp,res,res +L$28 zdep op1,28,29,tmp ; 8x + sub tmp,op1,tmp ; 7x + b L$loop + sh2addl tmp,res,res ; += 4x7 +L$29 sh1addl op1,op1,tmp ; 3x + sub res,tmp,res ; -= 3x + b L$foo + zdep op1,26,27,tmp ; 32x +L$30 zdep op1,27,28,tmp ; 16x + sub tmp,op1,tmp ; 15x + b L$loop + sh1addl tmp,res,res ; += 2x15 +L$31 zdep op1,26,27,tmp ; 32x + sub tmp,op1,tmp ; 31x +L$foo b L$loop + addl tmp,res,res + .exit + .procend +#endif + + +#ifdef L_divU +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define quotient %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU +$$divU + .proc + .callinfo frame=0,no_calls + .entry + comb,< divisor,0,L$largedivisor + sub %r0,divisor,%r1 ; clear cy as side-effect + ds %r0,%r1,%r0 + addc dividend,dividend,dividend + ds %r0,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,quotient + ds %r1,divisor,%r1 + bv 0(ret) + addc quotient,quotient,quotient +L$largedivisor + comclr,<< dividend,divisor,quotient + ldi 1,quotient + bv,n 0(ret) + .exit + .procend +#endif + + +#ifdef L_remU +#define dividend %r26 +#define divisor %r25 +#define quotient %r29 +#define tmp %r1 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$remU +$$remU + .proc + .callinfo frame=0,no_calls + .entry + comb,< divisor,0,L$largedivisor + sub %r0,divisor,%r1 ; clear cy as side-effect + ds %r0,%r1,%r0 + addc dividend,dividend,dividend + ds %r0,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,quotient + ds %r1,divisor,%r1 + comclr,>= %r1,%r0,%r0 + addl %r1,divisor,%r1 + bv 0(ret) + copy %r1,quotient +L$largedivisor + sub,>>= dividend,divisor,quotient + copy dividend,quotient + bv,n 0(ret) + .exit + .procend +#endif + + +#ifdef L_divI +#define dividend %r26 +#define divisor %r25 +#define quotient %r29 +#define tmp %r1 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI +$$divI + .proc + .callinfo frame=0,no_calls + .entry + xor dividend,divisor,quotient ; result sign + comclr,>= divisor,%r0,%r0 ; get absolute values + sub %r0,divisor,divisor + comclr,>= dividend,%r0,%r0 + sub %r0,dividend,dividend + + comb,< divisor,0,L$largedivisor + sub %r0,divisor,%r1 ; clear cy as side-effect + ds %r0,%r1,%r0 + addc dividend,dividend,dividend + ds %r0,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + comclr,>= %r1,%r0,%r0 + addl %r1,divisor,%r1 + comclr,>= quotient,%r0,%r0 ; skip of no need to negate + sub %r0,dividend,dividend + bv 0(ret) + copy dividend,quotient +L$largedivisor + comclr,<< dividend,divisor,quotient + ldi 1,quotient + bv,n 0(ret) + .exit + .procend +#endif + + +#ifdef L_remI +#define dividend %r26 +#define divisor %r25 +#define quotient %r29 +#define tmp %r1 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$remI +$$remI + .proc + .callinfo frame=0,no_calls + .entry + xor dividend,%r0,quotient ; result sign + comclr,>= divisor,%r0,%r0 ; get absolute values + sub %r0,divisor,divisor + comclr,>= dividend,%r0,%r0 + sub %r0,dividend,dividend + + comb,< divisor,0,L$largedivisor + sub %r0,divisor,%r1 ; clear cy as side-effect + ds %r0,%r1,%r0 + addc dividend,dividend,dividend + ds %r0,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + ds %r1,divisor,%r1 + addc dividend,dividend,dividend + comclr,>= %r1,%r0,%r0 + addl %r1,divisor,%r1 + comclr,>= quotient,%r0,%r0 ; skip of no need to negate + sub %r0,%r1,%r1 + bv 0(ret) + copy %r1,quotient +L$largedivisor + sub,>>= dividend,divisor,quotient + copy dividend,quotient + bv,n 0(ret) + .exit + .procend +#endif + + +#if defined (L_divU_3) && !defined (SMALL_LIB) +#undef L_divU_3 +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define result %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_3 +$$divU_3 + .proc + .callinfo frame=0,no_calls + .entry + sh2add %r26,%r26,%r29 ; r29 = lo(101 x r) + shd %r0,%r26,30,%r1 ; r1 = hi(100 x r) + addc %r1,%r0,%r1 ; r1 = hi(101 x r) +; r in r1,,r29 + zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) + add %r25,%r29,%r25 ; r25 = lo(10001 x r) + shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) + addc %r29,%r1,%r29 ; r29 = hi(10001 x r) +; r in r29,,r25 + zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) + add %r1,%r25,%r1 ; r1 = lo(100000001 x r) + shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) + addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) +; r in r25,,r1 + zdep %r1,15,16,%r29 + add %r29,%r1,%r29 + shd %r25,%r1,16,%r1 + addc %r1,%r25,%r1 +; r in r1,,r29 + sh1add %r29,%r26,%r0 ; r0 = lo(10 x r) + dividend + shd %r1,%r29,31,%r29 ; r29 = hi(10 x r) + addc %r29,%r0,%r29 + bv 0(ret) + extru %r29,30,31,result + .exit + .procend +#endif + + +#if defined (L_divU_5) && !defined (SMALL_LIB) +#undef L_divU_5 +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define result %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_5 +$$divU_5 + .proc + .callinfo frame=0,no_calls + .entry + sh1add %r26,%r26,%r29 ; r29 = lo(11 x r) + shd %r0,%r26,31,%r1 ; r1 = hi(10 x r) + addc %r1,%r0,%r1 ; r1 = hi(11 x r) +; r in r1,,r29 + zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) + add %r25,%r29,%r25 ; r25 = lo(10001 x r) + shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) + addc %r29,%r1,%r29 ; r29 = hi(10001 x r) +; r in r29,,r25 + zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) + add %r1,%r25,%r1 ; r1 = lo(100000001 x r) + shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) + addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) +; r in r25,,r1 + zdep %r1,15,16,%r29 + add %r29,%r1,%r29 + shd %r25,%r1,16,%r1 + addc %r1,%r25,%r1 +; r in r1,,r29 + sh2add %r29,%r26,%r0 ; r0 = lo(1000 x r) + dividend + shd %r1,%r29,30,%r29 ; r29 = hi(1000 x r) + addc %r29,%r0,%r29 + bv 0(ret) + extru %r29,29,30,result + .exit + .procend +#endif + + +#if defined (L_divU_6) && !defined (SMALL_LIB) +#undef L_divU_6 +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define result %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_6 +$$divU_6 + .proc + .callinfo frame=0,no_calls + .entry + sh2add %r26,%r26,%r29 ; r29 = lo(101 x r) + shd %r0,%r26,30,%r1 ; r1 = hi(100 x r) + addc %r1,%r0,%r1 ; r1 = hi(101 x r) +; r in r1,,r29 + zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) + add %r25,%r29,%r25 ; r25 = lo(10001 x r) + shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) + addc %r29,%r1,%r29 ; r29 = hi(10001 x r) +; r in r29,,r25 + zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) + add %r1,%r25,%r1 ; r1 = lo(100000001 x r) + shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) + addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) +; r in r25,,r1 + zdep %r1,15,16,%r29 + add %r29,%r1,%r29 + shd %r25,%r1,16,%r1 + addc %r1,%r25,%r1 +; r in r1,,r29 + sh1add %r29,%r26,%r0 ; r0 = lo(10 x r) + dividend + shd %r1,%r29,31,%r29 ; r29 = hi(10 x r) + addc %r29,%r0,%r29 + bv 0(ret) + extru %r29,29,30,result + .exit + .procend +#endif + + +#if defined (L_divU_9) && !defined (SMALL_LIB) +#undef L_divU_9 +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define result %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_9 +$$divU_9 + .proc + .callinfo frame=0,no_calls + .entry + zdep %r26,28,29,%r29 + sub %r29,%r26,%r29 + shd 0,%r26,29,%r1 + subb %r1,0,%r1 /* 111 */ + + zdep %r29,25,26,%r25 + add %r25,%r29,%r25 + shd %r1,%r29,26,%r29 + addc %r29,%r1,%r29 /* 111000111 */ + + sh3add %r25,%r26,%r1 + shd %r29,%r25,29,%r25 + addc %r25,0,%r25 /* 111000111001 */ + + zdep %r1,16,17,%r29 + sub %r29,%r1,%r29 + shd %r25,%r1,17,%r1 + subb %r1,%r25,%r1 /* 111000111000111000111000111 */ + + sh3add %r29,%r26,%r0 + shd %r1,%r29,29,%r29 + addc %r29,0,%r29 /* 111000111000111000111000111001 */ + bv 0(ret) + extru %r29,30,31,result + .exit + .procend +#endif + + +#if defined (L_divU_10) && !defined (SMALL_LIB) +#undef L_divU_10 +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define result %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_10 +$$divU_10 + .proc + .callinfo frame=0,no_calls + .entry + sh1add %r26,%r26,%r29 ; r29 = lo(11 x r) + shd %r0,%r26,31,%r1 ; r1 = hi(10 x r) + addc %r1,%r0,%r1 ; r1 = hi(11 x r) +; r in r1,,r29 + zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) + add %r25,%r29,%r25 ; r25 = lo(10001 x r) + shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) + addc %r29,%r1,%r29 ; r29 = hi(10001 x r) +; r in r29,,r25 + zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) + add %r1,%r25,%r1 ; r1 = lo(100000001 x r) + shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) + addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) +; r in r25,,r1 + zdep %r1,15,16,%r29 + add %r29,%r1,%r29 + shd %r25,%r1,16,%r1 + addc %r1,%r25,%r1 +; r in r1,,r29 + sh2add %r29,%r26,%r0 ; r0 = lo(1000 x r) + dividend + shd %r1,%r29,30,%r29 ; r29 = hi(1000 x r) + addc %r29,%r0,%r29 + bv 0(ret) + extru %r29,28,29,result + .exit + .procend +#endif + + +#if defined (L_divU_12) && !defined (SMALL_LIB) +#undef L_divU_12 +#define dividend %r26 +#define divisor %r25 +#define tmp %r1 +#define result %r29 +#define ret %r31 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_12 +$$divU_12 + .proc + .callinfo frame=0,no_calls + .entry + sh2add %r26,%r26,%r29 ; r29 = lo(101 x r) + shd %r0,%r26,30,%r1 ; r1 = hi(100 x r) + addc %r1,%r0,%r1 ; r1 = hi(101 x r) +; r in r1,,r29 + zdep %r29,27,28,%r25 ; r25 = lo(10000 x r) + add %r25,%r29,%r25 ; r25 = lo(10001 x r) + shd %r1,%r29,28,%r29 ; r29 = hi(10000 x r) + addc %r29,%r1,%r29 ; r29 = hi(10001 x r) +; r in r29,,r25 + zdep %r25,23,24,%r1 ; r1 = lo(100000000 x r) + add %r1,%r25,%r1 ; r1 = lo(100000001 x r) + shd %r29,%r25,24,%r25 ; r25 = hi(100000000 x r) + addc %r25,%r29,%r25 ; r25 = hi(100000001 x r) +; r in r25,,r1 + zdep %r1,15,16,%r29 + add %r29,%r1,%r29 + shd %r25,%r1,16,%r1 + addc %r1,%r25,%r1 +; r in r1,,r29 + sh1add %r29,%r26,%r0 ; r0 = lo(10 x r) + dividend + shd %r1,%r29,31,%r29 ; r29 = hi(10 x r) + addc %r29,%r0,%r29 + bv 0(ret) + extru %r29,28,29,result + .exit + .procend +#endif + + +#ifdef L_divU_3 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_3 +$$divU_3 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 3,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_5 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_5 +$$divU_5 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 5,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_6 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_6 +$$divU_6 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 6,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_7 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_7 +$$divU_7 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 7,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_9 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_9 +$$divU_9 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 9,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_10 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_10 +$$divU_10 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 10,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_12 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_12 +$$divU_12 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 12,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_14 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_14 +$$divU_14 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 14,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divU_15 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divU_15 +$$divU_15 + .proc + .callinfo frame=0,no_calls + .entry + b $$divU + ldi 15,%r25 + .exit + .procend + .import $$divU,MILLICODE +#endif + +#ifdef L_divI_3 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_3 +$$divI_3 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 3,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_5 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_5 +$$divI_5 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 5,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_6 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_6 +$$divI_6 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 6,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_7 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_7 +$$divI_7 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 7,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_9 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_9 +$$divI_9 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 9,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_10 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_10 +$$divI_10 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 10,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_12 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_12 +$$divI_12 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 12,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_14 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_14 +$$divI_14 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 14,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif + +#ifdef L_divI_15 + .space $TEXT$ + .subspa $MILLICODE$,quad=0,align=8,access=0x2c,sort=8 + .align 4 + .export $$divI_15 +$$divI_15 + .proc + .callinfo frame=0,no_calls + .entry + b $$divI + ldi 15,%r25 + .exit + .procend + .import $$divI,MILLICODE +#endif diff --git a/gnu/usr.bin/gcc/config/pa/pa-gas.h b/gnu/usr.bin/gcc/config/pa/pa-gas.h new file mode 100644 index 00000000000..d7da9e733b1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/pa-gas.h @@ -0,0 +1,21 @@ +/* Definitions of target machine for GNU compiler, for HP-UX using GNU as. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */ diff --git a/gnu/usr.bin/gcc/config/pa/pa-hpux10.h b/gnu/usr.bin/gcc/config/pa/pa-hpux10.h new file mode 100644 index 00000000000..ab7cee39389 --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/pa-hpux10.h @@ -0,0 +1,71 @@ +/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1 + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Tim Moore (moore@defmacro.cs.utah.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. */ + +/* We can debug dynamically linked executables on hpux9; we also want + dereferencing of a NULL pointer to cause a SEGV. */ +#undef LINK_SPEC +#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) +#define LINK_SPEC \ + "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }} -z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" +#else +#define LINK_SPEC \ + "-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}" +#endif + +/* The hpux10 assembler requires a .LEVEL pseudo-op at the start of + the assembly file. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +do { \ + if (TARGET_SNAKE) \ + fputs("\t.LEVEL 1.1\n", FILE); \ + else \ + fputs("\t.LEVEL 1.0\n", FILE); \ + fputs ("\t.SPACE $PRIVATE$\n\ +\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\ +\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\ +\t.SPACE $TEXT$\n\ +\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\ +\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\ +\t.IMPORT $global$,DATA\n\ +\t.IMPORT $$dyncall,MILLICODE\n", FILE);\ + if (profile_flag)\ + fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\ + if (write_symbols != NO_DEBUG) \ + output_file_directive ((FILE), main_input_filename); \ + } while (0) + +/* Under hpux10, the normal location of the `ld' and `as' programs is the + /usr/ccs/bin directory. */ + +#ifndef CROSS_COMPILE +#undef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/ccs/bin/" +#endif + +/* Under hpux10, the normal location of the various *crt*.o files is the + /usr/ccs/lib directory. */ + +#ifndef CROSS_COMPILE +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" +#endif + diff --git a/gnu/usr.bin/gcc/config/pa/pa-pro-end.h b/gnu/usr.bin/gcc/config/pa/pa-pro-end.h new file mode 100644 index 00000000000..8b1de1c5e5f --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/pa-pro-end.h @@ -0,0 +1,41 @@ +/* Definitions of target machine for GNU compiler, for PRO. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Make GCC agree with types.h. */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE + +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" + +/* Like the default, except no -lg. */ +#undef LIB_SPEC +#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dhppa -DPWB -Acpu(hppa) -Amachine(hppa)" + +/* hpux8 and later have C++ compatible include files, so do not + pretend they are `extern "C"'. */ +#define NO_IMPLICIT_EXTERN_C + +/* We don't want a crt0.o to get linked in automatically, we want the + linker script to pull it in. + */ +#define STARTFILE_SPEC "" diff --git a/gnu/usr.bin/gcc/config/pa/pa-pro.h b/gnu/usr.bin/gcc/config/pa/pa-pro.h new file mode 100644 index 00000000000..f64ac2dc54c --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/pa-pro.h @@ -0,0 +1,78 @@ +/* Definitions of target machine for GNU compiler, for PRO. + Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Global constructor and destructor support. */ +/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. + + Note that we want to give these sections the SHF_WRITE attribute + because these sections will actually contain data (i.e. tables of + addresses of functions in the current root executable or shared library + file) and, in the case of a shared library, the relocatable addresses + will have to be properly resolved/relocated (and then written into) by + the dynamic linker when it actually attaches the given shared library + to the executing process. */ + +#define CTORS_SECTION_ASM_OP "\t.section\t\".ctors\",#alloc,#write" +#define DTORS_SECTION_ASM_OP "\t.section\t\".dtors\",#alloc,#write" + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fputs ("\t.word\t ", FILE); \ + assemble_name (FILE, NAME); \ + fputs ("\n", FILE); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fputs ("\t.word\t ", FILE); \ + assemble_name (FILE, NAME); \ + fputs ("\n", FILE); \ + } while (0) + +/* JUMP_IN_DELAY + PORTABLE_RUNTIME + GAS + NO_SPACE_REGS + SOFT_FLOAT */ +#define TARGET_DEFAULT (4 + 8 + 64 + 128 + 256) diff --git a/gnu/usr.bin/gcc/config/pa/rtems.h b/gnu/usr.bin/gcc/config/pa/rtems.h new file mode 100644 index 00000000000..eebfd4f5cc1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/rtems.h @@ -0,0 +1,26 @@ +/* Definitions of target machine for GNU compiler, for PRO. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dhppa -DPWB -Acpu(hppa) -Amachine(hppa) \ + -Drtems -D__rtems__ -Asystem(rtems)" diff --git a/gnu/usr.bin/gcc/config/pa/t-pro b/gnu/usr.bin/gcc/config/pa/t-pro new file mode 100644 index 00000000000..f40b2e4e4d7 --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/t-pro @@ -0,0 +1,38 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1 = libgcc1.null +LIB1ASMSRC = +LIB1ASMFUNCS = + +LIBGCC1_TEST = + +ADA_CFLAGS=-mdisable-indexing + +LIB2FUNCS_EXTRA=fp-bit.c dp-bit.c lib2funcs.asm ee.asm ee_fp.asm + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +lib2funcs.asm: $(srcdir)/config/pa/lib2funcs.asm + rm -f lib2funcs.asm + cp $(srcdir)/config/pa/lib2funcs.asm . + +ee.asm: $(srcdir)/config/pa/ee.asm + rm -f ee.asm + cp $(srcdir)/config/pa/ee.asm . + +ee_fp.asm: $(srcdir)/config/pa/ee_fp.asm + rm -f ee_fp.asm + cp $(srcdir)/config/pa/ee_fp.asm . + +# Build the libraries for both speed and space optimizations + +MULTILIB_OPTIONS=mspace +MULTILIB_DIRNAMES=space +MULTILIB_MATCHES= + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/gnu/usr.bin/gcc/config/pa/xm-papro.h b/gnu/usr.bin/gcc/config/pa/xm-papro.h new file mode 100644 index 00000000000..d36e2015ce7 --- /dev/null +++ b/gnu/usr.bin/gcc/config/pa/xm-papro.h @@ -0,0 +1,58 @@ +/* Configuration for GNU C-compiler for PA-RISC. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@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. */ + +extern int errno; + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Doubles are stored in memory with the high order word first. This + matters when cross-compiling. */ +#define HOST_WORDS_BIG_ENDIAN 1 + +/* Place any machine-dependent include files here, in case we + are bootstrapping. */ + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ +#include "tm.h" + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +/* Don't try to use sys_siglist. */ +#define NO_SYS_SIGLIST + +/* HP's compiler has problems with enum bitfields. */ +#define ONLY_INT_FIELDS + +/* Always claim to use C alloca; this prevents losing if building with + gcc -fno-builtin ... */ +#define USE_C_ALLOCA diff --git a/gnu/usr.bin/gcc/config/psos.h b/gnu/usr.bin/gcc/config/psos.h new file mode 100644 index 00000000000..d4043002a1c --- /dev/null +++ b/gnu/usr.bin/gcc/config/psos.h @@ -0,0 +1,183 @@ +/* Operating system specific defines to be used when targeting GCC for some + embedded system running pSOS. We assume GNU tools with ELF, but + try to maintain compatibility with the MRI tools. Based on svr4.h. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. + + To use this file, make up a file with a name like: + + ?????-psos.h + + where ????? is replaced by the name of the basic hardware that you + are targeting for. Then, in the file ?????-psos.h, put something + like: + + #include "?????.h" + #include "psos.h" + + followed by any really system-specific defines (or overrides of + defines) which you find that you need. +*/ + + +/* Define a symbol indicating that we are using psos.h. */ + +#define USING_PSOS_H + + +/* All pSOS targets currently use the ELF object file format. */ + +#define OBJECT_FORMAT_ELF + + +/* Provide a NULL STARTFILE_SPEC. The startfile cannot be specified + here because it depends on the architecture (e.g. 68K), the + board-support package (e.g. M162) and the run-time configuration + (e.g. application vs. ram-image vs. rom-image). Specify the + startfile in a linker-script created from the generic + architecture-specific linker-scripts. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + + +/* Predefined macros (independent of processor type). */ + +#define CPP_PREDEFINES "-Dpsos" + + +/* Implicit library calls should use ANSI memcpy rather than BSD + bcopy, etc. */ + +#define TARGET_MEM_FUNCTIONS + + +/* When using stabs, gcc2_compiled must be a stabs entry, not an + ordinary symbol, or gdb won't see it. The stabs entry must be + before the N_SO in order for gdb to find it. */ + +#define ASM_IDENTIFY_GCC(FILE) \ +do \ + { \ + fputs (".stabs \"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \ + } \ +while (0) + +/* This is how we tell the assembler that a symbol is weak. */ + +#define ASM_WEAKEN_LABEL(FILE,NAME) \ + do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); } while (0) + +/* Switch into a generic section. */ + +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") + + +/* Define the pseudo-ops used to switch to the .ctors and .dtors + sections. */ + +#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" +#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" + +/* A default list of other sections which we might be "in" at any given + time. For targets that use additional sections (e.g. .tdesc) you + should override this definition in the target-specific file which + includes this file. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_ctors, in_dtors + +/* A default list of extra section function definitions. For targets + that use additional sections (e.g. .tdesc) you should override this + definition in the target-specific file which includes this file. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +extern void text_section (); + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ + +#ifndef INT_ASM_OP +#define INT_ASM_OP ".long" +#endif +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ + +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + + +/* Use DBX debugging info by default. */ + +#ifndef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#endif + +/* For pSOS we use DBX debugging info. */ + +#define DBX_DEBUGGING_INFO + + +/* Prevent generation of an exit function. */ + +#define HAVE_ATEXIT + diff --git a/gnu/usr.bin/gcc/config/ptx4.h b/gnu/usr.bin/gcc/config/ptx4.h new file mode 100644 index 00000000000..db761655674 --- /dev/null +++ b/gnu/usr.bin/gcc/config/ptx4.h @@ -0,0 +1,859 @@ +/* Operating system specific defines to be used when targeting GCC for some + generic System V Release 4 system. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Ron Guilmette (rfg@monkeys.com). + Renamed and changed to suit Dynix/ptx v4 and later. + Modified by Tim Wright (timw@sequent.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. + +*/ + +/* Define a symbol indicating that we are using svr4.h. */ +#define USING_SVR4_H + +/* For the sake of libgcc2.c, indicate target supports atexit. */ +#define HAVE_ATEXIT + +/* Cpp, assembler, linker, library, and startfile spec's. */ + +/* This defines which switch letters take arguments. On svr4, most of + the normal cases (defined in gcc.c) apply, and we also have -h* and + -z* options (for the linker). Note however that there is no such + thing as a -T option for svr4. */ + +#define SWITCH_TAKES_ARG(CHAR) \ + ( (CHAR) == 'D' \ + || (CHAR) == 'U' \ + || (CHAR) == 'o' \ + || (CHAR) == 'e' \ + || (CHAR) == 'u' \ + || (CHAR) == 'I' \ + || (CHAR) == 'm' \ + || (CHAR) == 'L' \ + || (CHAR) == 'A' \ + || (CHAR) == 'h' \ + || (CHAR) == 'z') + +/* This defines which multi-letter switches take arguments. On svr4, + there are no such switches except those implemented by GCC itself. */ + +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + && strcmp (STR, "Tdata") && strcmp (STR, "Ttext") \ + && strcmp (STR, "Tbss")) + +/* You should redefine CPP_PREDEFINES in any file which includes this one. + The definition should be appropriate for the type of target system + involved, and it should include any -A (assertion) options which are + appropriate for the given target system. */ +#undef CPP_PREDEFINES + +/* Provide an ASM_SPEC appropriate for svr4. Here we try to support as + many of the specialized svr4 assembler options as seems reasonable, + given that there are certain options which we can't (or shouldn't) + support directly due to the fact that they conflict with other options + for other svr4 tools (e.g. ld) or with other options for GCC itself. + For example, we don't support the -o (output file) or -R (remove + input file) options because GCC already handles these things. We + also don't support the -m (run m4) option for the assembler because + that conflicts with the -m (produce load map) option of the svr4 + linker. We do however allow passing arbitrary options to the svr4 + assembler via the -Wa, option. + + Note that gcc doesn't allow a space to follow -Y in a -Ym,* or -Yd,* + option. +*/ + +#undef ASM_SPEC +#define ASM_SPEC \ + "-no_0f_fix %{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}" + +/* svr4 assemblers need the `-' (indicating input from stdin) to come after + the -o option (and its argument) for some reason. If we try to put it + before the -o option, the assembler will try to read the file named as + the output file in the -o option as an input file (after it has already + written some stuff to it) and the binary stuff contained therein will + cause totally confuse the assembler, resulting in many spurious error + messages. */ + +#undef ASM_FINAL_SPEC +#define ASM_FINAL_SPEC "%{pipe:-}" + +/* Provide a LIB_SPEC appropriate for svr4. Here we tack on the default + standard C library (unless we are building a shared library). */ + +#undef LIB_SPEC +#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}" + +/* Provide a LIBGCC_SPEC appropriate for svr4. We also want to exclude + libgcc when -symbolic. */ + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "%{!shared:%{!symbolic:-lgcc}}" + +/* Provide an ENDFILE_SPEC appropriate for svr4. Here we tack on our own + 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 the normal svr3/svr4 "finalizer" file, + which is either `gcrtn.o' or `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}" + +/* Provide a LINK_SPEC appropriate for svr4. Here we provide support + for the special GCC options -static, -shared, and -symbolic which + allow us to link things in one of these three modes by applying the + appropriate combinations of options at link-time. We also provide + support here for as many of the other svr4 linker options as seems + reasonable, given that some of them conflict with options for other + svr4 tools (e.g. the assembler). In particular, we do support the + -z*, -V, -b, -t, -Qy, -Qn, and -YP* options here, and the -e*, + -l*, -o*, -r, -s, -u*, and -L* options are directly supported + by gcc.c itself. We don't directly support the -m (generate load + map) option because that conflicts with the -m (run m4) option of + the svr4 assembler. We also don't directly support the svr4 linker's + -I* or -M* options because these conflict with existing GCC options. + We do however allow passing arbitrary options to the svr4 linker + via the -Wl, option. We don't support the svr4 linker's -a option + at all because it is totally useless and because it conflicts with + GCC's own -a option. + + Note that gcc doesn't allow a space to follow -Y in a -YP,* option. + + When the -G link option is used (-shared and -symbolic) a final link is + not being done. */ + +#undef LINK_SPEC +#define LINK_SPEC "%{h*} %{v:-V} \ + %{b} %{Wl,*:%*} \ + %{static:-dn -Bstatic} \ + %{shared:-G -dy -z text} \ + %{symbolic:-Bsymbolic -G -dy -z text} \ + %{G:-G} \ + %{YP,*} \ + %{!YP,*:%{p:-Y P,/lib/libp:/usr/lib/libp:/lib:/usr/lib} \ + %{!p:-Y P,/lib:/usr/lib}} \ + %{Qy:} %{!Qn:-Qy}" + +/* Gcc automatically adds in one of the files /lib/values-Xc.o, + /lib/values-Xa.o, or /lib/values-Xt.o for each final link + step (depending upon the other gcc options selected, such as + -traditional and -ansi). These files each contain one (initialized) + copy of a special variable called `_lib_version'. Each one of these + files has `_lib_version' initialized to a different (enum) value. + The SVR4 library routines query the value of `_lib_version' at run + to decide how they should behave. Specifically, they decide (based + upon the value of `_lib_version') if they will act in a strictly ANSI + conforming manner or not. +*/ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\ + %{pg:gcrti.o%s}%{!pg:crti.o%s} \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}} \ + crtbegin.o%s" + +/* Attach a special .ident directive to the end of the file to identify + the version of GCC which compiled this code. The format of the + .ident string is patterned after the ones produced by native svr4 + C compilers. */ + +#define IDENT_ASM_OP ".ident" + +#define ASM_FILE_END(FILE) \ +do { \ + fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ + } while (0) + +/* Allow #sccs in preprocessor. */ + +#define SCCS_DIRECTIVE + +/* Output #ident as a .ident. */ + +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +/* Use periods rather than dollar signs in special g++ assembler names. */ + +#define NO_DOLLAR_IN_LABEL + +/* Writing `int' for a bitfield forces int alignment for the structure. */ + +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* Implicit library calls should use memcpy, not bcopy, etc. */ + +#define TARGET_MEM_FUNCTIONS + +/* Handle #pragma weak and #pragma pack. */ + +#define HANDLE_SYSV_PRAGMA + +/* System V Release 4 uses DWARF debugging info. */ + +#define DWARF_DEBUGGING_INFO + +/* The numbers used to denote specific machine registers in the System V + Release 4 DWARF debugging information are quite likely to be totally + different from the numbers used in BSD stabs debugging information + for the same kind of target machine. Thus, we undefine the macro + DBX_REGISTER_NUMBER here as an extra inducement to get people to + provide proper machine-specific definitions of DBX_REGISTER_NUMBER + (which is also used to provide DWARF registers numbers in dwarfout.c) + in their tm.h files which include this file. */ + +#undef DBX_REGISTER_NUMBER + +/* gas on SVR4 supports the use of .stabs. Permit -gstabs to be used + in general, although it will only work when using gas. */ + +#define DBX_DEBUGGING_INFO + +/* Use DWARF debugging info by default. */ + +#ifndef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG +#endif + +/* Make LBRAC and RBRAC addresses relative to the start of the + function. The native Solaris stabs debugging format works this + way, gdb expects it, and it reduces the number of relocation + entries. */ + +#define DBX_BLOCKS_FUNCTION_RELATIVE 1 + +/* When using stabs, gcc2_compiled must be a stabs entry, not an + ordinary symbol, or gdb won't see it. The stabs entry must be + before the N_SO in order for gdb to find it. */ + +#define ASM_IDENTIFY_GCC(FILE) \ +do \ + { \ + if (write_symbols != DBX_DEBUG) \ + fputs ("gcc2_compiled.:\n", FILE); \ + else \ + fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \ + } \ +while (0) + +/* Like block addresses, stabs line numbers are relative to the + current function. */ + +#define ASM_OUTPUT_SOURCE_LINE(file, line) \ +do \ + { \ + static int sym_lineno = 1; \ + 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; \ + } \ +while (0) + +/* In order for relative line numbers to work, we must output the + stabs entry for the function name first. */ + +#define DBX_FUNCTION_FIRST + +/* Generate a blank trailing N_SO to mark the end of the .o file, since + we can't depend upon the linker to mark .o file boundaries with + embedded stabs. */ + +#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ + fprintf (FILE, \ + "\t.text\n\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO) + +/* Define the actual types of some ANSI-mandated types. (These + definitions should work for most SVR4 systems). */ + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* This causes trouble, because it requires the host machine + to support ANSI C. */ +/* #define MULTIBYTE_CHARS */ + +#undef ASM_BYTE_OP +#define ASM_BYTE_OP ".byte" + +#undef SET_ASM_OP +#define SET_ASM_OP ".set" + +/* This is how to begin an assembly language file. Most svr4 assemblers want + at least a .file directive to come first, and some want to see a .version + directive come right after that. Here we just establish a default + which generates only the .file directive. If you need a .version + directive for any specific target, you should override this definition + in the target-specific file which includes this one. */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_directive ((FILE), main_input_filename) + +/* This is how to allocate empty space in some section. The .zero + pseudo-op is used for this on most svr4 assemblers. */ + +#define SKIP_ASM_OP ".zero" + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE)) + +/* The prefix to add to user-visible assembler symbols. + + For System V Release 4 the convention is *not* to prepend a leading + underscore onto user-level symbol names. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +/* 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 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) \ +do { \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \ +} while (0) + +/* This is how to store into the string LABEL + 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'. + + For most svr4 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_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ +do { \ + sprintf (LABEL, "*.%s%d", PREFIX, NUM); \ +} while (0) + +/* Output the label which precedes a jumptable. Note that for all svr4 + systems where we actually generate jumptables (which is to say every + svr4 target except i386, where we use casesi instead) we put the jump- + tables into the .rodata section and since other stuff could have been + put into the .rodata section prior to any given jumptable, we have to + make sure that the location counter for the .rodata section gets pro- + perly re-aligned prior to the actual beginning of the jump table. */ + +#define ALIGN_ASM_OP ".align" + +#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL +#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + ASM_OUTPUT_ALIGN ((FILE), 2); +#endif + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ + do { \ + ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ + } while (0) + +/* The standard SVR4 assembler seems to require that certain builtin + library routines (e.g. .udiv) be explicitly declared as .globl + in each assembly file where they are referenced. */ + +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) + +/* This says how to output assembler code to declare an + uninitialized external linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#define COMMON_ASM_OP ".comm" + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ +} while (0) + +/* This says how to output assembler code to declare an + uninitialized internal linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#define LOCAL_ASM_OP ".local" + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +/* This is the pseudo-op used to generate a 32-bit word of data with a + specific value in some section. This is the same for all known svr4 + assemblers. */ + +#define INT_ASM_OP ".long" + +/* This is the pseudo-op used to generate a contiguous sequence of byte + values from a double-quoted string WITHOUT HAVING A TERMINATING NUL + AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */ + +#undef ASCII_DATA_ASM_OP +#define ASCII_DATA_ASM_OP ".ascii" + +/* Support const sections and the ctors and dtors sections for g++. + Note that there appears to be two different ways to support const + sections at the moment. You can either #define the symbol + READONLY_DATA_SECTION (giving it some code which switches to the + readonly data section) or else you can #define the symbols + EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and + SELECT_RTX_SECTION. We do both here just to be on the safe side. */ + +#define USE_CONST_SECTION 1 + +#define CONST_SECTION_ASM_OP ".section\t.rodata" + +/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. + + Note that we want to give these sections the SHF_WRITE attribute + because these sections will actually contain data (i.e. tables of + addresses of functions in the current root executable or shared library + file) and, in the case of a shared library, the relocatable addresses + will have to be properly resolved/relocated (and then written into) by + the dynamic linker when it actually attaches the given shared library + to the executing process. (Note that on SVR4, you may wish to use the + `-z text' option to the ELF linker, when building a shared library, as + an additional check that you are doing everything right. But if you do + use the `-z text' option when building a shared library, you will get + errors unless the .ctors and .dtors sections are marked as writable + via the SHF_WRITE attribute.) */ + +#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" +#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" + +/* On svr4, we *do* have support for the .init and .fini sections, and we + can put stuff in there to be executed before and after `main'. We let + crtstuff.c and other files know this by defining the following symbols. + The definitions say how to change sections to the .init and .fini + sections. This is the same for all known svr4 assemblers. */ + +#define INIT_SECTION_ASM_OP ".section\t.init" +#define FINI_SECTION_ASM_OP ".section\t.fini" + +/* A default list of other sections which we might be "in" at any given + time. For targets that use additional sections (e.g. .tdesc) you + should override this definition in the target-specific file which + includes this file. */ + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_ctors, in_dtors + +/* A default list of extra section function definitions. For targets + that use additional sections (e.g. .tdesc) you should override this + definition in the target-specific file which includes this file. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#define READONLY_DATA_SECTION() const_section () + +extern void text_section (); + +#define CONST_SECTION_FUNCTION \ +void \ +const_section () \ +{ \ + if (!USE_CONST_SECTION) \ + text_section(); \ + else if (in_section != in_const) \ + { \ + fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ + in_section = in_const; \ + } \ +} + +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +/* Switch into a generic section. + This is currently only used to support section attributes. + + 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. */ +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") + + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } 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. */ + +#define SELECT_SECTION(DECL,RELOC) \ +{ \ + if (TREE_CODE (DECL) == STRING_CST) \ + { \ + if (! flag_writable_strings) \ + const_section (); \ + else \ + data_section (); \ + } \ + else if (TREE_CODE (DECL) == VAR_DECL) \ + { \ + if ((flag_pic && RELOC) \ + || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ + || !DECL_INITIAL (DECL) \ + || (DECL_INITIAL (DECL) != error_mark_node \ + && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else \ + const_section (); \ +} + +/* A C statement or statements to switch to the appropriate + section for output of RTX in mode MODE. RTX is some kind + of constant in RTL. The argument MODE is redundant except + in the case of a `const_int' rtx. Currently, these always + go into the const section. */ + +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) const_section() + +/* Define the strings used for the special svr4 .type and .size directives. + These strings generally do not vary from one system running svr4 to + another, but if a given system (e.g. m88k running svr) needs to use + different pseudo-op names for these, they may be overridden in the + file which includes this one. */ + +#define TYPE_ASM_OP ".type" +#define SIZE_ASM_OP ".size" + +/* This is how we tell the assembler that a symbol is weak. */ + +#define ASM_WEAKEN_LABEL(FILE,NAME) \ + do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ + fputc ('\n', FILE); } while (0) + +/* The following macro defines the format used to output the second + operand of the .type assembler directive. Different svr4 assemblers + expect various different forms for this operand. The one given here + is just a default. You may need to override it in your machine- + specific tm.h file (depending upon the particulars of your assembler). */ + +#define TYPE_OPERAND_FMT "@%s" + +/* Write the extra assembler code needed to declare a function's result. + Most svr4 assemblers don't require any special declaration of the + result value, but there are exceptions. */ + +#ifndef ASM_DECLARE_RESULT +#define ASM_DECLARE_RESULT(FILE, RESULT) +#endif + +/* 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. */ + +#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) + +/* Write the extra assembler code needed to declare an object properly. */ + +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ + putc ('\n', FILE); \ + size_directive_output = 0; \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } while (0) + +/* Output the size directive for a decl in rest_of_decl_compilation + in the case where we did not do so before the initializer. + Once we find the error_mark_node, we know that the value of + size_directive_output was set + by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ + +#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ +do { \ + char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ + && ! AT_END && TOP_LEVEL \ + && DECL_INITIAL (DECL) == error_mark_node \ + && !size_directive_output) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, name); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + } while (0) + +/* This is how to declare the size of a function. */ + +#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) + +/* A table of bytes codes used by the ASM_OUTPUT_ASCII and + ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table + corresponds to a particular byte value [0..255]. For any + given byte value, if the value in the corresponding table + position is zero, the given character can be output directly. + If the table value is 1, the byte must be output as a \ooo + octal escape. If the tables value is anything else, then the + byte value should be output as a \ followed by the value + in the table. Note that we can use standard UN*X escape + sequences for many control characters, but we don't use + \a to represent BEL because some svr4 assemblers (e.g. on + the i386) don't know about that. Also, we don't use \v + since some versions of gas, such as 2.2 did not accept it. */ + +#define ESCAPES \ +"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" + +/* Some svr4 assemblers have a limit on the number of characters which + can appear in the operand of a .string directive. If your assembler + has such a limitation, you should define STRING_LIMIT to reflect that + limit. Note that at least some svr4 assemblers have a limit on the + actual number of bytes in the double-quoted string, and that they + count each character in an escape sequence as one byte. Thus, an + escape sequence like \377 would count as four bytes. + + If your target assembler doesn't support the .string directive, you + should define this to zero. +*/ + +#define STRING_LIMIT ((unsigned) 256) + +#define STRING_ASM_OP ".string" + +/* 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). */ + +#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) + +/* The routine used to output sequences of byte values. 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. Note that if we find subparts of the + character sequence which end with NUL (and which are shorter than + STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */ + +#undef ASM_OUTPUT_ASCII +#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ + do \ + { \ + register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ + register unsigned char *limit = _ascii_bytes + (LENGTH); \ + register unsigned bytes_in_chunk = 0; \ + for (; _ascii_bytes < limit; _ascii_bytes++) \ + { \ + register unsigned char *p; \ + if (bytes_in_chunk >= 60) \ + { \ + fprintf ((FILE), "\"\n"); \ + bytes_in_chunk = 0; \ + } \ + for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ + continue; \ + if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ + { \ + if (bytes_in_chunk > 0) \ + { \ + fprintf ((FILE), "\"\n"); \ + bytes_in_chunk = 0; \ + } \ + ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ + _ascii_bytes = p; \ + } \ + else \ + { \ + register int escape; \ + register unsigned ch; \ + if (bytes_in_chunk == 0) \ + fprintf ((FILE), "\t%s\t\"", ASCII_DATA_ASM_OP); \ + switch (escape = ESCAPES[ch = *_ascii_bytes]) \ + { \ + case 0: \ + putc (ch, (FILE)); \ + bytes_in_chunk++; \ + break; \ + case 1: \ + fprintf ((FILE), "\\%03o", ch); \ + bytes_in_chunk += 4; \ + break; \ + default: \ + putc ('\\', (FILE)); \ + putc (escape, (FILE)); \ + bytes_in_chunk += 2; \ + break; \ + } \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\"\n"); \ + } \ + while (0) + +/* All SVR4 targets use the ELF object file format. */ +#define OBJECT_FORMAT_ELF diff --git a/gnu/usr.bin/gcc/config/rs6000/cygwin32.h b/gnu/usr.bin/gcc/config/rs6000/cygwin32.h new file mode 100644 index 00000000000..f527736a020 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/cygwin32.h @@ -0,0 +1,67 @@ +/* Operating system specific defines to be used when targeting GCC for + hosting on Windows NT 3.x, using the Cygnus API + + This is different to the winnt.h file, since that is used + to build GCC for use with a windows style library and tool + set, winnt.h uses the Microsoft tools to do that. + + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* Ugly hack */ +#include "rs6000/win-nt.h" + + +#ifdef CPP_PREDEFINES +#undef CPP_PREDEFINES +#endif + +#define CPP_PREDEFINES "-D_WIN32 -DWINNT -D__CYGWIN32__ -DPOSIX \ + -D_POWER -D_ARCH_PPC -D__PPC__ -Asystem(winnt) -Acpu(powerpc) -Amachine(powerpc)" + +#undef CPP_SPEC +#define CPP_SPEC "-remap %{posix: -D_POSIX_SOURCE} %(cpp_cpu)" + +/* We have to dynamic link to get to the system DLLs. All of libc, libm and + the Unix stuff is in cygwin.dll. The import library is called + 'libcygwin.a'. For Windows applications, include more libraries, but + always include kernel32. We'd like to specific subsystem windows to + ld, but that doesn't work just yet. */ + +#undef LIB_SPEC +#define LIB_SPEC "-lcygwin %{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32" + +#undef LINK_SPEC +#define LINK_SPEC "%{v:-V}" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crti%O%s crt0%O%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtn%O%s" + +#define PTRDIFF_TYPE "int" +#define WCHAR_UNSIGNED 1 +#define WCHAR_TYPE_SIZE 16 +#define WCHAR_TYPE "short unsigned int" + +#define DBX_DEBUGGING_INFO +#undef SDB_DEBUGGING_INFO +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG diff --git a/gnu/usr.bin/gcc/config/rs6000/eabi-ci.asm b/gnu/usr.bin/gcc/config/rs6000/eabi-ci.asm new file mode 100644 index 00000000000..6b753ca1239 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/eabi-ci.asm @@ -0,0 +1,119 @@ +# crti.s for eabi + +# Copyright (C) 1996 Free Software Foundation, Inc. +# Written By Michael Meissner +# +# This file 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. +# +# In addition to the permissions in the GNU General Public License, the +# Free Software Foundation gives you unlimited permission to link the +# compiled version of this file with other programs, and to distribute +# those programs without any restriction coming from the use of this +# file. (The General Public License restrictions do apply in other +# respects; for example, they cover modification of the file, and +# distribution when not linked into another program.) +# +# This file 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 this program; 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. +# + +# This file just supplies labeled starting points for the .got* and other +# special sections. It is linked in first before other modules. + + .file "crti.s" + .ident "GNU C crti.s" + +#include <ppc-asm.h> + + .section ".got","aw" + .globl __GOT_START__ + .type __GOT_START__,@object +__GOT_START__: + + .section ".got1","aw" + .globl __GOT1_START__ + .type __GOT1_START__,@object +__GOT1_START__: + + .section ".got2","aw" + .globl __GOT2_START__ + .type __GOT2_START__,@object +__GOT2_START__: + + .section ".fixup","aw" + .globl __FIXUP_START__ + .type __FIXUP_START__,@object +__FIXUP_START__: + + .section ".ctors","aw" + .globl __CTOR_LIST__ + .type __CTOR_LIST__,@object +__CTOR_LIST__: + + .section ".dtors","aw" + .globl __DTOR_LIST__ + .type __DTOR_LIST__,@object +__DTOR_LIST__: + + .section ".sdata","aw" + .globl __SDATA_START__ + .type __SDATA_START__,@object + .weak _SDA_BASE_ + .type _SDA_BASE_,@object +__SDATA_START__: +_SDA_BASE_: + + .section ".sbss","aw",@nobits + .globl __SBSS_START__ + .type __SBSS_START__,@object +__SBSS_START__: + + .section ".sdata2","a" + .weak _SDA2_BASE_ + .type _SDA2_BASE_,@object + .globl __SDATA2_START__ + .type __SDATA2_START__,@object +__SDATA2_START__: +_SDA2_BASE_: + + .section ".sbss2","a" + .globl __SBSS2_START__ + .type __SBSS2_START__,@object +__SBSS2_START__: + + .section ".gcc_except_table","aw" + .globl __EXCEPT_START__ + .type __EXCEPT_START__,@object +__EXCEPT_START__: + +# Head of __init function used for static constructors in Solaris + .section ".init","ax" + .align 2 +FUNC_START(__init) + stwu 1,-8(1) + mflr 0 + stw 0,12(1) + +# Head of __fini function used for static destructors in Solaris + .section ".fini","ax" + .align 2 +FUNC_START(__fini) + stwu 1,-8(1) + mflr 0 + stw 0,12(1) diff --git a/gnu/usr.bin/gcc/config/rs6000/eabi-cn.asm b/gnu/usr.bin/gcc/config/rs6000/eabi-cn.asm new file mode 100644 index 00000000000..06e895638dc --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/eabi-cn.asm @@ -0,0 +1,109 @@ +# crtn.s for eabi + +# Copyright (C) 1996 Free Software Foundation, Inc. +# Written By Michael Meissner +# +# This file 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. +# +# In addition to the permissions in the GNU General Public License, the +# Free Software Foundation gives you unlimited permission to link the +# compiled version of this file with other programs, and to distribute +# those programs without any restriction coming from the use of this +# file. (The General Public License restrictions do apply in other +# respects; for example, they cover modification of the file, and +# distribution when not linked into another program.) +# +# This file 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 this program; 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. +# + +# This file just supplies labeled ending points for the .got* and other +# special sections. It is linked in last after other modules. + + .file "crtn.s" + .ident "GNU C crtn.s" + + .section ".got","aw" + .globl __GOT_END__ + .type __GOT_END__,@object +__GOT_END__: + + .section ".got1","aw" + .globl __GOT1_END__ + .type __GOT1_END__,@object +__GOT1_END__: + + .section ".got2","aw" + .globl __GOT2_END__ + .type __GOT2_END__,@object +__GOT2_END__: + + .section ".fixup","aw" + .globl __FIXUP_END__ + .type __FIXUP_END__,@object +__FIXUP_END__: + + .section ".ctors","aw" + .globl __CTOR_END__ + .type __CTOR_END__,@object +__CTOR_END__: + + .section ".dtors","aw" + .globl __DTOR_END__ + .type __DTOR_END__,@object +__DTOR_END__: + + .section ".sdata","aw" + .globl __SDATA_END__ + .type __SDATA_END__,@object +__SDATA_END__: + + .section ".sbss","aw",@nobits + .globl __SBSS_END__ + .type __SBSS_END__,@object +__SBSS_END__: + + .section ".sdata2","a" + .globl __SDATA2_END__ + .type __SDATA2_END__,@object +__SDATA2_END__: + + .section ".sbss2","a" + .globl __SBSS2_END__ + .type __SBSS2_END__,@object +__SBSS2_END__: + + .section ".gcc_except_table","aw" + .globl __EXCEPT_END__ + .type __EXCEPT_END__,@object +__EXCEPT_END__: + +# Tail of __init used for static constructors in Solaris + .section ".init","ax" + lwz 0,12(1) + mtlr 0 + addi 1,1,8 + blr + +# Tail of __fini used for static destructors in Solaris + .section ".fini","ax" + lwz 0,12(1) + mtlr 0 + addi 1,1,8 + blr diff --git a/gnu/usr.bin/gcc/config/rs6000/linux.h b/gnu/usr.bin/gcc/config/rs6000/linux.h new file mode 100644 index 00000000000..10474e4d5cf --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/linux.h @@ -0,0 +1,67 @@ +/* Definitions of target machine for GNU compiler, + for IBM RS/6000 running AIX version 3.1. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Michael Meissner (meissner@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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "rs6000/sysv4.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-DPPC -Dunix -Dlinux -Dpowerpc -Asystem(unix) -Asystem(linux) -Acpu(powerpc) -Amachine(powerpc)" + +#undef LINK_SPEC +#define LINK_SPEC "-m elf32ppc %{shared:-shared} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \ + %{static:-static}}" + +#undef LIB_DEFAULT_SPEC +#define LIB_DEFAULT_SPEC "%(lib_linux)" + +#undef STARTFILE_DEFAULT_SPEC +#define STARTFILE_DEFAULT_SPEC "%(startfile_linux)" + +#undef ENDFILE_DEFAULT_SPEC +#define ENDFILE_DEFAULT_SPEC "%(endfile_linux)" + +#undef LINK_START_DEFAULT_SPEC +#define LINK_START_DEFAULT_SPEC "%(link_start_linux)" + +#undef LINK_OS_DEFAULT_SPEC +#define LINK_OS_DEFAULT_SPEC "%(link_os_linux)" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (PowerPC GNU/Linux)"); + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "mbig", "mcall-linux" } + +#undef DEFAULT_VTABLE_THUNKS +#define DEFAULT_VTABLE_THUNKS 1 diff --git a/gnu/usr.bin/gcc/config/rs6000/nt-ci.asm b/gnu/usr.bin/gcc/config/rs6000/nt-ci.asm new file mode 100644 index 00000000000..67ca9564abf --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/nt-ci.asm @@ -0,0 +1,48 @@ +# crti.s for Windows NT + +# Copyright (C) 1996 Free Software Foundation, Inc. +# Written By Michael Meissner +# +# This file 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. +# +# In addition to the permissions in the GNU General Public License, the +# Free Software Foundation gives you unlimited permission to link the +# compiled version of this file with other programs, and to distribute +# those programs without any restriction coming from the use of this +# file. (The General Public License restrictions do apply in other +# respects; for example, they cover modification of the file, and +# distribution when not linked into another program.) +# +# This file 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 this program; 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. +# + +# This file just supplies labeled starting points for the static constructors +# and destructors. It is linked in first before other modules. + + .file "crti.s" + .ident "GNU C crti.s" + + .section .ctors,"w" + .globl __CTOR_LIST__ +__CTOR_LIST__: + + .section .dtors,"w" + .globl __DTOR_LIST__ +__DTOR_LIST__: diff --git a/gnu/usr.bin/gcc/config/rs6000/nt-cn.asm b/gnu/usr.bin/gcc/config/rs6000/nt-cn.asm new file mode 100644 index 00000000000..dd6daf29b2e --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/nt-cn.asm @@ -0,0 +1,48 @@ +# crtn.s for Windows NT + +# Copyright (C) 1996 Free Software Foundation, Inc. +# Written By Michael Meissner +# +# This file 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. +# +# In addition to the permissions in the GNU General Public License, the +# Free Software Foundation gives you unlimited permission to link the +# compiled version of this file with other programs, and to distribute +# those programs without any restriction coming from the use of this +# file. (The General Public License restrictions do apply in other +# respects; for example, they cover modification of the file, and +# distribution when not linked into another program.) +# +# This file 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 this program; 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. +# + +# This file just supplies labeled ending points for the static constructors +# and destructors. It is linked in last after other modules. + + .file "crtn.s" + .ident "GNU C crtn.s" + + .section .ctors,"w" + .globl __CTOR_END__ +__CTOR_END__: + + .section .dtors,"w" + .globl __DTOR_END__ +__DTOR_END__: diff --git a/gnu/usr.bin/gcc/config/rs6000/ntstack.asm b/gnu/usr.bin/gcc/config/rs6000/ntstack.asm new file mode 100644 index 00000000000..aa4179e7a79 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/ntstack.asm @@ -0,0 +1,42 @@ +# Allocate stack for NT, inserting stack probes every 4k pages + + .file "ntstack.asm" + +# Setup MS Structured-Exception-Handling + .pdata + .align 2 + .ualong ..__allocate_stack,__allocate_stack.e,0,0,__allocate_stack.b + +# Switch to the relocation section + .reldata + .globl __allocate_stack + .globl ..__allocate_stack +__allocate_stack: + .ualong ..__allocate_stack,.toc + + .text + .align 2 +..__allocate_stack: + .function ..__allocate_stack +__allocate_stack.b: + addi 3,3,15 # round up to 16 byte alignment + lwz 0,0(1) # old stack link + rlwinm 3,3,0,0,28 + srawi. 4,3,12 # get # of pages to check + neg 3,3 # negate so we can use stwux + bgt- 0,.Lcheck + stwux 0,1,3 # small request, just decrement and return + blr + +.Lcheck: + mtctr 4 # number of pages to check + mr 5,1 # tmp pointer +.Lloop: + lwzu 6,-4096(5) # touch the page + bdnz+ .Lloop # and loop back + + stwux 0,1,3 # update stack pointer + blr + +__allocate_stack.e: +FE_MOT_RESVD..__allocate_stack: diff --git a/gnu/usr.bin/gcc/config/rs6000/rtems.h b/gnu/usr.bin/gcc/config/rs6000/rtems.h new file mode 100644 index 00000000000..10c6bf77b57 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/rtems.h @@ -0,0 +1,32 @@ +/* Definitions for rtems targeting a PowerPC using elf. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "rs6000/eabi.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-DPPC -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(powerpc) -Amachine(powerpc)" + +/* rtems is in the SUBTARGET_SWITCHES in rs6000/sysv4.h */ + +/* end of powerpc-rtems.h */ diff --git a/gnu/usr.bin/gcc/config/rs6000/sol-c0.c b/gnu/usr.bin/gcc/config/rs6000/sol-c0.c new file mode 100644 index 00000000000..bf935c3d371 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/sol-c0.c @@ -0,0 +1,122 @@ +/* Solaris PowerPC startfile. */ +/* Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with other files, + some of which are compiled with GCC, to produce an executable, + this library does not by itself 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. */ + +extern char **_environ; + +extern int atexit (void (*__func) (void)); +extern void __init (void) __attribute__ ((__longcall__)); +extern void __fini (void) __attribute__ ((__longcall__)); + +typedef void (*func_ptr) (void); +int (*__atexit)(func_ptr) = atexit; + +/* Exception handling */ +struct ex_shared1 { + void *prev; + void *next; + char *text_start; + char *range_start; + char *text_end; + char *range_end; +}; + +struct ex_shared { + void (*ex_register) (struct ex_shared1 *); + void (*ex_deregister) (struct ex_shared1 *); + struct ex_shared1 shared_info; +}; + +extern char _ex_text0[], _ex_text1[]; +extern char _ex_range0[], _ex_range1[]; +extern void _ex_register (struct ex_shared1 *); +extern void _ex_deregister (struct ex_shared1 *); +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + +struct ex_shared shared __attribute__((section(".ex_shared"))) = { + _ex_register, + _ex_deregister, + { + (void *)0, + (void *)0, + _ex_text0, + _ex_range0, + _ex_text1, + _ex_range1 + } +}; + +static void +deregister (void) +{ + (* shared.ex_deregister) (&shared.shared_info); +} + +/* Start function. */ +void +_start(int argc, char *argv[], char *envp[], void *auxp, void (*termfunc)()) +{ + int ret; + int dummy = 0; + +#if 0 + /* Disable this for now, it causes an impossible reload. */ + /* Load up r13/r2 before we do anything else. */ + __asm__ volatile ("mr %%r13,%0;mr %%r2,%1" : "=r" (dummy) : "r" (&_SDA_BASE_[0]), "r" (&_SDA2_BASE_[0]), "r" (dummy)); +#endif + + _environ = envp + dummy; + + /* Register loader termination function (the || dummy is to make sure the above asm + is not optimized away). */ + if (termfunc) + atexit (termfunc); + + /* Register exception handler if needed */ + if (shared.ex_register) + (* shared.ex_register) (&shared.shared_info); + + if (shared.ex_deregister) + atexit (deregister); + + /* Call any global constructors and destructors. */ + __init (); + + atexit (__fini); + + /* Call the main program now */ + ret = main (argc, argv, envp, auxp); + + /* Return to the os */ + exit (ret); +} + +/* Provide a dummy __eabi in case main got compiled without -mcall-solaris. */ +void +__eabi () +{ +} diff --git a/gnu/usr.bin/gcc/config/rs6000/sol-ci.asm b/gnu/usr.bin/gcc/config/rs6000/sol-ci.asm new file mode 100644 index 00000000000..d0eced3a09c --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/sol-ci.asm @@ -0,0 +1,104 @@ +# crti.s for solaris + +# Copyright (C) 1996 Free Software Foundation, Inc. +# Written By Michael Meissner +# +# This file 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. +# +# In addition to the permissions in the GNU General Public License, the +# Free Software Foundation gives you unlimited permission to link the +# compiled version of this file with other programs, and to distribute +# those programs without any restriction coming from the use of this +# file. (The General Public License restrictions do apply in other +# respects; for example, they cover modification of the file, and +# distribution when not linked into another program.) +# +# This file 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 this program; 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. +# + +# This file just supplies labeled starting points for the .got* and other +# special sections. It is linked in first before other modules. + + .file "scrti.s" + .ident "GNU C scrti.s" + +# Start of .text + .section ".text" + .globl _ex_text0 +_ex_text0: + +# Exception range + .section ".exception_ranges","aw" + .globl _ex_range0 +_ex_range0: + +# List of C++ constructors + .section ".ctors","aw" + .globl __CTOR_LIST__ + .type __CTOR_LIST__,@object +__CTOR_LIST__: + +# List of C++ destructors + .section ".dtors","aw" + .globl __DTOR_LIST__ + .type __DTOR_LIST__,@object +__DTOR_LIST__: + +# Head of __init function used for static constructors in Solaris + .section ".init","ax" + .align 2 + .globl __init + .type __init,@function +__init: stwu %r1,-16(%r1) + mflr %r0 + stw %r31,12(%r1) + stw %r0,16(%r1) + + bl _GLOBAL_OFFSET_TABLE_-4 # get the GOT address + mflr %r31 + +# lwz %r3,_ex_shared0@got(%r31) +# lwz %r4,-8(%r3) # _ex_register or 0 +# cmpi %cr0,%r4,0 +# beq .Lno_reg +# mtlr %r4 +# blrl +#.Lno_reg: + +# Head of __fini function used for static destructors in Solaris + .section ".fini","ax" + .align 2 + .globl __fini + .type __fini,@function +__fini: stwu %r1,-16(%r1) + mflr %r0 + stw %r31,12(%r1) + stw %r0,16(%r1) + + bl _GLOBAL_OFFSET_TABLE_-4 # get the GOT address + mflr %r31 + +# _environ and its evil twin environ, pointing to the environment + .section ".sdata","aw" + .align 2 + .globl _environ + .space 4 + .weak environ + .set environ,_environ diff --git a/gnu/usr.bin/gcc/config/rs6000/sol-cn.asm b/gnu/usr.bin/gcc/config/rs6000/sol-cn.asm new file mode 100644 index 00000000000..2bc992e1391 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/sol-cn.asm @@ -0,0 +1,82 @@ +# crtn.s for solaris + +# Copyright (C) 1996 Free Software Foundation, Inc. +# Written By Michael Meissner +# +# This file 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. +# +# In addition to the permissions in the GNU General Public License, the +# Free Software Foundation gives you unlimited permission to link the +# compiled version of this file with other programs, and to distribute +# those programs without any restriction coming from the use of this +# file. (The General Public License restrictions do apply in other +# respects; for example, they cover modification of the file, and +# distribution when not linked into another program.) +# +# This file 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 this program; 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. +# + +# This file just supplies labeled ending points for the .got* and other +# special sections. It is linked in last after other modules. + + .file "scrtn.s" + .ident "GNU C scrtn.s" + +# Default versions of exception handling register/deregister + .weak _ex_register + .weak _ex_deregister + .set _ex_register,0 + .set _ex_deregister,0 + +# End list of C++ constructors + .section ".ctors","aw" + .globl __CTOR_END__ + .type __CTOR_END__,@object +__CTOR_END__: + +# End list of C++ destructors + .section ".dtors","aw" + .globl __DTOR_END__ + .type __DTOR_END__,@object +__DTOR_END__: + + .section ".text" + .globl _ex_text1 +_ex_text1: + + .section ".exception_ranges","aw" + .globl _ex_range1 +_ex_range1: + +# Tail of __init used for static constructors in Solaris + .section ".init","ax" + lwz %r0,16(%r1) + lwz %r31,12(%r1) + mtlr %r0 + addi %r1,%r1,16 + blr + +# Tail of __fini used for static destructors in Solaris + .section ".fini","ax" + lwz %r0,16(%r1) + lwz %r31,12(%r1) + mtlr %r0 + addi %r1,%r1,16 + blr diff --git a/gnu/usr.bin/gcc/config/rs6000/sol2.h b/gnu/usr.bin/gcc/config/rs6000/sol2.h new file mode 100644 index 00000000000..0a73c4d26d5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/sol2.h @@ -0,0 +1,178 @@ +/* Definitions of target machine for GNU compiler, + for IBM RS/6000 running AIX version 3.1. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by David Reese (Dave.Reese@East.Sun.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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "rs6000/sysv4le.h" + +/* Default ABI to use */ +#undef RS6000_ABI_NAME +#define RS6000_ABI_NAME "solaris" + +#undef ASM_CPU_SPEC +#define ASM_CPU_SPEC "-le -s" + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_POWERPC | \ + MASK_NEW_MNEMONICS | \ + MASK_LITTLE_ENDIAN | \ + MASK_REGNAMES) + +#undef LIB_DEFAULT_SPEC +#define LIB_DEFAULT_SPEC "%(lib_solaris)" + +#undef STARTFILE_DEFAULT_SPEC +#define STARTFILE_DEFAULT_SPEC "%(startfile_solaris)" + +#undef ENDFILE_DEFAULT_SPEC +#define ENDFILE_DEFAULT_SPEC "%(endfile_solaris)" + +#undef LINK_START_DEFAULT_SPEC +#define LINK_START_DEFAULT_SPEC "%(link_start_solaris)" + +#undef CPP_SPEC +#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\ +%(cpp_sysv) %(cpp_endian) %(cpp_cpu) \ +%{mmvme: %(cpp_os_mvme) } \ +%{msim: %(cpp_os_sim) } \ +%{mcall-linux: %(cpp_os_linux) } \ +%{mcall-solaris: %(cpp_os_solaris) } \ +%{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(cpp_os_default) }}}}" + +#undef CPP_OS_DEFAULT_SPEC +#define CPP_OS_DEFAULT_SPEC "%(cpp_os_solaris)" + +#undef LINK_OS_DEFAULT_SPEC +#define LINK_OS_DEFAULT_SPEC "%(link_os_solaris)" + +#undef CPP_ENDIAN_LITTLE_SPEC +#define CPP_ENDIAN_LITTLE_SPEC CPP_ENDIAN_SOLARIS_SPEC + +/* Don't turn -B into -L if the argument specifies a relative file name. */ +#undef RELATIVE_PREFIX_NOT_LINKDIR + +#define DEFAULT_PCC_STRUCT_RETURN 0 + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (PowerPC Solaris)"); + + +/* Macros to check register numbers against specific register classes. */ + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + + +#if 0 +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "\t%s\t", ".lcomm"); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ +} while (0) +#endif + +/* Like block addresses, stabs line numbers are relative to the + current function. */ + +/* use .stabd instead of .stabn */ + +#define ASM_STABN_OP ".stabd" + +#undef ASM_OUTPUT_SOURCE_LINE +#define ASM_OUTPUT_SOURCE_LINE(file, line) \ +do \ + { \ + static int sym_lineno = 1; \ + char *_p; \ + fprintf (file, "\t.stabd 68,0,%d,.LM%d-", \ + line, sym_lineno); \ + STRIP_NAME_ENCODING (_p, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ + assemble_name (file, _p); \ + fprintf (file, "\n.LM%d:\n", sym_lineno); \ + sym_lineno += 1; \ + } \ +while (0) + +/* This is how to output an assembler line defining a `double' constant. */ + +#undef ASM_OUTPUT_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", \ + t[0] & 0xffffffff, t[1] & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ + fprintf (FILE, "\t.double %s\n", str); \ + } \ + } + +/* This is how to output an assembler line defining a `float' constant. */ + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.float %s\n", str); \ + } \ + } + + +/* Sun-ppc assembler does not permit '.' in some symbol names. + Use 'name_.labelno' instead. */ +#undef ASM_FORMAT_PRIVATE_NAME +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s_.%d", (NAME), (LABELNO))) + + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS +#define MULTILIB_DEFAULTS { "mlittle", "mcall-solaris" } + +#define STDC_0_IN_SYSTEM_HEADERS diff --git a/gnu/usr.bin/gcc/config/rs6000/t-ppccomm b/gnu/usr.bin/gcc/config/rs6000/t-ppccomm new file mode 100644 index 00000000000..c6f9b6c7629 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/t-ppccomm @@ -0,0 +1,73 @@ +# Common support for PowerPC eabi, System V targets. + +# Do not build libgcc1. +LIBGCC1 = +CROSS_LIBGCC1 = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... [taken from t-sparclite] +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c eabi.S eabi-ctors.c tramp.S + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +eabi.S: $(srcdir)/config/rs6000/eabi.asm + cat $(srcdir)/config/rs6000/eabi.asm > eabi.S + +eabi-ctors.c: $(srcdir)/config/rs6000/eabi-ctors.c + cat $(srcdir)/config/rs6000/eabi-ctors.c > eabi-ctors.c + +tramp.S: $(srcdir)/config/rs6000/tramp.asm + cat $(srcdir)/config/rs6000/tramp.asm > tramp.S + +# Switch synonyms +MULTILIB_MATCHES_FLOAT = msoft-float=mcpu?403 msoft-float=mcpu?821 msoft-float=mcpu?860 +MULTILIB_MATCHES_ENDIAN = mlittle=mlittle-endian mbig=mbig-endian +MULTILIB_MATCHES_SYSV = mcall-sysv=mcall-sysv-eabi mcall-sysv=mcall-sysv-noeabi + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib +EXTRA_MULTILIB_PARTS = ecrti$(objext) ecrtn$(objext) scrt0$(objext) scrti$(objext) scrtn$(objext) + +# We build {e,s}crti.o, {e,s}crtn.o, and scrt0.o which serve to add begin and +# end labels to all of the special sections used when we link using gcc. + +# Assemble startup files. +ecrti.S: $(srcdir)/config/rs6000/eabi-ci.asm + cat $(srcdir)/config/rs6000/eabi-ci.asm >ecrti.S + +ecrtn.S: $(srcdir)/config/rs6000/eabi-cn.asm + cat $(srcdir)/config/rs6000/eabi-cn.asm >ecrtn.S + +scrti.S: $(srcdir)/config/rs6000/sol-ci.asm + cat $(srcdir)/config/rs6000/sol-ci.asm >scrti.S + +scrtn.S: $(srcdir)/config/rs6000/sol-cn.asm + cat $(srcdir)/config/rs6000/sol-cn.asm >scrtn.S + +scrt0.c: $(srcdir)/config/rs6000/sol-c0.c + cat $(srcdir)/config/rs6000/sol-c0.c >scrt0.c + +# Build multiple copies of ?crt{i,n}.o, one for each target switch. +$(T)ecrti$(objext): ecrti.S + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ecrti.S -o $(T)ecrti$(objext) + +$(T)ecrtn$(objext): ecrtn.S + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ecrtn.S -o $(T)ecrtn$(objext) + +$(T)scrti$(objext): scrti.S + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c scrti.S -o $(T)scrti$(objext) + +$(T)scrtn$(objext): scrtn.S + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c scrtn.S -o $(T)scrtn$(objext) + +$(T)scrt0$(objext): scrt0.c + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c scrt0.c -o $(T)scrt0$(objext) + +# It is important that crtbegin.o, etc., aren't surprised by stuff in .sdata. +CRTSTUFF_T_CFLAGS = -msdata=none +CRTSTUFF_T_CFLAGS_S = -fpic -msdata=none diff --git a/gnu/usr.bin/gcc/config/rs6000/t-ppcos b/gnu/usr.bin/gcc/config/rs6000/t-ppcos new file mode 100644 index 00000000000..480665a8937 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/t-ppcos @@ -0,0 +1,12 @@ +# Target config file for a System V based system (Solaris, GNU/Linux, Netbsd) +# with gas. + +# Build libgcc.a with different options. With gas, build pic libraries +# as well no floating point +MULTILIB_OPTIONS = msoft-float fPIC +MULTILIB_DIRNAMES = nof pic +MULTILIB_EXCEPTIONS = +MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT} \ + fPIC=mrelocatable-lib \ + fPIC=mrelocatable \ + fPIC=fpic diff --git a/gnu/usr.bin/gcc/config/rs6000/t-winnt b/gnu/usr.bin/gcc/config/rs6000/t-winnt new file mode 100644 index 00000000000..f58aefed523 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/t-winnt @@ -0,0 +1,35 @@ +# Do not build libgcc1. +LIBGCC1 = +CROSS_LIBGCC1 = + +EXTRA_PARTS = crti.o crtn.o + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... [taken from t-sparclite] +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c ntstack.S + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +ntstack.S: $(srcdir)/config/rs6000/ntstack.asm + cat $(srcdir)/config/rs6000/ntstack.asm > ntstack.S + +# For NT we build crti.o and crtn.o which serve to add begin and +# end labels for the static constructors and destructors. + +# Assemble startup files. +crti.s: $(srcdir)/config/rs6000/nt-ci.asm + cat $(srcdir)/config/rs6000/nt-ci.asm >crti.s + +crtn.s: $(srcdir)/config/rs6000/nt-cn.asm + cat $(srcdir)/config/rs6000/nt-cn.asm >crtn.s + +crti.o: crti.s + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crti.o crti.s + +crtn.o: crtn.s + $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtn.o crtn.s diff --git a/gnu/usr.bin/gcc/config/rs6000/t-xnewas b/gnu/usr.bin/gcc/config/rs6000/t-xnewas new file mode 100644 index 00000000000..285f8259d07 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/t-xnewas @@ -0,0 +1,58 @@ +# Same as t-newas, except don't build libgcc1-test. This is because +# the compiler emits code to call external functions to save the +# arguments that are in libc, but since libgcc1-test is linked without +# libc, they will show up as errors. +LIBGCC1_TEST = + +# Do not build libgcc1. +LIBGCC1 = +CROSS_LIBGCC1 = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... [taken from t-sparclite] +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +# Build the libraries for both hard and soft floating point and all of the +# different processor models + +MULTILIB_OPTIONS = msoft-float \ + mcpu=common/mcpu=power/mcpu=powerpc + +MULTILIB_DIRNAMES = soft-float \ + common power powerpc + +MULTILIB_MATCHES = msoft-float=mcpu?403 \ + mcpu?power=mpower \ + mcpu?power=mrios1 \ + mcpu?power=mcpu?rios1 \ + mcpu?power=mcpu?rsc \ + mcpu?power=mcpu?rsc1 \ + mcpu?power=mpower2 \ + mcpu?power=mrios2 \ + mcpu?power=mcpu=rios2 \ + mcpu?powerpc=mcpu?601 \ + mcpu?powerpc=mcpu?602 \ + mcpu?powerpc=mcpu?603 \ + mcpu?powerpc=mcpu?603e \ + mcpu?powerpc=mcpu?604 \ + mcpu?powerpc=mcpu?620 \ + mcpu?powerpc=mcpu?403 \ + mcpu?powerpc=mpowerpc \ + mcpu?powerpc=mpowerpc-gpopt \ + mcpu?powerpc=mpowerpc-gfxopt + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +# Aix 3.2.x needs milli.exp for -mcpu=common +EXTRA_PARTS = milli.exp +milli.exp: $(srcdir)/config/rs6000/milli.exp + rm -f milli.exp + cp $(srcdir)/config/rs6000/milli.exp ./milli.exp diff --git a/gnu/usr.bin/gcc/config/rs6000/t-xrs6000 b/gnu/usr.bin/gcc/config/rs6000/t-xrs6000 new file mode 100644 index 00000000000..f5d34d658b7 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/t-xrs6000 @@ -0,0 +1,28 @@ +# Same as t-rs6000, except don't build libgcc1-test. This is because +# the compiler emits code to call external functions to save the +# arguments that are in libc, but since libgcc1-test is linked without +# libc, they will show up as errors. +LIBGCC1_TEST = + +# Do not build libgcc1. +LIBGCC1 = +CROSS_LIBGCC1 = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... [taken from t-sparclite] +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +# Build the libraries for both hard and soft floating point + +MULTILIB_OPTIONS = msoft-float +MULTILIB_DIRNAMES = soft-float + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/gnu/usr.bin/gcc/config/rs6000/tramp.asm b/gnu/usr.bin/gcc/config/rs6000/tramp.asm new file mode 100644 index 00000000000..47ab7d65b1f --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/tramp.asm @@ -0,0 +1,120 @@ +/* Special support for trampolines + * + * Copyright (C) 1996, 1997 Free Software Foundation, Inc. + * Written By Michael Meissner + * + * This file 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. + * + * In addition to the permissions in the GNU General Public License, the + * Free Software Foundation gives you unlimited permission to link the + * compiled version of this file with other programs, and to distribute + * those programs without any restriction coming from the use of this + * file. (The General Public License restrictions do apply in other + * respects; for example, they cover modification of the file, and + * distribution when not linked into another program.) + * + * This file 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 this program; 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. + */ + +/* Set up trampolines */ + + .file "tramp.asm" + .section ".text" + #include "ppc-asm.h" + + .globl __trampoline_initial + .type __trampoline_initial,@object + .align 2 +__trampoline_initial: + mflr r0 + bl 1f +.Lfunc = .-__trampoline_initial + .long 0 /* will be replaced with function address */ +.Lchain = .-__trampoline_initial + .long 0 /* will be replaced with static chain */ +1: mflr r11 + mtlr r0 + lwz r0,0(r11) /* function address */ + lwz r11,4(r11) /* static chain */ + mtctr r0 + bctr + +__trampoline_size = .-__trampoline_initial + .size __trampoline_initial,__trampoline_size + + .section ".got2","aw" +.LCTOC1 = .+32768 +.Ltramp = .-.LCTOC1 + .long __trampoline_initial-4 + + .section ".text" +.LCL0: + .long .LCTOC1-.LCF0 + +/* R3 = stack address to store trampoline */ +/* R4 = length of trampoline area */ +/* R5 = function address */ +/* R6 = static chain */ + +FUNC_START(__trampoline_setup) + mflr r0 /* save return address */ + bl .LCF0 /* load up __trampoline_initial into r7 */ +.LCF0: + mflr r11 + lwz r12,(.LCL0-.LCF0)(r11) + add r11,r12,r11 + lwz r7,.Ltramp(r11) /* trampoline address -4 */ + + li r8,__trampoline_size /* verify that the trampoline is big enough */ + cmpw cr1,r8,r4 + srwi r4,r4,2 /* # words to move */ + addi r9,r3,-4 /* adjust pointer for lwzu */ + mtctr r4 + blt cr1,.Labort + + mtlr r0 + + /* Copy the instructions to the stack */ +.Lmove: + lwzu r10,4(r7) + stwu r10,4(r9) + bdnz .Lmove + + /* Store correct function and static chain */ + stw r5,.Lfunc(r3) + stw r6,.Lchain(r3) + + /* Now flush both caches */ + mtctr r4 +.Lcache: + icbi 0,r3 + dcbf 0,r3 + addi r3,r3,4 + bdnz .Lcache + + /* Finally synchronize things & return */ + sync + isync + blr + +.Labort: + bl abort +FUNC_END(__trampoline_setup) +/* END CYGNUS LOCAL -- waiting for FSF sources to be restored/meissner */ diff --git a/gnu/usr.bin/gcc/config/rs6000/vxppc.h b/gnu/usr.bin/gcc/config/rs6000/vxppc.h new file mode 100644 index 00000000000..0dddc498325 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/vxppc.h @@ -0,0 +1,63 @@ +/* Definitions of target machine for GNU compiler. Vxworks PowerPC version. + Copyright (C) 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file just exists to give specs for the PowerPC running on VxWorks. */ + +#include "rs6000/sysv4.h" + +#undef CPP_SPEC +#define CPP_SPEC "\ +%{posix: -D_POSIX_SOURCE} \ +%{!mcpu*: \ + %{mpowerpc*: -D_ARCH_PPC -DCPU=PPC603} \ + %{!mno-powerpc: -D_ARCH_PPC -DCPU=PPC603}} \ +%{mcpu=powerpc: -D_ARCH_PPC -DCPU=PPC603} \ +%{mcpu=403: -D_ARCH_PPC -DCPU=PPC403} \ +%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR -DCPU=PPC601} \ +%{mcpu=603: -D_ARCH_PPC -DCPU=PPC603} \ +%{mcpu=604: -D_ARCH_PPC -DCPU=PPC604}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "\ +-D__vxworks -D__vxworks__ -Asystem(vxworks) -Asystem(embedded) \ +-Acpu(powerpc) -Amachine(powerpc)" + +/* VxWorks does all the library stuff itself. */ + +#undef LIB_SPEC +#define LIB_SPEC "" + +/* VxWorks uses object files, not loadable images. make linker just + combine objects. */ + +#undef LINK_SPEC +#define LINK_SPEC "-r" + +/* VxWorks provides the functionality of crt0.o and friends itself. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "" + +/* We use stabs-in-elf for debugging */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG diff --git a/gnu/usr.bin/gcc/config/rs6000/win-nt.h b/gnu/usr.bin/gcc/config/rs6000/win-nt.h new file mode 100644 index 00000000000..2fcf44647d2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/win-nt.h @@ -0,0 +1,478 @@ +/* Definitions of target machine for GNU compiler, for PowerPC + running Windows/NT. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +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. */ + +/* Say this is Windows/NT for the other config files. */ +#define WINDOWS_NT 1 +#define COFF_WITH_PE 1 + +/* Default ABI to compile code for */ +#define DEFAULT_ABI ABI_NT + +#include "rs6000/powerpc.h" + +/* Pseudo target that we can test in the md file. */ +#undef TARGET_WINDOWS_NT +#define TARGET_WINDOWS_NT 1 + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-DWIN32 -D_WIN32 \ + -DWINNT -D__STDC__=0 -DALMOST_STDC \ + -D_POWER -D_ARCH_PPC -D__PPC__ -Asystem(winnt) -Acpu(powerpc) -Amachine(powerpc)" + +#if 0 +#include "winnt/win-nt.h" +#endif + +#undef LIB_SPEC +#define LIB_SPEC "%{mwindows:-subsystem:windows -entry:WinMainCRTStartup \ + USER32.LIB GDI32.LIB COMDLG32.LIB WINSPOOL.LIB} \ + %{!mwindows:-subsystem console -e mainCRTStartup} \ + %{mcrtmt:LIBCMT.LIB KERNEL32.LIB} %{!mcrtmt:-lkernel32 -lcygwin} \ + %{v}" + +#undef LINK_SPEC +#define LINK_SPEC "%{v:-V}" + +/* Allow switches specified in LIB_SPEC, but don't do anything with them + in the compiler. */ +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "windows", 0 }, \ + { "crtmt", 0 }, + +#undef XCOFF_DEBUGGING_INFO + +/* this is pure coff, not xcoff */ +#define SDB_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#undef SDB_DELIM +#define SDB_DELIM ";" + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#undef PROCESSOR_DEFAULT +#define PROCESSOR_DEFAULT PROCESSOR_POWERPC + +/* NT always runs little endian */ +#undef BYTES_BIG_ENDIAN +#define BYTES_BIG_ENDIAN 0 + +#undef WORDS_BIG_ENDIAN +#define WORDS_BIG_ENDIAN 0 + +/* Define cutoff for using external functions to save floating point. + Currently on NT, always use inline stores */ +#undef FP_SAVE_INLINE +#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 64) + +/* Note, little endian systems trap on unaligned addresses, so never + turn off strict alignment in that case. */ + +#undef STRICT_ALIGNMENT +#define STRICT_ALIGNMENT 1 + +/* Align stack to 16 byte boundaries */ +#undef STACK_BOUNDARY +#define STACK_BOUNDARY 128 + +/* No data type wants to be aligned rounder than this. */ +#undef BIGGEST_ALIGNMENT +#define BIGGEST_ALIGNMENT 128 + +/* NT aligns internal doubles in structures on dword boundaries. */ +#undef BIGGEST_FIELD_ALIGNMENT +#define BIGGEST_FIELD_ALIGNMENT 64 + +#undef ADJUST_FIELD_ALIGN +#undef ROUND_TYPE_ALIGN + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (PowerPC PE)"); + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC) + +#undef PROCESSOR_DEFAULT +#define PROCESSOR_DEFAULT PROCESSOR_PPC601 + +/* Address to save the TOC register */ +#undef RS6000_SAVE_TOC +#define RS6000_SAVE_TOC plus_constant (virtual_incoming_args_rtx, -RS6000_SAVE_AREA - 8) + +/* Windows NT specifies that r13 is reserved to the OS, so it is not available + to the normal user. */ + +#undef FIXED_R13 +#define FIXED_R13 1 + +/* This says how to output an assembler line + to define a global common symbol. */ + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \ + do { fputs ("\t.comm \t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + if ( (SIZE) > 4) \ + fprintf ((FILE), ",%d,%d\n", (SIZE), 3); \ + else \ + fprintf( (FILE), ",%d\n", (SIZE)); \ + } while (0) + +#undef ASM_OUTPUT_ALIGNED_LOCAL + +/* This says how to output an assembler line + to define a global common symbol. */ + +#undef ASM_OUTPUT_COMMON +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ + do { fputs ("\t.comm \t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%d\n", (SIZE)); } while (0) + +/* This says how to output an assembler line + to define an aligned local common symbol. */ + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + bss_section (); \ + ASM_OUTPUT_ALIGN (FILE, exact_log2 (ALIGN / BITS_PER_UNIT)); \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + ASM_OUTPUT_SKIP (FILE, SIZE); \ +} while (0) + +/* Describe how to emit uninitialized external linkage items */ +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ +do { \ + ASM_GLOBALIZE_LABEL (FILE, NAME); \ + ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +/* This says out to put a global symbol in the BSS section */ +#undef ASM_OUTPUT_ALIGNED_BSS +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN)) + + +/* Stuff to force fit us into the Motorola PPC assembler */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +do { \ + output_file_directive ((FILE), main_input_filename); \ + rs6000_file_start (FILE, TARGET_CPU_DEFAULT); \ + data_section (); \ +} while (0) + +#undef ASM_FILE_END + +#undef ASM_DECLARE_FUNCTION_NAME +#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ +{ \ + tree exception_args; \ + int i; \ + \ + if (TREE_PUBLIC (DECL)) \ + { \ + fprintf (FILE, "\t.globl .."); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } \ + \ + fprintf (FILE, "\n#\tFunction: '.."); \ + assemble_name (FILE, NAME); \ + fputs ("'\n", FILE); \ + fputs ("#\tText in section: <default>\n\n", FILE); \ + fputs ("#\tSetup MS Structured-Exception-Handling\n", FILE); \ + fputs ("\t.pdata\n", FILE); \ + fputs ("\t.align 2\n", FILE); \ + fputs ("\t.ualong ..", FILE); \ + assemble_name (FILE, NAME); \ + fputs (",", FILE); \ + assemble_name (FILE, NAME); \ + fputs (".e,", FILE); \ + exception_args = lookup_attribute ("exception", \ + TYPE_ATTRIBUTES (TREE_TYPE (DECL))); \ + \ + if (exception_args) \ + exception_args = TREE_VALUE (exception_args); \ + \ + for (i = 0; i < 2; i++) \ + { \ + if (!exception_args) \ + fputs ("0,", FILE); \ + else \ + { \ + tree field = TREE_VALUE (exception_args); \ + exception_args = TREE_PURPOSE (exception_args); \ + if (TREE_CODE (field) == STRING_CST) \ + fprintf (FILE, "%.*s,", TREE_STRING_LENGTH (field), \ + TREE_STRING_POINTER (field)); \ + else if (TREE_CODE (field) == IDENTIFIER_NODE) \ + fprintf (FILE, "%.*s,", IDENTIFIER_LENGTH (field), \ + IDENTIFIER_POINTER (field)); \ + else \ + abort (); \ + } \ + } \ + \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ".b\n\n"); \ + fprintf (FILE, "#\tSwitch to the relocation section\n"); \ + fprintf (FILE, "\t.reldata\n"); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ":\n"); \ + fprintf (FILE, "\t.ualong .."); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",.toc\n"); \ + \ + if (lookup_attribute ("dllexport", \ + TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \ + { \ + fprintf (FILE, "\t.globl __imp_"); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n__imp_"); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ":\n\t.ulong "); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } \ + \ + fprintf (FILE, "\t.section .text\n\t.align 2\n.."); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ":\n"); \ + fprintf (FILE, "\t.function\t.."); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ +} + +/* This is how to output an assembler line defining a `double' constant. */ + +#undef ASM_OUTPUT_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ + fprintf (FILE, "\t.ualong 0x%lx\n\t.long 0x%lx\n", \ + t[0] & 0xffffffff, t[1] & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ + fprintf (FILE, "\t.double %s\n", str); \ + } \ + } + +/* This is how to output an assembler line defining a `float' constant. */ + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ + { \ + if (REAL_VALUE_ISINF (VALUE) \ + || REAL_VALUE_ISNAN (VALUE) \ + || REAL_VALUE_MINUS_ZERO (VALUE)) \ + { \ + long t; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ + fprintf (FILE, "\t.ualong 0x%lx\n", t & 0xffffffff); \ + } \ + else \ + { \ + char str[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ + fprintf (FILE, "\t.float %s\n", str); \ + } \ + } + +/* Output before instructions. */ +#undef TEXT_SECTION_ASM_OP +#define TEXT_SECTION_ASM_OP "\t.text" + +/* Output before writable data. */ +#undef DATA_SECTION_ASM_OP +#define DATA_SECTION_ASM_OP "\t.data" + +/* Output to the bss section. */ +#undef BSS_SECTION_ASM_OP +#define BSS_SECTION_ASM_OP "\t.section .bss" + +/* Define the extra sections we need. We define a dummy TOC section, + plus sections to hold the list of static constructors (.ctors) and + destructors (.dtors). */ + +#undef READONLY_DATA_SECTION +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_toc, in_ctors, in_dtors + +/* Define the routines to implement these extra sections. */ + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION \ + TOC_SECTION_FUNCTION \ + +#define TOC_SECTION_FUNCTION \ +void \ +toc_section () \ +{ \ +} + +#define CTORS_SECTION_ASM_OP ".section\t.ctors" +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#define DTORS_SECTION_ASM_OP ".section\t.dtors" +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +#undef SELECT_SECTION +#undef SELECT_RTX_SECTION + +/* Make sure __main gets called */ +#define INVOKE__main 1 + +/* A C statement (sans semicolon) to output an element in the table of + global constructors. */ +#undef ASM_OUTPUT_CONSTRUCTOR +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctors_section (); \ + fprintf (FILE, "\t.ualong "); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* A C statement (sans semicolon) to output an element in the table of + global destructors. */ +#undef ASM_OUTPUT_DESTRUCTOR +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtors_section (); \ + fprintf (FILE, "\t.ualong "); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + + +/* Text to write out after a CALL that may be replaced by glue code by + the loader. The motorola asm demands that, for dll support, a .znop + be issued after a bl instruction, and the symbol on the .znop is the + symbol on the bl instruction */ + +#undef RS6000_CALL_GLUE +#define RS6000_CALL_GLUE "nop #\tFIXME: only works for non-dll calls." + +#define RS6000_CALL_GLUE2 ".znop " + +#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY + +/* Output something to declare an external symbol to the assembler. Most + assemblers don't need this. */ + +#undef ASM_OUTPUT_EXTERNAL + +#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ +{ \ + char *_name; \ + rtx _symref = XEXP (DECL_RTL (DECL), 0); \ + if ((TREE_CODE (DECL) == VAR_DECL \ + || TREE_CODE (DECL) == FUNCTION_DECL) \ + && (NAME)[strlen (NAME) - 1] != ']') \ + { \ + _name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \ + strcpy (_name, XSTR (_symref, 0)); \ + XSTR (_symref, 0) = _name; \ + } \ + else \ + _name = XSTR (_symref, 0); \ + \ + if (DECL_FUNCTION_CODE (DECL) == 0) \ + { \ + fputs ("\t.extern ", FILE); \ + assemble_name (FILE, _name); \ + putc ('\n', FILE); \ + if (TREE_CODE (DECL) == FUNCTION_DECL) \ + { \ + fputs ("\t.extern ..", FILE); \ + assemble_name (FILE, _name); \ + putc ('\n', FILE); \ + } \ + } \ +} + +/* Similar, but for libcall. We only have to worry about the function name, + not that of the descriptor. */ + +#undef ASM_OUTPUT_EXTERNAL_LIBCALL + +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ +{ fprintf (FILE, "\t.extern .."); \ + assemble_name (FILE, XSTR (FUN, 0)); \ + fprintf (FILE, "\n"); \ +} + +/* The prefix to add to user-visible assembler symbols. */ + +#define USER_LABEL_PREFIX ".." + +/* Eliminate AIX style constant pool processing */ +#undef LEGITIMATE_CONSTANT_POOL_BASE_P +#define LEGITIMATE_CONSTANT_POOL_BASE_P(X) 0 + +#undef LEGITIMATE_CONSTANT_POOL_ADDRESS_P +#define LEGITIMATE_CONSTANT_POOL_ADDRESS_P(X) 0 + +#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY + +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(x) + +/* Output assembler code for a block containing the constant parts + of a trampoline, leaving space for the variable parts. + + The trampoline should set the static chain pointer to value placed + into the trampoline and should branch to the specified routine. */ +#define TRAMPOLINE_TEMPLATE(FILE) rs6000_trampoline_template (FILE) diff --git a/gnu/usr.bin/gcc/config/rs6000/x-cygwin32 b/gnu/usr.bin/gcc/config/rs6000/x-cygwin32 new file mode 100644 index 00000000000..5e796a0e916 --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/x-cygwin32 @@ -0,0 +1,4 @@ +# Don't run fixproto +STMP_FIXPROTO = +# Don't need collect2 +USE_COLLECT2 = diff --git a/gnu/usr.bin/gcc/config/rs6000/xm-cygwin32.h b/gnu/usr.bin/gcc/config/rs6000/xm-cygwin32.h new file mode 100644 index 00000000000..677254b371c --- /dev/null +++ b/gnu/usr.bin/gcc/config/rs6000/xm-cygwin32.h @@ -0,0 +1,26 @@ +/* Configuration for GNU C-compiler for hosting on Windows NT. + using a unix style C library. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#define NO_STAB_H + +#include "rs6000/xm-rs6000.h" + +#define EXECUTABLE_SUFFIX ".exe" diff --git a/gnu/usr.bin/gcc/config/sh/elf.h b/gnu/usr.bin/gcc/config/sh/elf.h new file mode 100644 index 00000000000..a56077e544e --- /dev/null +++ b/gnu/usr.bin/gcc/config/sh/elf.h @@ -0,0 +1,122 @@ +/* Definitions of target machine for gcc for Hitachi Super-H using ELF. + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Ian Lance Taylor <ian@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. */ + +/* Mostly like the regular SH configuration. */ +#include "sh/sh.h" + +/* No SDB debugging info. */ +#undef SDB_DEBUGGING_INFO + +/* Undefine some macros defined in both sh.h and svr4.h. */ +#undef IDENT_ASM_OP +#undef ASM_FILE_END +#undef ASM_OUTPUT_SOURCE_LINE +#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END +#undef CTORS_SECTION_ASM_OP +#undef DTORS_SECTION_ASM_OP +#undef ASM_OUTPUT_SECTION_NAME +#undef ASM_OUTPUT_CONSTRUCTOR +#undef ASM_OUTPUT_DESTRUCTOR +#undef ASM_DECLARE_FUNCTION_NAME +#undef PREFERRED_DEBUGGING_TYPE + +/* Be ELF-like. */ +#include "svr4.h" + +/* The prefix to add to user-visible assembler symbols. + Note that svr4.h redefined it from the original value (that we want) + in sh.h */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "_" + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX "." + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) do { \ + output_file_directive ((FILE), main_input_filename); \ + if (TARGET_LITTLE_ENDIAN) \ + fprintf ((FILE), "\t.little\n"); \ +} while (0) + + + +/* Let code know that this is ELF. */ +#define CPP_PREDEFINES "-D__sh__ -D__ELF__ -Acpu(sh) -Amachine(sh)" + +/* Pass -ml and -mrelax to the assembler and linker. */ +#undef ASM_SPEC +#define ASM_SPEC "%{ml:-little} %{mrelax:-relax}" + +#undef LINK_SPEC +#define LINK_SPEC "%{ml:-m shlelf} %{mrelax:-relax}" + +/* svr4.h undefined DBX_REGISTER_NUMBER, so we need to define it + again. */ +#define DBX_REGISTER_NUMBER(REGNO) \ + (((REGNO) >= 22 && (REGNO) <= 39) ? ((REGNO) + 1) : (REGNO)) + +/* SH ELF, unlike most ELF implementations, uses underscores before + symbol names. */ +#undef ASM_OUTPUT_LABELREF +#define ASM_OUTPUT_LABELREF(STREAM,NAME) \ + asm_fprintf (STREAM, "%U%s", NAME) + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \ + sprintf ((STRING), "*%s%s%d", LOCAL_LABEL_PREFIX, (PREFIX), (NUM)) + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + asm_fprintf ((FILE), "%L%s%d:\n", (PREFIX), (NUM)) + +#undef ASM_OUTPUT_SOURCE_LINE +#define ASM_OUTPUT_SOURCE_LINE(file, line) \ +do \ + { \ + static int sym_lineno = 1; \ + asm_fprintf ((file), ".stabn 68,0,%d,%LLM%d-", \ + (line), sym_lineno); \ + assemble_name ((file), \ + XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\ + asm_fprintf ((file), "\n%LLM%d:\n", sym_lineno); \ + sym_lineno += 1; \ + } \ +while (0) + +#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END +#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ +do { \ + text_section (); \ + fprintf ((FILE), "\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO); \ +} while (0) + +/* Arrange to call __main, rather than using crtbegin.o and crtend.o + and relying on .init and .fini being executed at appropriate times. */ +#undef INIT_SECTION_ASM_OP +#undef FINI_SECTION_ASM_OP +#undef STARTFILE_SPEC +#undef ENDFILE_SPEC + +/* HANDLE_SYSV_PRAGMA (defined by svr4.h) takes precedence over HANDLE_PRAGMA. + We want to use the HANDLE_PRAGMA from sh.h. */ +#undef HANDLE_SYSV_PRAGMA diff --git a/gnu/usr.bin/gcc/config/sh/rtems.h b/gnu/usr.bin/gcc/config/sh/rtems.h new file mode 100644 index 00000000000..2e864ad5c29 --- /dev/null +++ b/gnu/usr.bin/gcc/config/sh/rtems.h @@ -0,0 +1,28 @@ +/* Definitions for rtems targeting a SH using elf. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "sh/elf.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__sh__ -D__ELF__ -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(sh) -Amachine(sh)" diff --git a/gnu/usr.bin/gcc/config/sparc/aout.h b/gnu/usr.bin/gcc/config/sparc/aout.h new file mode 100644 index 00000000000..478d710f82f --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/aout.h @@ -0,0 +1,26 @@ +/* Definitions of target machine for GNU compiler, for SPARC using a.out. + Copyright (C) 1994, 1996 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@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. */ + +#include "sparc/sparc.h" /* SPARC definitions */ +#include "aoutos.h" /* A.out definitions */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)" diff --git a/gnu/usr.bin/gcc/config/sparc/elf.h b/gnu/usr.bin/gcc/config/sparc/elf.h new file mode 100644 index 00000000000..70cb26a93be --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/elf.h @@ -0,0 +1,42 @@ +/* Definitions of target machine for GNU compiler, + for SPARC running in an embedded environment using the ELF file format. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "sol2.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -D__elf__ -Acpu(sparc) -Amachine(sparc)" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +/* Use the default. */ +#undef LINK_SPEC + +/* Don't set the target flags, this is done by the linker script */ +#undef LIB_SPEC +#define LIB_SPEC "" + +/* FIXME: until fixed */ +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 64 diff --git a/gnu/usr.bin/gcc/config/sparc/linux-aout.h b/gnu/usr.bin/gcc/config/sparc/linux-aout.h new file mode 100644 index 00000000000..7075b5fbe7c --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/linux-aout.h @@ -0,0 +1,111 @@ +/* Definitions for SPARC running Linux-based GNU systems with a.out. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Eddie C. Dost (ecd@skynet.be) + +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 <aoutos.h> +#include <sparc/sparc.h> + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. + For now, we play safe. It may change later. */ + +#if 0 +#undef MULTIBYTE_CHARS +#define MULTIBYTE_CHARS 1 +#endif + +/* We need that too. */ +#define HANDLE_SYSV_PRAGMA + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with a.out)"); + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -Dsparc -Dlinux -Asystem(unix) -Asystem(posix)" + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" + +/* Don't default to pcc-struct-return, because gcc is the only compiler, + and we want to retain compatibility with older gcc versions. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +#undef LIB_SPEC + +#if 1 +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#define LIB_SPEC \ +"%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" +#else +#define LIB_SPEC \ +"%{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg -static}}}" +#endif + +#undef LINK_SPEC +#define LINK_SPEC "-m sparclinux" + +/* The sun bundled assembler doesn't accept -Yd, (and neither does gas). + It's safe to pass -s always, even if -g is not used. */ +#undef ASM_SPEC +#define ASM_SPEC \ + "%{V} %{v:%{!V:-V}} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} %{fPIC:-K PIC}" + +#if 0 +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. GNU/Linux does not support + long double yet. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif diff --git a/gnu/usr.bin/gcc/config/sparc/linux.h b/gnu/usr.bin/gcc/config/sparc/linux.h new file mode 100644 index 00000000000..9ce30d108ee --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/linux.h @@ -0,0 +1,234 @@ +/* Definitions for SPARC running Linux-based GNU systems with ELF. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Eddie C. Dost (ecd@skynet.be) + +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. */ + +#define LINUX_DEFAULT_ELF + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is. + For now, we play safe. It may change later. */ + +#if 0 +#undef MULTIBYTE_CHARS +#define MULTIBYTE_CHARS 1 +#endif + +/* Use stabs instead of DWARF debug format. */ +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include <sparc/sysv4.h> + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux 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:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on + the GNU/Linux 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 + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +/* This is for -profile to use -lc_p instead of -lc. */ +#undef CC1_SPEC +#define CC1_SPEC "%{profile:-p} \ +%{sun4:} %{target:} \ +%{mcypress:-mcpu=cypress} \ +%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \ +%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \ +" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with ELF)"); + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Dunix -Dsparc -Dlinux -Asystem(unix) -Asystem(posix)" + +#undef CPP_SUBTARGET_SPEC +#ifdef USE_GNULIBC_1 +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" +#else +#define CPP_SUBTARGET_SPEC \ +"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" +#endif + +#undef LIB_SPEC +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#if 1 +#ifdef USE_GNULIBC_1 +#define LIB_SPEC \ + "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \ + %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}" +#else +#define LIB_SPEC \ + "%{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ + %{profile:-lc_p} %{!profile: -lc}}" +#endif +#else +#define LIB_SPEC \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif + +/* Provide a LINK_SPEC appropriate for GNU/Linux. 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. */ + +/* If ELF is the default format, we should not use /lib/elf. */ + +#undef LINK_SPEC +#ifdef USE_GNULIBC_1 +#ifndef LINUX_DEFAULT_ELF +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/elf/ld-linux.so.1} \ + %{!rpath:-rpath /lib/elf/}} %{static:-static}}}" +#else +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \ + %{static:-static}}}" +#endif +#else +#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ + %{static:-static}}}" +#endif + +/* The sun bundled assembler doesn't accept -Yd, (and neither does gas). + It's safe to pass -s always, even if -g is not used. */ +#undef ASM_SPEC +#define ASM_SPEC \ + "%{V} %{v:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} %{fPIC:-K PIC}" + +/* Same as sparc.h */ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* We use stabs-in-elf for debugging, because that is what the native + toolchain uses. XXX */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* This is how to store into the string LABEL + 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(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + + +#if 0 +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. GNU/Linux does not support + long double yet. */ +#define LONG_DOUBLE_TYPE_SIZE 128 +#endif diff --git a/gnu/usr.bin/gcc/config/sparc/linux64.h b/gnu/usr.bin/gcc/config/sparc/linux64.h new file mode 100644 index 00000000000..74f632bb48c --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/linux64.h @@ -0,0 +1,236 @@ +/* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF. + Copyright 1996, 1997 Free Software Foundation, Inc. + Contributed by David S. Miller (davem@caip.rutgers.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. */ + +/* ??? bi-architecture support will require changes to the linker + related specs, among perhaps other things (multilibs). */ +/* #define SPARC_BI_ARCH */ + +#define LINUX_DEFAULT_ELF + +/* Don't assume anything about the header files. */ +#define NO_IMPLICIT_EXTERN_C + +#undef HAVE_ATEXIT +#define HAVE_ATEXIT + +#include <sparc/sysv4.h> + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +#undef ASM_CPU_DEFAULT_SPEC +#define ASM_CPU_DEFAULT_SPEC "-Av9a" + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC \ + "%{!shared:-lgcc}" + +/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add + the GNU/Linux 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:crt1.o%s}}}\ + crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}" + +/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on + the GNU/Linux 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 + GNU/Linux "finalizer" file, `crtn.o'. */ + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (sparc64 GNU/Linux with ELF)"); + +/* A 64 bit v9 compiler with stack-bias, + in a Medium/Anywhere code model environment. */ + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT \ + (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \ + + MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU) + +/* The default code model. */ +#undef SPARC_DEFAULT_CMODEL +#define SPARC_DEFAULT_CMODEL CM_MEDANY + +#undef SIZE_TYPE +#define SIZE_TYPE "long long unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long long int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 128 + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Dunix -Dsparc -Dlinux -Asystem(unix) -Asystem(posix)" + +#undef CPP_SUBTARGET_SPEC +#define CPP_SUBTARGET_SPEC "\ +%{fPIC:-D__PIC__ -D__pic__} \ +%{fpic:-D__PIC__ -D__pic__} \ +%{posix:-D_POSIX_SOURCE} \ +" +/* We no longer link with libc_p.a or libg.a by default. If you + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#undef LIB_SPEC +#define LIB_SPEC \ + "%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \ + %{!ggdb:-lc} %{ggdb:-lg}}" + +/* Provide a LINK_SPEC appropriate for GNU/Linux. 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. */ + +/* If ELF is the default format, we should not use /lib/elf. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf64_sparc -Y P,/usr/lib %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux64.so.2}} \ + %{static:-static}}} \ +%{mlittle-endian:-EL} \ +" + +/* The sun bundled assembler doesn't accept -Yd, (and neither does gas). + It's safe to pass -s always, even if -g is not used. */ +#undef ASM_SPEC +#define ASM_SPEC "\ +%{V} \ +%{v:%{!V:-V}} \ +%{!Qn:-Qy} \ +%{n} \ +%{T} \ +%{Ym,*} \ +%{Wa,*:%*} \ +-s %{fpic:-K PIC} %{fPIC:-K PIC} \ +%{mlittle-endian:-EL} \ +%(asm_cpu) %(asm_arch) \ +" + +/* Same as sparc.h */ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* System V Release 4 uses DWARF debugging info. Buf DWARF1 doesn't do + 64-bit anything, so we use DWARF2. */ + +#undef DWARF2_DEBUGGING_INFO +#undef DWARF_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO +#define DWARF2_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* This is how to store into the string LABEL + 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(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + +/* Stabs doesn't use this, and it confuses a simulator. */ +/* ??? Need to see what DWARF needs, if anything. */ +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(FILE) + +/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler. + ??? If ints are 64 bits then UNALIGNED_INT_ASM_OP (defined elsewhere) is + misnamed. These should all refer to explicit sizes (half/word/xword?), + anything other than short/int/long/etc. */ + +#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword" + +/* DWARF bits. */ + +/* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets. + Obviously the Dwarf2 folks havn't tried to actually build systems + with their spec. On a 64-bit system, only 64-bit relocs become + RELATIVE relocations. */ + +/* #define DWARF_OFFSET_SIZE PTR_SIZE */ diff --git a/gnu/usr.bin/gcc/config/sparc/rtems.h b/gnu/usr.bin/gcc/config/sparc/rtems.h new file mode 100644 index 00000000000..55b7779818a --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/rtems.h @@ -0,0 +1,28 @@ +/* Definitions for rtems targeting a SPARC using a.out. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.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. */ + +#include "sparc/aout.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(sparc) -Amachine(sparc)" diff --git a/gnu/usr.bin/gcc/config/sparc/sol2-g1.asm b/gnu/usr.bin/gcc/config/sparc/sol2-g1.asm new file mode 100644 index 00000000000..b9d878856f8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/sol2-g1.asm @@ -0,0 +1,88 @@ +! gcrt1.s for solaris 2.0. + +! Copyright (C) 1992 Free Software Foundation, Inc. +! Written By David Vinayak Henkel-Wallace, June 1992 +! +! This file 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. +! +! In addition to the permissions in the GNU General Public License, the +! Free Software Foundation gives you unlimited permission to link the +! compiled version of this file with other programs, and to distribute +! those programs without any restriction coming from the use of this +! file. (The General Public License restrictions do apply in other +! respects; for example, they cover modification of the file, and +! distribution when not linked into another program.) +! +! This file 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 this program; 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. +! + +! This file takes control of the process from the kernel, as specified +! in section 3 of the SVr4 ABI. +! This file is the first thing linked into any executable. + + .section ".text" + .proc 022 + .global _start + +_start: + mov 0, %fp ! Mark bottom frame pointer + ld [%sp + 64], %l0 ! argc + add %sp, 68, %l1 ! argv + + ! Leave some room for a call. Sun leaves 32 octets (to sit on + ! a cache line?) so we do too. + sub %sp, 32, %sp + + ! %g1 may contain a function to be registered w/atexit + orcc %g0, %g1, %g0 + be .nope + mov %g1, %o0 + call atexit + nop +.nope: + ! Now make sure constructors and destructors are handled. + set _fini, %o0 + call atexit, 1 + nop + call _init, 0 + nop + + ! We ignore the auxiliary vector; there's no defined way to + ! access those data anyway. Instead, go straight to main: + mov %l0, %o0 ! argc + mov %l1, %o1 ! argv + set ___Argv, %o3 + st %o1, [%o3] ! *___Argv + ! Skip argc words past argv, to env: + sll %l0, 2, %o2 + add %o2, 4, %o2 + add %l1, %o2, %o2 ! env + set _environ, %o3 + st %o2, [%o3] ! *_environ + call main, 4 + nop + call exit, 0 + nop + call _exit, 0 + nop + ! We should never get here. + + .type _start,#function + .size _start,.-_start diff --git a/gnu/usr.bin/gcc/config/sparc/splet.h b/gnu/usr.bin/gcc/config/sparc/splet.h new file mode 100644 index 00000000000..23c6414417a --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/splet.h @@ -0,0 +1,53 @@ +/* Definitions of target machine for GNU compiler, for SPARClet. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Doug Evans (dje@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. */ + +#include "sparc/aout.h" + +/* -mbroken-saverestore is not included here because the long term + default is -mno-broken-saverestore. */ +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE) + +/* -mlive-g0 is only supported on the sparclet. */ +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ +{"big-endian", -MASK_LITTLE_ENDIAN}, \ +{"little-endian", MASK_LITTLE_ENDIAN}, \ +{"live-g0", MASK_LIVE_G0}, \ +{"no-live-g0", -MASK_LIVE_G0}, \ +{"broken-saverestore", MASK_BROKEN_SAVERESTORE}, \ +{"no-broken-saverestore", -MASK_BROKEN_SAVERESTORE}, + +#undef ASM_SPEC +#define ASM_SPEC "%{mlittle-endian:-EL} %(asm_cpu)" + +/* Require the user to supply crt0.o. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef LINK_SPEC +#define LINK_SPEC "%{mlittle-endian:-EL}" + +/* sparclet chips are bi-endian. */ +#undef BYTES_BIG_ENDIAN +#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) +#undef WORDS_BIG_ENDIAN +#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN) diff --git a/gnu/usr.bin/gcc/config/sparc/sun4gas.h b/gnu/usr.bin/gcc/config/sparc/sun4gas.h new file mode 100644 index 00000000000..3cea9560b4f --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/sun4gas.h @@ -0,0 +1,27 @@ +/* Definitions of target machine for GNU compiler, for SunOS 4.x with gas + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* gas supports unaligned data. */ +#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword" +#define UNALIGNED_INT_ASM_OP ".uaword" +#define UNALIGNED_SHORT_ASM_OP ".uahalf" + +/* defaults.h will define DWARF2_UNWIND_INFO for us. */ +#undef DWARF2_UNWIND_INFO diff --git a/gnu/usr.bin/gcc/config/sparc/t-elf b/gnu/usr.bin/gcc/config/sparc/t-elf new file mode 100644 index 00000000000..da9df38368e --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/t-elf @@ -0,0 +1,39 @@ +# we need to supply our own assembly versions of libgcc1.c files, +# since the user may not have native 'cc' available + +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = sparc/lb1spc.asm +LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 + +# crt0 is built elsewhere +LIBGCC1_TEST = + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +# MULTILIB_OPTIONS should have msparclite too, but we'd have to make +# gas build... +#MULTILIB_OPTIONS = msoft-float mcpu=v8 +MULTILIB_OPTIONS = msoft-float +#MULTILIB_DIRNAMES = soft v8 +MULTILIB_DIRNAMES = soft +#MULTILIB_MATCHES = msoft-float=mno-fpu mcpu?v8=mv8 +MULTILIB_MATCHES = msoft-float=mno-fpu + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib + +# Assemble startup files. +crti.o: $(srcdir)/config/sparc/sol2-ci.asm $(GCC_PASSES) + $(GCC_FOR_TARGET) -c -o crti.o -x assembler $(srcdir)/config/sparc/sol2-ci.asm +crtn.o: $(srcdir)/config/sparc/sol2-cn.asm $(GCC_PASSES) + $(GCC_FOR_TARGET) -c -o crtn.o -x assembler $(srcdir)/config/sparc/sol2-cn.asm diff --git a/gnu/usr.bin/gcc/config/sparc/t-linux b/gnu/usr.bin/gcc/config/sparc/t-linux new file mode 100644 index 00000000000..6e37a023005 --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/t-linux @@ -0,0 +1,6 @@ +LIBGCC1 = +CROSS_LIBGCC1 = + +# We don't want to build .umul, etc., because gnu/Linux provides them, +# which means that libgcc1-test will fail for cross-compiler. +LIBGCC1_TEST = diff --git a/gnu/usr.bin/gcc/config/sparc/t-splet b/gnu/usr.bin/gcc/config/sparc/t-splet new file mode 100644 index 00000000000..3409f5dfe88 --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/t-splet @@ -0,0 +1,23 @@ +# configuration file for a bare sparclet cpu, aout format files + +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = sparc/lb1spc.asm +LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + cat $(srcdir)/config/fp-bit.c > dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c + +MULTILIB_OPTIONS = mlittle-endian mlive-g0 mbroken-saverestore +MULTILIB_DIRNAMES = little live-g0 brknsave + +LIBGCC = stmp-multilib +INSTALL_LIBGCC = install-multilib diff --git a/gnu/usr.bin/gcc/config/sparc/vxsim.h b/gnu/usr.bin/gcc/config/sparc/vxsim.h new file mode 100644 index 00000000000..6c80375f56b --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/vxsim.h @@ -0,0 +1,131 @@ +/* Definitions of target machine for GNU compiler, for SPARC VxSim + Copyright 1996 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */ +#include "sparc/sysv4.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-DCPU=SIMSPARCSOLARIS -D__vxworks -D__vxworks__ -Dsparc -D__svr4__ -D__SVR4 \ + -Asystem(embedded) -Asystem(svr4) -Acpu(sparc) -Amachine(sparc)\ + -D__GCC_NEW_VARARGS__" + +#undef CPP_SPEC +#define CPP_SPEC "" + +#undef CC1_SPEC +#define CC1_SPEC "-fno-builtin %{sun4:} %{target:}" + +/* The sun bundled assembler doesn't accept -Yd, (and neither does gas). + It's safe to pass -s always, even if -g is not used. */ +#undef ASM_SPEC +#define ASM_SPEC \ + "%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \ + %{fpic:-K PIC} %{fPIC:-K PIC}" + +/* However it appears that Solaris 2.0 uses the same reg numbering as + the old BSD-style system did. */ + +#undef DBX_REGISTER_NUMBER +/* Same as sparc.h */ +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* We use stabs-in-elf for debugging, because that is what the native + toolchain uses. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */ +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.skip %u\n", (SIZE)) + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + fputs ("\t.local\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + putc ('\n', (FILE)); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ +} while (0) + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.common" + +/* This is how to output a definition of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d:\n", PREFIX, NUM) + +/* This is how to output a reference to an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + +#undef ASM_OUTPUT_INTERNAL_LABELREF +#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, ".L%s%d", PREFIX, NUM) + +/* This is how to store into the string LABEL + 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(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*.L%s%d", PREFIX, NUM) + + + +#undef LIB_SPEC +#define LIB_SPEC "" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "" + +#undef LINK_SPEC +#define LINK_SPEC "-r" + +/* This defines which switch letters take arguments. + It is as in svr4.h but with -R added. */ + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + ( (CHAR) == 'D' \ + || (CHAR) == 'U' \ + || (CHAR) == 'o' \ + || (CHAR) == 'e' \ + || (CHAR) == 'u' \ + || (CHAR) == 'I' \ + || (CHAR) == 'm' \ + || (CHAR) == 'L' \ + || (CHAR) == 'R' \ + || (CHAR) == 'A' \ + || (CHAR) == 'h' \ + || (CHAR) == 'z') + +/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h. + Instead, it is enabled here, because it does work under Solaris. */ +/* Define for support of TFmode long double and REAL_ARITHMETIC. + Sparc ABI says that long double is 4 words. */ +#define LONG_DOUBLE_TYPE_SIZE 64 diff --git a/gnu/usr.bin/gcc/config/sparc/xm-linux.h b/gnu/usr.bin/gcc/config/sparc/xm-linux.h new file mode 100644 index 00000000000..f68f5715662 --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/xm-linux.h @@ -0,0 +1,28 @@ +/* Configuration for GCC for SPARC running Linux-based GNU systems. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Eddie C. Dost (ecd@skynet.be) + +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. */ + +#ifndef inhibit_libc +#include <alloca.h> +#include <stdlib.h> +#include <string.h> +#endif + +#include <xm-linux.h> diff --git a/gnu/usr.bin/gcc/config/sparc/xm-sp64.h b/gnu/usr.bin/gcc/config/sparc/xm-sp64.h new file mode 100644 index 00000000000..5954affa3b5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/sparc/xm-sp64.h @@ -0,0 +1,25 @@ +/* Configuration for GCC for Sparc v9 running 64-bit native. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include <sparc/xm-sparc.h> + +/* This describes the machine the compiler is hosted on. */ +#undef HOST_BITS_PER_LONG +#define HOST_BITS_PER_LONG 64 diff --git a/gnu/usr.bin/gcc/config/t-gnu b/gnu/usr.bin/gcc/config/t-gnu new file mode 100644 index 00000000000..58969f21e20 --- /dev/null +++ b/gnu/usr.bin/gcc/config/t-gnu @@ -0,0 +1,13 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1=libgcc1.null + +# The pushl in CTOR initialization interferes with frame pointer elimination. + +# We need to use -fPIC when we are using gcc to compile the routines in +# crtstuff.c. This is only really needed when we are going to use gcc/g++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fPIC when compiling the +# routines in crtstuff.c. + +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/gnu/usr.bin/gcc/config/t-linux b/gnu/usr.bin/gcc/config/t-linux new file mode 100644 index 00000000000..843fa1bdf79 --- /dev/null +++ b/gnu/usr.bin/gcc/config/t-linux @@ -0,0 +1,10 @@ +# Don't run fixproto +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = + +# Compile crtbeginS.o and crtendS.o with pic. +CRTSTUFF_T_CFLAGS_S = -fPIC +# Compile libgcc2.a with pic. +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/gnu/usr.bin/gcc/config/t-linux-aout b/gnu/usr.bin/gcc/config/t-linux-aout new file mode 100644 index 00000000000..a7c091799e8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/t-linux-aout @@ -0,0 +1,5 @@ +# Don't run fixproto +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = diff --git a/gnu/usr.bin/gcc/config/t-linux-gnulibc1 b/gnu/usr.bin/gcc/config/t-linux-gnulibc1 new file mode 100644 index 00000000000..7bb7bce85b3 --- /dev/null +++ b/gnu/usr.bin/gcc/config/t-linux-gnulibc1 @@ -0,0 +1,2 @@ +# We are building for the Linux C library 5. +T_CFLAGS = -DUSE_GNULIBC_1 diff --git a/gnu/usr.bin/gcc/config/t-netbsd b/gnu/usr.bin/gcc/config/t-netbsd new file mode 100644 index 00000000000..a3d9e22eaf0 --- /dev/null +++ b/gnu/usr.bin/gcc/config/t-netbsd @@ -0,0 +1,8 @@ +LIBGCC1=libgcc1.null +CROSS_LIBGCC1=libgcc1.null + +# Don't run fixproto +STMP_FIXPROTO = + +# Don't install "assert.h" in gcc. We use the one in glibc. +INSTALL_ASSERT_H = diff --git a/gnu/usr.bin/gcc/config/t-rtems b/gnu/usr.bin/gcc/config/t-rtems new file mode 100644 index 00000000000..25dd398dd52 --- /dev/null +++ b/gnu/usr.bin/gcc/config/t-rtems @@ -0,0 +1,2 @@ +# RTEMS uses newlib which does not require prototype fixing +STMP_FIXPROTO = diff --git a/gnu/usr.bin/gcc/config/v850/lib1funcs.asm b/gnu/usr.bin/gcc/config/v850/lib1funcs.asm new file mode 100644 index 00000000000..b140c4385e1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/v850/lib1funcs.asm @@ -0,0 +1,1269 @@ +/* libgcc1 routines for NEC V850. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 this program; 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. */ + +#ifdef L_mulsi3 + .text + .globl ___mulsi3 + .type ___mulsi3,@function + +/* + * In order to not deal with negative numbers (mulh is a signed multiply + * and we want an unsigned multiply, code the multiplication as a series + * of 7 bit multiplies). + * + * int __mulsi3 (unsigned a, unsigned b) + * { + * int i, j; + * int ret = 0; + * + * for (i = 0; i < 32; i += 7) + * { + * short a_part = a & 0x7f; + * unsigned b_tmp = b; + * a >>= 7; + * + * for (j = 0; (i+j) < 32; j += 7) + * { + * short b_part = b_tmp & 0x7f; + * ret += (((int)a_part) * ((int)b_part)) << (i+j); + * b_tmp >>= 7; + * } + * } + * + * return ret; + * } + */ + +___mulsi3: + mov 0,r10 /* total */ + mov 0,r14 /* i = 0, index for multiply a's part */ + movea lo(31),r0,r16 /* upper bounds for loop */ +.L5: + mov r7,r13 /* b_tmp = b */ + andi 0x7f,r6,r15 /* a_part = (a & 127) */ + shr 7,r6 /* a >>= 7 */ + mov r14,r12 /* i+j = i */ +.L9: + andi 0x7f,r13,r11 /* b_part = (b_tmp & 127) */ + mulh r15,r11 /* ((int)a_part) * ((int)b_part) */ + shr 7,r13 /* b_tmp >>= 7 */ + shl r12,r11 /* (((int)a_part) * ((int)b_part)) << (i+j) */ + add r11,r10 /* ret += (((int)a_part) * ((int)b_part)) << (i+j) */ + add 7,r12 /* i+j += 7 */ + cmp r16,r12 /* i+j < 32 */ + ble .L9 + + add 7,r14 /* i += 7 */ + cmp r16,r14 /* i < 32 */ + ble .L5 + + jmp [r31] /* return */ + .size __mulsi3,.-__mulsi3 +#endif + +#ifdef L_udivsi3 + .global ___udivsi3 +___udivsi3: + mov 1,r12 + mov 0,r10 + cmp r6,r7 + bnl .L12 + movhi hi(-2147483648),r0,r13 + cmp r0,r7 + blt .L12 +.L4: + shl 1,r7 + shl 1,r12 + cmp r6,r7 + bnl .L12 + cmp r0,r12 + be .L8 + mov r7,r5 + and r13,r5 + be .L4 + br .L12 +.L9: + cmp r7,r6 + bl .L10 + sub r7,r6 + or r12,r10 +.L10: + shr 1,r12 + shr 1,r7 +.L12: + cmp r0,r12 + bne .L9 +.L8: + jmp [r31] + .size __udivsi3,.-__udivsi3 +#endif + +#ifdef L_divsi3 + .text + .globl ___divsi3 + .type ___divsi3,@function +___divsi3: + add -8,sp + st.w r31,4[sp] + st.w r22,0[sp] + mov 1,r22 + tst r7,r7 + bp .L3 + subr r0,r7 + subr r0,r22 +.L3: + tst r6,r6 + bp .L4 + subr r0,r6 + subr r0,r22 +.L4: + jarl ___udivsi3,r31 + cmp r0,r22 + bp .L7 + subr r0,r10 +.L7: + ld.w 0[sp],r22 + ld.w 4[sp],r31 + add 8,sp + jmp [r31] + .size __divsi3,.-__divsi3 +#endif + +#ifdef L_umodsi3 + .text + .globl ___umodsi3 + .type ___umodsi3,@function +___umodsi3: + add -12,sp + st.w r31,8[sp] + st.w r7,4[sp] + st.w r6,0[sp] + jarl ___udivsi3,r31 + ld.w 4[sp],r7 + mov r10,r6 + jarl ___mulsi3,r31 + ld.w 0[sp],r6 + subr r6,r10 + ld.w 8[sp],r31 + add 12,sp + jmp [r31] + .size __umodsi3,.-__umodsi3 +#endif /* L_umodsi3 */ + +#ifdef L_modsi3 + .text + .globl ___modsi3 + .type ___modsi3,@function +___modsi3: + add -12,sp + st.w r31,8[sp] + st.w r7,4[sp] + st.w r6,0[sp] + jarl ___divsi3,r31 + ld.w 4[sp],r7 + mov r10,r6 + jarl ___mulsi3,r31 + ld.w 0[sp],r6 + subr r6,r10 + ld.w 8[sp],r31 + add 12,sp + jmp [r31] + .size __modsi3,.-__modsi3 +#endif /* L_modsi3 */ + +#ifdef L_save_2 + .text + .align 2 + .globl __save_r2_r29 + .type __save_r2_r29,@function + /* Allocate space and save registers 2, 20 .. 29 on the stack */ + /* Called via: jalr __save_r2_r29,r10 */ +__save_r2_r29: + mov ep,r1 + addi -44,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + sst.w r24,20[ep] + sst.w r23,24[ep] + sst.w r22,28[ep] + sst.w r21,32[ep] + sst.w r20,36[ep] + sst.w r2,40[ep] + mov r1,ep + jmp [r10] + .size __save_r2_r29,.-__save_r2_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r2_r29 */ + .align 2 + .globl __return_r2_r29 + .type __return_r2_r29,@function +__return_r2_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + sld.w 20[ep],r24 + sld.w 24[ep],r23 + sld.w 28[ep],r22 + sld.w 32[ep],r21 + sld.w 36[ep],r20 + sld.w 40[ep],r2 + addi 44,sp,sp + mov r1,ep + jmp [r31] + .size __return_r2_r29,.-__return_r2_r29 +#endif /* L_save_2 */ + +#ifdef L_save_20 + .text + .align 2 + .globl __save_r20_r29 + .type __save_r20_r29,@function + /* Allocate space and save registers 20 .. 29 on the stack */ + /* Called via: jalr __save_r20_r29,r10 */ +__save_r20_r29: + mov ep,r1 + addi -40,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + sst.w r24,20[ep] + sst.w r23,24[ep] + sst.w r22,28[ep] + sst.w r21,32[ep] + sst.w r20,36[ep] + mov r1,ep + jmp [r10] + .size __save_r20_r29,.-__save_r20_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r20_r29 */ + .align 2 + .globl __return_r20_r29 + .type __return_r20_r29,@function +__return_r20_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + sld.w 20[ep],r24 + sld.w 24[ep],r23 + sld.w 28[ep],r22 + sld.w 32[ep],r21 + sld.w 36[ep],r20 + addi 40,sp,sp + mov r1,ep + jmp [r31] + .size __return_r20_r29,.-__return_r20_r29 +#endif /* L_save_20 */ + +#ifdef L_save_21 + .text + .align 2 + .globl __save_r21_r29 + .type __save_r21_r29,@function + /* Allocate space and save registers 21 .. 29 on the stack */ + /* Called via: jalr __save_r21_r29,r10 */ +__save_r21_r29: + mov ep,r1 + addi -36,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + sst.w r24,20[ep] + sst.w r23,24[ep] + sst.w r22,28[ep] + sst.w r21,32[ep] + mov r1,ep + jmp [r10] + .size __save_r21_r29,.-__save_r21_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r21_r29 */ + .align 2 + .globl __return_r21_r29 + .type __return_r21_r29,@function +__return_r21_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + sld.w 20[ep],r24 + sld.w 24[ep],r23 + sld.w 28[ep],r22 + sld.w 32[ep],r21 + addi 36,sp,sp + mov r1,ep + jmp [r31] + .size __return_r21_r29,.-__return_r21_r29 +#endif /* L_save_21 */ + +#ifdef L_save_22 + .text + .align 2 + .globl __save_r22_r29 + .type __save_r22_r29,@function + /* Allocate space and save registers 22 .. 29 on the stack */ + /* Called via: jalr __save_r22_r29,r10 */ +__save_r22_r29: + mov ep,r1 + addi -32,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + sst.w r24,20[ep] + sst.w r23,24[ep] + sst.w r22,28[ep] + mov r1,ep + jmp [r10] + .size __save_r22_r29,.-__save_r22_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r22_r29 */ + .align 2 + .globl __return_r22_r29 + .type __return_r22_r29,@function +__return_r22_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + sld.w 20[ep],r24 + sld.w 24[ep],r23 + sld.w 28[ep],r22 + addi 32,sp,sp + mov r1,ep + jmp [r31] + .size __return_r22_r29,.-__return_r22_r29 +#endif /* L_save_22 */ + +#ifdef L_save_23 + .text + .align 2 + .globl __save_r23_r29 + .type __save_r23_r29,@function + /* Allocate space and save registers 23 .. 29 on the stack */ + /* Called via: jalr __save_r23_r29,r10 */ +__save_r23_r29: + mov ep,r1 + addi -28,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + sst.w r24,20[ep] + sst.w r23,24[ep] + mov r1,ep + jmp [r10] + .size __save_r23_r29,.-__save_r23_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r23_r29 */ + .align 2 + .globl __return_r23_r29 + .type __return_r23_r29,@function +__return_r23_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + sld.w 20[ep],r24 + sld.w 24[ep],r23 + addi 28,sp,sp + mov r1,ep + jmp [r31] + .size __return_r23_r29,.-__return_r23_r29 +#endif /* L_save_23 */ + +#ifdef L_save_24 + .text + .align 2 + .globl __save_r24_r29 + .type __save_r24_r29,@function + /* Allocate space and save registers 24 .. 29 on the stack */ + /* Called via: jalr __save_r24_r29,r10 */ +__save_r24_r29: + mov ep,r1 + addi -24,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + sst.w r24,20[ep] + mov r1,ep + jmp [r10] + .size __save_r24_r29,.-__save_r24_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r24_r29 */ + .align 2 + .globl __return_r24_r29 + .type __return_r24_r29,@function +__return_r24_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + sld.w 20[ep],r24 + addi 24,sp,sp + mov r1,ep + jmp [r31] + .size __return_r24_r29,.-__return_r24_r29 +#endif /* L_save_24 */ + +#ifdef L_save_25 + .text + .align 2 + .globl __save_r25_r29 + .type __save_r25_r29,@function + /* Allocate space and save registers 25 .. 29 on the stack */ + /* Called via: jalr __save_r25_r29,r10 */ +__save_r25_r29: + mov ep,r1 + addi -20,sp,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + sst.w r25,16[ep] + mov r1,ep + jmp [r10] + .size __save_r25_r29,.-__save_r25_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r25_r29 */ + .align 2 + .globl __return_r25_r29 + .type __return_r25_r29,@function +__return_r25_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + sld.w 16[ep],r25 + addi 20,sp,sp + mov r1,ep + jmp [r31] + .size __return_r25_r29,.-__return_r25_r29 +#endif /* L_save_25 */ + +#ifdef L_save_26 + .text + .align 2 + .globl __save_r26_r29 + .type __save_r26_r29,@function + /* Allocate space and save registers 26 .. 29 on the stack */ + /* Called via: jalr __save_r26_r29,r10 */ +__save_r26_r29: + mov ep,r1 + add -16,sp + mov sp,ep + sst.w r29,0[ep] + sst.w r28,4[ep] + sst.w r27,8[ep] + sst.w r26,12[ep] + mov r1,ep + jmp [r10] + .size __save_r26_r29,.-__save_r26_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r26_r29 */ + .align 2 + .globl __return_r26_r29 + .type __return_r26_r29,@function +__return_r26_r29: + mov ep,r1 + mov sp,ep + sld.w 0[ep],r29 + sld.w 4[ep],r28 + sld.w 8[ep],r27 + sld.w 12[ep],r26 + addi 16,sp,sp + mov r1,ep + jmp [r31] + .size __return_r26_r29,.-__return_r26_r29 +#endif /* L_save_26 */ + +#ifdef L_save_27 + .text + .align 2 + .globl __save_r27_r29 + .type __save_r27_r29,@function + /* Allocate space and save registers 27 .. 29 on the stack */ + /* Called via: jalr __save_r27_r29,r10 */ +__save_r27_r29: + add -12,sp + st.w r29,0[sp] + st.w r28,4[sp] + st.w r27,8[sp] + jmp [r10] + .size __save_r27_r29,.-__save_r27_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r27_r29 */ + .align 2 + .globl __return_r27_r29 + .type __return_r27_r29,@function +__return_r27_r29: + ld.w 0[sp],r29 + ld.w 4[sp],r28 + ld.w 8[sp],r27 + add 12,sp + jmp [r31] + .size __return_r27_r29,.-__return_r27_r29 +#endif /* L_save_27 */ + +#ifdef L_save_28 + .text + .align 2 + .globl __save_r28_r29 + .type __save_r28_r29,@function + /* Allocate space and save registers 28,29 on the stack */ + /* Called via: jalr __save_r28_r29,r10 */ +__save_r28_r29: + add -8,sp + st.w r29,0[sp] + st.w r28,4[sp] + jmp [r10] + .size __save_r28_r29,.-__save_r28_r29 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r28_r29 */ + .align 2 + .globl __return_r28_r29 + .type __return_r28_r29,@function +__return_r28_r29: + ld.w 0[sp],r29 + ld.w 4[sp],r28 + add 8,sp + jmp [r31] + .size __return_r28_r29,.-__return_r28_r29 +#endif /* L_save_28 */ + +#ifdef L_save_29 + .text + .align 2 + .globl __save_r29 + .type __save_r29,@function + /* Allocate space and save register 29 on the stack */ + /* Called via: jalr __save_r29,r10 */ +__save_r29: + add -4,sp + st.w r29,0[sp] + jmp [r10] + .size __save_r29,.-__save_r29 + + /* Restore saved register 29, deallocate stack and return to the user */ + /* Called via: jr __return_r29 */ + .align 2 + .globl __return_r29 + .type __return_r29,@function +__return_r29: + ld.w 0[sp],r29 + add 4,sp + jmp [r31] + .size __return_r29,.-__return_r29 +#endif /* L_save_28 */ + +#ifdef L_save_2c + .text + .align 2 + .globl __save_r2_r31 + .type __save_r2_r31,@function + /* Allocate space and save registers 20 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r2_r31,r10 */ +__save_r2_r31: + mov ep,r1 + addi -64,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r24,36[ep] + sst.w r23,40[ep] + sst.w r22,44[ep] + sst.w r21,48[ep] + sst.w r20,52[ep] + sst.w r2,56[ep] + sst.w r31,60[ep] + mov r1,ep + jmp [r10] + .size __save_r2_r31,.-__save_r2_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r20_r31 */ + .align 2 + .globl __return_r2_r31 + .type __return_r2_r31,@function +__return_r2_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r24 + sld.w 40[ep],r23 + sld.w 44[ep],r22 + sld.w 48[ep],r21 + sld.w 52[ep],r20 + sld.w 56[ep],r2 + sld.w 60[ep],r31 + addi 64,sp,sp + mov r1,ep + jmp [r31] + .size __return_r2_r31,.-__return_r2_r31 +#endif /* L_save_2c */ + +#ifdef L_save_20c + .text + .align 2 + .globl __save_r20_r31 + .type __save_r20_r31,@function + /* Allocate space and save registers 20 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r20_r31,r10 */ +__save_r20_r31: + mov ep,r1 + addi -60,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r24,36[ep] + sst.w r23,40[ep] + sst.w r22,44[ep] + sst.w r21,48[ep] + sst.w r20,52[ep] + sst.w r31,56[ep] + mov r1,ep + jmp [r10] + .size __save_r20_r31,.-__save_r20_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r20_r31 */ + .align 2 + .globl __return_r20_r31 + .type __return_r20_r31,@function +__return_r20_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r24 + sld.w 40[ep],r23 + sld.w 44[ep],r22 + sld.w 48[ep],r21 + sld.w 52[ep],r20 + sld.w 56[ep],r31 + addi 60,sp,sp + mov r1,ep + jmp [r31] + .size __return_r20_r31,.-__return_r20_r31 +#endif /* L_save_20c */ + +#ifdef L_save_21c + .text + .align 2 + .globl __save_r21_r31 + .type __save_r21_r31,@function + /* Allocate space and save registers 21 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r21_r31,r10 */ +__save_r21_r31: + mov ep,r1 + addi -56,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r24,36[ep] + sst.w r23,40[ep] + sst.w r22,44[ep] + sst.w r21,48[ep] + sst.w r31,52[ep] + mov r1,ep + jmp [r10] + .size __save_r21_r31,.-__save_r21_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r21_r31 */ + .align 2 + .globl __return_r21_r31 + .type __return_r21_r31,@function +__return_r21_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r24 + sld.w 40[ep],r23 + sld.w 44[ep],r22 + sld.w 48[ep],r21 + sld.w 52[ep],r31 + addi 56,sp,sp + mov r1,ep + jmp [r31] + .size __return_r21_r31,.-__return_r21_r31 +#endif /* L_save_21c */ + +#ifdef L_save_22c + .text + .align 2 + .globl __save_r22_r31 + .type __save_r22_r31,@function + /* Allocate space and save registers 22 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r22_r31,r10 */ +__save_r22_r31: + mov ep,r1 + addi -52,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r24,36[ep] + sst.w r23,40[ep] + sst.w r22,44[ep] + sst.w r31,48[ep] + mov r1,ep + jmp [r10] + .size __save_r22_r31,.-__save_r22_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r22_r31 */ + .align 2 + .globl __return_r22_r31 + .type __return_r22_r31,@function +__return_r22_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r24 + sld.w 40[ep],r23 + sld.w 44[ep],r22 + sld.w 48[ep],r31 + addi 52,sp,sp + mov r1,ep + jmp [r31] + .size __return_r22_r31,.-__return_r22_r31 +#endif /* L_save_22c */ + +#ifdef L_save_23c + .text + .align 2 + .globl __save_r23_r31 + .type __save_r23_r31,@function + /* Allocate space and save registers 23 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r23_r31,r10 */ +__save_r23_r31: + mov ep,r1 + addi -48,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r24,36[ep] + sst.w r23,40[ep] + sst.w r31,44[ep] + mov r1,ep + jmp [r10] + .size __save_r23_r31,.-__save_r23_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r23_r31 */ + .align 2 + .globl __return_r23_r31 + .type __return_r23_r31,@function +__return_r23_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r24 + sld.w 40[ep],r23 + sld.w 44[ep],r31 + addi 48,sp,sp + mov r1,ep + jmp [r31] + .size __return_r23_r31,.-__return_r23_r31 +#endif /* L_save_23c */ + +#ifdef L_save_24c + .text + .align 2 + .globl __save_r24_r31 + .type __save_r24_r31,@function + /* Allocate space and save registers 24 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r24_r31,r10 */ +__save_r24_r31: + mov ep,r1 + addi -44,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r24,36[ep] + sst.w r31,40[ep] + mov r1,ep + jmp [r10] + .size __save_r24_r31,.-__save_r24_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r24_r31 */ + .align 2 + .globl __return_r24_r31 + .type __return_r24_r31,@function +__return_r24_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r24 + sld.w 40[ep],r31 + addi 44,sp,sp + mov r1,ep + jmp [r31] + .size __return_r24_r31,.-__return_r24_r31 +#endif /* L_save_24c */ + +#ifdef L_save_25c + .text + .align 2 + .globl __save_r25_r31 + .type __save_r25_r31,@function + /* Allocate space and save registers 25 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r25_r31,r10 */ +__save_r25_r31: + mov ep,r1 + addi -40,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r25,32[ep] + sst.w r31,36[ep] + mov r1,ep + jmp [r10] + .size __save_r25_r31,.-__save_r25_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r25_r31 */ + .align 2 + .globl __return_r25_r31 + .type __return_r25_r31,@function +__return_r25_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r25 + sld.w 36[ep],r31 + addi 40,sp,sp + mov r1,ep + jmp [r31] + .size __return_r25_r31,.-__return_r25_r31 +#endif /* L_save_25c */ + +#ifdef L_save_26c + .text + .align 2 + .globl __save_r26_r31 + .type __save_r26_r31,@function + /* Allocate space and save registers 26 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r26_r31,r10 */ +__save_r26_r31: + mov ep,r1 + addi -36,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r26,28[ep] + sst.w r31,32[ep] + mov r1,ep + jmp [r10] + .size __save_r26_r31,.-__save_r26_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r26_r31 */ + .align 2 + .globl __return_r26_r31 + .type __return_r26_r31,@function +__return_r26_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r26 + sld.w 32[ep],r31 + addi 36,sp,sp + mov r1,ep + jmp [r31] + .size __return_r26_r31,.-__return_r26_r31 +#endif /* L_save_26c */ + +#ifdef L_save_27c + .text + .align 2 + .globl __save_r27_r31 + .type __save_r27_r31,@function + /* Allocate space and save registers 27 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r27_r31,r10 */ +__save_r27_r31: + mov ep,r1 + addi -32,sp,sp + mov sp,ep + sst.w r29,16[ep] + sst.w r28,20[ep] + sst.w r27,24[ep] + sst.w r31,28[ep] + mov r1,ep + jmp [r10] + .size __save_r27_r31,.-__save_r27_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r27_r31 */ + .align 2 + .globl __return_r27_r31 + .type __return_r27_r31,@function +__return_r27_r31: + mov ep,r1 + mov sp,ep + sld.w 16[ep],r29 + sld.w 20[ep],r28 + sld.w 24[ep],r27 + sld.w 28[ep],r31 + addi 32,sp,sp + mov r1,ep + jmp [r31] + .size __return_r27_r31,.-__return_r27_r31 +#endif /* L_save_27c */ + +#ifdef L_save_28c + .text + .align 2 + .globl __save_r28_r31 + .type __save_r28_r31,@function + /* Allocate space and save registers 28 .. 29, 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r28_r31,r10 */ +__save_r28_r31: + addi -28,sp,sp + st.w r29,16[sp] + st.w r28,20[sp] + st.w r31,24[sp] + jmp [r10] + .size __save_r28_r31,.-__save_r28_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r28_r31 */ + .align 2 + .globl __return_r28_r31 + .type __return_r28_r31,@function +__return_r28_r31: + ld.w 16[sp],r29 + ld.w 20[sp],r28 + ld.w 24[sp],r31 + addi 28,sp,sp + jmp [r31] + .size __return_r28_r31,.-__return_r28_r31 +#endif /* L_save_28c */ + +#ifdef L_save_29c + .text + .align 2 + .globl __save_r29_r31 + .type __save_r29_r31,@function + /* Allocate space and save registers 29 & 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r29_r31,r10 */ +__save_r29_r31: + addi -24,sp,sp + st.w r29,16[sp] + st.w r31,20[sp] + jmp [r10] + .size __save_r29_r31,.-__save_r29_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r29_r31 */ + .align 2 + .globl __return_r29_r31 + .type __return_r29_r31,@function +__return_r29_r31: + ld.w 16[sp],r29 + ld.w 20[sp],r31 + addi 24,sp,sp + jmp [r31] + .size __return_r29_r31,.-__return_r29_r31 +#endif /* L_save_29c */ + +#ifdef L_save_31c + .text + .align 2 + .globl __save_r31 + .type __save_r31,@function + /* Allocate space and save register 31 on the stack */ + /* Also allocate space for the argument save area */ + /* Called via: jalr __save_r29_r31,r10 */ +__save_r31: + addi -20,sp,sp + st.w r31,16[sp] + jmp [r10] + .size __save_r31,.-__save_r31 + + /* Restore saved registers, deallocate stack and return to the user */ + /* Called via: jr __return_r31 */ + .align 2 + .globl __return_r31 + .type __return_r31,@function +__return_r31: + ld.w 16[sp],r31 + addi 20,sp,sp + jmp [r31] + .size __return_r29_r31,.-__return_r29_r31 +#endif /* L_save_31c */ + +#ifdef L_save_varargs + .text + .align 2 + .globl __save_r6_r9 + .type __save_r6_r9,@function + /* Save registers 6 .. 9 on the stack for variable argument functions */ + /* Called via: jalr __save_r6_r9,r10 */ +__save_r6_r9: + mov ep,r1 + mov sp,ep + sst.w r6,0[ep] + sst.w r7,4[ep] + sst.w r8,8[ep] + sst.w r9,12[ep] + mov r1,ep + jmp [r10] + .size __save_r6_r9,.-__save_r6_r9 +#endif /* L_save_varargs */ + +#ifdef L_save_interrupt + .text + .align 2 + .globl __save_interrupt + .type __save_interrupt,@function + /* Save registers r1, r4 on stack and load up with expected values */ + /* Note, 12 bytes of stack have already been allocated. */ + /* Called via: jalr __save_interrupt,r10 */ +__save_interrupt: + st.w ep,0[sp] + st.w gp,4[sp] + st.w r1,8[sp] + movhi hi(__ep),r0,ep + movea lo(__ep),ep,ep + movhi hi(__gp),r0,gp + movea lo(__gp),gp,gp + jmp [r10] + .size __save_interrupt,.-__save_interrupt + + /* Restore saved registers, deallocate stack and return from the interrupt */ + /* Called via: jr __return_interrupt */ + .align 2 + .globl __return_interrupt + .type __return_interrupt,@function +__return_interrupt: + ld.w 0[sp],ep + ld.w 4[sp],gp + ld.w 8[sp],r1 + ld.w 12[sp],r10 + add 16,sp + reti + .size __return_interrupt,.-__return_interrupt +#endif /* L_save_interrupt */ + +#ifdef L_save_all_interrupt + .text + .align 2 + .globl __save_all_interrupt + .type __save_all_interrupt,@function + /* Save all registers except for those saved in __save_interrupt */ + /* allocate enough stack for all of the registers & 16 bytes of space */ + /* Called via: jalr __save_all_interrupt,r10 */ +__save_all_interrupt: + addi -120,sp,sp + mov ep,r1 + mov sp,ep + sst.w r31,116[ep] + sst.w r2,112[ep] + sst.w gp,108[ep] + sst.w r6,104[ep] + sst.w r7,100[ep] + sst.w r8,96[ep] + sst.w r9,92[ep] + sst.w r11,88[ep] + sst.w r12,84[ep] + sst.w r13,80[ep] + sst.w r14,76[ep] + sst.w r15,72[ep] + sst.w r16,68[ep] + sst.w r17,64[ep] + sst.w r18,60[ep] + sst.w r19,56[ep] + sst.w r20,52[ep] + sst.w r21,48[ep] + sst.w r22,44[ep] + sst.w r23,40[ep] + sst.w r24,36[ep] + sst.w r25,32[ep] + sst.w r26,28[ep] + sst.w r27,24[ep] + sst.w r28,20[ep] + sst.w r29,16[ep] + mov r1,ep + jmp [r10] + .size __save_all_interrupt,.-__save_all_interrupt + + .globl __restore_all_interrupt + .type __restore_all_interrupt,@function + /* Restore all registers saved in __save_all_interrupt */ + /* & deallocate the stack space */ + /* Called via: jalr __restore_all_interrupt,r10 */ +__restore_all_interrupt: + mov ep,r1 + mov sp,ep + sld.w 116[ep],r31 + sld.w 112[ep],r2 + sld.w 108[ep],gp + sld.w 104[ep],r6 + sld.w 100[ep],r7 + sld.w 96[ep],r8 + sld.w 92[ep],r9 + sld.w 88[ep],r11 + sld.w 84[ep],r12 + sld.w 80[ep],r13 + sld.w 76[ep],r14 + sld.w 72[ep],r15 + sld.w 68[ep],r16 + sld.w 64[ep],r17 + sld.w 60[ep],r18 + sld.w 56[ep],r19 + sld.w 52[ep],r20 + sld.w 48[ep],r21 + sld.w 44[ep],r22 + sld.w 40[ep],r23 + sld.w 36[ep],r24 + sld.w 32[ep],r25 + sld.w 28[ep],r26 + sld.w 24[ep],r27 + sld.w 20[ep],r28 + sld.w 16[ep],r29 + mov r1,ep + addi 120,sp,sp + jmp [r10] + .size __restore_all_interrupt,.-__restore_all_interrupt +#endif /* L_save_all_interrupt */ diff --git a/gnu/usr.bin/gcc/config/v850/t-v850 b/gnu/usr.bin/gcc/config/v850/t-v850 new file mode 100644 index 00000000000..d1d9b16f1b6 --- /dev/null +++ b/gnu/usr.bin/gcc/config/v850/t-v850 @@ -0,0 +1,52 @@ +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = v850/lib1funcs.asm +LIB1ASMFUNCS = _mulsi3 \ + _divsi3 \ + _udivsi3 \ + _modsi3 \ + _umodsi3 \ + _save_2 \ + _save_20 \ + _save_21 \ + _save_22 \ + _save_23 \ + _save_24 \ + _save_25 \ + _save_26 \ + _save_27 \ + _save_28 \ + _save_29 \ + _save_2c \ + _save_20c \ + _save_21c \ + _save_22c \ + _save_23c \ + _save_24c \ + _save_25c \ + _save_26c \ + _save_27c \ + _save_28c \ + _save_29c \ + _save_31c \ + _save_varargs \ + _save_interrupt \ + _save_all_interrupt + + +# These are really part of libgcc1, but this will cause them to be +# built correctly, so... + +LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c + +dp-bit.c: $(srcdir)/config/fp-bit.c + echo '#ifdef __LITTLE_ENDIAN__' > dp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >>dp-bit.c + echo '#endif' >> dp-bit.c + cat $(srcdir)/config/fp-bit.c >> dp-bit.c + +fp-bit.c: $(srcdir)/config/fp-bit.c + echo '#define FLOAT' > fp-bit.c + echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c + echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c + echo '#endif' >> fp-bit.c + cat $(srcdir)/config/fp-bit.c >> fp-bit.c diff --git a/gnu/usr.bin/gcc/config/v850/v850.c b/gnu/usr.bin/gcc/config/v850/v850.c new file mode 100644 index 00000000000..8f5c768bbe2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/v850/v850.c @@ -0,0 +1,2284 @@ +/* Subroutines for insn-output.c for NEC V850 series + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Jeff Law (law@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. */ + +#include <stdio.h> +#include <ctype.h> +#include "config.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "recog.h" +#include "expr.h" +#include "tree.h" +#include "obstack.h" + +/* True if the current function has anonymous arguments. */ +int current_function_anonymous_args; + +/* Information about the various small memory areas. */ +struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = +{ + /* name value max physical max */ + { "tda", (char *)0, 0, 256 }, + { "sda", (char *)0, 0, 65536 }, + { "zda", (char *)0, 0, 32768 }, +}; + +/* True if we don't need to check any more if the current + function is an interrupt handler */ +static int v850_interrupt_cache_p = FALSE; + +/* Whether current function is an interrupt handler. */ +static int v850_interrupt_p = FALSE; + + +/* Sometimes certain combinations of command options do not make + sense on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + Don't use this macro to turn on various extra optimizations for + `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ + +void +override_options () +{ + int i; + extern int atoi (); + + /* Parse -m{s,t,z}da=nnn switches */ + for (i = 0; i < (int)SMALL_MEMORY_max; i++) + { + if (small_memory[i].value) + { + if (!isdigit (*small_memory[i].value)) + error ("%s=%s is not numeric.", + small_memory[i].name, + small_memory[i].value); + else + { + small_memory[i].max = atoi (small_memory[i].value); + if (small_memory[i].max > small_memory[i].physical_max) + error ("%s=%s is too large.", + small_memory[i].name, + small_memory[i].value); + } + } + } +} + + +/* Output assembly code for the start of the file. */ + +void +asm_file_start (file) + FILE *file; +{ + output_file_directive (file, main_input_filename); +} + + +/* Return an RTX to represent where a value with mode MODE will be returned + from a function. If the result is 0, the argument is pushed. */ + +rtx +function_arg (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + rtx result = 0; + int size, align; + + if (TARGET_GHS && !named) + return NULL_RTX; + + if (mode == BLKmode) + size = int_size_in_bytes (type); + else + size = GET_MODE_SIZE (mode); + + if (type) + align = TYPE_ALIGN (type) / BITS_PER_UNIT; + else + align = size; + + cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); + + if (cum->nbytes > 4 * UNITS_PER_WORD) + return 0; + + if (type == NULL_TREE + && cum->nbytes + size > 4 * UNITS_PER_WORD) + return 0; + + switch (cum->nbytes / UNITS_PER_WORD) + { + case 0: + result = gen_rtx (REG, mode, 6); + break; + case 1: + result = gen_rtx (REG, mode, 7); + break; + case 2: + result = gen_rtx (REG, mode, 8); + break; + case 3: + result = gen_rtx (REG, mode, 9); + break; + default: + result = 0; + } + + return result; +} + + +/* Return the number of words which must be put into registers + for values which are part in registers and part in memory. */ + +int +function_arg_partial_nregs (cum, mode, type, named) + CUMULATIVE_ARGS *cum; + enum machine_mode mode; + tree type; + int named; +{ + int size, align; + + if (TARGET_GHS && !named) + return 0; + + if (mode == BLKmode) + size = int_size_in_bytes (type); + else + size = GET_MODE_SIZE (mode); + + if (type) + align = TYPE_ALIGN (type) / BITS_PER_UNIT; + else + align = size; + + cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); + + if (cum->nbytes > 4 * UNITS_PER_WORD) + return 0; + + if (cum->nbytes + size <= 4 * UNITS_PER_WORD) + return 0; + + if (type == NULL_TREE + && cum->nbytes + size > 4 * UNITS_PER_WORD) + return 0; + + return (4 * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD; +} + + +/* Return the high and low words of a CONST_DOUBLE */ + +static void +const_double_split (x, p_high, p_low) + rtx x; + HOST_WIDE_INT *p_high; + HOST_WIDE_INT *p_low; +{ + if (GET_CODE (x) == CONST_DOUBLE) + { + long t[2]; + REAL_VALUE_TYPE rv; + + switch (GET_MODE (x)) + { + case DFmode: + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_DOUBLE (rv, t); + *p_high = t[1]; /* since v850 is little endian */ + *p_low = t[0]; /* high is second word */ + return; + + case SFmode: + REAL_VALUE_FROM_CONST_DOUBLE (rv, x); + REAL_VALUE_TO_TARGET_SINGLE (rv, *p_high); + *p_low = 0; + return; + + case VOIDmode: + case DImode: + *p_high = CONST_DOUBLE_HIGH (x); + *p_low = CONST_DOUBLE_LOW (x); + return; + } + } + + fatal_insn ("const_double_split got a bad insn:", x); +} + + +/* Return the cost of the rtx R with code CODE. */ + +static int +const_costs_int (value, zero_cost) + HOST_WIDE_INT value; + int zero_cost; +{ + if (CONST_OK_FOR_I (value)) + return zero_cost; + else if (CONST_OK_FOR_J (value)) + return 1; + else if (CONST_OK_FOR_K (value)) + return 2; + else + return 4; +} + +int +const_costs (r, c) + rtx r; + enum rtx_code c; +{ + HOST_WIDE_INT high, low; + + switch (c) + { + case CONST_INT: + return const_costs_int (INTVAL (r), 0); + + case CONST_DOUBLE: + const_double_split (r, &high, &low); + if (GET_MODE (r) == SFmode) + return const_costs_int (high, 1); + else + return const_costs_int (high, 1) + const_costs_int (low, 1); + + case SYMBOL_REF: + case LABEL_REF: + case CONST: + return 2; + + case HIGH: + return 1; + + default: + return 4; + } +} + + +/* Print operand X using operand code CODE to assembly language output file + FILE. */ + +void +print_operand (file, x, code) + FILE *file; + rtx x; + int code; +{ + HOST_WIDE_INT high, low; + + switch (code) + { + case 'b': + case 'B': + case 'c': + case 'C': + switch ((code == 'B' || code == 'C') + ? reverse_condition (GET_CODE (x)) : GET_CODE (x)) + { + case NE: + if (code == 'c' || code == 'C') + fprintf (file, "nz"); + else + fprintf (file, "ne"); + break; + case EQ: + if (code == 'c' || code == 'C') + fprintf (file, "z"); + else + fprintf (file, "e"); + break; + case GE: + fprintf (file, "ge"); + break; + case GT: + fprintf (file, "gt"); + break; + case LE: + fprintf (file, "le"); + break; + case LT: + fprintf (file, "lt"); + break; + case GEU: + fprintf (file, "nl"); + break; + case GTU: + fprintf (file, "h"); + break; + case LEU: + fprintf (file, "nh"); + break; + case LTU: + fprintf (file, "l"); + break; + default: + abort (); + } + break; + case 'F': /* high word of CONST_DOUBLE */ + if (GET_CODE (x) == CONST_INT) + fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1); + else if (GET_CODE (x) == CONST_DOUBLE) + { + const_double_split (x, &high, &low); + fprintf (file, "%ld", (long) high); + } + else + abort (); + break; + case 'G': /* low word of CONST_DOUBLE */ + if (GET_CODE (x) == CONST_INT) + fprintf (file, "%ld", (long) INTVAL (x)); + else if (GET_CODE (x) == CONST_DOUBLE) + { + const_double_split (x, &high, &low); + fprintf (file, "%ld", (long) low); + } + else + abort (); + break; + case 'L': + fprintf (file, "%d\n", INTVAL (x) & 0xffff); + break; + case 'M': + fprintf (file, "%d", exact_log2 (INTVAL (x))); + break; + case 'O': + if (special_symbolref_operand (x, VOIDmode)) + { + char* name; + + if (GET_CODE (x) == SYMBOL_REF) + name = XSTR (x, 0); + else if (GET_CODE (x) == CONST) + name = XSTR (XEXP (XEXP (x, 0), 0), 0); + else + abort (); + + if (ZDA_NAME_P (name)) + fprintf (file, "zdaoff"); + else if (SDA_NAME_P (name)) + fprintf (file, "sdaoff"); + else if (TDA_NAME_P (name)) + fprintf (file, "tdaoff"); + else + abort(); + } + else + abort(); + break; + case 'P': + if (special_symbolref_operand (x, VOIDmode)) + output_addr_const (file, x); + else + abort(); + break; + case 'Q': + if (special_symbolref_operand (x, VOIDmode)) + { + char* name; + + if (GET_CODE (x) == SYMBOL_REF) + name = XSTR (x, 0); + else if (GET_CODE (x) == CONST) + name = XSTR (XEXP (XEXP (x, 0), 0), 0); + else + abort (); + + if (ZDA_NAME_P (name)) + fprintf (file, "r0"); + else if (SDA_NAME_P (name)) + fprintf (file, "gp"); + else if (TDA_NAME_P (name)) + fprintf (file, "ep"); + else + abort(); + } + else + abort(); + break; + case 'R': /* 2nd word of a double. */ + switch (GET_CODE (x)) + { + case REG: + fprintf (file, reg_names[REGNO (x) + 1]); + break; + case MEM: + print_operand_address (file, + XEXP (adj_offsettable_operand (x, 4), 0)); + break; + } + break; + case 'S': + { + /* if it's a reference to a TDA variable, use sst/sld vs. st/ld */ + if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), FALSE)) + fputs ("s", file); + + break; + } + case 'T': + { + /* Like an 'S' operand above, but for unsigned loads only. */ + if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), TRUE)) + fputs ("s", file); + + break; + } + case 'W': /* print the instruction suffix */ + switch (GET_MODE (x)) + { + default: + abort (); + + case QImode: fputs (".b", file); break; + case HImode: fputs (".h", file); break; + case SImode: fputs (".w", file); break; + case SFmode: fputs (".w", file); break; + } + break; + case '.': /* register r0 */ + fputs (reg_names[0], file); + break; + case 'z': /* reg or zero */ + if (x == const0_rtx) + fputs (reg_names[0], file); + else if (GET_CODE (x) == REG) + fputs (reg_names[REGNO (x)], file); + else + abort (); + break; + default: + switch (GET_CODE (x)) + { + case MEM: + if (GET_CODE (XEXP (x, 0)) == CONST_INT) + output_address (gen_rtx (PLUS, SImode, + gen_rtx (REG, SImode, 0), + XEXP (x, 0))); + else + output_address (XEXP (x, 0)); + break; + + case REG: + fputs (reg_names[REGNO (x)], file); + break; + case SUBREG: + fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file); + break; + case CONST_INT: + case SYMBOL_REF: + case CONST: + case LABEL_REF: + case CODE_LABEL: + print_operand_address (file, x); + break; + default: + abort (); + } + break; + + } +} + + +/* Output assembly language output for the address ADDR to FILE. */ + +void +print_operand_address (file, addr) + FILE *file; + rtx addr; +{ + switch (GET_CODE (addr)) + { + case REG: + fprintf (file, "0["); + print_operand (file, addr, 0); + fprintf (file, "]"); + break; + case LO_SUM: + if (GET_CODE (XEXP (addr, 0)) == REG) + { + /* reg,foo */ + fprintf (file, "lo("); + print_operand (file, XEXP (addr, 1), 0); + fprintf (file, ")["); + print_operand (file, XEXP (addr, 0), 0); + fprintf (file, "]"); + } + break; + case PLUS: + if (GET_CODE (XEXP (addr, 0)) == REG + || GET_CODE (XEXP (addr, 0)) == SUBREG) + { + /* reg,foo */ + print_operand (file, XEXP (addr, 1), 0); + fprintf (file, "["); + print_operand (file, XEXP (addr, 0), 0); + fprintf (file, "]"); + } + else + { + print_operand (file, XEXP (addr, 0), 0); + fprintf (file, "+"); + print_operand (file, XEXP (addr, 1), 0); + } + break; + case SYMBOL_REF: + if (ENCODED_NAME_P (XSTR (addr, 0))) + { + char* name = XSTR (addr, 0); + char* off_name; + char* reg_name; + + if (ZDA_NAME_P (name)) + { + off_name = "zdaoff"; + reg_name = "r0"; + } + else if (SDA_NAME_P (name)) + { + off_name = "sdaoff"; + reg_name = "gp"; + } + else if (TDA_NAME_P (name)) + { + off_name = "tdaoff"; + reg_name = "ep"; + } + else + abort(); + + fprintf (file, "%s(", off_name); + output_addr_const (file, addr); + fprintf (file, ")[%s]", reg_name); + } + else + output_addr_const (file, addr); + break; + case CONST: + if (special_symbolref_operand (addr, VOIDmode)) + { + char* name = XSTR (XEXP (XEXP (addr, 0), 0), 0); + char* off_name; + char* reg_name; + + if (ZDA_NAME_P (name)) + { + off_name = "zdaoff"; + reg_name = "r0"; + } + else if (SDA_NAME_P (name)) + { + off_name = "sdaoff"; + reg_name = "gp"; + } + else if (TDA_NAME_P (name)) + { + off_name = "tdaoff"; + reg_name = "ep"; + } + else + abort(); + + fprintf (file, "%s(", off_name); + output_addr_const (file, addr); + fprintf (file, ")[%s]", reg_name); + } + else + output_addr_const (file, addr); + break; + default: + output_addr_const (file, addr); + break; + } +} + + +/* Return appropriate code to load up a 1, 2, or 4 integer/floating + point value. */ + +char * +output_move_single (operands) + rtx *operands; +{ + rtx dst = operands[0]; + rtx src = operands[1]; + + if (REG_P (dst)) + { + if (REG_P (src)) + return "mov %1,%0"; + + else if (GET_CODE (src) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (src); + + if (CONST_OK_FOR_J (value)) /* signed 5 bit immediate */ + return "mov %1,%0"; + + else if (CONST_OK_FOR_K (value)) /* signed 16 bit immediate */ + return "movea lo(%1),%.,%0"; + + else if (CONST_OK_FOR_L (value)) /* upper 16 bits were set */ + return "movhi hi(%1),%.,%0"; + + else /* random constant */ + return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; + } + + else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode) + { + HOST_WIDE_INT high, low; + + const_double_split (src, &high, &low); + if (CONST_OK_FOR_J (high)) /* signed 5 bit immediate */ + return "mov %F1,%0"; + + else if (CONST_OK_FOR_K (high)) /* signed 16 bit immediate */ + return "movea lo(%F1),%.,%0"; + + else if (CONST_OK_FOR_L (high)) /* upper 16 bits were set */ + return "movhi hi(%F1),%.,%0"; + + else /* random constant */ + return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0"; + } + + else if (GET_CODE (src) == MEM) + return "%S1ld%W1 %1,%0"; + + else if (special_symbolref_operand (src, VOIDmode)) + return "movea %O1(%P1),%Q1,%0"; + + else if (GET_CODE (src) == LABEL_REF + || GET_CODE (src) == SYMBOL_REF + || GET_CODE (src) == CONST) + { + return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; + } + + else if (GET_CODE (src) == HIGH) + return "movhi hi(%1),%.,%0"; + + else if (GET_CODE (src) == LO_SUM) + { + operands[2] = XEXP (src, 0); + operands[3] = XEXP (src, 1); + return "movea lo(%3),%2,%0"; + } + } + + else if (GET_CODE (dst) == MEM) + { + if (REG_P (src)) + return "%S0st%W0 %1,%0"; + + else if (GET_CODE (src) == CONST_INT && INTVAL (src) == 0) + return "%S0st%W0 %.,%0"; + + else if (GET_CODE (src) == CONST_DOUBLE + && CONST0_RTX (GET_MODE (dst)) == src) + return "%S0st%W0 %.,%0"; + } + + fatal_insn ("output_move_single:", gen_rtx (SET, VOIDmode, dst, src)); + return ""; +} + + +/* Return appropriate code to load up an 8 byte integer or floating point value */ + +char * +output_move_double (operands) + rtx *operands; +{ + enum machine_mode mode = GET_MODE (operands[0]); + rtx dst = operands[0]; + rtx src = operands[1]; + + if (register_operand (dst, mode) + && register_operand (src, mode)) + { + if (REGNO (src) + 1 == REGNO (dst)) + return "mov %R1,%R0\n\tmov %1,%0"; + else + return "mov %1,%0\n\tmov %R1,%R0"; + } + + /* Storing 0 */ + if (GET_CODE (dst) == MEM + && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0) + || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src)))) + return "st.w %.,%0\n\tst.w %.,%R0"; + + if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) + { + HOST_WIDE_INT high_low[2]; + int i; + rtx xop[10]; + + if (GET_CODE (src) == CONST_DOUBLE) + const_double_split (src, &high_low[1], &high_low[0]); + else + { + high_low[0] = INTVAL (src); + high_low[1] = (INTVAL (src) >= 0) ? 0 : -1; + } + + for (i = 0; i < 2; i++) + { + xop[0] = gen_rtx (REG, SImode, REGNO (dst)+i); + xop[1] = GEN_INT (high_low[i]); + output_asm_insn (output_move_single (xop), xop); + } + + return ""; + } + + if (GET_CODE (src) == MEM) + { + int ptrreg = -1; + int dreg = REGNO (dst); + rtx inside = XEXP (src, 0); + + if (GET_CODE (inside) == REG) + ptrreg = REGNO (inside); + else if (GET_CODE (inside) == SUBREG) + ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside); + else if (GET_CODE (inside) == PLUS) + ptrreg = REGNO (XEXP (inside, 0)); + else if (GET_CODE (inside) == LO_SUM) + ptrreg = REGNO (XEXP (inside, 0)); + + if (dreg == ptrreg) + return "ld.w %R1,%R0\n\tld.w %1,%0"; + } + + if (GET_CODE (src) == MEM) + return "ld.w %1,%0\n\tld.w %R1,%R0"; + + if (GET_CODE (dst) == MEM) + return "st.w %1,%0\n\tst.w %R1,%R0"; + + return "mov %1,%0\n\tmov %R1,%R0"; +} + + +/* Return maximum offset supported for a short EP memory reference of mode + MODE and signedness UNSIGNEDP. */ + +int +ep_memory_offset (mode, unsignedp) + enum machine_mode mode; + int unsignedp; +{ + int max_offset = 0; + + switch (mode) + { + case QImode: + max_offset = (1 << 7); + break; + + case HImode: + max_offset = (1 << 8); + break; + + case SImode: + case SFmode: + max_offset = (1 << 8); + break; + } + + return max_offset; +} + +/* Return true if OP is a valid short EP memory reference */ + +int +ep_memory_operand (op, mode, unsigned_load) + rtx op; + enum machine_mode mode; + int unsigned_load; +{ + rtx addr, op0, op1; + int max_offset; + int mask; + + if (GET_CODE (op) != MEM) + return FALSE; + + max_offset = ep_memory_offset (mode, unsigned_load); + + mask = GET_MODE_SIZE (mode) - 1; + + addr = XEXP (op, 0); + if (GET_CODE (addr) == CONST) + addr = XEXP (addr, 0); + + switch (GET_CODE (addr)) + { + default: + break; + + case SYMBOL_REF: + return TDA_NAME_P (XSTR (addr, 0)); + + case REG: + return REGNO (addr) == EP_REGNUM; + + case PLUS: + op0 = XEXP (addr, 0); + op1 = XEXP (addr, 1); + if (GET_CODE (op1) == CONST_INT + && INTVAL (op1) < max_offset + && (INTVAL (op1) & mask) == 0) + { + if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM) + return TRUE; + + if (GET_CODE (op0) == SYMBOL_REF && TDA_NAME_P (XSTR (op0, 0))) + return TRUE; + } + break; + } + + return FALSE; +} + +/* Return true if OP is either a register or 0 */ + +int +reg_or_0_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == CONST_INT) + return INTVAL (op) == 0; + + else if (GET_CODE (op) == CONST_DOUBLE) + return CONST_DOUBLE_OK_FOR_G (op); + + else + return register_operand (op, mode); +} + +/* Return true if OP is either a register or a signed five bit integer */ + +int +reg_or_int5_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == CONST_INT) + return CONST_OK_FOR_J (INTVAL (op)); + + else + return register_operand (op, mode); +} + +/* Return true if OP is a valid call operand. */ + +int +call_address_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + /* Only registers are valid call operands if TARGET_LONG_CALLS. */ + if (TARGET_LONG_CALLS) + return GET_CODE (op) == REG; + return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG); +} + +int +special_symbolref_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == SYMBOL_REF) + return ENCODED_NAME_P (XSTR (op, 0)); + + else if (GET_CODE (op) == CONST) + return (GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && ENCODED_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0)) + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT + && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1)))); + + return FALSE; +} + +int +movsi_source_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + /* Some constants, as well as symbolic operands + must be done with HIGH & LO_SUM patterns. */ + if (CONSTANT_P (op) + && GET_CODE (op) != HIGH + && !(GET_CODE (op) == CONST_INT + && (CONST_OK_FOR_J (INTVAL (op)) + || CONST_OK_FOR_K (INTVAL (op)) + || CONST_OK_FOR_L (INTVAL (op))))) + return special_symbolref_operand (op, mode); + else + return general_operand (op, mode); +} + +int +power_of_two_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != CONST_INT) + return 0; + + if (exact_log2 (INTVAL (op)) == -1) + return 0; + return 1; +} + +int +not_power_of_two_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + unsigned int mask; + + if (mode == QImode) + mask = 0xff; + else if (mode == HImode) + mask = 0xffff; + else if (mode == SImode) + mask = 0xffffffff; + else + return 0; + + if (GET_CODE (op) != CONST_INT) + return 0; + + if (exact_log2 (~INTVAL (op) & mask) == -1) + return 0; + return 1; +} + + +/* Substitute memory references involving a pointer, to use the ep pointer, + taking care to save and preserve the ep. */ + +static void +substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep) + rtx first_insn; + rtx last_insn; + int uses; + int regno; + rtx *p_r1; + rtx *p_ep; +{ + rtx reg = gen_rtx (REG, Pmode, regno); + rtx insn; + int i; + + if (!*p_r1) + { + regs_ever_live[1] = 1; + *p_r1 = gen_rtx (REG, Pmode, 1); + *p_ep = gen_rtx (REG, Pmode, 30); + } + + if (TARGET_DEBUG) + fprintf (stderr, "Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n", + 2 * (uses - 3), uses, reg_names[regno], + IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), + INSN_UID (first_insn), INSN_UID (last_insn)); + + if (GET_CODE (first_insn) == NOTE) + first_insn = next_nonnote_insn (first_insn); + + last_insn = next_nonnote_insn (last_insn); + for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn)) + { + if (GET_CODE (insn) == INSN) + { + rtx pattern = single_set (insn); + + /* Replace the memory references. */ + if (pattern) + { + rtx *p_mem; + /* Memory operands are signed by default. */ + int unsignedp = FALSE; + + if (GET_CODE (SET_DEST (pattern)) == MEM + && GET_CODE (SET_SRC (pattern)) == MEM) + p_mem = (rtx *)0; + + else if (GET_CODE (SET_DEST (pattern)) == MEM) + p_mem = &SET_DEST (pattern); + + else if (GET_CODE (SET_SRC (pattern)) == MEM) + p_mem = &SET_SRC (pattern); + + else + p_mem = (rtx *)0; + + if (p_mem) + { + rtx addr = XEXP (*p_mem, 0); + + if (GET_CODE (addr) == REG && REGNO (addr) == regno) + *p_mem = change_address (*p_mem, VOIDmode, *p_ep); + + else if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && REGNO (XEXP (addr, 0)) == regno + && GET_CODE (XEXP (addr, 1)) == CONST_INT + && (((unsigned)INTVAL (XEXP (addr, 1))) + < ep_memory_offset (GET_MODE (*p_mem), + unsignedp))) + *p_mem = change_address (*p_mem, VOIDmode, + gen_rtx (PLUS, Pmode, + *p_ep, XEXP (addr, 1))); + } + } + } + } + + /* Optimize back to back cases of ep <- r1 & r1 <- ep. */ + insn = prev_nonnote_insn (first_insn); + if (insn && GET_CODE (insn) == INSN + && GET_CODE (PATTERN (insn)) == SET + && SET_DEST (PATTERN (insn)) == *p_ep + && SET_SRC (PATTERN (insn)) == *p_r1) + delete_insn (insn); + else + emit_insn_before (gen_rtx (SET, Pmode, *p_r1, *p_ep), first_insn); + + emit_insn_before (gen_rtx (SET, Pmode, *p_ep, reg), first_insn); + emit_insn_before (gen_rtx (SET, Pmode, *p_ep, *p_r1), last_insn); +} + + +/* In rare cases, correct code generation requires extra machine + dependent processing between the second jump optimization pass and + delayed branch scheduling. On those machines, define this macro + as a C statement to act on the code starting at INSN. + + On the 850, we use it to implement the -mep mode to copy heavily used + pointers to ep to use the implicit addressing */ + +void v850_reorg (start_insn) + rtx start_insn; +{ + struct { + int uses; + rtx first_insn; + rtx last_insn; + } regs[FIRST_PSEUDO_REGISTER]; + + int i; + int use_ep = FALSE; + rtx r1 = NULL_RTX; + rtx ep = NULL_RTX; + rtx insn; + rtx pattern; + + /* If not ep mode, just return now */ + if (!TARGET_EP) + return; + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + regs[i].uses = 0; + regs[i].first_insn = NULL_RTX; + regs[i].last_insn = NULL_RTX; + } + + for (insn = start_insn; insn != NULL_RTX; insn = NEXT_INSN (insn)) + { + switch (GET_CODE (insn)) + { + /* End of basic block */ + default: + if (!use_ep) + { + int max_uses = -1; + int max_regno = -1; + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (max_uses < regs[i].uses) + { + max_uses = regs[i].uses; + max_regno = i; + } + } + + if (max_uses > 3) + substitute_ep_register (regs[max_regno].first_insn, + regs[max_regno].last_insn, + max_uses, max_regno, &r1, &ep); + } + + use_ep = FALSE; + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + regs[i].uses = 0; + regs[i].first_insn = NULL_RTX; + regs[i].last_insn = NULL_RTX; + } + break; + + case NOTE: + break; + + case INSN: + pattern = single_set (insn); + + /* See if there are any memory references we can shorten */ + if (pattern) + { + rtx src = SET_SRC (pattern); + rtx dest = SET_DEST (pattern); + rtx mem; + /* Memory operands are signed by default. */ + int unsignedp = FALSE; + + if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM) + mem = NULL_RTX; + + else if (GET_CODE (dest) == MEM) + mem = dest; + + else if (GET_CODE (src) == MEM) + mem = src; + + else + mem = NULL_RTX; + + if (mem && ep_memory_operand (mem, GET_MODE (mem), unsignedp)) + use_ep = TRUE; + + else if (!use_ep && mem + && GET_MODE_SIZE (GET_MODE (mem)) <= UNITS_PER_WORD) + { + rtx addr = XEXP (mem, 0); + int regno = -1; + int short_p; + + if (GET_CODE (addr) == REG) + { + short_p = TRUE; + regno = REGNO (addr); + } + + else if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && GET_CODE (XEXP (addr, 1)) == CONST_INT + && (((unsigned)INTVAL (XEXP (addr, 1))) + < ep_memory_offset (GET_MODE (mem), unsignedp))) + { + short_p = TRUE; + regno = REGNO (XEXP (addr, 0)); + } + + else + short_p = FALSE; + + if (short_p) + { + regs[regno].uses++; + regs[regno].last_insn = insn; + if (!regs[regno].first_insn) + regs[regno].first_insn = insn; + } + } + + /* Loading up a register in the basic block zaps any savings + for the register */ + if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG) + { + enum machine_mode mode = GET_MODE (dest); + int word = 0; + int regno; + int endregno; + + while (GET_CODE (dest) == SUBREG) + { + word = SUBREG_WORD (dest); + dest = SUBREG_REG (dest); + } + + regno = REGNO (dest) + word; + endregno = regno + HARD_REGNO_NREGS (regno, mode); + + if (!use_ep) + { + /* See if we can use the pointer before this + modification. */ + int max_uses = -1; + int max_regno = -1; + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (max_uses < regs[i].uses) + { + max_uses = regs[i].uses; + max_regno = i; + } + } + + if (max_uses > 3 + && max_regno >= regno + && max_regno < endregno) + { + substitute_ep_register (regs[max_regno].first_insn, + regs[max_regno].last_insn, + max_uses, max_regno, &r1, &ep); + + /* Since we made a substitution, zap all remembered + registers. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + regs[i].uses = 0; + regs[i].first_insn = NULL_RTX; + regs[i].last_insn = NULL_RTX; + } + } + } + + for (i = regno; i < endregno; i++) + { + regs[i].uses = 0; + regs[i].first_insn = NULL_RTX; + regs[i].last_insn = NULL_RTX; + } + } + } + } + } +} + + +/* # of registers saved by the interrupt handler. */ +#define INTERRUPT_FIXED_NUM 4 + +/* # of bytes for registers saved by the interrupt handler. */ +#define INTERRUPT_FIXED_SAVE_SIZE (4 * INTERRUPT_FIXED_NUM) + +/* # of registers saved in register parameter area. */ +#define INTERRUPT_REGPARM_NUM 4 +/* # of words saved for other registers. */ +#define INTERRUPT_ALL_SAVE_NUM \ + (30 - INTERRUPT_FIXED_NUM + INTERRUPT_REGPARM_NUM) + +#define INTERRUPT_ALL_SAVE_SIZE (4 * INTERRUPT_ALL_SAVE_NUM) + +int +compute_register_save_size (p_reg_saved) + long *p_reg_saved; +{ + int size = 0; + int i; + int interrupt_handler = v850_interrupt_function_p (current_function_decl); + int call_p = regs_ever_live[31]; + long reg_saved = 0; + + /* Count the return pointer if we need to save it. */ + if (profile_flag && !call_p) + regs_ever_live[31] = call_p = 1; + + /* Count space for the register saves. */ + if (interrupt_handler) + { + for (i = 0; i <= 31; i++) + switch (i) + { + default: + if (regs_ever_live[i] || call_p) + { + size += 4; + reg_saved |= 1L << i; + } + break; + + /* We don't save/restore r0 or the stack pointer */ + case 0: + case STACK_POINTER_REGNUM: + break; + + /* For registers with fixed use, we save them, set them to the + appropriate value, and then restore them. + These registers are handled specially, so don't list them + on the list of registers to save in the prologue. */ + case 1: /* temp used to hold ep */ + case 4: /* gp */ + case 10: /* temp used to call interrupt save/restore */ + case EP_REGNUM: /* ep */ + size += 4; + break; + } + } + + else + for (i = 0; i <= 31; i++) + if (regs_ever_live[i] && ((! call_used_regs[i]) || i == 31)) + { + size += 4; + reg_saved |= 1L << i; + } + + if (p_reg_saved) + *p_reg_saved = reg_saved; + + return size; +} + +int +compute_frame_size (size, p_reg_saved) + int size; + long *p_reg_saved; +{ + extern int current_function_outgoing_args_size; + + return (size + + compute_register_save_size (p_reg_saved) + + current_function_outgoing_args_size); +} + + +void +expand_prologue () +{ + unsigned int i; + int offset; + unsigned int size = get_frame_size (); + unsigned int actual_fsize; + unsigned int init_stack_alloc = 0; + rtx save_regs[32]; + rtx save_all; + int num_save; + int default_stack; + int code; + int interrupt_handler = v850_interrupt_function_p (current_function_decl); + long reg_saved = 0; + + actual_fsize = compute_frame_size (size, ®_saved); + + /* Save/setup global registers for interrupt functions right now */ + if (interrupt_handler) + { + emit_insn (gen_save_interrupt ()); + actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE; + if (((1L << 31) & reg_saved) != 0) + actual_fsize -= INTERRUPT_ALL_SAVE_SIZE; + } + + /* Save arg registers to the stack if necessary. */ + else if (current_function_anonymous_args) + { + if (TARGET_PROLOG_FUNCTION) + emit_insn (gen_save_r6_r9 ()); + else + { + offset = 0; + for (i = 6; i < 10; i++) + { + emit_move_insn (gen_rtx (MEM, SImode, + plus_constant (stack_pointer_rtx, + offset)), + gen_rtx (REG, SImode, i)); + offset += 4; + } + } + } + + /* Identify all of the saved registers */ + num_save = 0; + default_stack = 0; + for (i = 1; i < 31; i++) + { + if (((1L << i) & reg_saved) != 0) + save_regs[num_save++] = gen_rtx (REG, Pmode, i); + } + + /* If the return pointer is saved, the helper functions also allocate + 16 bytes of stack for arguments to be saved in. */ + if (((1L << 31) & reg_saved) != 0) + { + save_regs[num_save++] = gen_rtx (REG, Pmode, 31); + default_stack = 16; + } + + /* See if we have an insn that allocates stack space and saves the particular + registers we want to. */ + save_all = NULL_RTX; + if (TARGET_PROLOG_FUNCTION && num_save > 0 && actual_fsize >= default_stack) + { + int alloc_stack = (4 * num_save) + default_stack; + int unalloc_stack = actual_fsize - alloc_stack; + int save_func_len = 4; + int save_normal_len; + + if (unalloc_stack) + save_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4; + + /* see if we would have used ep to save the stack */ + if (TARGET_EP && num_save > 3 && (unsigned)actual_fsize < 255) + save_normal_len = (3 * 2) + (2 * num_save); + else + save_normal_len = 4 * num_save; + + save_normal_len += CONST_OK_FOR_J (actual_fsize) ? 2 : 4; + + /* Don't bother checking if we don't actually save any space. + This happens for instance if one register is saved and additional + stack space is allocated. */ + if (save_func_len < save_normal_len) + { + save_all = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (num_save + (TARGET_V850 ? 2 : 1))); + XVECEXP (save_all, 0, 0) = gen_rtx (SET, VOIDmode, + stack_pointer_rtx, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (-alloc_stack))); + + if (TARGET_V850) + { + XVECEXP (save_all, 0, num_save+1) + = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 10)); + } + + offset = - default_stack; + for (i = 0; i < num_save; i++) + { + XVECEXP (save_all, 0, i+1) + = gen_rtx (SET, VOIDmode, + gen_rtx (MEM, Pmode, + plus_constant (stack_pointer_rtx, offset)), + save_regs[i]); + offset -= 4; + } + + code = recog (save_all, NULL_RTX, NULL_PTR); + if (code >= 0) + { + rtx insn = emit_insn (save_all); + INSN_CODE (insn) = code; + actual_fsize -= alloc_stack; + + if (TARGET_DEBUG) + fprintf (stderr, "Saved %d bytes via prologue function (%d vs. %d) for function %s\n", + save_normal_len - save_func_len, + save_normal_len, save_func_len, + IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); + } + else + save_all = NULL_RTX; + } + } + + /* If no prolog save function is available, store the registers the old fashioned + way (one by one). */ + if (!save_all) + { + /* Special case interrupt functions that save all registers for a call. */ + if (interrupt_handler && ((1L << 31) & reg_saved) != 0) + emit_insn (gen_save_all_interrupt ()); + + else + { + /* If the stack is too big, allocate it in chunks so we can do the + register saves. We use the register save size so we use the ep + register. */ + if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize)) + init_stack_alloc = compute_register_save_size (NULL); + else + init_stack_alloc = actual_fsize; + + /* Save registers at the beginning of the stack frame */ + offset = init_stack_alloc - 4; + + if (init_stack_alloc) + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (-init_stack_alloc))); + + /* Save the return pointer first. */ + if (num_save > 0 && REGNO (save_regs[num_save-1]) == 31) + { + emit_move_insn (gen_rtx (MEM, SImode, + plus_constant (stack_pointer_rtx, + offset)), + save_regs[--num_save]); + offset -= 4; + } + + for (i = 0; i < num_save; i++) + { + emit_move_insn (gen_rtx (MEM, SImode, + plus_constant (stack_pointer_rtx, + offset)), + save_regs[i]); + offset -= 4; + } + } + } + + /* Allocate the rest of the stack that was not allocated above (either it is + > 32K or we just called a function to save the registers and needed more + stack. */ + if (actual_fsize > init_stack_alloc) + { + int diff = actual_fsize - init_stack_alloc; + if (CONST_OK_FOR_K (diff)) + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (-diff))); + else + { + rtx reg = gen_rtx (REG, Pmode, 12); + emit_move_insn (reg, GEN_INT (-diff)); + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); + } + } + + /* If we need a frame pointer, set it up now. */ + if (frame_pointer_needed) + emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); +} + + +void +expand_epilogue () +{ + unsigned int i; + int offset; + unsigned int size = get_frame_size (); + long reg_saved = 0; + unsigned int actual_fsize = compute_frame_size (size, ®_saved); + unsigned int init_stack_free = 0; + rtx restore_regs[32]; + rtx restore_all; + int num_restore; + int default_stack; + int code; + int interrupt_handler = v850_interrupt_function_p (current_function_decl); + + /* Eliminate the initial stack stored by interrupt functions. */ + if (interrupt_handler) + { + actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE; + if (((1L << 31) & reg_saved) != 0) + actual_fsize -= INTERRUPT_ALL_SAVE_SIZE; + } + + /* Cut off any dynamic stack created. */ + if (frame_pointer_needed) + emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); + + /* Identify all of the saved registers */ + num_restore = 0; + default_stack = 0; + for (i = 1; i < 31; i++) + { + if (((1L << i) & reg_saved) != 0) + restore_regs[num_restore++] = gen_rtx (REG, Pmode, i); + } + + /* If the return pointer is saved, the helper functions also allocate + 16 bytes of stack for arguments to be saved in. */ + if (((1L << 31) & reg_saved) != 0) + { + restore_regs[num_restore++] = gen_rtx (REG, Pmode, 31); + default_stack = 16; + } + + /* See if we have an insn that restores the particular registers we + want to. */ + restore_all = NULL_RTX; + if (TARGET_PROLOG_FUNCTION && num_restore > 0 && actual_fsize >= default_stack + && !interrupt_handler) + { + int alloc_stack = (4 * num_restore) + default_stack; + int unalloc_stack = actual_fsize - alloc_stack; + int restore_func_len = 4; + int restore_normal_len; + + if (unalloc_stack) + restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4; + + /* see if we would have used ep to restore the registers */ + if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255) + restore_normal_len = (3 * 2) + (2 * num_restore); + else + restore_normal_len = 4 * num_restore; + + restore_normal_len += (CONST_OK_FOR_J (actual_fsize) ? 2 : 4) + 2; + + /* Don't bother checking if we don't actually save any space. */ + if (restore_func_len < restore_normal_len) + { + restore_all = gen_rtx (PARALLEL, VOIDmode, + rtvec_alloc (num_restore + 2)); + XVECEXP (restore_all, 0, 0) = gen_rtx (RETURN, VOIDmode); + XVECEXP (restore_all, 0, 1) + = gen_rtx (SET, VOIDmode, stack_pointer_rtx, + gen_rtx (PLUS, Pmode, + stack_pointer_rtx, + GEN_INT (alloc_stack))); + + offset = alloc_stack - 4; + for (i = 0; i < num_restore; i++) + { + XVECEXP (restore_all, 0, i+2) + = gen_rtx (SET, VOIDmode, + restore_regs[i], + gen_rtx (MEM, Pmode, + plus_constant (stack_pointer_rtx, offset))); + offset -= 4; + } + + code = recog (restore_all, NULL_RTX, NULL_PTR); + if (code >= 0) + { + rtx insn; + + actual_fsize -= alloc_stack; + if (actual_fsize) + { + if (CONST_OK_FOR_K (actual_fsize)) + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (actual_fsize))); + else + { + rtx reg = gen_rtx (REG, Pmode, 12); + emit_move_insn (reg, GEN_INT (actual_fsize)); + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + reg)); + } + } + + insn = emit_jump_insn (restore_all); + INSN_CODE (insn) = code; + + if (TARGET_DEBUG) + fprintf (stderr, "Saved %d bytes via epilogue function (%d vs. %d) in function %s\n", + restore_normal_len - restore_func_len, + restore_normal_len, restore_func_len, + IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); + } + else + restore_all = NULL_RTX; + } + } + + /* If no epilog save function is available, restore the registers the + old fashioned way (one by one). */ + if (!restore_all) + { + /* If the stack is large, we need to cut it down in 2 pieces. */ + if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize)) + init_stack_free = 4 * num_restore; + else + init_stack_free = actual_fsize; + + /* Deallocate the rest of the stack if it is > 32K or if extra stack + was allocated for an interrupt handler that makes a call. */ + if (actual_fsize > init_stack_free || (interrupt_handler && actual_fsize)) + { + int diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free); + if (CONST_OK_FOR_K (diff)) + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (diff))); + else + { + rtx reg = gen_rtx (REG, Pmode, 12); + emit_move_insn (reg, GEN_INT (diff)); + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + reg)); + } + } + + /* Special case interrupt functions that save all registers + for a call. */ + if (interrupt_handler && ((1L << 31) & reg_saved) != 0) + emit_insn (gen_restore_all_interrupt ()); + else + { + /* Restore registers from the beginning of the stack frame */ + offset = init_stack_free - 4; + + /* Restore the return pointer first. */ + if (num_restore > 0 && REGNO (restore_regs[num_restore-1]) == 31) + { + emit_move_insn (restore_regs[--num_restore], + gen_rtx (MEM, SImode, + plus_constant (stack_pointer_rtx, + offset))); + offset -= 4; + } + + for (i = 0; i < num_restore; i++) + { + emit_move_insn (restore_regs[i], + gen_rtx (MEM, SImode, + plus_constant (stack_pointer_rtx, + offset))); + + offset -= 4; + } + + /* Cut back the remainder of the stack. */ + if (init_stack_free) + emit_insn (gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (init_stack_free))); + } + + /* And return or use reti for interrupt handlers. */ + if (interrupt_handler) + emit_jump_insn (gen_restore_interrupt ()); + else if (actual_fsize) + emit_jump_insn (gen_return_internal ()); + else + emit_jump_insn (gen_return ()); + } + + current_function_anonymous_args = 0; + v850_interrupt_cache_p = FALSE; + v850_interrupt_p = FALSE; +} + + +/* Update the condition code from the insn. */ + +void +notice_update_cc (body, insn) + rtx body; + rtx insn; +{ + switch (get_attr_cc (insn)) + { + case CC_NONE: + /* Insn does not affect CC at all. */ + break; + + case CC_NONE_0HIT: + /* Insn does not change CC, but the 0'th operand has been changed. */ + if (cc_status.value1 != 0 + && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1)) + cc_status.value1 = 0; + break; + + case CC_SET_ZN: + /* Insn sets the Z,N flags of CC to recog_operand[0]. + V,C is in an unusable state. */ + CC_STATUS_INIT; + cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY; + cc_status.value1 = recog_operand[0]; + break; + + case CC_SET_ZNV: + /* Insn sets the Z,N,V flags of CC to recog_operand[0]. + C is in an unusable state. */ + CC_STATUS_INIT; + cc_status.flags |= CC_NO_CARRY; + cc_status.value1 = recog_operand[0]; + break; + + case CC_COMPARE: + /* The insn is a compare instruction. */ + CC_STATUS_INIT; + cc_status.value1 = SET_SRC (body); + break; + + case CC_CLOBBER: + /* Insn doesn't leave CC in a usable state. */ + CC_STATUS_INIT; + break; + } +} + + +/* Return nonzero if ATTR is a valid attribute for DECL. + ATTRIBUTES are any existing attributes and ARGS are the arguments + supplied with ATTR. + + Supported attributes: + + interrupt_handler or interrupt: output a prologue and epilogue suitable + for an interrupt handler. */ + +int +v850_valid_machine_decl_attribute (decl, attributes, attr, args) + tree decl; + tree attributes; + tree attr; + tree args; +{ + if (args != NULL_TREE) + return 0; + + if (is_attribute_p ("interrupt_handler", attr) + || is_attribute_p ("interrupt", attr)) + return TREE_CODE (decl) == FUNCTION_DECL; + + return 0; +} + + +/* Return nonzero if FUNC is an interrupt function as specified + by the "interrupt" attribute. */ + +int +v850_interrupt_function_p (func) + tree func; +{ + tree a; + int ret = 0; + + if (v850_interrupt_cache_p) + return v850_interrupt_p; + + if (TREE_CODE (func) != FUNCTION_DECL) + return 0; + + a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func)); + if (a != NULL_TREE) + ret = 1; + + else + { + a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func)); + ret = a != NULL_TREE; + } + + /* Its not safe to trust global variables until after function inlining has + been done. */ + if (reload_completed | reload_in_progress) + v850_interrupt_p = ret; + + return ret; +} + + +extern struct obstack *saveable_obstack; + +v850_encode_data_area (decl) + tree decl; +{ + char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0); + int len = strlen (str); + char *newstr; + + /* In the Cygnus sources we actually do something; this is just + here to make merges easier. */ + return; +} + +/* Return true if the given RTX is a register which can be restored + by a function epilogue. */ +int +register_is_ok_for_epilogue (op, mode) + rtx op; + enum machine_mode mode; +{ + /* The save/restore routines can only cope with registers 2, and 20 - 31 */ + return (GET_CODE (op) == REG) + && (((REGNO (op) >= 20) && REGNO (op) <= 31) + || REGNO (op) == 2); +} + +/* Return non-zero if the given RTX is suitable for collapsing into + jump to a function epilogue. */ +int +pattern_is_ok_for_epilogue (op, mode) + rtx op; + enum machine_mode mode; +{ + int count = XVECLEN (op, 0); + int i; + + /* If there are no registers to restore then the function epilogue + is not suitable. */ + if (count <= 2) + return 0; + + /* The pattern matching has already established that we are performing a + function epilogue and that we are popping at least one register. We must + now check the remaining entries in the vector to make sure that they are + also register pops. There is no good reason why there should ever be + anything else in this vector, but being paranoid always helps... + + The test below performs the C equivalent of this machine description + pattern match: + + (set (match_operand:SI n "register_is_ok_for_epilogue" "r") + (mem:SI (plus:SI (reg:SI 3) (match_operand:SI n "immediate_operand" "i")))) + */ + + for (i = 3; i < count; i++) + { + rtx vector_element = XVECEXP (op, 0, i); + rtx dest; + rtx src; + rtx plus; + + if (GET_CODE (vector_element) != SET) + return 0; + + dest = SET_DEST (vector_element); + src = SET_SRC (vector_element); + + if (GET_CODE (dest) != REG + || GET_MODE (dest) != SImode + || ! register_is_ok_for_epilogue (dest, SImode) + || GET_CODE (src) != MEM + || GET_MODE (src) != SImode) + return 0; + + plus = XEXP (src, 0); + + if (GET_CODE (plus) != PLUS + || GET_CODE (XEXP (plus, 0)) != REG + || GET_MODE (XEXP (plus, 0)) != SImode + || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM + || GET_CODE (XEXP (plus, 1)) != CONST_INT) + return 0; + } + + return 1; +} + +/* Construct a JR instruction to a routine that will perform the equivalent of + the RTL passed in as an argument. This RTL is a function epilogue that + pops registers off the stack and possibly releases some extra stack space + as well. The code has already verified that the RTL matches these + requirements. */ +char * +construct_restore_jr (op) + rtx op; +{ + int count = XVECLEN (op, 0); + int stack_bytes; + unsigned long int mask; + unsigned long int first; + unsigned long int last; + int i; + static char buff [100]; /* XXX */ + + if (count <= 2) + { + error ("Bogus JR construction: %d\n", count); + return NULL; + } + + /* Work out how many bytes to pop off the stack before retrieving + registers. */ + if (GET_CODE (XVECEXP (op, 0, 1)) != SET) + abort (); + if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS) + abort (); + if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT) + abort (); + + stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)); + + /* Each pop will remove 4 bytes from the stack... */ + stack_bytes -= (count - 2) * 4; + + /* Make sure that the amount we are popping either 0 or 16 bytes. */ + if (stack_bytes != 0 && stack_bytes != 16) + { + error ("Bad amount of stack space removal: %d", stack_bytes); + return NULL; + } + + /* Now compute the bit mask of registers to push. */ + mask = 0; + for (i = 2; i < count; i++) + { + rtx vector_element = XVECEXP (op, 0, i); + + if (GET_CODE (vector_element) != SET) + abort (); + if (GET_CODE (SET_DEST (vector_element)) != REG) + abort (); + if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode)) + abort (); + + mask |= 1 << REGNO (SET_DEST (vector_element)); + } + + /* Scan for the first register to pop. */ + for (first = 0; first < 32; first++) + { + if (mask & (1 << first)) + break; + } + + if (first >= 32) + abort (); + + /* Discover the last register to pop. */ + if (mask & (1 << 31)) + { + if (stack_bytes != 16) + abort (); + + last = 31; + } + else + { + if (stack_bytes != 0) + abort (); + if ((mask & (1 << 29)) == 0) + abort (); + + last = 29; + } + + /* Paranoia */ + for (i = (first == 2 ? 20 : first + 1); i < 29; i++) + if ((mask & (1 << i)) == 0) + abort (); + + if (first == last) + sprintf (buff, "jr __return_%s", reg_names [first]); + else + sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]); + + return buff; +} + + +/* Return non-zero if the given RTX is suitable for collapsing into + a jump to a function prologue. */ +int +pattern_is_ok_for_prologue (op, mode) + rtx op; + enum machine_mode mode; +{ + int count = XVECLEN (op, 0); + int i; + rtx vector_element; + + /* If there are no registers to save then the function prologue + is not suitable. */ + if (count <= 2) + return 0; + + /* The pattern matching has already established that we are adjusting the + stack and pushing at least one register. We must now check that the + remaining entries in the vector to make sure that they are also register + pushes, except for the last entry which should be a CLOBBER of r10. + + The test below performs the C equivalent of this machine description + pattern match: + + (set (mem:SI (plus:SI (reg:SI 3) + (match_operand:SI 2 "immediate_operand" "i"))) + (match_operand:SI 3 "register_is_ok_for_epilogue" "r")) + + */ + + for (i = 2; i < count - 1; i++) + { + rtx dest; + rtx src; + rtx plus; + + vector_element = XVECEXP (op, 0, i); + + if (GET_CODE (vector_element) != SET) + return 0; + + dest = SET_DEST (vector_element); + src = SET_SRC (vector_element); + + if (GET_CODE (dest) != MEM + || GET_MODE (dest) != SImode + || GET_CODE (src) != REG + || GET_MODE (src) != SImode + || ! register_is_ok_for_epilogue (src, SImode)) + return 0; + + plus = XEXP (dest, 0); + + if ( GET_CODE (plus) != PLUS + || GET_CODE (XEXP (plus, 0)) != REG + || GET_MODE (XEXP (plus, 0)) != SImode + || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM + || GET_CODE (XEXP (plus, 1)) != CONST_INT) + return 0; + + /* If the register is being pushed somewhere other than the stack + space just acquired by the first operand then abandon this quest. + Note: the test is <= because both values are negative. */ + if (INTVAL (XEXP (plus, 1)) + <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1))) + { + return 0; + } + } + + /* Make sure that the last entry in the vector is a clobber. */ + vector_element = XVECEXP (op, 0, i); + + if (GET_CODE (vector_element) != CLOBBER + || GET_CODE (XEXP (vector_element, 0)) != REG + || REGNO (XEXP (vector_element, 0)) != 10) + return 0; + + return 1; +} + +/* Construct a JARL instruction to a routine that will perform the equivalent + of the RTL passed as a parameter. This RTL is a function prologue that + saves some of the registers r20 - r31 onto the stack, and possibly acquires + some stack space as well. The code has already verified that the RTL + matches these requirements. */ +char * +construct_save_jarl (op) + rtx op; +{ + int count = XVECLEN (op, 0); + int stack_bytes; + unsigned long int mask; + unsigned long int first; + unsigned long int last; + int i; + static char buff [100]; /* XXX */ + + if (count <= 2) + { + error ("Bogus JARL construction: %d\n", count); + return NULL; + } + + /* Paranoia. */ + if (GET_CODE (XVECEXP (op, 0, 0)) != SET) + abort (); + if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS) + abort (); + if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG) + abort (); + if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT) + abort (); + + /* Work out how many bytes to push onto the stack after storing the + registers. */ + stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)); + + /* Each push will put 4 bytes from the stack... */ + stack_bytes += (count - 2) * 4; + + /* Make sure that the amount we are popping either 0 or 16 bytes. */ + if (stack_bytes != 0 && stack_bytes != -16) + { + error ("Bad amount of stack space removal: %d", stack_bytes); + return NULL; + } + + /* Now compute the bit mask of registers to push. */ + mask = 0; + for (i = 1; i < count - 1; i++) + { + rtx vector_element = XVECEXP (op, 0, i); + + if (GET_CODE (vector_element) != SET) + abort (); + if (GET_CODE (SET_SRC (vector_element)) != REG) + abort (); + if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode)) + abort (); + + mask |= 1 << REGNO (SET_SRC (vector_element)); + } + + /* Scan for the first register to push. */ + for (first = 0; first < 32; first++) + { + if (mask & (1 << first)) + break; + } + + if (first >= 32) + abort (); + + /* Discover the last register to push. */ + if (mask & (1 << 31)) + { + if (stack_bytes != -16) + abort(); + + last = 31; + } + else + { + if (stack_bytes != 0) + abort (); + if ((mask & (1 << 29)) == 0) + abort (); + + last = 29; + } + + /* Paranoia */ + for (i = (first == 2 ? 20 : first + 1); i < 29; i++) + if ((mask & (1 << i)) == 0) + abort (); + + if (first == last) + sprintf (buff, "jarl __save_%s, r10", reg_names [first]); + else + sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first], + reg_names [last]); + + return buff; +} + diff --git a/gnu/usr.bin/gcc/config/v850/v850.h b/gnu/usr.bin/gcc/config/v850/v850.h new file mode 100644 index 00000000000..19eab5fdaf8 --- /dev/null +++ b/gnu/usr.bin/gcc/config/v850/v850.h @@ -0,0 +1,1475 @@ +/* Definitions of target machine for GNU compiler. NEC V850 series + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Jeff Law (law@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. */ + +#include "svr4.h" /* Automatically does #undef CPP_PREDEFINES */ + +#undef ASM_SPEC +#define ASM_SPEC "%{mv*:-mv%*}" + +#ifndef CPP_SPEC +#define CPP_SPEC "-D__v850__" +#endif + +#undef ASM_FINAL_SPEC +#undef LIB_SPEC +#undef ENDFILE_SPEC +#undef LINK_SPEC +#undef STARTFILE_SPEC + +/* Names to predefine in the preprocessor for this target machine. */ +#define CPP_PREDEFINES "-D__v851__ -D__v850" + +/* Print subsidiary information on the compiler version in use. */ + +#ifndef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (NEC V850)"); +#endif + + +/* Run-time compilation parameters selecting different hardware subsets. */ + +extern int target_flags; + +/* Target flags bits, see below for an explanation of the bits. */ +#define MASK_GHS 0x00000001 +#define MASK_LONG_CALLS 0x00000002 +#define MASK_EP 0x00000004 +#define MASK_PROLOG_FUNCTION 0x00000008 +#define MASK_DEBUG 0x40000000 + +#define MASK_CPU 0x00000030 +#define MASK_V850 0x00000010 + +#define MASK_BIG_SWITCH 0x00000100 + +#ifndef MASK_DEFAULT +#define MASK_DEFAULT MASK_V850 +#endif + +#define TARGET_V850 ((target_flags & MASK_CPU) == MASK_V850) + + +/* Macros used in the machine description to test the flags. */ + +/* The GHS calling convention support doesn't really work, + mostly due to a lack of documentation. Outstanding issues: + + * How do varargs & stdarg really work. How to they handle + passing structures (if at all). + + * Doubles are normally 4 byte aligned, except in argument + lists where they are 8 byte aligned. Is the alignment + in the argument list based on the first parameter, + first stack parameter, etc etc. + + * Passing/returning of large structures probably isn't the same + as GHS. We don't have enough documentation on their conventions + to be compatible. + + * Tests of SETUP_INCOMING_VARARGS need to be made runtime checks + since it depends on TARGET_GHS. */ +#define TARGET_GHS (target_flags & MASK_GHS) + +/* Don't do PC-relative calls, instead load the address of the target + function into a register and perform a register indirect call. */ +#define TARGET_LONG_CALLS (target_flags & MASK_LONG_CALLS) + +/* Whether to optimize space by using ep (r30) for pointers with small offsets + in basic blocks. */ +#define TARGET_EP (target_flags & MASK_EP) + +/* Whether to call out-of-line functions to save registers or not. */ +#define TARGET_PROLOG_FUNCTION (target_flags & MASK_PROLOG_FUNCTION) + +/* Whether to emit 2 byte per entry or 4 byte per entry switch tables. */ +#define TARGET_BIG_SWITCH (target_flags & MASK_BIG_SWITCH) + +/* General debug flag */ +#define TARGET_DEBUG (target_flags & MASK_DEBUG) + +/* Macro to define tables used to set the flags. + This is a list in braces of pairs in braces, + each pair being { "NAME", VALUE } + where VALUE is the bits to set or minus the bits to clear. + An empty string NAME is used to identify the default VALUE. */ + +#define TARGET_SWITCHES \ + {{ "ghs", MASK_GHS }, \ + { "no-ghs", -MASK_GHS }, \ + { "long-calls", MASK_LONG_CALLS }, \ + { "no-long-calls", -MASK_LONG_CALLS }, \ + { "ep", MASK_EP }, \ + { "no-ep", -MASK_EP }, \ + { "prolog-function", MASK_PROLOG_FUNCTION }, \ + { "no-prolog-function", -MASK_PROLOG_FUNCTION }, \ + { "space", MASK_EP | MASK_PROLOG_FUNCTION }, \ + { "debug", MASK_DEBUG }, \ + { "v850", MASK_V850 }, \ + { "v850", -(MASK_V850 ^ MASK_CPU) }, \ + { "big-switch", MASK_BIG_SWITCH }, \ + EXTRA_SWITCHES \ + { "", TARGET_DEFAULT}} + +#ifndef EXTRA_SWITCHES +#define EXTRA_SWITCHES +#endif + +#ifndef TARGET_DEFAULT +#define TARGET_DEFAULT MASK_DEFAULT +#endif + +/* Information about the various small memory areas. */ +struct small_memory_info { + char *name; + char *value; + long max; + long physical_max; +}; + +enum small_memory_type { + /* tiny data area, using EP as base register */ + SMALL_MEMORY_TDA = 0, + /* small data area using dp as base register */ + SMALL_MEMORY_SDA, + /* zero data area using r0 as base register */ + SMALL_MEMORY_ZDA, + SMALL_MEMORY_max +}; + +extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max]; + +/* This macro is similar to `TARGET_SWITCHES' but defines names of + command options that have values. Its definition is an + initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + fixed part of the option name, and the address of a variable. The + variable, type `char *', is set to the variable part of the given + option if the fixed part matches. The actual option name is made + by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the + given option is `-mshort-data-512', the variable `m88k_short_data' + will be set to the string `"512"'. + + extern char *m88k_short_data; + #define TARGET_OPTIONS \ + { { "short-data-", &m88k_short_data } } */ + +#define TARGET_OPTIONS \ +{ \ + { "tda=", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \ + { "tda-", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \ + { "sda=", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \ + { "sda-", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \ + { "zda=", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \ + { "zda-", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \ +} + +/* Sometimes certain combinations of command options do not make + sense on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + Don't use this macro to turn on various extra optimizations for + `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ +#define OVERRIDE_OPTIONS override_options () + + +/* Show we can debug even without a frame pointer. */ +#define CAN_DEBUG_WITHOUT_FP + +/* Some machines may desire to change what optimizations are + performed for various optimization levels. This macro, if + defined, is executed once just after the optimization level is + determined and before the remainder of the command options have + been parsed. Values set in this macro are used as the default + values for the other command line options. + + LEVEL is the optimization level specified; 2 if `-O2' is + specified, 1 if `-O' is specified, and 0 if neither is specified. + + You should not use this macro to change options that are not + machine-specific. These should uniformly selected by the same + optimization level on all supported machines. Use this macro to + enable machine-specific optimizations. + + *Do not examine `write_symbols' in this macro!* The debugging + options are not supposed to alter the generated code. */ + +#define OPTIMIZATION_OPTIONS(LEVEL) \ +{ \ + if (LEVEL) \ + target_flags |= (MASK_EP | MASK_PROLOG_FUNCTION); \ +} + + +/* Target machine storage layout */ + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. + This is not true on the NEC V850. */ +#define BITS_BIG_ENDIAN 0 + +/* Define this if most significant byte of a word is the lowest numbered. */ +/* This is not true on the NEC V850. */ +#define BYTES_BIG_ENDIAN 0 + +/* Define this if most significant word of a multiword number is lowest + numbered. + This is not true on the NEC V850. */ +#define WORDS_BIG_ENDIAN 0 + +/* Number of bits in an addressable storage unit */ +#define BITS_PER_UNIT 8 + +/* Width in bits of a "word", which is the contents of a machine register. + Note that this is not necessarily the width of data type `int'; + if using 16-bit ints on a 68000, this would still be 32. + But on a machine with 16-bit registers, this would be 16. */ +#define BITS_PER_WORD 32 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD 4 + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ +#define POINTER_SIZE 32 + +/* Define this macro if it is advisable to hold scalars in registers + in a wider mode than that declared by the program. In such cases, + the value is constrained to be within the bounds of the declared + type, but kept valid in the wider mode. The signedness of the + extension may differ from that of the type. + + Some simple experiments have shown that leaving UNSIGNEDP alone + generates the best overall code. */ + +#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ + if (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < 4) \ + { (MODE) = SImode; } + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY 32 + +/* The stack goes in 32 bit lumps. */ +#define STACK_BOUNDARY 32 + +/* Allocation boundary (in *bits*) for the code of a function. + 16 is the minimum boundary; 32 would give better performance. */ +#define FUNCTION_BOUNDARY 16 + +/* No data type wants to be aligned rounder than this. */ +#define BIGGEST_ALIGNMENT 32 + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY 32 + +/* No structure field wants to be aligned rounder than this. */ +#define BIGGEST_FIELD_ALIGNMENT 32 + +/* Define this if move instructions will actually fail to work + when given unaligned data. */ +#define STRICT_ALIGNMENT 1 + +/* Define this as 1 if `char' should by default be signed; else as 0. + + On the NEC V850, loads do sign extension, so make this default. */ +#define DEFAULT_SIGNED_CHAR 1 + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ + +#define FIRST_PSEUDO_REGISTER 34 + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. */ + +#define FIXED_REGISTERS \ + { 1, 1, 0, 1, 1, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 1, 0, \ + 1, 1} + +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you + like. */ + +#define CALL_USED_REGISTERS \ + { 1, 1, 0, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 1, 1, \ + 1, 1} + +/* List the order in which to allocate registers. Each register must be + listed once, even those in FIXED_REGISTERS. + + On the 850, we make the return registers first, then all of the volatile + registers, then the saved registers in reverse order to better save the + registers with an out of line function, and finally the fixed + registers. */ + +#define REG_ALLOC_ORDER \ +{ \ + 10, 11, /* return registers */ \ + 12, 13, 14, 15, 16, 17, 18, 19, /* scratch registers */ \ + 6, 7, 8, 9, 31, /* argument registers */ \ + 29, 28, 27, 26, 25, 24, 23, 22, /* saved registers */ \ + 21, 20, 2, \ + 0, 1, 3, 4, 5, 30, 32, 33 /* fixed registers */ \ +} + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. */ + +#define HARD_REGNO_NREGS(REGNO, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode + MODE. */ + +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((((REGNO) & 1) == 0) || (GET_MODE_SIZE (MODE) <= 4)) + +/* Value is 1 if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ +#define MODES_TIEABLE_P(MODE1, MODE2) \ + (MODE1 == MODE2 || GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4) + + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + +enum reg_class { + NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ + +#define REG_CLASS_NAMES \ +{ "NO_REGS", "GENERAL_REGS", "ALL_REGS", "LIM_REGS" } + +/* Define which registers fit in which classes. + This is an initializer for a vector of HARD_REG_SET + of length N_REG_CLASSES. */ + +#define REG_CLASS_CONTENTS \ +{ 0x00000000, /* No regs */ \ + 0xffffffff, /* GENERAL_REGS */ \ + 0xffffffff, /* ALL_REGS */ \ +} + +/* The same information, inverted: + Return the class number of the smallest class containing + reg number REGNO. This could be a conditional expression + or could index an array. */ + +#define REGNO_REG_CLASS(REGNO) GENERAL_REGS + +/* The class value for index registers, and the one for base regs. */ + +#define INDEX_REG_CLASS NO_REGS +#define BASE_REG_CLASS GENERAL_REGS + +/* Get reg_class from a letter such as appears in the machine description. */ + +#define REG_CLASS_FROM_LETTER(C) (NO_REGS) + +/* Macros to check register numbers against specific register classes. */ + +/* These assume that REGNO is a hard or pseudo reg number. + They give nonzero only if REGNO is a hard reg of the suitable class + or a pseudo reg currently allocated to a suitable hard reg. + Since they use reg_renumber, they are safe only once reg_renumber + has been allocated, which happens in local-alloc.c. */ + +#define REGNO_OK_FOR_BASE_P(regno) \ + ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0) + +#define REGNO_OK_FOR_INDEX_P(regno) 0 + +/* Given an rtx X being reloaded into a reg required to be + in class CLASS, return the class of reg to actually use. + In general this is just CLASS; but on some machines + in some cases it is preferable to use a more restrictive class. */ + +#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS) + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ + +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* The letters I, J, K, L, M, N, O, P in a register constraint string + can be used to stand for particular ranges of immediate operands. + This macro defines what the ranges are. + C is the letter, and VALUE is a constant value. + Return 1 if VALUE is in the range specified by C. */ + +#define INT_7_BITS(VALUE) ((unsigned) (VALUE) + 0x40 < 0x80) +#define INT_8_BITS(VALUE) ((unsigned) (VALUE) + 0x80 < 0x100) +/* zero */ +#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0) +/* 5 bit signed immediate */ +#define CONST_OK_FOR_J(VALUE) ((unsigned) (VALUE) + 0x10 < 0x20) +/* 16 bit signed immediate */ +#define CONST_OK_FOR_K(VALUE) ((unsigned) (VALUE) + 0x8000 < 0x10000) +/* valid constant for movhi instruction. */ +#define CONST_OK_FOR_L(VALUE) \ + (((unsigned) ((int) (VALUE) >> 16) + 0x8000 < 0x10000) \ + && CONST_OK_FOR_I ((VALUE & 0xffff))) +/* 16 bit unsigned immediate */ +#define CONST_OK_FOR_M(VALUE) ((unsigned)(VALUE) < 0x10000) +/* 5 bit unsigned immediate in shift instructions */ +#define CONST_OK_FOR_N(VALUE) ((unsigned) (VALUE) <= 31) + +#define CONST_OK_FOR_O(VALUE) 0 +#define CONST_OK_FOR_P(VALUE) 0 + + +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \ + (C) == 'J' ? CONST_OK_FOR_J (VALUE) : \ + (C) == 'K' ? CONST_OK_FOR_K (VALUE) : \ + (C) == 'L' ? CONST_OK_FOR_L (VALUE) : \ + (C) == 'M' ? CONST_OK_FOR_M (VALUE) : \ + (C) == 'N' ? CONST_OK_FOR_N (VALUE) : \ + (C) == 'O' ? CONST_OK_FOR_O (VALUE) : \ + (C) == 'P' ? CONST_OK_FOR_P (VALUE) : \ + 0) + +/* Similar, but for floating constants, and defining letters G and H. + Here VALUE is the CONST_DOUBLE rtx itself. + + `G' is a zero of some form. */ + +#define CONST_DOUBLE_OK_FOR_G(VALUE) \ + ((GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ + && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \ + || (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_INT \ + && CONST_DOUBLE_LOW (VALUE) == 0 \ + && CONST_DOUBLE_HIGH (VALUE) == 0)) + +#define CONST_DOUBLE_OK_FOR_H(VALUE) 0 + +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'G' ? CONST_DOUBLE_OK_FOR_G (VALUE) \ + : (C) == 'H' ? CONST_DOUBLE_OK_FOR_H (VALUE) \ + : 0) + + +/* Stack layout; function entry, exit and calling. */ + +/* Define this if pushing a word on the stack + makes the stack pointer a smaller address. */ + +#define STACK_GROWS_DOWNWARD + +/* Define this if the nominal address of the stack frame + is at the high-address end of the local variables; + that is, each additional local variable allocated + goes at a more negative offset in the frame. */ + +#define FRAME_GROWS_DOWNWARD + +/* Offset within stack frame to start allocating local variables at. + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the + first local allocated. Otherwise, it is the offset to the BEGINNING + of the first local allocated. */ + +#define STARTING_FRAME_OFFSET 0 + +/* Offset of first parameter from the argument pointer register value. */ +/* Is equal to the size of the saved fp + pc, even if an fp isn't + saved since the value is used before we know. */ + +#define FIRST_PARM_OFFSET(FNDECL) 0 + +/* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 3 + +/* Base register for access to local variables of the function. */ +#define FRAME_POINTER_REGNUM 32 + +/* On some machines the offset between the frame pointer and starting + offset of the automatic variables is not known until after register + allocation has been done (for example, because the saved registers + are between these two locations). On those machines, define + `FRAME_POINTER_REGNUM' the number of a special, fixed register to + be used internally until the offset is known, and define + `HARD_FRAME_POINTER_REGNUM' to be actual the hard register number + used for the frame pointer. + + You should define this macro only in the very rare circumstances + when it is not possible to calculate the offset between the frame + pointer and the automatic variables until after register + allocation has been completed. When this macro is defined, you + must also indicate in your definition of `ELIMINABLE_REGS' how to + eliminate `FRAME_POINTER_REGNUM' into either + `HARD_FRAME_POINTER_REGNUM' or `STACK_POINTER_REGNUM'. + + Do not define this macro if it would be the same as + `FRAME_POINTER_REGNUM'. */ +#define HARD_FRAME_POINTER_REGNUM 29 + +/* Base register for access to arguments of the function. */ +#define ARG_POINTER_REGNUM 33 + +/* Register in which static-chain is passed to a function. */ +#define STATIC_CHAIN_REGNUM 5 + +/* Value should be nonzero if functions must have frame pointers. + Zero means the frame pointer need not be set up (and parms + may be accessed via the stack pointer) in functions that seem suitable. + This is computed in `reload', in reload1.c. */ +#define FRAME_POINTER_REQUIRED 0 + +/* If defined, this macro specifies a table of register pairs used to + eliminate unneeded registers that point into the stack frame. If + it is not defined, the only elimination attempted by the compiler + is to replace references to the frame pointer with references to + the stack pointer. + + The definition of this macro is a list of structure + initializations, each of which specifies an original and + replacement register. + + On some machines, the position of the argument pointer is not + known until the compilation is completed. In such a case, a + separate hard register must be used for the argument pointer. + This register can be eliminated by replacing it with either the + frame pointer or the argument pointer, depending on whether or not + the frame pointer has been eliminated. + + In this case, you might specify: + #define ELIMINABLE_REGS \ + {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} + + Note that the elimination of the argument pointer with the stack + pointer is specified first since that is the preferred elimination. */ + +#define ELIMINABLE_REGS \ +{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \ + { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }} \ + +/* A C expression that returns non-zero if the compiler is allowed to + try to replace register number FROM-REG with register number + TO-REG. This macro need only be defined if `ELIMINABLE_REGS' is + defined, and will usually be the constant 1, since most of the + cases preventing register elimination are things that the compiler + already knows about. */ + +#define CAN_ELIMINATE(FROM, TO) \ + ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1) + +/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It + specifies the initial difference between the specified pair of + registers. This macro must be defined if `ELIMINABLE_REGS' is + defined. */ + +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ +{ \ + if ((FROM) == FRAME_POINTER_REGNUM) \ + (OFFSET) = get_frame_size () + current_function_outgoing_args_size; \ + else if ((FROM) == ARG_POINTER_REGNUM) \ + (OFFSET) = compute_frame_size (get_frame_size (), (long *)0); \ + else \ + abort (); \ +} + +/* A guess for the V850. */ +#define PROMOTE_PROTOTYPES 1 + +/* Keep the stack pointer constant throughout the function. */ +#define ACCUMULATE_OUTGOING_ARGS + +/* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + FUNDECL is the declaration node of the function (as a tree), + FUNTYPE is the data type of the function (as a tree), + or for a library call it is an identifier node for the subroutine name. + SIZE is the number of bytes of arguments passed on the stack. */ + +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 + + +/* Define a data type for recording info about an argument list + during the scan of that argument list. This data type should + hold all necessary information about the function itself + and about the args processed so far, enough to enable macros + such as FUNCTION_ARG to determine where the next arg should go. */ + +#define CUMULATIVE_ARGS struct cum_arg +struct cum_arg { int nbytes; }; + +/* Define where to put the arguments to a function. + Value is zero to push the argument on the stack, + or a hard register in which to store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + +struct rtx_def *function_arg(); +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ + function_arg (&CUM, MODE, TYPE, NAMED) + +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ + function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED) + +/* Initialize a variable CUM of type CUMULATIVE_ARGS + for a call to a function whose data type is FNTYPE. + For a library call, FNTYPE is 0. */ + +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ + ((CUM).nbytes = 0) + +/* Update the data in CUM to advance over an argument + of mode MODE and data type TYPE. + (TYPE is null for libcalls where that information may not be available.) */ + +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM).nbytes += ((MODE) != BLKmode \ + ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD \ + : (int_size_in_bytes (TYPE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD)) + +/* When a parameter is passed in a register, stack space is still + allocated for it. */ +#define REG_PARM_STACK_SPACE(DECL) (!TARGET_GHS ? 16 : 0) + +/* Define this if the above stack space is to be considered part of the + space allocated by the caller. */ +#define OUTGOING_REG_PARM_STACK_SPACE + +extern int current_function_anonymous_args; +/* Do any setup necessary for varargs/stdargs functions. */ +#define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PAS, SECOND) \ + current_function_anonymous_args = (!TARGET_GHS ? 1 : 0); + +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ + ((TYPE) && int_size_in_bytes (TYPE) > 8) + +#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ + ((TYPE) && int_size_in_bytes (TYPE) > 8) + +/* 1 if N is a possible register number for function argument passing. */ + +#define FUNCTION_ARG_REGNO_P(N) (N >= 6 && N <= 9) + +/* Define how to find the value returned by a function. + VALTYPE is the data type of the value (as a tree). + If the precise function being called is known, FUNC is its FUNCTION_DECL; + otherwise, FUNC is 0. */ + +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), 10) + +/* Define how to find the value returned by a library function + assuming the value has mode MODE. */ + +#define LIBCALL_VALUE(MODE) \ + gen_rtx (REG, MODE, 10) + +/* 1 if N is a possible register number for a function value. */ + +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 10) + +/* Return values > 8 bytes in length in memory. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 +#define RETURN_IN_MEMORY(TYPE) \ + (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode) + +/* Register in which address to store a structure value + is passed to a function. On the V850 it's passed as + the first parameter. */ + +#define STRUCT_VALUE 0 + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ + +#define EXIT_IGNORE_STACK 1 + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + +#define FUNCTION_PROFILER(FILE, LABELNO) ; + +#define TRAMPOLINE_TEMPLATE(FILE) \ + do { \ + fprintf (FILE, "\tjarl .+4,r12\n"); \ + fprintf (FILE, "\tld.w 12[r12],r5\n"); \ + fprintf (FILE, "\tld.w 16[r12],r12\n"); \ + fprintf (FILE, "\tjmp [r12]\n"); \ + fprintf (FILE, "\tnop\n"); \ + fprintf (FILE, "\t.long 0\n"); \ + fprintf (FILE, "\t.long 0\n"); \ + } while (0) + +/* Length in units of the trampoline for entering a nested function. */ + +#define TRAMPOLINE_SIZE 24 + +/* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. + CXT is an RTX for the static chain value for the function. */ + +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ +{ \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 16)), \ + (CXT)); \ + emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 20)), \ + (FNADDR)); \ +} + +/* Addressing modes, and classification of registers for them. */ + + +/* 1 if X is an rtx for a constant that is a valid address. */ + +/* ??? This seems too exclusive. May get better code by accepting more + possibilities here, in particular, should accept ZDA_NAME SYMBOL_REFs. */ + +#define CONSTANT_ADDRESS_P(X) \ + (GET_CODE (X) == CONST_INT \ + && CONST_OK_FOR_K (INTVAL (X))) + +/* Maximum number of registers that can appear in a valid memory address. */ + +#define MAX_REGS_PER_ADDRESS 1 + +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx + and check its validity for a certain class. + We have two alternate definitions for each of them. + The usual definition accepts all pseudo regs; the other rejects + them unless they have been allocated suitable hard regs. + The symbol REG_OK_STRICT causes the latter definition to be used. + + Most source files want to accept pseudo regs in the hope that + they will get allocated to the class that the insn wants them to be in. + Source files for reload pass need to be strict. + After reload, it makes no difference, since pseudo regs have + been eliminated by then. */ + +#ifndef REG_OK_STRICT + +/* Nonzero if X is a hard reg that can be used as an index + or if it is a pseudo reg. */ +#define REG_OK_FOR_INDEX_P(X) 0 +/* Nonzero if X is a hard reg that can be used as a base reg + or if it is a pseudo reg. */ +#define REG_OK_FOR_BASE_P(X) 1 +#define REG_OK_FOR_INDEX_P_STRICT(X) 0 +#define REG_OK_FOR_BASE_P_STRICT(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#define STRICT 0 + +#else + +/* Nonzero if X is a hard reg that can be used as an index. */ +#define REG_OK_FOR_INDEX_P(X) 0 +/* Nonzero if X is a hard reg that can be used as a base reg. */ +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#define STRICT 1 + +#endif + +/* A C expression that defines the optional machine-dependent + constraint letters that can be used to segregate specific types of + operands, usually memory references, for the target machine. + Normally this macro will not be defined. If it is required for a + particular target machine, it should return 1 if VALUE corresponds + to the operand type represented by the constraint letter C. If C + is not defined as an extra constraint, the value returned should + be 0 regardless of VALUE. + + For example, on the ROMP, load instructions cannot have their + output in r0 if the memory reference contains a symbolic address. + Constraint letter `Q' is defined as representing a memory address + that does *not* contain a symbolic address. An alternative is + specified with a `Q' constraint on the input and `r' on the + output. The next alternative specifies `m' on the input and a + register class that does not include r0 on the output. */ + +#define EXTRA_CONSTRAINT(OP, C) \ + ((C) == 'Q' ? ep_memory_operand (OP, GET_MODE (OP)) \ + : (C) == 'R' ? special_symbolref_operand (OP, VOIDmode) \ + : (C) == 'S' ? (GET_CODE (OP) == SYMBOL_REF && ! ZDA_NAME_P (XSTR (OP, 0))) \ + : (C) == 'T' ? 0 \ + : (C) == 'U' ? ((GET_CODE (OP) == SYMBOL_REF && ZDA_NAME_P (XSTR (OP, 0))) \ + || (GET_CODE (OP) == CONST \ + && GET_CODE (XEXP (OP, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (OP, 0), 0)) == SYMBOL_REF \ + && ZDA_NAME_P (XSTR (XEXP (XEXP (OP, 0), 0), 0)))) \ + : 0) + +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression + that is a valid memory address for an instruction. + The MODE argument is the machine mode for the MEM expression + that wants to use this address. + + The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS, + except for CONSTANT_ADDRESS_P which is actually + machine-independent. */ + +/* Accept either REG or SUBREG where a register is valid. */ + +#define RTX_OK_FOR_BASE_P(X) \ + ((REG_P (X) && REG_OK_FOR_BASE_P (X)) \ + || (GET_CODE (X) == SUBREG && REG_P (SUBREG_REG (X)) \ + && REG_OK_FOR_BASE_P (SUBREG_REG (X)))) + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +do { \ + if (RTX_OK_FOR_BASE_P (X)) goto ADDR; \ + if (CONSTANT_ADDRESS_P (X) \ + && (MODE == QImode || INTVAL (X) % 2 == 0)) \ + goto ADDR; \ + if (GET_CODE (X) == LO_SUM \ + && GET_CODE (XEXP (X, 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ + && CONSTANT_P (XEXP (X, 1)) \ + && (GET_CODE (XEXP (X, 1)) != CONST_INT \ + || ((MODE == QImode || INTVAL (XEXP (X, 1)) % 2 == 0) \ + && CONST_OK_FOR_K (INTVAL (XEXP (X, 1))))) \ + && GET_MODE_SIZE (MODE) <= GET_MODE_SIZE (word_mode)) \ + goto ADDR; \ + if (special_symbolref_operand (X, MODE) \ + && (GET_MODE_SIZE (MODE) <= GET_MODE_SIZE (word_mode))) \ + goto ADDR; \ + if (GET_CODE (X) == PLUS \ + && CONSTANT_ADDRESS_P (XEXP (X, 1)) \ + && (MODE == QImode || INTVAL (XEXP (X, 1)) % 2 == 0) \ + && RTX_OK_FOR_BASE_P (XEXP (X, 0))) goto ADDR; \ +} while (0) + + +/* Try machine-dependent ways of modifying an illegitimate address + to be legitimate. If we find one, return the new, valid address. + This macro is used in only one place: `memory_address' in explow.c. + + OLDX is the address as it was before break_out_memory_refs was called. + In some cases it is useful to look at this to decide what needs to be done. + + MODE and WIN are passed so that this macro can use + GO_IF_LEGITIMATE_ADDRESS. + + It is always safe for this macro to do nothing. It exists to recognize + opportunities to optimize the output. */ + +#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} + +/* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. */ + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} + +/* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + +#define LEGITIMATE_CONSTANT_P(X) \ + (GET_CODE (X) == CONST_DOUBLE \ + || !(GET_CODE (X) == CONST \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ + && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ + && ! CONST_OK_FOR_K (INTVAL (XEXP (XEXP (X, 0), 1))))) + +/* In rare cases, correct code generation requires extra machine + dependent processing between the second jump optimization pass and + delayed branch scheduling. On those machines, define this macro + as a C statement to act on the code starting at INSN. */ + +#define MACHINE_DEPENDENT_REORG(INSN) v850_reorg (INSN) + + +/* Tell final.c how to eliminate redundant test instructions. */ + +/* Here we define machine-dependent flags and fields in cc_status + (see `conditions.h'). No extra ones are needed for the vax. */ + +/* Store in cc_status the expressions + that the condition codes will describe + after execution of an instruction whose pattern is EXP. + Do not alter them if the instruction would not alter the cc's. */ + +#define CC_OVERFLOW_UNUSABLE 0x200 +#define CC_NO_CARRY CC_NO_OVERFLOW +#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN) + +/* A part of a C `switch' statement that describes the relative costs + of constant RTL expressions. It must contain `case' labels for + expression codes `const_int', `const', `symbol_ref', `label_ref' + and `const_double'. Each case must ultimately reach a `return' + statement to return the relative cost of the use of that kind of + constant value in an expression. The cost may depend on the + precise value of the constant, which is available for examination + in X, and the rtx code of the expression in which it is contained, + found in OUTER_CODE. + + CODE is the expression code--redundant, since it can be obtained + with `GET_CODE (X)'. */ + +#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ + case CONST_INT: \ + case CONST_DOUBLE: \ + case CONST: \ + case SYMBOL_REF: \ + case LABEL_REF: \ + { \ + int _zxy = const_costs(RTX, CODE); \ + return (_zxy) ? COSTS_N_INSNS (_zxy) : 0; \ + } + +/* A crude cut at RTX_COSTS for the V850. */ + +/* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. + + There aren't DImode MOD, DIV or MULT operations, so call them + very expensive. Everything else is pretty much a constant cost. */ + +#define RTX_COSTS(RTX,CODE,OUTER_CODE) \ + case MOD: \ + case DIV: \ + return 60; \ + case MULT: \ + return 20; + +/* All addressing modes have the same cost on the V850 series. */ +#define ADDRESS_COST(ADDR) 1 + +/* Nonzero if access to memory by bytes or half words is no faster + than accessing full words. */ +#define SLOW_BYTE_ACCESS 1 + +/* Define this if zero-extension is slow (more than one real instruction). */ +#define SLOW_ZERO_EXTEND + +/* According expr.c, a value of around 6 should minimize code size, and + for the V850 series, that's our primary concern. */ +#define MOVE_RATIO 6 + +/* Indirect calls are expensive, never turn a direct call + into an indirect call. */ +#define NO_FUNCTION_CSE + +/* A list of names for sections other than the standard two, which are + `in_text' and `in_data'. You need not define this macro on a + system with no other sections (that GCC needs to use). */ +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, in_dtors + +/* One or more functions to be defined in `varasm.c'. These + functions should do jobs analogous to those of `text_section' and + `data_section', for your additional sections. Do not define this + macro if you do not define `EXTRA_SECTIONS'. */ +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ +CONST_SECTION_FUNCTION \ +CTORS_SECTION_FUNCTION \ +DTORS_SECTION_FUNCTION \ + \ +void \ +sdata_section () \ +{ \ + if (in_section != in_sdata) \ + { \ + fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \ + in_section = in_sdata; \ + } \ +} \ + \ +void \ +tdata_section () \ +{ \ + if (in_section != in_tdata) \ + { \ + fprintf (asm_out_file, "%s\n", TDATA_SECTION_ASM_OP); \ + in_section = in_tdata; \ + } \ +} \ + \ +void \ +zdata_section () \ +{ \ + if (in_section != in_zdata) \ + { \ + fprintf (asm_out_file, "%s\n", ZDATA_SECTION_ASM_OP); \ + in_section = in_zdata; \ + } \ +} + +#define TEXT_SECTION_ASM_OP "\t.section .text" +#define DATA_SECTION_ASM_OP "\t.section .data" +#define BSS_SECTION_ASM_OP "\t.section .bss" +#define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\"" +#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\"" +#define ZDATA_SECTION_ASM_OP "\t.section .zdata,\"aw\"" +#define ZBSS_SECTION_ASM_OP "\t.section .zbss,\"aw\"" +#define TDATA_SECTION_ASM_OP "\t.section .tdata,\"aw\"" + +/* A C statement or statements to switch to the appropriate section + for output of EXP. You can assume that EXP is either a `VAR_DECL' + node or a constant of some sort. RELOC indicates whether the + initial value of EXP requires link-time relocations. Select the + section by calling `text_section' or one of the alternatives for + other sections. + + Do not define this macro if you put all read-only variables and + constants in the read-only data section (usually the text section). */ +#undef SELECT_SECTION +#define SELECT_SECTION(EXP, RELOC) \ +do { \ + if (TREE_CODE (EXP) == VAR_DECL) \ + { \ + if (!TREE_READONLY (EXP) || TREE_SIDE_EFFECTS (EXP) \ + || !DECL_INITIAL (EXP) \ + || (DECL_INITIAL (EXP) != error_mark_node \ + && !TREE_CONSTANT (DECL_INITIAL (EXP)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else if (TREE_CODE (EXP) == STRING_CST) \ + { \ + if (! flag_writable_strings) \ + const_section (); \ + else \ + data_section (); \ + } \ + \ + else \ + const_section (); \ + \ +} while (0) + +/* A C statement or statements to switch to the appropriate section + for output of RTX in mode MODE. You can assume that RTX is some + kind of constant in RTL. The argument MODE is redundant except in + the case of a `const_int' rtx. Select the section by calling + `text_section' or one of the alternatives for other sections. + + Do not define this macro if you put all constants in the read-only + data section. */ +/* #define SELECT_RTX_SECTION(MODE, RTX) */ + +/* Output at beginning/end of assembler file. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) asm_file_start(FILE) + +#define ASM_COMMENT_START "#" + +/* Output to assembler file text saying following lines + may contain character constants, extra white space, comments, etc. */ + +#define ASM_APP_ON "#APP\n" + +/* Output to assembler file text saying following lines + no longer contain unusual constructs. */ + +#define ASM_APP_OFF "#NO_APP\n" + +/* This is how to output an assembler line defining a `double' constant. + It is .double or .float, depending. */ + +#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf (FILE, "\t.double %s\n", dstr); \ + } while (0) + + +/* This is how to output an assembler line defining a `float' constant. */ +#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf (FILE, "\t.float %s\n", dstr); \ + } while (0) + +/* This is how to output an assembler line defining an `int' constant. */ + +#define ASM_OUTPUT_INT(FILE, VALUE) \ +( fprintf (FILE, "\t.long "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* Likewise for `char' and `short' constants. */ + +#define ASM_OUTPUT_SHORT(FILE, VALUE) \ +( fprintf (FILE, "\t.hword "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +#define ASM_OUTPUT_CHAR(FILE, VALUE) \ +( fprintf (FILE, "\t.byte "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* This is how to output an assembler line for a numeric constant byte. */ +#define ASM_OUTPUT_BYTE(FILE, VALUE) \ + fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) + +/* Define the parentheses used to group arithmetic operations + in assembler code. */ + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* This says how to output the assembler to define a global + uninitialized but not common symbol. + Try to use asm_output_bss to implement this macro. */ + +#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \ + asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED)) + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ + +#define ASM_OUTPUT_LABEL(FILE, NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + +/* This is how to output a command to make the user-level label named NAME + defined for reference from other files. */ + +#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ + do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + +/* This is how to output a reference to a user-level label named NAME. + `assemble_name' uses this. */ + +#undef ASM_OUTPUT_LABELREF +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ + do { \ + char* real_name; \ + STRIP_NAME_ENCODING (real_name, (NAME)); \ + fprintf (FILE, "_%s", real_name); \ + } while (0) + +/* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable named NAME. + LABELNO is an integer which is different for each call. */ + +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) + +/* This is how we tell the assembler that two symbols have the same value. */ + +#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \ + do { assemble_name(FILE, NAME1); \ + fputs(" = ", FILE); \ + assemble_name(FILE, NAME2); \ + fputc('\n', FILE); } while (0) + + +/* How to refer to registers in assembler output. + This sequence is indexed by compiler's hard-register-number (see above). */ + +#define REGISTER_NAMES \ +{ "r0", "r1", "r2", "sp", "gp", "r5", "r6" , "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "ep", "r31", \ + ".fp", ".ap"} + +#define ADDITIONAL_REGISTER_NAMES \ +{ { "zero", 0 }, \ + { "hp", 2 }, \ + { "r3", 3 }, \ + { "r4", 4 }, \ + { "tp", 5 }, \ + { "fp", 29 }, \ + { "r30", 30 }, \ + { "lp", 31} } + +/* Print an instruction operand X on file FILE. + look in v850.c for details */ + +#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE) + +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ + ((CODE) == '.') + +/* Print a memory operand whose address is X, on file FILE. + This uses a function in output-vax.c. */ + +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) + +#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) +#define ASM_OUTPUT_REG_POP(FILE,REGNO) + +/* This is how to output an element of a case-vector that is absolute. */ + +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + asm_fprintf (FILE, "\t%s .L%d\n", \ + (TARGET_BIG_SWITCH ? ".long" : ".short"), VALUE) + +/* This is how to output an element of a case-vector that is relative. */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t%s .L%d-.L%d\n", \ + (TARGET_BIG_SWITCH ? ".long" : ".short"), \ + VALUE, REL) + +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG) != 0) \ + fprintf (FILE, "\t.align %d\n", (LOG)) + +/* We don't have to worry about dbx compatibility for the v850. */ +#define DEFAULT_GDB_EXTENSIONS 1 + +/* Use stabs debugging info by default. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#define DBX_REGISTER_NUMBER(REGNO) REGNO + +/* Define to use software floating point emulator for REAL_ARITHMETIC and + decimal <-> binary conversion. */ +#define REAL_ARITHMETIC + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? SImode : HImode) + +/* Define this if the case instruction drops through after the table + when the index is out of range. Don't define it if the case insn + jumps to the default label instead. */ +/* #define CASE_DROPS_THROUGH */ + +/* We must use a PC relative entry for small tables. It would be more + efficient to use an absolute entry for big tables, but this is not + a runtime choice yet. */ +#define CASE_VECTOR_PC_RELATIVE + +/* The switch instruction requires that the jump table immediately follow + it. */ +#define JUMP_TABLES_IN_TEXT_SECTION + +/* svr4.h defines this assuming that 4 byte alignment is required. */ +#undef ASM_OUTPUT_BEFORE_CASE_LABEL +#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + ASM_OUTPUT_ALIGN ((FILE), (TARGET_BIG_SWITCH ? 2 : 1)); + +#define WORD_REGISTER_OPERATIONS + +/* Byte and short loads sign extend the value to a word. */ +#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND + +/* Specify the tree operation to be used to convert reals to integers. */ +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* This flag, if defined, says the same insns that convert to a signed fixnum + also convert validly to an unsigned one. */ +#define FIXUNS_TRUNC_LIKE_FIX_TRUNC + +/* This is the kind of divide that is easiest to do in the general case. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ +#define MOVE_MAX 4 + +/* Define if shifts truncate the shift count + which implies one can omit a sign-extension or zero-extension + of a shift count. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +#define STORE_FLAG_VALUE 1 + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +#define Pmode SImode + +/* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ +#define FUNCTION_MODE QImode + +/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS + is a valid machine specific attribute for DECL. + The attributes in ATTRIBUTES have previously been assigned to DECL. */ +#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ +v850_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) + +/* Tell compiler we have {ZDA,TDA,SDA} small data regions */ +#define HAVE_ZDA 1 +#define HAVE_SDA 1 +#define HAVE_TDA 1 + +/* Tell compiler we want to support GHS pragmas */ +#define HANDLE_GHS_PRAGMA + +/* The assembler op to to start the file. */ + +#define FILE_ASM_OP "\t.file\n" + +/* Enable the register move pass to improve code. */ +#define ENABLE_REGMOVE_PASS + + +/* Implement ZDA, TDA, and SDA */ + +#define EP_REGNUM 30 /* ep register number */ + +#define ENCODE_SECTION_INFO(DECL) \ +do { \ + if ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \ + && TREE_CODE (DECL) == VAR_DECL) \ + v850_encode_data_area (DECL); \ +} while (0) + +#define ZDA_NAME_FLAG_CHAR '@' +#define TDA_NAME_FLAG_CHAR '%' +#define SDA_NAME_FLAG_CHAR '&' + +#define ZDA_NAME_P(NAME) (*(NAME) == ZDA_NAME_FLAG_CHAR) +#define TDA_NAME_P(NAME) (*(NAME) == TDA_NAME_FLAG_CHAR) +#define SDA_NAME_P(NAME) (*(NAME) == SDA_NAME_FLAG_CHAR) + +#define ENCODED_NAME_P(SYMBOL_NAME) \ + (ZDA_NAME_P (SYMBOL_NAME) \ + || TDA_NAME_P (SYMBOL_NAME) \ + || SDA_NAME_P (SYMBOL_NAME)) + +#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ + (VAR) = (SYMBOL_NAME) + (ENCODED_NAME_P (SYMBOL_NAME) || *(SYMBOL_NAME) == '*') + +/* Define this if you have defined special-purpose predicates in the + file `MACHINE.c'. This macro is called within an initializer of an + array of structures. The first field in the structure is the name + of a predicate and the second field is an array of rtl codes. For + each predicate, list all rtl codes that can be in expressions + matched by the predicate. The list should have a trailing comma. */ + +#define PREDICATE_CODES \ +{ "ep_memory_operand", { MEM }}, \ +{ "reg_or_0_operand", { REG, SUBREG, CONST_INT, CONST_DOUBLE }}, \ +{ "reg_or_int5_operand", { REG, SUBREG, CONST_INT }}, \ +{ "call_address_operand", { REG, SYMBOL_REF }}, \ +{ "movsi_source_operand", { LABEL_REF, SYMBOL_REF, CONST_INT, \ + CONST_DOUBLE, CONST, HIGH, MEM, \ + REG, SUBREG }}, \ +{ "special_symbolref_operand", { SYMBOL_REF }}, \ +{ "power_of_two_operand", { CONST_INT }}, \ +{ "pattern_is_ok_for_prologue", { PARALLEL }}, \ +{ "pattern_is_ok_for_epilogue", { PARALLEL }}, \ +{ "register_is_ok_for_epilogue",{ REG }}, \ +{ "not_power_of_two_operand", { CONST_INT }}, + +extern void override_options (); +extern void asm_file_start (); +extern int function_arg_partial_nregs (); +extern int const_costs (); +extern void print_operand (); +extern void print_operand_address (); +extern char *output_move_double (); +extern char *output_move_single (); +extern int ep_operand (); +extern int reg_or_0_operand (); +extern int reg_or_int5_operand (); +extern int call_address_operand (); +extern int movsi_source_operand (); +extern int power_of_two_operand (); +extern int not_power_of_two_operand (); +extern void v850_reorg (); +extern int compute_register_save_size (); +extern int compute_frame_size (); +extern void expand_prologue (); +extern void expand_epilogue (); +extern void notice_update_cc (); +extern int v850_valid_machine_decl_attribute (); +extern int v850_interrupt_function_p (); + +extern int pattern_is_ok_for_prologue(); +extern int pattern_is_ok_for_epilogue(); +extern int register_is_ok_for_epilogue (); +extern char *construct_save_jarl (); +extern char *construct_restore_jr (); + + diff --git a/gnu/usr.bin/gcc/config/v850/v850.md b/gnu/usr.bin/gcc/config/v850/v850.md new file mode 100644 index 00000000000..0ba10ca0cc0 --- /dev/null +++ b/gnu/usr.bin/gcc/config/v850/v850.md @@ -0,0 +1,1273 @@ +;; GCC machine description for NEC V850 +;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +;; Contributed by Jeff Law (law@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. + +;; The original PO technology requires these to be ordered by speed, +;; so that assigner will pick the fastest. + +;; See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; The V851 manual states that the instruction address space is 16M; +;; the various branch/call instructions only have a 22bit offset (4M range). +;; +;; One day we'll probably need to handle calls to targets more than 4M +;; away. + +;; The size of instructions in bytes. + +(define_attr "length" "" + (const_int 200)) + +;; Types of instructions (for scheduling purposes). + +(define_attr "type" "load,mult,other" + (const_string "other")) + +;; Condition code settings. +;; none - insn does not affect cc +;; none_0hit - insn does not affect cc but it does modify operand 0 +;; This attribute is used to keep track of when operand 0 changes. +;; See the description of NOTICE_UPDATE_CC for more info. +;; set_znv - sets z,n,v to usable values; c is unknown. +;; set_zn - sets z,n to usable values; v,c is unknown. +;; compare - compare instruction +;; clobber - value of cc is unknown +(define_attr "cc" "none,none_0hit,set_zn,set_znv,compare,clobber" + (const_string "clobber")) + +;; Function units for the V850. As best as I can tell, there's +;; a traditional memory load/use stall as well as a stall if +;; the result of a multiply is used too early. +;; +(define_function_unit "memory" 1 0 (eq_attr "type" "load") 2 0) +(define_function_unit "mult" 1 0 (eq_attr "type" "mult") 2 0) + + +;; ---------------------------------------------------------------------- +;; MOVE INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; movqi + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register or 0 */ + if (!register_operand (operand0, QImode) + && !reg_or_0_operand (operand1, QImode)) + operands[1] = copy_to_mode_reg (QImode, operand1); +}") + +(define_insn "*movqi_internal" + [(set (match_operand:QI 0 "general_operand" "=r,r,r,Q,r,m,m") + (match_operand:QI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))] + "register_operand (operands[0], QImode) + || reg_or_0_operand (operands[1], QImode)" + "* return output_move_single (operands);" + [(set_attr "length" "2,4,2,2,4,4,4") + (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") + (set_attr "type" "other,other,load,other,load,other,other")]) + +;; movhi + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register or 0 */ + if (!register_operand (operand0, HImode) + && !reg_or_0_operand (operand1, HImode)) + operands[1] = copy_to_mode_reg (HImode, operand1); +}") + +(define_insn "*movhi_internal" + [(set (match_operand:HI 0 "general_operand" "=r,r,r,Q,r,m,m") + (match_operand:HI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))] + "register_operand (operands[0], HImode) + || reg_or_0_operand (operands[1], HImode)" + "* return output_move_single (operands);" + [(set_attr "length" "2,4,2,2,4,4,4") + (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") + (set_attr "type" "other,other,load,other,load,other,other")]) + +;; movsi and helpers + +(define_insn "*movsi_high" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (match_operand 1 "" "")))] + "" + "movhi hi(%1),%.,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit") + (set_attr "type" "other")]) + +(define_insn "*movsi_lo" + [(set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "i")))] + "" + "movea lo(%2),%1,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit") + (set_attr "type" "other")]) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register or 0 */ + if (!register_operand (operand0, SImode) + && !reg_or_0_operand (operand1, SImode)) + operands[1] = copy_to_mode_reg (SImode, operand1); + + /* Some constants, as well as symbolic operands + must be done with HIGH & LO_SUM patterns. */ + if (CONSTANT_P (operands[1]) + && GET_CODE (operands[1]) != HIGH + && !special_symbolref_operand (operands[1], VOIDmode) + && !(GET_CODE (operands[1]) == CONST_INT + && (CONST_OK_FOR_J (INTVAL (operands[1])) + || CONST_OK_FOR_K (INTVAL (operands[1])) + || CONST_OK_FOR_L (INTVAL (operands[1]))))) + { + rtx high; + rtx temp; + + if (reload_in_progress || reload_completed) + temp = operands[0]; + else + temp = gen_reg_rtx (SImode); + + emit_insn (gen_rtx (SET, SImode, temp, + gen_rtx (HIGH, SImode, operand1))); + emit_insn (gen_rtx (SET, SImode, operand0, + gen_rtx (LO_SUM, SImode, temp, operand1))); + DONE; + } +}") + +(define_insn "*movsi_internal" + [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m") + (match_operand:SI 1 "movsi_source_operand" "Jr,K,L,Q,Ir,m,R,r,I"))] + "register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode)" + "* return output_move_single (operands);" + [(set_attr "length" "2,4,4,2,2,4,4,4,4") + (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") + (set_attr "type" "other,other,other,load,other,load,other,other,other")]) + + + +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register or 0 */ + if (!register_operand (operand0, DImode) + && !reg_or_0_operand (operand1, DImode)) + operands[1] = copy_to_mode_reg (DImode, operand1); +}") + +(define_insn "*movdi_internal" + [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,m,m,r") + (match_operand:DI 1 "general_operand" "Jr,K,L,i,m,r,IG,iF"))] + "register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode)" + "* return output_move_double (operands);" + [(set_attr "length" "4,8,8,16,8,8,8,16") + (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") + (set_attr "type" "other,other,other,other,load,other,other,other")]) + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register or 0 */ + if (!register_operand (operand0, SFmode) + && !reg_or_0_operand (operand1, SFmode)) + operands[1] = copy_to_mode_reg (SFmode, operand1); +}") + +(define_insn "*movsf_internal" + [(set (match_operand:SF 0 "general_operand" "=r,r,r,r,r,Q,r,m,m,r") + (match_operand:SF 1 "general_operand" "Jr,K,L,n,Q,Ir,m,r,IG,iF"))] + "register_operand (operands[0], SFmode) + || reg_or_0_operand (operands[1], SFmode)" + "* return output_move_single (operands);" + [(set_attr "length" "2,4,4,8,2,2,4,4,4,8") + (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") + (set_attr "type" "other,other,other,other,load,other,load,other,other,other")]) + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " +{ + /* One of the ops has to be in a register or 0 */ + if (!register_operand (operand0, DFmode) + && !reg_or_0_operand (operand1, DFmode)) + operands[1] = copy_to_mode_reg (DFmode, operand1); +}") + +(define_insn "*movdf_internal" + [(set (match_operand:DF 0 "general_operand" "=r,r,r,r,r,m,m,r") + (match_operand:DF 1 "general_operand" "Jr,K,L,i,m,r,IG,iF"))] + "register_operand (operands[0], DFmode) + || reg_or_0_operand (operands[1], DFmode)" + "* return output_move_double (operands);" + [(set_attr "length" "4,8,8,16,8,8,8,16") + (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") + (set_attr "type" "other,other,other,other,load,other,other,other")]) + + +;; ---------------------------------------------------------------------- +;; TEST INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "*v850_tst1" + [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") + (const_int 1) + (match_operand:QI 1 "const_int_operand" "n")))] + "" + "tst1 %1,%0" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +;; This replaces ld.b;sar;andi with tst1;setf nz. + +;; ??? The zero_extract sets the Z bit to the opposite of what one would +;; expect. This perhaps should be wrapped in a (eq: X (const_int 0)). + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extract:SI (match_operand:QI 1 "memory_operand" "") + (const_int 1) + (match_operand 2 "const_int_operand" "")))] + "" + [(set (cc0) (zero_extract:SI (match_dup 1) + (const_int 1) + (match_dup 2))) + (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) + +(define_insn "tstsi" + [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] + "" + "cmp %.,%0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "cmpsi" + [(set (cc0) + (compare (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] + "" + "@ + cmp %1,%0 + cmp %1,%0" + [(set_attr "length" "2,2") + (set_attr "cc" "compare")]) + +;; ---------------------------------------------------------------------- +;; ADD INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") + (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))] + "" + "@ + add %2,%0 + addi %2,%1,%0 + addi %O2(%P2),%1,%0" + [(set_attr "length" "2,4,4") + (set_attr "cc" "set_zn,set_zn,set_zn")]) + +;; ---------------------------------------------------------------------- +;; SUBTRACT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI (match_operand:SI 1 "register_operand" "0,r") + (match_operand:SI 2 "register_operand" "r,0")))] + "" + "@ + sub %2,%0 + subr %1,%0" + [(set_attr "length" "2,2") + (set_attr "cc" "set_zn")]) + +(define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "0")))] + "" + "subr %.,%0" + [(set_attr "length" "2") + (set_attr "cc" "set_zn")]) + +;; ---------------------------------------------------------------------- +;; MULTIPLY INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "mulhisi3" + [(set (match_operand:SI 0 "register_operand" "") + (mult:SI + (sign_extend:SI (match_operand:HI 1 "register_operand" "")) + (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))] + "" + "") + +(define_insn "*mulhisi3_internal1" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI + (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) + (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] + "" + "mulh %2,%0" + [(set_attr "length" "2") + (set_attr "cc" "none_0hit") + (set_attr "type" "mult")]) + +;; ??? Sign extending constants isn't valid. Fix? + +(define_insn "*mulhisi3_internal2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (mult:SI + (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,r")) + (sign_extend:SI (match_operand 2 "const_int_operand" "J,K"))))] + "" + "@ + mulh %2,%0 + mulhi %2,%1,%0" + [(set_attr "length" "2,4") + (set_attr "cc" "none_0hit,none_0hit") + (set_attr "type" "mult")]) + + +;; ---------------------------------------------------------------------- +;; AND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "*v850_clr1_1" + [(set (match_operand:QI 0 "memory_operand" "=m") + (subreg:QI + (and:SI (subreg:SI (match_dup 0) 0) + (match_operand:QI 1 "not_power_of_two_operand" "")) 0))] + "" + "* +{ + rtx xoperands[2]; + xoperands[0] = operands[0]; + xoperands[1] = GEN_INT (~INTVAL (operands[1]) & 0xff); + output_asm_insn (\"clr1 %M1,%0\", xoperands); + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*v850_clr1_2" + [(set (match_operand:HI 0 "memory_operand" "=m") + (subreg:HI + (and:SI (subreg:SI (match_dup 0) 0) + (match_operand:HI 1 "not_power_of_two_operand" "")) 0))] + "" + "* +{ + int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff); + + rtx xoperands[2]; + xoperands[0] = gen_rtx (MEM, QImode, + plus_constant (XEXP (operands[0], 0), log2 / 8)); + xoperands[1] = GEN_INT (log2 % 8); + output_asm_insn (\"clr1 %1,%0\", xoperands); + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*v850_clr1_3" + [(set (match_operand:SI 0 "memory_operand" "=m") + (and:SI (match_dup 0) + (match_operand:SI 1 "not_power_of_two_operand" "")))] + "" + "* +{ + int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff); + + rtx xoperands[2]; + xoperands[0] = gen_rtx (MEM, QImode, + plus_constant (XEXP (operands[0], 0), log2 / 8)); + xoperands[1] = GEN_INT (log2 % 8); + output_asm_insn (\"clr1 %1,%0\", xoperands); + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "@ + and %2,%0 + and %.,%0 + andi %2,%1,%0" + [(set_attr "length" "2,2,4") + (set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; OR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "*v850_set1_1" + [(set (match_operand:QI 0 "memory_operand" "=m") + (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0) + (match_operand 1 "power_of_two_operand" "")) 0))] + "" + "set1 %M1,%0" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*v850_set1_2" + [(set (match_operand:HI 0 "memory_operand" "=m") + (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0) + (match_operand 1 "power_of_two_operand" "")) 0))] + "" + "* +{ + int log2 = exact_log2 (INTVAL (operands[1])); + + if (log2 < 8) + return \"set1 %M1,%0\"; + else + { + rtx xoperands[2]; + xoperands[0] = gen_rtx (MEM, QImode, + plus_constant (XEXP (operands[0], 0), log2 / 8)); + xoperands[1] = GEN_INT (log2 % 8); + output_asm_insn (\"set1 %1,%0\", xoperands); + } + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*v850_set1_3" + [(set (match_operand:SI 0 "memory_operand" "=m") + (ior:SI (match_dup 0) + (match_operand 1 "power_of_two_operand" "")))] + "" + "* +{ + int log2 = exact_log2 (INTVAL (operands[1])); + + if (log2 < 8) + return \"set1 %M1,%0\"; + else + { + rtx xoperands[2]; + xoperands[0] = gen_rtx (MEM, QImode, + plus_constant (XEXP (operands[0], 0), log2 / 8)); + xoperands[1] = GEN_INT (log2 % 8); + output_asm_insn (\"set1 %1,%0\", xoperands); + } + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "@ + or %2,%0 + or %.,%0 + ori %2,%1,%0" + [(set_attr "length" "2,2,4") + (set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; XOR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "*v850_not1_1" + [(set (match_operand:QI 0 "memory_operand" "=m") + (subreg:QI (xor:SI (subreg:SI (match_dup 0) 0) + (match_operand 1 "power_of_two_operand" "")) 0))] + "" + "not1 %M1,%0" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*v850_not1_2" + [(set (match_operand:HI 0 "memory_operand" "=m") + (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0) + (match_operand 1 "power_of_two_operand" "")) 0))] + "" + "* +{ + int log2 = exact_log2 (INTVAL (operands[1])); + + if (log2 < 8) + return \"not1 %M1,%0\"; + else + { + rtx xoperands[2]; + xoperands[0] = gen_rtx (MEM, QImode, + plus_constant (XEXP (operands[0], 0), log2 / 8)); + xoperands[1] = GEN_INT (log2 % 8); + output_asm_insn (\"not1 %1,%0\", xoperands); + } + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*v850_not1_3" + [(set (match_operand:SI 0 "memory_operand" "=m") + (xor:SI (match_dup 0) + (match_operand 1 "power_of_two_operand" "")))] + "" + "* +{ + int log2 = exact_log2 (INTVAL (operands[1])); + + if (log2 < 8) + return \"not1 %M1,%0\"; + else + { + rtx xoperands[2]; + xoperands[0] = gen_rtx (MEM, QImode, + plus_constant (XEXP (operands[0], 0), log2 / 8)); + xoperands[1] = GEN_INT (log2 % 8); + output_asm_insn (\"not1 %1,%0\", xoperands); + } + return \"\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "@ + xor %2,%0 + xor %.,%0 + xori %2,%1,%0" + [(set_attr "length" "2,2,4") + (set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; NOT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "not %1,%0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +;; ----------------------------------------------------------------- +;; BIT FIELDS +;; ----------------------------------------------------------------- + +;; ??? Is it worth defining insv and extv for the V850 series?!? + +;; An insv pattern would be useful, but does not get used because +;; store_bit_field never calls insv when storing a constant value into a +;; single-bit bitfield. + +;; extv/extzv patterns would be useful, but do not get used because +;; optimize_bitfield_compare in fold-const usually converts single +;; bit extracts into an AND with a mask. + +;; ----------------------------------------------------------------- +;; Scc INSTRUCTIONS +;; ----------------------------------------------------------------- + +(define_insn "sle" + [(set (match_operand:SI 0 "register_operand" "=r") + (le:SI (cc0) (const_int 0)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) + return 0; + + return \"setf le,%0\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sleu" + [(set (match_operand:SI 0 "register_operand" "=r") + (leu:SI (cc0) (const_int 0)))] + "" + "setf nh,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sge" + [(set (match_operand:SI 0 "register_operand" "=r") + (ge:SI (cc0) (const_int 0)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) + return 0; + + return \"setf ge,%0\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sgeu" + [(set (match_operand:SI 0 "register_operand" "=r") + (geu:SI (cc0) (const_int 0)))] + "" + "setf nl,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "slt" + [(set (match_operand:SI 0 "register_operand" "=r") + (lt:SI (cc0) (const_int 0)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) + return 0; + + return \"setf lt,%0\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sltu" + [(set (match_operand:SI 0 "register_operand" "=r") + (ltu:SI (cc0) (const_int 0)))] + "" + "setf l,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sgt" + [(set (match_operand:SI 0 "register_operand" "=r") + (gt:SI (cc0) (const_int 0)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) + return 0; + + return \"setf gt,%0\"; +}" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sgtu" + [(set (match_operand:SI 0 "register_operand" "=r") + (gtu:SI (cc0) (const_int 0)))] + "" + "setf h,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "seq" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq:SI (cc0) (const_int 0)))] + "" + "setf z,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +(define_insn "sne" + [(set (match_operand:SI 0 "register_operand" "=r") + (ne:SI (cc0) (const_int 0)))] + "" + "setf nz,%0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + + +;; ---------------------------------------------------------------------- +;; JUMP INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Conditional jump instructions + +(define_expand "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_expand "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "") + +(define_insn "*branch_normal" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + return 0; + + if (get_attr_length (insn) == 2) + return \"b%b1 %l0\"; + else + return \"b%B1 .+6\;jr %l0\"; +}" + [(set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (pc))) + (const_int 256)) + (const_int 2) + (const_int 6))) + (set_attr "cc" "none")]) + +(define_insn "*branch_invert" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + return 0; + if (get_attr_length (insn) == 2) + return \"b%B1 %l0\"; + else + return \"b%b1 .+6\;jr %l0\"; +}" + [(set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (pc))) + (const_int 256)) + (const_int 2) + (const_int 6))) + (set_attr "cc" "none")]) + +;; Unconditional and other jump instructions. + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "* +{ + if (get_attr_length (insn) == 2) + return \"br %0\"; + else + return \"jr %0\"; +}" + [(set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (pc))) + (const_int 256)) + (const_int 2) + (const_int 4))) + (set_attr "cc" "none")]) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "register_operand" "r"))] + "" + "jmp %0" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +(define_insn "tablejump" + [(set (pc) (match_operand:SI 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "" + "jmp %0" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +(define_expand "casesi" + [(match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "register_operand" "") + (match_operand 3 "" "") (match_operand 4 "" "")] + "" + " +{ + rtx reg = gen_reg_rtx (SImode); + rtx tableaddress = gen_reg_rtx (SImode); + rtx mem; + + /* Subtract the lower bound from the index. */ + emit_insn (gen_subsi3 (reg, operands[0], operands[1])); + /* Compare the result against the number of table entries. */ + emit_insn (gen_cmpsi (reg, operands[2])); + /* Branch to the default label if out of range of the table. */ + emit_jump_insn (gen_bgtu (operands[4])); + + /* Shift index for the table array access. */ + emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1))); + /* Load the table address into a pseudo. */ + emit_insn (gen_movsi (tableaddress, + gen_rtx (LABEL_REF, VOIDmode, operands[3]))); + /* Add the table address to the index. */ + emit_insn (gen_addsi3 (reg, reg, tableaddress)); + /* Load the table entry. */ + mem = gen_rtx (MEM, CASE_VECTOR_MODE, reg); + RTX_UNCHANGING_P (mem); + if (! TARGET_BIG_SWITCH) + { + rtx reg2 = gen_reg_rtx (HImode); + emit_insn (gen_movhi (reg2, mem)); + emit_insn (gen_extendhisi2 (reg, reg2)); + } + else + emit_insn (gen_movsi (reg, mem)); + /* Add the table address. */ + emit_insn (gen_addsi3 (reg, reg, tableaddress)); + /* Branch to the switch label. */ + emit_jump_insn (gen_tablejump (reg, operands[3])); + DONE; +}") + +;; Call subroutine with no return value. + +(define_expand "call" + [(call (match_operand:QI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ + if (! call_address_operand (XEXP (operands[0], 0)) + || TARGET_LONG_CALLS) + XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); + emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1])); + DONE; +}") + +(define_insn "call_internal" + [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) + (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:SI 31))] + "" + "@ + jarl %0,r31 + jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %0" + [(set_attr "length" "4,8")]) + +;; Call subroutine, returning value in operand 0 +;; (which must be a hard register). + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" "")))] + "" + " +{ + if (! call_address_operand (XEXP (operands[1], 0)) + || TARGET_LONG_CALLS) + XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); + emit_call_insn (gen_call_value_internal (operands[0], + XEXP (operands[1], 0), + operands[2])); + DONE; +}") + +(define_insn "call_value_internal" + [(set (match_operand 0 "" "=r,r") + (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) + (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:SI 31))] + "" + "@ + jarl %1,r31 + jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %1" + [(set_attr "length" "4,8")]) + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +;; ---------------------------------------------------------------------- +;; EXTEND INSTRUCTIONS +;; ---------------------------------------------------------------------- + + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI + (match_operand:HI 1 "register_operand" "r")))] + "" + "andi 65535,%1,%0" + [(set_attr "length" "4") + (set_attr "cc" "set_znv")]) + + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI + (match_operand:QI 1 "register_operand" "r")))] + "" + "andi 255,%1,%0" + [(set_attr "length" "4") + (set_attr "cc" "set_znv")]) + +;;- sign extension instructions + + +;; ??? This is missing a sign extend from memory pattern to match the ld.h +;; instruction. + +(define_expand "extendhisi2" + [(set (match_dup 2) + (ashift:SI (match_operand:HI 1 "register_operand" "") + (const_int 16))) + (set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_dup 2) + (const_int 16)))] + "" + " +{ + operands[1] = gen_lowpart (SImode, operands[1]); + operands[2] = gen_reg_rtx (SImode); +}") + + +;; ??? This is missing a sign extend from memory pattern to match the ld.b +;; instruction. + +(define_expand "extendqisi2" + [(set (match_dup 2) + (ashift:SI (match_operand:QI 1 "register_operand" "") + (const_int 24))) + (set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_dup 2) + (const_int 24)))] + "" + " +{ + operands[1] = gen_lowpart (SImode, operands[1]); + operands[2] = gen_reg_rtx (SImode); +}") + +;; ---------------------------------------------------------------------- +;; SHIFTS +;; ---------------------------------------------------------------------- + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashift:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "@ + shl %2,%0 + shl %2,%0" + [(set_attr "length" "4,2") + (set_attr "cc" "set_znv")]) + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (lshiftrt:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "@ + shr %2,%0 + shr %2,%0" + [(set_attr "length" "4,2") + (set_attr "cc" "set_znv")]) + +(define_insn "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashiftrt:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "@ + sar %2,%0 + sar %2,%0" + [(set_attr "length" "4,2") + (set_attr "cc" "set_znv")]) + +;; ---------------------------------------------------------------------- +;; PROLOGUE/EPILOGUE +;; ---------------------------------------------------------------------- +(define_expand "prologue" + [(const_int 0)] + "" + "expand_prologue (); DONE;") + +(define_expand "epilogue" + [(return)] + "" + " +{ + /* Try to use the trivial return first. Else use the + full epilogue. */ + if (0) + emit_jump_insn (gen_return ()); + else + expand_epilogue (); + DONE; +}") + +(define_insn "return" + [(return)] + "reload_completed && compute_frame_size (get_frame_size (), (long *)0) == 0" + "jmp [r31]" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +(define_insn "return_internal" + [(return) + (use (reg:SI 31))] + "" + "jmp [r31]" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + + + +;; ---------------------------------------------------------------------- +;; HELPER INSTRUCTIONS for saving the prologue and epilog registers +;; ---------------------------------------------------------------------- + +;; This pattern will match a stack adjust RTX followed by any number of push +;; RTXs. These RTXs will then be turned into a suitable call to a worker +;; function. + + +(define_insn "" + [(match_parallel 0 "pattern_is_ok_for_prologue" + [(set (reg:SI 3) + (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) + (set (mem:SI (plus:SI (reg:SI 3) + (match_operand:SI 2 "immediate_operand" "i"))) + (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] + "TARGET_PROLOG_FUNCTION" + "* return construct_save_jarl (operands[0]); + " + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + + +;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. +(define_insn "save_interrupt" + [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16))) + (set (mem:SI (reg:SI 3)) (reg:SI 30)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 4)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))] + "" + "add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10" + [(set_attr "length" "12") + (set_attr "cc" "clobber")]) + + +;; Save all registers except for the registers saved in save_interrupt when +;; an interrupt function makes a call. +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. +;; This is needed because the rest of the compiler is not ready to handle +;; insns this complicated. + +(define_insn "save_all_interrupt" + [(unspec_volatile [(const_int 0)] 0)] + "" + "jarl __save_all_interrupt,r10" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + + + + +;; This pattern will match a return RTX followed by any number of pop RTXs +;; and possible a stack adjustment as well. These RTXs will be turned into +;; a suitable call to a worker function. + + +(define_insn "" +[(match_parallel 0 "pattern_is_ok_for_epilogue" + [(return) + (set (reg:SI 3) + (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) + (set (match_operand:SI 2 "register_is_ok_for_epilogue" "r") + (mem:SI (plus:SI (reg:SI 3) + (match_operand:SI 3 "immediate_operand" "i"))))])] + "TARGET_PROLOG_FUNCTION && TARGET_V850" + "* return construct_restore_jr (operands[0]); + " + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +;; Restore r1, r4, r10, and return from the interrupt +(define_insn "restore_interrupt" + [(return) + (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 16))) + (set (reg:SI 30) (mem:SI (plus:SI (reg:SI 3) (const_int 12)))) + (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 8)))) + (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4)))) + (set (reg:SI 1) (mem:SI (reg:SI 3)))] + "" + "jr __return_interrupt" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +;; Restore all registers saved when an interrupt function makes a call. +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. +;; This is needed because the rest of the compiler is not ready to handle +;; insns this complicated. + +(define_insn "restore_all_interrupt" + [(unspec_volatile [(const_int 0)] 1)] + "" + "jarl __restore_all_interrupt,r10" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +;; Save r6-r9 for a variable argument function +(define_insn "save_r6_r9" + [(set (mem:SI (reg:SI 3)) (reg:SI 6)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8)) + (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9)) + (clobber (reg:SI 10))] + "TARGET_PROLOG_FUNCTION" + "jarl __save_r6_r9,r10" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + diff --git a/gnu/usr.bin/gcc/config/v850/xm-v850.h b/gnu/usr.bin/gcc/config/v850/xm-v850.h new file mode 100644 index 00000000000..1e43d033f6f --- /dev/null +++ b/gnu/usr.bin/gcc/config/v850/xm-v850.h @@ -0,0 +1,49 @@ +/* Configuration for NEC V850. + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +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. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 + +#ifdef __v850 +#ifndef __STDC__ +extern char *malloc (), *realloc (), *calloc (); +#else +extern void *malloc (), *realloc (), *calloc (); +#endif +extern void free (); +#endif + +/* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + +#include "tm.h" diff --git a/gnu/usr.bin/gcc/config/xm-std32.h b/gnu/usr.bin/gcc/config/xm-std32.h new file mode 100644 index 00000000000..c52782e9741 --- /dev/null +++ b/gnu/usr.bin/gcc/config/xm-std32.h @@ -0,0 +1,34 @@ +/* Configuration for GNU C-compiler for standard 32-bit host machine. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* #defines that need visibility everywhere. */ +#define FALSE 0 +#define TRUE 1 + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +/* Arguments to use with `exit'. */ +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 diff --git a/gnu/usr.bin/gcc/cp/ChangeLog.1 b/gnu/usr.bin/gcc/cp/ChangeLog.1 new file mode 100644 index 00000000000..024a4e62126 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/ChangeLog.1 @@ -0,0 +1,9451 @@ +Sun Nov 26 14:47:42 1995 Richard Kenner <kenner@mole.gnu.ai.mit.edu> + + * Version 2.7.2 released. + +Mon Nov 20 14:05:00 1995 Mike Stump <mrs@cygnus.com> + + * g++.c (pfatal_with_name): Add missing third argument to concat. + +Thu Oct 26 13:59:54 1995 Mike Stump <mrs@cygnus.com> + + * init.c (expand_aggr_init): Handle cv qualifiers on the object's + type. + +Sat Nov 11 08:25:55 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * Version 2.7.1 released. + +Thu Nov 2 17:02:47 1995 Jason Merrill <jason@yorick.cygnus.com> + + * call.c (convert_harshness): Handle references to arrays. + +Fri Oct 27 14:20:21 1995 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (comp_target_types): Check multi-level pointer + conversions in both directions. + +Tue Oct 17 21:39:05 1995 Jason Merrill <jason@yorick.cygnus.com> + + * parse.y (explicit_instantiation): Fix 'extern template' with no + return type. + +Mon Oct 16 14:35:20 1995 Jason Merrill <jason@yorick.cygnus.com> + + * parse.y (explicit_instantiation): Support automatic instantiation + of constructors. + (named_class_head_*): Support out-of-class definition of nested + types. + +Wed Oct 11 12:20:56 1995 Mike Stump <mrs@cygnus.com> + + * search.c (envelope_add_decl): New routine. Fix so that + methods are hidden in the same way that other members are. + (dfs_pushdecls): Cleanup and move functionality out of line, + into envelope_add_decl. + +Tue Oct 10 15:46:01 1995 Mike Stump <mrs@cygnus.com> + + * typeck.c (mark_addressable): Only call assemble_external if we + have started the output file. + +Tue Oct 10 11:27:18 1995 Jason Merrill <jason@yorick.cygnus.com> + + * decl.c (start_function): Fix earlier cv-quals change. + +Mon Oct 9 23:53:05 1995 Mike Stump <mrs@cygnus.com> + + * parse.y (complex_direct_notype_declarator): Only push the class if + we are not already in the class. + +Mon Oct 9 11:22:03 1995 Doug Evans <dje@canuck.cygnus.com> + + * decl.c (duplicate_decls): Call merge_machine_decl_attributes. + Update olddecl's attributes too. + (grokdeclarator): #if 0 out call to build_decl_attribute_variant. + * typeck.c (common_type): Call merge_machine_type_attributes. + +Fri Oct 6 14:44:27 1995 Mike Stump <mrs@cygnus.com> + + * typeck.c (mark_addressable): Add missing call to + assemble_external. + +Wed Oct 4 15:06:39 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (store_parm_decls): Make sure the unwinder start comes + before the exception specification start. + * except.c (expand_exception_blocks): Make sure the unwinder end + comes after the terminate protected catch clause region and after + the end of the exception specification region. + +Wed Oct 4 12:47:02 1995 Jason Merrill <jason@yorick.cygnus.com> + + * lex.c (real_yylex): Fix identifier case for linemode. + (handle_sysv_pragma): Don't abort when we see a pragma we don't + recognize. + +Tue Oct 3 14:09:46 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (store_parm_decls): Add a call to start_eh_unwinder. + * except.c (init_exception_processing): __throw doesn't take any + arguments. + (expand_builtin_throw): Likewise. Always use Pmode, instead of SImode + for all pointers. Use expand_builtin_return_addr to unwind the + first level off the stack. + (do_unwind): Always use Pmode, instead of SImode for all pointers. + (expand_exception_blocks): Add a call to end_eh_unwinder. + (start_eh_unwinder, end_eh_unwinder): New routines to build machine + independent stack unwinders for function/method calls. + +Mon Oct 2 17:20:42 1995 Mike Stump <mrs@cygnus.com> + + * tree.c (unsave_expr_now): Make sure we process the argument list + of any called functions. Fixes incorrect code generation for + cleanups. + +Mon Oct 2 13:04:16 1995 Mike Stump <mrs@cygnus.com> + + * typeck.c (get_member_function_from_ptrfunc): Save function if it + needs it. Cures core dump on things like (this->*(f()))(). + +Sat Sep 23 22:51:25 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (start_function): Conform to gcc cv-quals convention (no + expression has a cv-qualified type) in RESULT_DECLs. + * method.c (make_thunk): Likewise. + +Fri Sep 22 10:21:13 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (pushtag): Add in the namespace name for the tag. + +Thu Sep 21 13:11:13 1995 Mike Stump <mrs@cygnus.com> + + * parse.y (maybe_base_class_list, base_class_list, base_class, + base_class_access_list): Make sure we see the typenames for base + classes. + * lex.c (see_typename): Instead of failing to see a typename when + there is no next token, perfer a typename, and get the next token. + +Wed Sep 20 12:35:27 1995 Michael Meissner <meissner@cygnus.com> + + * decl.c (init_decl_processing): Add __builtin_expect. + +Tue Sep 19 16:48:11 1995 Mike Stump <mrs@cygnus.com> + + * cvt.c (cp_convert_to_pointer): Don't allow leftover conversions to + or from pointer to member functions, they must all be handled before + this point. + +Fri Sep 15 17:14:47 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (resolve_offset_ref): Fix wording of non-static member + being referenced as a static. + +Fri Sep 15 12:39:11 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_indirect_ref): Only bash pointer if we actually + call build_expr_type_conversion. + +Thu Sep 14 18:24:56 1995 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (build_expr_type_conversion): Handle conversion from + reference. + * typeck.c (build_indirect_ref): Avoid infinite recursion. + +Thu Sep 14 17:23:28 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (expand_start_early_try_stmts): New routine to start a try + block at the start of the function, for function-try-blocks. + * cp-tree.h (expand_start_early_try_stmts): Declare it. + * parse.y (function_try_block): Use it, instead of doing it here, as + we don't want to include rtl.h here, as that conflicts with RETURN + in the parser. + +Wed Sep 13 18:32:24 1995 Mike Stump <mrs@cygnus.com> + + * lex.c (reinit_parse_for_block): Support saving inline + function-try-blocks, uses peekyylex. + * parse.y (eat_saved_input): New rule, permit the parser to see that + END_OF_SAVED_INPUT is ok, as it can see this when parsing the + handlers of a function-try-block. + (fndef): Use it. + (component_decl): Make sure TRY and RETURN can come after fn.def2. + * spew.c (peekyylex): New routine to peek at what will come next. + +Wed Sep 13 16:52:06 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (comptypes): Tighten up comparisons of template type + parms. + + * decl.c (duplicate_decls): Turn off whining about virtual functions + redeclared inline for now. + +Wed Sep 13 11:13:40 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (store_in_parms): New routine to put things before we + put base inits. + * cp-tree.h (store_in_parms): Declare it. + * decl.c (store_parm_decls): Use it to makr sure the starting of the + eh spec comes before base inits. + (finish_function): Use sequences instead of the obsolete + reorder_insns. + * parse.y (fndef): Enhance readability and maintainability. Update + to include function_try_block syntax. + (function_try_block): Add. + +Tue Sep 12 17:43:07 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * call.c (convert_harshness): Use comptypes, not ==, to check if + TYPE and PARMTYPE are equivalent on a function type. + +Tue Sep 12 17:31:33 1995 Douglas Rupp <drupp@cs.washington.edu> + + * Make-lang.in (cc1plus) : Removed unnecessary $(exeext). + +Mon Sep 11 23:24:07 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Never allocate storage for thrown pointer + to objects. + +Mon Sep 11 19:36:45 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_start_catch_block): Pointers to objects come + back from catch matching already dereferenced, don't dereference + again. + +Mon Sep 11 15:46:28 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Only decay the throw expression, don't do + any default conversions. This is so that one can throw and catch + characters, and not have them match integers. + +Mon Sep 11 13:46:45 1995 Mike Stump <mrs@cygnus.com> + + * error.c (dump_aggr_type): Deal with anonymous unions that don't + have a TYPE_NAME. + +Fri Sep 8 20:40:27 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * lex.c (handle_sysv_pragma): Deal with getting a comma from yylex. + +Fri Sep 8 15:51:41 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_end_eh_spec): Handle empty EH specifications. + +Fri Sep 8 15:27:22 1995 Mike Stump <mrs@cygnus.com> + + * cp-tree.h (expand_start_eh_spec): Declare new routine. + (expand_end_eh_spec): Likewise. + * decl.c (store_parm_decls): Call expand_start_eh_spec to process + exception specifications. + * except.c (expand_leftover_cleanups): Remove unused parameter. + (expand_end_catch_block): Likewise. + (expand_exception_blocks): Likewise. + (expand_start_eh_spec): New routine to mark the start of an + exception specification region. + (expand_end_eh_spec): New routine to mark the end of an exception + specification region. + (expand_exception_blocks): Call expand_end_eh_spec to process + exception specifications. + +Fri Sep 8 14:40:48 1995 Per Bothner <bothner@kalessin.cygnus.com> + + * lex.c (do_identifier): Use global binding in preference of + dead for local variable. + +Wed Sep 6 19:32:59 1995 Mike Stump <mrs@cygnus.com> + + * cp-tree.h (build_exception_variant): Remove used first argument. + * decl.c (duplicate_decls): Likewise. + (grokfndecl): Likewise. + (revert_static_member_fn): Likewise. + * decl2.c (grok_method_quals): Likewise. + * tree.c (build_exception_variant): Likewise. + * typeck.c (common_type): Likewise. + * decl2.c (grokclassfn): After changing the type, call + build_exception_variant, if necessary. + +Tue Sep 5 15:56:27 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Run cleanups for the throw expression. + +Wed Aug 30 15:24:38 1995 Stephen L. Favor <sfavor@tigger.intecom.com> + + * except.c (expand_builtin_throw): Moved gen_label_rtx calls beyond + the store_parm_decls call which does initialization in the emit_* + code concerning label numbering. + +Thu Aug 31 09:01:07 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_internal_throw): Let the frontend be responsible + for managing all frontend EH parameters, the backend routine only + needs to deal with backend values. type and value are no longer + passed to __throw. + (init_exception_processing): Likewise. + (expand_start_all_catch): Likewise. + (expand_end_all_catch): Likewise. + (expand_leftover_cleanups): Likewise. + (expand_end_catch_block): Likewise. + (expand_builtin_throw): Likewise. + (expand_throw): Likewise. + +Tue Aug 29 15:04:36 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cp-tree.h (DECL_REAL_CONTEXT): Give the real declaration context + for a decl. + * decl.c (cp_finish_decl): Use it. + +Tue Aug 29 10:30:27 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_internal_throw): Oops, almost forgot type and + value are now trees. + +Mon Aug 28 17:57:45 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + Fix the attribute handling to make sure they get noted before we + create the function's RTL, in case they can affect that. + * decl.c (grokfndecl): New arg ATTRLIST. Run + cplus_decl_attributes before creating the decl's rtl. + (grokdeclarator): New arg ATTRLIST, passed down into grokfndecl. + (shadow_tag, groktypename, start_decl, start_method): Pass a + NULL_TREE to grokdeclarator's new last arg. + * decl2.c (grokfield): New arg ATTRLIST, passed into grokdeclarator. + (grokbitfield, grokoptypename): Pass a NULL_TREE to + grokdeclarator's new last arg. + * except.c (expand_start_catch_block): Likewise. + * pt.c (process_template_parm, end_template_decl, + do_function_instantiation): Likewise. + * cp-tree.h (grokfield): Add arg. + (grokdeclarator): Move the prototype from here... + * decl.h: ...to here. + * lex.c (cons_up_default_function): Pass NULL_TREE to grokfield + ATTRLIST argument. + * parse.y: Create a list for the grokfield arg where appropriate, + and pass it down instead of calling cplus_decl_attributes. + +Mon Aug 28 15:07:24 1995 Mike Stump <mrs@cygnus.com> + + * except.c: Always allow turning on exception handling. Allow cross + compilations to use EH. + +Thu Aug 24 17:39:24 1995 Mike Stump <mrs@cygnus.com> + + * except.c (saved_pc, saved_throw_type, saved_throw_value): Use + trees, instead of rtxs, and don't depend on using special machine + dependent registers. + (expand_internal_throw): Likewise. + (init_exception_processing): Likewise. + (expand_start_all_catch): Likewise. + (expand_end_all_catch): Likewise. + (expand_start_catch_block): Likewise. + (expand_leftover_cleanups): Likewise. + (expand_end_catch_block): Likewise. + (expand_builtin_throw): Likewise. + (expand_throw): Likewise. + +Wed Aug 23 17:25:51 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (build_expr_type_conversion): Handle conversions to + reference types. + +Wed Aug 23 15:33:59 1995 Mike Stump <mrs@cygnus.com> + + * except.c (do_unwind): Work around backend bug with -fpic. + +Tue Aug 22 17:20:07 1995 Per Bothner <bothner@kalessin.cygnus.com> + + * decl2.c (flag_new_for_scope): Add a new mode that follows ANSI + for-scoping, but supports (and warns about) old programs. + Make the new mode (with value 1) the default. + (lang_f_options): The on-value for flag_new_for_scope is now 2. + * cp-tree.h (DECL_DEAD_FOR_LOCAL, DECL_ERROR_REPORTED): New macros + (DECL_SHADOWED_FOR_VAR): Likewise. + * decl.c (struct binding_level): New fields dead_vars_from_for + and is_for_scope. + (note_level_for_for): New function. + (poplevel): Special processing if is_for_scope. + (pushdecl): Warn if for-scope variable shadows local. + * lex.c (do_identifier): Handle old (non-ANSI) for scoping, + and warn if conflicts. + * parse.y (FOR): Call note_level_for_for. + +Mon Aug 21 10:28:31 1995 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (import_export_inline): Class interface hackery does not + apply to synthesized methods. + +Sun Aug 20 16:29:00 1995 Mike Stump <mrs@cygnus.com> + + * search.c (virtual_context): Find the right context more often. + Solves a `recoverable compiler error, fixups for virtual function' + problem. + +Sun Aug 20 13:53:24 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_start_all_catch): Ensure that we always transfer + control to the right EH handler, by rethrowing the end label on the + region, instead of hoping we are nested and falling through. + (expand_leftover_cleanups): Likewise. + (end_protect): Since we now rethrow the end label, put a + nop after it, so that outer regions are recognized. + * init.c (build_vec_delete_1): New routine to handle most of vector + deleting, all code moved here from build_vec_delete. + (build_array_eh_cleanup): Use build_vec_delete_1 to do all the real + work. + (expand_vec_init): If the array needs partial destructing, setup an + EH region to handle it. + (build_vec_delete): Move lots of code to build_vec_delete_1, use + build_vec_delete_1 to do the grunt work. + +Sat Aug 19 14:25:33 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + Handle decl attributes properly for function definitions without + previous attribute-loaded declarations. + * decl.c (start_function): New arg ATTRS. Add a call to + cplus_decl_attributes with it before we create the RTL. + * cp-tree.h (start_function): Update prototype. + * parse.y (fn.def1): Pass ATTRS into start_function instead of + trying to call cplus_decl_attributes too late. Pass a NULL_TREE + for other use. + * decl2.c (finish_file): Pass NULL_TREE as fourth arg to + start_function. + * method.c (synthesize_method): Likewise. + * except.c (expand_builtin_throw): Likewise for start on __throw. + +Sat Aug 19 13:36:08 1995 Mike Stump <mrs@cygnus.com> + + * class.c (set_rtti_entry): Turn on -fvtable-thunk -frtti support. + This changes -fvtable-thunks vtable layout, so a recompile will be + necessary, if you use -fvtable-thunks. + (get_vtable_entry): Use n, instead of i to be consistent with the + rest of the compiler. + (get_vtable_entry_n): Likewise. + (add_virtual_function): Add a slot for the tdesc, if -fvtable-thunks + are being used. + (finish_struct_1): Likewise. + (skip_rtti_stuff): New routine to collapse similar code from many + different parts of the compiler. I think I got them all. + (modify_one_vtable): Use it. + (fixup_vtable_deltas1): Likewise. + (override_one_vtable): Likewise. + * decl2.c (mark_vtable_entries): Likewise. + * tree.c (debug_binfo): Likewise. + * search.c (expand_upcast_fixups): Likewise. + (get_abstract_virtuals_1): Likewise. Use virtuals, instead of tmp to + consistent with the rest of the compiler. + (get_abstract_virtuals): Likewise. + * cp-tree.h (skip_rtti_stuff): New routine, declare it. + * gc.c (build_headof): Support -fvtable-thunk and -frtti together. + (build_typeid): Likewise. + (build_classof): Remove old style way of doing rtti. Remove support + for `classof' and `headof'. + * gxx.gperf: Likewise. + * hash.h: Likewise. + * parse.y: Likewise. + +Fri Aug 18 17:31:58 1995 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (start_function): Clear ctor_label and dtor_label. + + * class.c (finish_struct_1): Fix handling of access decls. + +Tue Aug 15 19:21:54 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_struct): Only do minimal processing here, so it + can be used for class template definitions, as well. + (finish_struct_1): New function with the rest of the code. + +Tue Aug 15 09:46:16 1995 Mike Stump <mrs@cygnus.com> + + * class.c (prepare_fresh_vtable): On second though, always build the + offset (see Aug 10 change), unless -fvtable-thunks is given. It + does this by calling the new routine set_rtti_entry. + (finish_struct): Likewise. + (set_rtti_entry): New routine to update the rtti information at the + start of the vtable. + +Mon Aug 14 12:21:22 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * error.c (dump_decl, case IDENTIFIER_NODE): Only work on a dtor + if it's declared in the C++ language spec. + (dump_function_decl): Likewise. + (dump_function_name): Likewise. + (ident_fndecl): Make sure we got something back from lookup_name. + * decl.c (start_function): Likewise. + +Fri Aug 11 16:52:15 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Don't call build_new when calling a + constructor without an instance. + +Thu Aug 10 20:00:17 1995 Mike Stump <mrs@cygnus.com> + + * class.c (prepare_fresh_vtable): Always build the offset to the + complete object, as it doesn't cost much. This allows dynamic_cast + to void * to work when -frtti isn't given. + (finish_struct): Likewise. + +Thu Aug 10 16:31:28 1995 Mike Stump <mrs@cygnus.com> + + * except.c (build_eh_type): Split out some functionality to new + routine named build_eh_type_type. + (build_eh_type_type): New routine. + (expand_start_catch_block): Use build_eh_type_type, as we never want + the dynamic type of the catch parameter, just the static type. + Fixes core dumps when -frtti is used and one catchs pointers to + classes. + +Thu Aug 10 14:55:29 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_builtin_throw): Since we now use normal calling + conventions for __throw, we have to remove the first layer off the + stack, so that the next context we search for handlers is the outer + context instead of the context that had the call to __throw, if we + don't immediately find the desired context. + +Tue Aug 8 17:44:23 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * tree.c (cp_expand_decl_cleanup): Returns int, not tree. + * cp-tree.h: Update. + + * parse.y (template_type_parm): Add support for `typename'. + +Tue Aug 8 12:06:31 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_internal_throw): New internal routine to throw a + value. + (expand_end_all_catch, expand_leftover_cleanups): All throwers + changed to use `expand_internal_throw' instead of jumping to throw + label. + (expand_end_catch_block, expand_throw): Likewise. + (throw_label): Removed. + (expand_builtin_throw): Changed so that EH parameters are passed by + normal function call conventions. Completes Aug 4th work. + +Fri Aug 4 17:17:08 1995 Mike Stump <mrs@cygnus.com> + + * cp-tree.h (expand_builtin_throw): Declare it. + * decl2.c (finish_file): Call expand_builtin_throw. + * except.c (make_first_label): Remove. + (init_exception_processing): Don't use a LABEL_REF for throw_label, + instead use a SYMBOL_REF, this is so that we don't use LABEL_REFs in + other functions that don't really appear in those functions. This + solves a problem where cc1plus consumed exponential amounts of + memory when -Wall was used. + (expand_end_all_catch, expand_leftover_cleanups, + expand_end_catch_block, expand_throw): Change all uses of + throw_label to match new style. + (do_unwind): Rename parameter to inner_throw_label, as it is now + different from throw_label. Also, assume that our caller will wrap + the passed label with a LABEL_REF, if needed. + (expand_builtin_throw): Make external, change so that the generated + throw is now a real function. + (expand_exception_blocks): Never generate throw code inside another + function. + +Fri Aug 4 12:20:02 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (grokdeclarator): Move checking of mutable const objects + and mutable static objects down, as we might decide during parsing + to unset staticp or constp (for example, when const is part of the + object being pointed to). + +Thu Aug 3 17:13:43 1995 Mike Stump <mrs@cygnus.com> + + * except.c (output_exception_table_entry): Enhance portability to + weird machines. + (emit_exception_table): Likewise. + +Thu Aug 3 16:41:38 1995 Mike Stump <mrs@cygnus.com> + + * typeck.c (build_ptrmemfunc): Handle casting of pointer to + non-virtual member functions. + +Wed Aug 2 11:58:25 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_typeid): Strip cv qualifiers so that const T&, T&, T + and const T all match. + +Wed Aug 2 11:25:33 1995 Mike Stump <mrs@cygnus.com> + + * except.c (build_eh_type): Strip cv qualifiers so that const T&, + T&, T and const T all match. + +Tue Aug 1 14:20:16 1995 Mike Stump <mrs@cygnus.com> + + * except.c: Fix up comments, cleanup code and eliminate exceptNode, + exceptStack, exceptstack, push_except_stmts, pop_except_stmts, + new_except_stack, push_last_insn, pop_last_insn, insn_save_node and + InsnSave. Also, numerous speed improvements, and correctness + improvements. Double faulting in all situations should now be + handled correctly. + (expand_start_all_catch): Instead of having many terminate protected + regions, just have one. + (expand_start_catch_block): No longer have to protect + false_label_rtx, as it isn't used for EH region marking. + (expand_end_catch_block): Expand out EH cleanups here by using + expand_leftover_cleanups. + (expand_end_all_catch): Use sequences instead of playing with insn + links directly. + (expand_exception_blocks): Likewise. Also protect all catch clauses + with one terminate region. + +Mon Jul 31 13:24:30 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * method.c (report_type_mismatch): Don't talk about an object + parameter for non-methods. + +Sun Jul 30 13:13:02 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_struct): Catch private and protected members of + anonymous unions here. + * decl2.c (finish_anon_union): And here. + * parse.y: Instead of here. + + * errfn.c (ARGSLIST): Support passing four args. + * error.c (cv_as_string): New function. + (cp_printers): Add it. + * call.c (build_method_call): Report 'const' at end of pseudo-decl. + + * method.c (report_type_mismatch): Deal with a bad_arg of 0. + + * init.c (expand_aggr_init): Handle volatile objects, too. + +Sat Jul 29 13:42:03 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (struct binding_level): Keep list of incomplete decls. + (print_binding_level): Use list_length to count them. + (pushdecl): Build up the list. + (hack_incomplete_structures): Walk it and prune completed decls. + +Fri Jul 28 15:26:44 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (comp_target_types): Don't check const and volatile for + function types. + (comp_ptr_ttypes_real): Likewise. + +Thu Jul 27 15:40:48 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (comp_target_types): Fix. + +Thu Jul 27 15:10:48 1995 Mike Stump <mrs@cygnus.com> + + * cp-tree.h (unsave_expr_now, build_unsave_expr, + cp_expand_decl_cleanup): Declare new routines. + * decl.c (cp_finish_decl, store_parm_decls, + hack_incomplete_structures): Change all cals from + expand_decl_cleanup to cp_expand_decl_cleanup. + * gc.c (protect_value_from_gc): Likewise. + * expr.c (cplus_expand_expr): Handle UNSAVE_EXPRs. + * tree.c (unsave_expr): New routine to build an UNSAVE_EXPR. + (unsave_expr_now): Backend routine used by tree expander. + (cp_expand_decl_cleanup): Wrap second argument in an UNSAVE_EXPR to + work around a limitation in the backend. The backend uses the + cleanups multiple times, on disjoint control flows, so we cannot + pass unsaved SAVE_EXPRs to the backend. + * tree.def (UNSAVE_EXPR): New tree code. + * typeck.c (c_expand_return): Move goto/return code up inside + conditional, as we don't always want to do this, we only want to do + this when we don't otherwise finish with this control flow. + +Thu Jul 27 10:38:43 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (typespec): Only complain about typeof if we're not + getting it from a system header. + +Thu Jul 27 10:26:23 1995 Doug Evans <dje@canuck.cygnus.com> + + Clean up prefix attribute handling. + * parse.y (reserved_declspecs): Link prefix attributes with declspecs. + (declmods): Likewise. + (all rules that reference typed_declspecs and declmods): Call + split_specs_attrs or strip_attrs to separate declspecs and attrs. + (lang_extdef): Delete resetting of prefix_attributes. + (template_def, notype_declarator rule): Use NULL_TREE for + prefix_attributes. + (condition): Use NULL_TREE for prefix_attributes. + (setattrs): Deleted. + (nomods_initdcl0): Set prefix_attributes to NULL_TREE. + (component_decl): Delete resetting of prefix_attributes. + (component_decl_1, notype_components rule): Use NULL_TREE for + prefix_attributes. + (simple_stmt): Delete resetting of prefix_attributes. + +Mon Jul 24 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (convert_harshness): Deal with reference conversions before + others. Actually do array->pointer decay. Call comp_target_types + with pointer types rather than their targets. + + * typeck.c (comp_target_types): Avoid assigning D const * to B *. + +Mon Jul 24 08:54:46 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * pt.c (to_be_restored): Move decl to global scope. + +Sat Jul 22 12:22:11 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (start_decl): Put back clearing of DECL_IN_AGGR_P. + +Fri Jul 21 17:09:02 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (grokdeclarator): Downgrade error about 'extern int A::i' + to pedwarn. + + * pt.c (instantiate_template): Also avoid instantiation if the + function has already been declared to be a specialization. + + * decl2.c (check_classfn): Ignore cname argument, and return the + matching function. + + * decl.c (start_decl): Handle declarations of member functions + outside of the class (i.e. specialization declarations). + +Thu Jul 20 10:34:48 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_struct): Don't mess with the type of bitfields. + + * various.c: s/TYPE_POINTER_TO/build_pointer_type/. + +Thu Jul 20 01:43:10 1995 Mike Stump <mrs@cygnus.com> + + * init.c (expand_aggr_init): Assume LOOKUP_ONLYCONVERTING if init + is not a parameter list (TREE_LIST). + (expand_default_init): If LOOKUP_ONLYCONVERTING is set, then set + LOOKUP_NO_CONVERSION so that we don't allow two-level conversions, + but don't set it otherwise. + +Wed Jul 19 20:32:01 1995 Mike Stump <mrs@cygnus.com> + + * init.c (expand_default_init): Don't allow two-level conversions + during construction. + +Wed Jul 19 18:06:37 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_headof): The type of dyncasting to a pointer to cv + void, should be pointer to cv void. + +Wed Jul 19 17:25:43 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_dynamic_cast): Allow casting in const. + +Wed Jul 19 16:34:27 1995 Mike Stump <mrs@cygnus.com> + + * typeck.c (build_const_cast): If we are passed error_mark_node, + return it. + +Wed Jul 19 15:24:48 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * class.c (push_nested_class): Make sure TYPE is non-nil. + + * cvt.c (type_promotes_to): Watch for error_mark_node on the + incoming TYPE. + +Wed Jul 19 13:23:12 1995 Gerald Baumgartner <gb@alexander.cs.purdue.edu> + + * cp-tree.h (SIGTABLE_VT_OFF_NAME): Renamed from SIGTABLE_OFFSET_NAME. + (SIGTABLE_VB_OFF_NAME): New macro. + (vt_off_identifier): Renamed from offset_identifier. + (vb_off_identifier): Added extern declaration. + + * decl.c (vt_off_identifier): Renamed from offset identifier. + (vb_off_identifier): New variable to hold the identifier for the + sigtable field vb_off. + (init_decl_processing): Initialize vb_off_identifier. + Renamed vt_off_identifier from offset_identifier. + * sig.c (build_signature_method_call): Renamed offset_identifier and + local variable offset to vt_off_identifer and vt_off, respecitively. + * sig.c (build_signature_table_constructor): Renamed offset to vt_off. + + * decl.c (init_decl_processing): Add vb_off field to + sigtable_entry_type. Reorder fields so that pfn gets properly + aligned at a 64 bit boundary on the Alpha. + * sig.c (build_signature_table_constructor): Build the constructor + according to the new layout. Set the vb_off field to -1 for now. + + * decl.c (init_decl_processing): Align sigtable_entry_type on word + boundaries instead of double word boundaries to save space. + +Tue Jul 18 16:58:37 1995 Mike Stump <mrs@cygnus.com> + + * cvt.c (cp_convert): Always call build_cplus_new for a ctor. + +Tue Jul 18 14:24:53 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (opt.component_decl_list): Only forbid private/protected + in anonymous unions. We need to make this know when the type is + defined for an object, to not give the error. + +Mon Jul 17 14:22:44 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (opt.component_decl_list): Don't allow access control + as private or protected for union members. + +Sun Jul 16 14:01:00 1995 Jim Wilson <wilson@chestnut.cygnus.com> + + * lex.c (check_newline): For 'p' case, move goto skipline line to + before end brace for 'pragma'. + +Fri Jul 7 13:55:58 1995 Mike Stump <mrs@cygnus.com> + + * g++.1: Tiny updates. + +Fri Jul 7 13:05:20 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (cp_finish_decl): Only destruct local static variables if + they are constructed, and only construct the first time control + passes completely through its declaration (if not initialized with a + constant-expression). + (expand_static_init): Likewise. + +Wed Jul 5 14:05:04 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * typeck.c (comptypes, case OFFSET_REF): If either offset basetype + is a TEMPLATE_TYPE_PARM, give a match. + +Fri Jun 30 15:42:57 1995 Mike Stump <mrs@cygnus.com> + + * method.c (build_overload_value): Handle encoding of null pointer + constants (or any pointer with a constant numeric value) for + templates. + +Fri Jun 30 13:45:51 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * call.c (convert_harshness): Add QUAL_CODE when we're faced with + const vs non-const for void conversions. + +Fri Jun 30 10:19:52 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_start_all_catch): Fix problem with finding an + outer nested try block when there is no code to separate it from an + inner try block. + +Fri Jun 30 02:22:26 1995 Mike Stump <mrs@cygnus.com> + + * search.c (dfs_pushdecls): Consume 2 or 3 orders of magnitude less + memory please when virtual bases are used. + +Thu Jun 29 19:03:47 1995 Mike Stump <mrs@cygnus.com> + + * class.c (build_vbase_path): Avoid testing things that cannot be + null to see if they are null. + * cvt.c (convert_pointer_to_vbase): Remove code that doesn't work. + * decl.c (finish_function): Pass a type into the new + convert_pointer_to_vbase instead of a binfo. + * search.c (convert_pointer_to_vbase): Rewritten to use get_vbase + and convert_pointer_to_real. + (expand_indirect_vtbls_init): Use convert_pointer_to_vbase instead + of the more cryptic call to get_vbase. + +Thu Jun 29 09:35:05 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (BOOL_TYPE_SIZE): Fix broken SLOW_BYTE_ACCESS check. + +Thu Jun 29 03:43:55 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (instantiate_template): Don't strip 'this' twice. + + * pt.c (coerce_template_parms): Allow null pointer constants. + + * decl.c (revert_static_member_fn): But only if DECL_ARGUMENTS is + set. + +Wed Jun 28 18:39:03 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (revert_static_member_fn): Also remove 'this' from + DECL_ARGUMENTS. + * decl2.c (check_classfn): Don't revert this function until we get a + match. + +Wed Jun 28 14:07:27 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (component_decl): Clear PREFIX_ATTRIBUTES here. + +Wed Jun 28 11:05:13 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_file): Handle global vector news. + * init.c (build_new): Encode vector news so that later we will know + how many elements there are. + +Mon Jun 26 13:38:06 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * expr.c (cplus_expand_expr): Don't mess with temp slots. + + * decl2.c (warn_if_unknown_interface): Don't crash if tinst_for_decl + returns null. + + * decl2.c (check_classfn): Use revert_static_member_fn. + * decl.c (revert_static_member_fn): Diagnose static member functions + declared const or volatile. + + * decl2.c (grokfield): Check for missing default args here, too. + (check_default_args): Function to do the checking. + * decl.c (pushdecl): Use it. + + * decl.c (pushdecl): Don't warn about shadowing a member of `this' + if there is no `this'. + +Sun Jun 25 11:34:25 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Downgrade 'called before definition' + to a warning, as it ought to go away after Monterey. + +Sat Jun 24 14:18:42 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (coerce_template_parms): Don't do extra checking on pointer + to member arguments. + + * class.c (finish_struct): const and reference members don't prevent + a class from being an aggregate. + + * class.c (finish_struct): Signatures are always aggregates. + +Fri Jun 23 17:20:29 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (check_classfn): Improve error message. + + * pt.c (tsubst): Handle PROMOTE_PROTOTYPES. + +Thu Jun 22 01:50:42 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (comptypes): Don't ignore method quals. + + * class.c (finish_struct): Non-abstract virtuals are always USED. + + * decl.c (build_ptrmemfunc_type): The underlying union type isn't + IS_AGGR_TYPE, either. + * class.c (finish_struct): Use CLASSTYPE_NON_AGGREGATE instead. + * cp-tree.h: Likewise. + + * cp-tree.h (lang_type): Add aggregate. + (CLASSTYPE_AGGREGATE): New macro. + (TYPE_NON_AGGREGATE_CLASS): Likewise. + * class.c (finish_struct): Determine whether a class is an + aggregate. + * decl.c (cp_finish_decl): Check TYPE_NON_AGGREGATE_CLASS instead of + TYPE_NEEDS_CONSTRUCTING. + * typeck2.c (digest_init): Check TYPE_NON_AGGREGATE_CLASS for + subobjects, too. + + * pt.c (tsubst, PARM_TYPE): Propagate DECL_ARTIFICIAL. + + * decl.c (start_function): For pre-parsed functions, layout all of + the parm decls again. + (grokvardecl): TREE_PUBLIC depends on DECL_THIS_EXTERN, not + DECL_EXTERNAL. + + * pt.c (coerce_template_parms): Improve checking for invalid + template parms. + +Wed Jun 21 12:01:16 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Forbid declaration of a static member + with the same name as its enclosing class. + +Mon Jun 19 10:28:14 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (finish_function): Clear current_class_decl. + + * typeck.c (build_conditional_expr): Use convert (boolean_type_node + instead of truthvalue_conversion. + + * class.c (finish_struct): A data member with the same name as the + class doesn't suppress constructors. + +Fri Jun 16 18:11:39 1995 Gerald Baumgartner <gb@alexander.cs.purdue.edu> + + * decl.c (start_function): If current_class_decl is a signature + pointer, don't dereference it but set C_C_D to current_class_decl. + +Fri Jun 16 17:06:28 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (duplicate_decls): Complain about virtual functions + redeclared to be inline. + +Fri Jun 16 13:20:38 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (get_unique_name): New routine to name unnamed namespaces. + (push_namespace): Use get_unique_name for naming unnamed namespaces. + +Thu Jun 15 15:00:41 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y: Call cplus_decl_attributes with prefix_attributes where + appropriate. + +Wed Jun 14 19:24:49 1995 Mike Stump <mrs@cygnus.com> + + * search.c (get_vbase): New routine to switch hierarchies from the + CLASSTYPE_VBASECLASSES to the normal one. + (expand_indirect_vtbls_init): Use get_vbase to figure out how we + want to convert to a vbase pointer. + +Mon Jun 12 17:50:30 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (instantiate_class_template): Add the new instantiation to + template_classes. + (do_pending_expansions): Call instantiate_member_templates on all of + the classes in template_classes. + +Mon Jun 12 12:36:59 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (complete_array_type): Fill in the TYPE_DOMAIN of our + TYPE_MAIN_VARIANT if it is not filled in. + * init.c (build_delete): If the TYPE_DOMAIN is not set, give an + error instead of core dumping. + +Mon Jun 12 10:41:40 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (can_convert): Also check for distance > 0. + (can_convert_arg): Likewise. + (user_harshness): Likewise. + +Fri Jun 9 19:17:21 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * g++.c (MATH_LIBRARY): Provide default. + (main): Always link with the math library if we link with libstdc++. + + * decl.c (start_function): Complain about redefinition of a function + even when the pending_inline version is compiled after the other + version. + +Thu Jun 8 15:44:38 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * gc.c (build_dynamic_cast): Build up a reference to a parameter of + aggregate type. + +Wed Jun 7 15:31:57 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (build_vec_delete): Resolve an offset ref before we try to + use it. + +Wed Jun 7 14:19:32 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_modify_expr): If the class lacks a constructor or + assignment operator, return error_mark_node. + (common_type): Use build_cplus_array_type. + +Tue Jun 6 09:41:27 1995 Mike Stump <mrs@cygnus.com> + + * class.c (dont_allow_type_definitions): New variable set when types + cannot be defined. + (finish_struct): Use it. + * cp-tree.h (dont_allow_type_definitions): Define it. + * parse.y (primary, handler_seq): Set it. + +Mon Jun 5 18:49:38 1995 Mike Stump <mrs@cygnus.com> + + * method.c (build_opfncall): Use DECL_CHAIN, not TREE_CHAIN for + results from lookup_fnfields. Always give warning/error on bad + code. + +Mon Jun 5 11:39:37 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (member_init_ok_or_else): Don't allow initialization of + an ancestor's member from within a constructor. + +Mon Jun 5 11:20:34 1995 Gerald Baumgartner <gb@alexander.cs.purdue.edu> + + * sig.c (build_signature_table_constructor): Use DECL_CONTEXT + instead of DECL_CLASS_CONTEXT for calculating the vfield offset so + abstract virtual functions are handled correctly. + + * sig.c (build_signature_table_constructor): Store the correct + delta in signature table entries. It does not yet work for + classes with virtual base classes as implementations of signatures. + (build_signature_method_call): Add the delta to the object_ptr + before generating the function call. + + * call.c (build_method_call): Make instance_ptr the signature + pointer itself instead of dereferencing the optr. + * sig.c (build_signature_method_call): Dereference the optr for the + direct and virtual calls. + + * sig.c (build_signature_table_constructor): Make the tag for + default implementations -1 instead of 2. + (build_signature_method_call): Change the generated conditional + expression correspondingly. + + * sig.c (build_signature_pointer_constructor): Deleted the sorry + message that said we can't handle multiple inheritance for + implementations of signatures + (build_signature_method_call): Use the offset from the sigtable + entry instead of the vptr field from the signature pointer for + building a virtual function call. + + * class.c (build_vfn_ref): Deleted signature specific code, we don't + call this function anymore from build_signature_method_call. + + * cp-tree.h (SIGNATURE_VPTR_NAME): Deleted. We use the right vptr + field in the object now instead of in the signature pointer/ref. + (build_vptr_ref): Deleted extern declaration. + * sig.c (build_vptr_ref): Deleted. + (build_signature_pointer_or_reference_type): Deleted construction of + the vptr field. + (build_signature_pointer_constructor): Deleted initialization of/ + assignment to the vptr field. + + * sig.c (build_signature_table_constructor): Convert the signature + table entry fields to their correct types. + + * sig.c (build_signature_table_constructor): Don't call digest_init + for the fields of a sigtable entry, it's wasted time. + + * sig.c (build_signature_table_constructor): Correctly set the + offset and index fields of a sigtable entry. Build the constructor + the way digest_init does, digest_init can't handle initializing an + anonymous union inside a struct. + (build_signature_method_call): Use the index field instead of the + delta field to get the vtable index. + + * decl.c (init_decl_processing): Fix number of fields for building + sigtable_entry_type. + + * cp-tree.h (tag_identifier, offset_identifier): Added extern decls. + (SIGTABLE_CODE_NAME): Renamed to SIGTABLE_TAG_NAME. + (SIGTABLE_PFN_NAME): Deleted, we'll use VTABLE_PFN_NAME instead. + * decl.c (tag_identifier, offset_identifier): New variables to + hold the identifiers for the sigtable fields tag and offset. + (init_decl_processing): Initialize these variables. + (init_decl_processing): Use these variables to build the + sigtable_entry_type structure. Rename the code and offset fields + to tag and delta, respectively; add offset and index fields. Changed + types of fields from short_integer_type_node to delta_type_node. + * sig.c (build_signature_table_constructor): Rename code and offset + to tag and delta, respectively. + (build_signature_method_call): Likewise. Use above variables. + +Thu Jun 1 17:03:51 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (lookup_name_real): Don't try to look anything up in an + erroneous object. + +Fri Jun 2 10:30:14 1995 Mike Stump <mrs@cygnus.com> + + * method.c (build_overload_int): New routine. Break out + functionality from build_overload_value so we can reuse it. + (build_overload_value): Handle pointer to member functions as value + parameters for templates. + (build_overload_identifier): Since template parameters are shared + among all instantiations, we have to substitute in the real types + in TREE_TYPE (parm). + pt.c (coerce_template_parms): Likewise. + (push_template_decls): Likewise. + (grok_template_type): Deleted as template parameters are shared + among all instantiations. + +Wed May 31 19:10:32 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (grokdeclarator): Always give errors on constant overflow + for array indices. + +Wed May 31 11:39:43 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (commonparms): Don't abort if simple_cst_equal returns < 0. + (build_c_cast): Don't tack on a NON_LVALUE_EXPR when casting to + reference type. + (build_indirect_ref): Fix check for *&. + +Fri Jun 16 06:54:03 1995 Mike Stump <mrs@cygnus.com> + + * Version 2.7.0 released. + +Fri Jun 16 15:07:29 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * Make-lang.in (DEMANGLER_PROG): Add LIBS. + +Thu Jun 15 15:00:41 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (define_function): Don't set DECL_INTERFACE_KNOWN. + +Wed Jun 7 20:00:31 1995 Mike Stump <mrs@cygnus.com> + + * *.[chy]: Change all callers of finish_decl to cp_finish_decl. + * decl.c (finish_decl): New routine to handle call backs from the + mid end (declare_hidden_char_array). + +Wed Jun 7 19:02:50 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (start_function): Handle setting C_C_D here. + (set_C_C_D): Removed. + (struct saved_scope): Remove class_decl. + (push_to_top_level): Don't save current_class_decl. + (pop_from_top_level): Don't restore current_class_decl or C_C_D. + (struct cp_function): Add C_C_D. + (push_cp_function_context): Save C_C_D. + (pop_cp_function_context): Restore C_C_D. + +Fri Jun 2 11:05:58 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (set_C_C_D): New function. suspend_momentary before + building C_C_D. + (pop_from_top_level): Call it. + (start_function): Likewise. + (pop_cp_function_context): Likewise. + + * class.c, cp-tree.h, decl.c, decl2.c, parse.y: Lose all references + to current_vtable_decl, CLASSTYPE_INST_VAR and CLASSTYPE_VTBL_PTR. + + * decl.c (push_cp_function_context): Save current_class_decl. + (pop_cp_function_context): Restore current_class_decl and set C_C_D. + (pop_from_top_level): Don't use CLASSTYPE_INST_VAR to set C_C_D. + (start_function): Likewise. + + * class.c (popclass): Don't mess with current_class_decl, + current_vtable_decl, or C_C_D. + +Mon May 29 12:45:10 1995 Paul Eggert <eggert@twinsun.com> + + * Make-lang.in (c++.mostlyclean): Remove $(DEMANGLER_PROG). + +Wed May 24 15:55:18 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * decl.c (duplicate_decls): Check simple_cst_equal result against 0. + * decl2.c (finish_anon_union): Likewise. + * method.c (largest_union_member): Likewise. + +Wed May 24 14:41:11 1995 H.J. Lu <hjl@nynexst.com> + + * Make-lang.in (cxxmain.o): Replace single quotes with backslashes. + +Mon May 22 17:38:48 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * Make-lang.in (g++, g++-cross, cc1plus, DEMANGLER_PROG): + Use $@ instead of output name so works even if have .exe. + (cxxmain.o): Use cp if ln -s fails. + (c++.install-man): Use $(exeext) in executable names. + (c++.mostlyclean, stage[1-4]): Use $(objext) in object file names. + * Makefile.in (../cc1plus): Use $(exeext) in name of executable. + +Wed May 24 01:39:03 1995 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): parms can be null, duh. + +Tue May 23 01:32:09 1995 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): If convert_arguments failed, just bail. + +Fri May 19 10:31:11 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (convert_force): Pass LOOKUP_NORMAL to cp_convert. + + * tree.c (copy_to_permanent): Oops. + +Fri May 19 10:01:07 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-tree.h (break_out_target_exprs): Add decl. + +Thu May 18 13:02:30 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (start_function): Move *all* interface handling stuff after + the pushdecl. + + * tree.c (mapcar): Renamed from make_deep_copy and generalized. + (perm_manip): Return t if permanent, otherwise 0. + (copy_to_permanent): Use them. + (bot_manip): Helper for break_out_target_exprs. + (break_out_target_exprs): New function. Uses mapcar. + + * typeck.c (convert_arguments): Use it. + + * method.c (hack_identifier): Use convert_from_reference to + dereference a reference. + +Wed May 17 17:54:54 1995 Mike Stump <mrs@cygnus.com> + + * call.c (convert_harshness): Move reference bashing before pointer + to member bashing. + +Wed May 17 16:57:53 1995 Mike Stump <mrs@cygnus.com> + + * cvt.c (convert_to_reference): Only complain, if complaints are + wanted. + * typeck.c (build_function_call_real): Likewise. If + LOOKUP_SPECULATIVELY is set and something won't work, return + NULL_TREE. + * cvt.c (cp_convert): Likewise. Pass flags down to build_method_call. + (convert): Pass LOOKUP_NORMAL to cp_convert. + * typeck.c (convert_for_assignment): Likewise. + (convert_force): Pass LOOKUP_COMPLAIN to cp_convert. + (convert_arguments): Get out early if we get an error_mark_node. + (convert_for_initialization): Use cp_convert instead of convert so + that we can pass flags down. + * cp-tree.h (LOOKUP_SPECULATIVELY): Added documentation. + +Wed May 17 01:43:58 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck2.c (store_init_value): Don't take the MAIN_VARIANT of the + decl type. + + * class.c (finish_struct): Don't complain about a class with no + user-defined constructors but with a member that has no default + constructor, as this is OK for aggregates. + + * expr.c (cplus_expand_expr, NEW_EXPR): If this is an explicit + constructor call, mark slot addressable. + +Tue May 16 18:37:51 1995 Douglas Rupp <drupp@cs.washington.edu> + + * g++.c: Changed WINNT to _WIN32. + +Tue May 16 12:40:16 1995 Jason Merrill <jason@lisa.cygnus.com> + + * lex.c (handle_sysv_pragma): Don't use token_buffer. + +Tue May 16 12:05:26 1995 Mike Stump <mrs@cygnus.com> + + * call.c (resolve_scope_to_name): Add initial semantic support for + namespaces. + * class.c (finish_struct): Likewise. + * cp-tree.h (NAMESPACE_LEVEL): Likewise. + * cvt.c (build_up_reference, convert_to_reference): Likewise. + * decl.c (binding_level::namespace_p, suspend_binding_level): Likewise. + (resume_binding_level, toplevel_bindings_p): Likewise + (namespace_bindings_p, declare_namespace_level): Likewise. + (resume_level, push_namespace, pop_namespace): Likewise. + (pop_everything, pushtag, duplicate_decls, pushdecl): Likewise. + (implicitly_declare, lookup_namespace_name): Likewise. + (lookup_name_real, start_decl, make_temporary_for_reference): Likewise. + (obscure_complex_init, finish_decl, expand_static_init): Likewise. + (grokvardecl, grokdeclarator, parmlist_is_exprlist): Likewise. + (store_parm_decls, hack_incomplete_structures): Likewise. + * decl2.c (get_temp_name, finish_anon_union): Likewise. + (current_namespace, push_namespace, pop_namespace): Likewise. + (do_namespace_alias, do_toplevel_using_decl): Likewise. + (do_class_using_decl): Likewise. + * error.c (dump_decl): Likewise. + * init.c (build_member_call, build_offset_ref): Likewise. + * lex.c (identifier_type): Likewise. + * parse.y (lang_extdef, using_decl, extdef): Likewise. + (component_decl_1, nested_name_specifier_1): Likewise. + * spew.c (yylex): Likewise. + * tree.def (NAMESPACE_DECL): Likewise. + +Tue May 16 11:55:35 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (push_overloaded_decl): Return the new decl even if it + can't be pushed. + +Tue May 16 11:00:37 1995 Jason Merrill <jason@lisa.cygnus.com> + + * typeck.c (decay_conversion): Split out from default_conversion. + (default_conversion): Call it. + (build_binary_op): Likewise. + (build_binary_op_nodefault): Use decay_conversion for truth ops. + +Mon May 15 12:47:56 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (warn_extern_redeclared_static): This is a pedwarn. + (duplicate_decls): Always use the old decl's linkage info. Don't + play with linkage of consts. + (pushdecl): Don't play with linkage of consts. + (redeclaration_error_message): Don't complain about an old public + decl and a new non-public decl here. + (grokvardecl): Handle linkage of consts here. + (grokdeclarator): An 'extern inline' is public. Pass constp to + grokvardecl. + (start_function): Wait until after the pushdecl to do some linkage + stuff. + + * decl2.c (import_export_vtable): Make duplicates weak rather than + static if supported. + (import_export_inline): Likewise. + * pt.c (do_pending_expansions): Likewise. + + * class.c (build_vbase_path): flag_assume_nonnull_objects only + affects reference conversion. + + * init.c (emit_base_init): Build up an RTL_EXPR and add it to + rtl_expr_chain. + * decl.c, decl2.c: s/base_init_insns/base_init_expr/. + +Tue May 16 07:06:28 1995 Paul Eggert <eggert@twinsun.com> + + * method.c (numeric_output_need_bar): Renamed from misspelling. + + * typeck.c (build_ptrmemfunc): Fix misspellings in messages. + +Sun May 14 10:26:22 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * lang-options.h, lang-specs.h: New files. + +Thu May 11 00:31:48 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (default_conversion): Don't check for BLKmode before + pulling out the decl_constant_value. + + * decl.c (start_function): Clear named_labels and shadowed_labels. + + * typeck.c (build_function_call_real): Also synthesize methods here. + +Wed May 10 00:55:59 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_file): Synthesize exported methods before the + reconsider loop. + + * parse.y: Move declaration of flag_new_for_scope to file scope. + +Tue May 9 19:10:33 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c: Add flag_new_for_scope for new -ffor-scope flag. + * parse.y (FOR): Conditionalize the pushing and poping of scope for + the for-init-statement upon the new flag_new_for_scope. + * parse.y (try_block): Simplify and use compstmt. + +Mon May 8 12:41:52 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (define_function): Mark function decl artificial. + +Sun May 7 00:51:28 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y (simple_stmt, FOR): Put back push/pop for condition scope. + + * decl2.c (grokclassfn): DECLs don't have cv-qualified types. + * tree.c (build_cplus_method_type): Likewise. + + * cp-tree.h (SET_DECL_ARTIFICIAL): Just set DECL_ARTIFICIAL to 1. + + * typeck.c (build_function_call_real): If convert_arguments failed, + just bail. + (convert_arguments): If one of the arguments is error_mark_node, + just bail. + +Sat May 6 02:39:41 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (duplicate_decls): Don't check DECL_NOT_REALLY_EXTERN for + decls that don't include it. + +Fri May 5 14:23:30 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (duplicate_decls): Decls that have DECL_INTERFACE_KNOWN or + DECL_NOT_REALLY_EXTERN set aren't extern decls. + + * typeck.c (build_indirect_ref): Don't call default_conversion for a + parameter of reference_type. + * cvt.c (convert_from_reference): Just use build_indirect_ref. + + * pt.c (do_type_instantiation): Only instantiate member functions + that actually come from templates. + +Fri May 5 09:46:05 1995 Mike Stump <mrs@cygnus.com> + + * parse.y: Generalized cleanup of poplevels, and compound statements + and compound statements in try blocks. Rewritten `for' rule so that + the scope of variables declared in the for clause is shortened to + span just to the end of the statement, instead of the whole + containing block. + +Fri May 5 00:37:14 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (convert_harshness): Handle pointers to members better. + +Thu May 4 16:00:26 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (delete_sanity): Do access control here. + * init.c (build_delete): Instead of here. + + * Make-lang.in: Build c++filt. + +Wed May 3 02:59:53 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (cplus_decl_attributes): If we just modified a TYPE_DECL, + update our IDENTIFIER_TYPE_VALUE. + +Fri Apr 28 07:58:41 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * lex.c (cons_up_default_function): Fix linkage of #pragma + implemented functions. + +Thu Apr 27 16:56:24 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * method.c (build_overload_name): Simplify and fix repeated type + folding. + + * decl.c (grokdeclarator): Prohibit pointers to void or reference + members. + +Thu Apr 27 09:49:07 1995 Mike Stump <mrs@cygnus.com> + + * typeck2.c (process_init_constructor): Make sure initializers are + fully digested. + +Thu Apr 27 01:11:55 1995 Jason Merrill <jason@python.cygnus.com> + + * lex.c (cons_up_default_function): Always defer synthesis. + +Thu Apr 27 00:20:37 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (mark_inline_for_output): Don't play with pending_inline + stuff. + +Wed Apr 26 17:48:24 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (user_harshness): New function; like build_type_conversion, + but doesn't actually build anything. + (compute_conversion_costs): Use it instead of build_type_conversion. + +Wed Apr 26 17:11:25 1995 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_function_call_real): Improve error message for + calling a non-function. + + * method.c (hack_identifier): Lose check for calling a data member. + +Wed Apr 26 16:59:13 1995 Mike Stump <mrs@cygnus.com> + + * typeck2.c (build_functional_cast): Remove very old cruft. + Seems like good code is generated without it. + +Wed Apr 26 00:47:16 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * method.c (do_build_assign_ref): Fix handling of anonymous unions. + (do_build_copy_constructor): Likewise. + + * parse.y (simple_stmt, SWITCH): Call {push,pop}_switch. + + * decl.c (push_switch): New function. + (pop_switch): Likewise. + (define_case_label): Check for jumping over initialization. + + * call.c (build_method_call): Check for an inline function being + called before its definition has been seen. + * typeck.c (build_function_call_real): Likewise. + + * decl.c (duplicate_decls): Check for a function being redeclared + inline after its address has been taken. + + * typeck.c (build_conditional_expr): Handle related class lvalues. + +Tue Apr 25 13:20:45 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (do_pending_expansions): Don't expand unused templates. + + * parse.y (component_decl): Accept a lone semicolon. + +Tue Apr 25 00:25:56 1995 Jason Merrill <jason@rtl.cygnus.com> + + * call.c (build_method_call): Don't allow an RTL_EXPR to serve as the + object parameter anymore. + + * expr.c (cplus_expand_expr): Don't create RTL_EXPRs with no insns. + +Mon Apr 24 12:35:48 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y (simple_stmt, decl case): Clear prefix_attributes. + (lang_extdef): Likewise. + + * parse.y (maybe_parmlist): New rule for use in declarators where + this could either be a list of expressions or parameters. Calls + suspend_momentary before deciding which. + (direct_after_type_declarator): Use it. + (complex_direct_notype_declarator): Use it. + + * pt.c (tsubst): Propagate attributes const and noreturn. + + * typeck.c (build_modify_expr): If warn_synth, call build_opfncall + before doing the default thing. + +Thu Apr 27 21:49:36 1995 Doug Evans <dje@cygnus.com> + + * typeck.c (common_type): Call lookup_attribute instead of + value_member. + +Tue Apr 25 18:07:43 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> + + * Make-lang.in: Change "realclean" to "maintainer-clean". + +Sun Apr 23 12:32:38 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_file): Fix broken linked list handling. + +Fri Apr 21 18:08:43 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_base_struct): Don't set TYPE_HAS_COMPLEX_*_REF + as often. + (finish_struct): Likewise. + + * various: Use TYPE_HAS_TRIVIAL_* instead of TYPE_HAS_COMPLEX_*. + + * cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): New macro. + (TYPE_HAS_TRIVIAL_ASSIGN_REF): New macro. + +Fri Apr 21 15:52:22 1995 Jason Merrill <jason@python.cygnus.com> + + * typeck.c (c_expand_return): Only expand a returned TARGET_EXPR if + it is of the same type as the return value. + +Fri Apr 21 03:01:46 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_file): Reconsider if synthesizing a method wrote + out its assembly. + + * typeck.c (convert_for_initialization): Don't call a trivial copy + constructor. + + * typeck2.c (store_init_value): Only abort if the type has a + non-trivial copy constructor. + + * typeck.c (c_expand_return): If we're returning in a register and + the return value is a TARGET_EXPR, expand it. Only do + expand_aggr_init if we're returning in memory. + (expand_target_expr): Function to expand a TARGET_EXPR. + (build_modify_expr): Use it. + + * tree.c (build_cplus_new): Layout the slot. + + * expr.c (cplus_expand_expr): Use expand_call to expand the call + under a NEW_EXPR, so the target is not discarded. + +Thu Apr 20 14:59:31 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_dynamic_cast): Tighten error checking. + +Thu Apr 20 11:23:54 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * expr.c (cplus_expand_expr): Only abort if the returned target is + different from what we expected if the type has a non-trivial copy + constructor. + + * decl2.c (cplus_decl_attributes): Attributes applied to a template + really apply to the template's result. + + * tree.c (lvalue_p): Check IS_AGGR_TYPE instead of TREE_ADDRESSABLE + to decide whether to consider a CALL_EXPR an lvalue. + + * class.c (finish_struct_bits): Only set TREE_ADDRESSABLE if the + type has a non-trivial copy constructor. + + * decl.c (start_function): If interface_known, unset + DECL_NOT_REALLY_EXTERN on the function. + +Wed Apr 19 16:53:13 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (do_function_instantiation): Handle explicit instantiation of + member functions. + (do_type_instantiation): Handle 'inline template class foo<int>', + meaning just spit out the vtable. + + * lex.c (cons_up_default_function): Set DECL_NOT_REALLY_EXTERN on + the consed functions. + + * decl2.c (import_export_inline): Set DECL_INTERFACE_KNOWN. + +Wed Apr 19 16:28:17 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * call.c, class.c, decl2.c, gc.c, init.c, parse.y, pt.c, search.c, + typeck.c: Include output.h. + +Wed Apr 19 14:57:21 1995 Gerald Baumgartner <gb@alexander.cs.purdue.edu> + + * call.c (build_method_call): Allow a signature member functions to + be called from a default implementation. + +Wed Apr 19 10:21:17 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c (finish_repo): Remember what directory we are in. + + * search.c (expand_upcast_fixups): Don't mess with abort_fndecl. + + * repo.c: Use obstacks instead of fixed-size buffers. Don't spit + out the second copy of the symbol name. Don't remember COLLECT_GCC. + +Wed Apr 19 02:32:40 1995 Mike Stump <mrs@cygnus.com> + + * search.c (virtual_context): New function to get the virtual + context of a function. + (expand_upcast_fixups): New function to generate runtime vtables. + (fixup_virtual_upcast_offsets): Likewise. + (expand_indirect_vtbls_init): Use fixup_virtual_upcast_offsets to + ensure that the this offsets for upcasts from virtual bases into + other virtual bases or non-virtual bases are correct at construction + time and destruction time. + * class.c (fixup_vtable_deltas): Modify to fixup all offsets in all + vtables in all virtual bases, instead of just one vtable in each + virtual base. + (fixup_vtable_deltas1): Likewise. + +Tue Apr 18 03:57:35 1995 Michael Meissner <meissner@cygnus.com> + + * Makefile.in (lex.o): Add dependency on c-pragma.h. + + * lex.c (handle_sysv_pragma): Use NULL_PTR and NULL_TREE as + appropriate, instead of 0. + +Mon Apr 17 12:28:42 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (pushdecl): Use decls_match, not duplicate_decls, for + comparing local and global decls. + +Fri Apr 14 01:46:52 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (convert_arguments): Only prohibit passing to ... of + types with non-trivial copy constructors. + + * repo.c (repo_template_used): Don't try to mess with no id. + +Fri Apr 14 23:32:50 1995 Per Bothner <bothner@rtl.cygnus.com> + + * decl.c (duplicate_decls): Use cp_warning_at for redundant-decls. + +Thu Apr 13 15:37:42 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-tree.h (current_tinst_level): Delete declaration, since it's + static inside pt.c. + + * typeck.c (build_modify_expr): Catch incompatible array assignment. + + * parse.y (attribute_list, attrib): Rewrite actions to feed the + right stuff to decl_attributes. + +Thu Apr 13 11:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * search.c (dfs_debug_mark): Check for magic virtual like + import_export_vtable. + + * typeck.c (build_binary_op_nodefault): Don't call cp_pedwarn with + four args. + +Wed Apr 12 12:02:57 1995 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (finish_file): Move prevtable pass before needs_messing_up + decision. + +Tue Apr 11 11:20:27 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (finish_decl): If we're writing out a static data member of + a class, we want the debug info for that class. + + * gc.c (build_t_desc): Check linkage of a class properly. + + * class.c (finish_struct): Set the 'headof' offset for the main + vtable properly. + (prepare_fresh_vtable): Fix typeinfo pointer here. + (modify_one_vtable): Instead of here. + +Mon Apr 10 12:15:59 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c (repo_get_id): New function to return the interesting + identifier for a repo entity. + (repo_template_used): Use it. + (repo_template_instantiated): Mark the id as chosen. + (init_repo): Record whether or not the id was chosen. + (finish_repo): Note if an id was newly chosen. + + * pt.c (do_function_instantiation): Call repo_template_instantiated. + (do_type_instantiation): Likewise. Don't diagnose multiple + instantiation. + + * decl2.c (finish_file): Use DECL_NOT_REALLY_EXTERN when deciding + whether or not to synthesize a method. + + Undo these changes: + * class.c (finish_vtbls): build more vtables if flag_rtti is on. + * class.c (modify_all_direct_vtables): ditto. + * init.c (expand_direct_vtbls_init): expand more vtables if + flag_rtti is on. + +Sat Apr 8 17:45:41 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_headof): Use ptrdiff_type_node instead of + integer_type_node on pointer arithmetic. + +Sat Apr 8 11:57:04 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_modify_expr): Undo previous change. + +Thu Apr 6 01:23:50 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * Makefile.in (compiler): Remove ../cc1plus before rebuilding it. + + * repo.c (get_base_filename): Put the .rpo file in the directory + with the object file, not the source. + + * typeck.c (build_conditional_expr): Handle pmf's better. + + * repo.c (finish_repo): Also use ASM_OUTPUT_LABELREF to print out + the name of the symbol. + +Wed Apr 5 15:24:12 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c (open_repo_file): Make repo filename DOS-compliant. + (*): Also write a new repo file if some previously-used + templates are no longer used. Only remember the identifier. + + * lex.c (cons_up_default_function): If this function belongs to a + template class, call repo_template_used for it. + + * repo.c (repo_template_used): Using a class means using its vtable, + if any. + (finish_repo): Likewise. + + * typeck.c (build_modify_expr): Only wrap TARGET_EXPRs in RTL_EXPRs + if the type has a complex copy constructor. + + * decl2.c (lang_decode_option): -frepo implies + -fno-implicit-templates. + + * decl.c (start_function): Clear current_{base,member}_init_list. + + * lex.c (init_lex): Also unset *_eq if ! flag_operator_names. + +Tue Apr 4 16:11:08 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (struct cp_function): Add {base,member}_init_list. + (push_cp_function_context): Save current_{base,member}_init_list. + (pop_cp_function_context): Restore them. + +Mon Apr 3 16:55:08 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c (get_base_filename): Take filename parm, fix logic bug. + + * typeck.c (build_compound_expr): Do not warn about a compound expr + in which the first expression has no side effects. + (build_x_compound_expr): Warn here instead. + (build_conditional_expr): Don't warn about a conditional expression + between an enum and the type it promotes to. + + * init.c (build_new): Handle initialization of arrays of builtins + properly. + +Mon Apr 3 15:08:04 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * repo.c: Include config.h to get definitions of bcopy and rindex + on systems that don't have them (e.g., SVR4). + +Mon Apr 3 14:41:55 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_table): Pass NULL_TREE instead of init to + finish_decl so that it won't try and do error checking on the + initializer. + +Mon Apr 3 10:45:50 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c (get_base_filename): Analyze COLLECT_GCC_OPTIONS to + determine whether this compile used -c -o. + (open_repo_file): Use get_base_filename. Remove the extension. + (finish_repo): Spit out the values of main_input_filename, + COLLECT_GCC and COLLECT_GCC_OPTIONS. + + * parse.y (structsp): Add TYPENAME_KEYWORD complex_type_name. + +Sun Apr 2 23:43:51 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * search.c (compute_access): Don't try to do access control on + nested types. + +Fri Mar 31 10:14:23 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * repo.c: New file to handle things repo. + + * pt.c (instantiate_template): Call repo_template_used if the + definition is accessible. + (mark_function_instantiated): Split out from + do_function_instantiation. + (mark_class_instantiated): Split out from do_type_instantiation. + + * parse.y (template_instantiate_once): Call repo_template_used. + + * lex.c (lang_init): Call init_repo. + + * decl2.c: Handle flag_use_repository. + (finish_file): Call finish_repo. + + * decl.c (start_method): Call repo_template_used if this is a + template method. + + * Makefile.in (CXX_OBJS): Add repo.o. + (repo.o): Add dependencies. + + * Make-lang.in (CXX_SRCS): Add repo.c. + + * decl.c (start_function): If DECL_INTERFACE_KNOWN and + DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL. + + * typeck.c (build_binary_op_nodefault): Identify the invalid operand + types used. + + * decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN. + +Thu Mar 30 17:54:42 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Tidy up use of build_type + and result_type. When checking for comparison between signed + and unsigned, use result_type rather than the (possibly shortened) + type of op0. Also, don't warn about equality comparison of a + signed operand to an unsigned constant that fits in the signed + type. + + * method.c (do_build_copy_constructor): Reverse + current_base_init_list after we've built it up. + +Thu Mar 30 14:35:18 1995 Mike Stump <mrs@cygnus.com> + + * except.c (build_throw): Never warn about the value of throw not + being used. + +Thu Mar 30 13:16:54 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_start_catch_block): Check for bad catch parameter + declarations. + +Thu Mar 30 13:06:11 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if + DECL_EXTERNAL is not already set. + +Thu Mar 30 11:26:24 1995 Mike Stump <mrs@cygnus.com> + + * method.c (emit_thunk): Let poplevel know that the last level is + for a function so it can create a BLOCK_NODE and set DECL_INITIAL. + +Thu Mar 30 11:15:06 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN + here. + + * decl.c (grokdeclarator): OK, don't abort if we see a decl with + METHOD_TYPE. + (finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on + all deferred inlines. + +Wed Mar 29 19:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cp-tree.h (DECL_THIS_INLINE): New macro. + (DECL_NOT_REALLY_EXTERN): New macro. + (DECL_THIS_STATIC): New macro. + + * decl.c: Lose all references to current_extern_inline. Break + inline semantics into DECL_INLINE for actual inlining and + DECL_THIS_INLINE for the linkage wierdness. Use DECL_THIS_STATIC. + * decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to + emit an inline here. Associated changes. + * lex.c: Likewise. + * pt.c: Likewise. + * typeck.c: Likewise. + + * call.c (build_method_call): Don't bother trying to handle inlines + specially. + * cvt.c (convert_to_aggr): Likewise. + + * pt.c (do_function_instantiation): Handle instantiation of + public inlines, too. + +Wed Mar 29 16:04:25 1995 Mike Stump <mrs@cygnus.com> + + * except.c (init_exception_processing): Change the interface for + __throw_type_match and add decl for new rtti matching routine + __throw_type_match_rtti. + (build_eh_type): New routine to build a run time descriptor for the + expression given. + (expand_start_catch_block): Update to use new calling convention for + the matcher. + (expand_throw): Update to use build_eh_type. + +Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org> + + * g++.c: Removed __NetBSD__ from conditional. + Declare strerror if HAVE_STRERROR is defined; otherwise + declare sys_errlist and sys_nerr. + (my_strerror): New function. + +Tue Mar 28 14:16:35 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * search.c (get_binfo): Don't try to be so clever. + + * tree.c (copy_to_permanent): Also suspend_momentary(). + + * cvt.c (cp_convert_to_pointer): Hand off to convert_fn_pointer even + if the types are the same. + + * decl.c (start_function): Handle extern inlines more like C++ says + we should. + + * init.c (build_member_call): Hand constructor calls off to + build_functional_cast. + + * typeck2.c (build_functional_cast): Use DECL_NESTED_TYPENAME to get + the name of the type. + +Tue Mar 28 13:13:56 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Check for the decl returned by + grokfndecl to be null before using build_decl_attribute_variant. + +Mon Mar 27 18:04:41 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (build_new): Use build_pointer_type instead of + TYPE_POINTER_TO. + +Fri Mar 24 12:11:24 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_conditional_expr): Handle pmfs. + (convert_for_assignment): Fix pmf support. + + * cvt.c (convert_fn_ptr): Support !flag_vtable_thunks. + (cp_convert_to_pointer): Handle pmfs. + (cp_convert): Pass pmfs to cp_convert_to_pointer. + + * typeck.c (common_type): Handle inheritance for pmfs. + + * typeck2.c (build_m_component_ref): Do access control. + + * typeck.c (comp_target_types): Check for conversion to void * + before checking trickier conversions. + + * decl.c (duplicate_decls): Propagate DECL_ABSTRACT_VIRTUAL_P. + + * pt.c (push_tinst_level): Complain if template instantiation depth + is greater than max_tinst_depth. + + * typeck.c (common_type): Assume that we can call common_type to + unify the target type of a pointer. + +Thu Mar 23 00:48:44 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_file): Don't synthesize methods at + finish_vtable_prevardecl time. Do synthesize methods that are not + used, but are public and not external. + + * cvt.c (build_type_conversion): Only give an error if for_sure. + + * typeck.c (comp_target_types): Only support pointer conversions if + nptrs > 0. + +Wed Mar 22 19:30:15 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (build_new): Catch use of an initializer list where it + shouldn't be. + +Wed Mar 22 16:21:07 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_new): Wrap alloc_expr in an RTL_EXPR if nelts is + non-constant. + + * decl2.c: temp_name_counter is now public. + + * decl.c (struct cp_function): Add temp_name_counter field. + (push_cp_function_context): Save it. + (pop_cp_function_context): Restore it. + + * typeck.c (common_type): Handle unifying function types, and unify + unmatched things to void* with a compiler_error, rather than + silently like before. + +Wed Mar 22 15:10:34 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_prevtable_vardecl, finish_vtable_vardecl): Revert + Brendan's last change and fix latent problem that causes TD entries + to not come out when the things that need them has yet to be + expanded. + +Wed Mar 22 15:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_binary_op_nodefault, comparison ops): Update type0 + and type1, since we might have changed op0 or op1. + +Wed Mar 22 13:33:45 1995 Jason Merrill <jason@python.cygnus.com> + + * typeck.c (common_type): Don't mess up templates. + +Wed Mar 22 04:56:00 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (common_type): Handle ptms properly. Also handle + T* -> void*. + (build_binary_op_nodefault): New variable build_type controls what + type is given to the expression when it is created. Set this to + boolean_type_node for comparison ops instead of using result_type. + (comp_target_types): Allow T * -> void *. + + * cvt.c (cp_convert_to_pointer): Do access control when converting + ptms, too. + +Tue Mar 21 17:25:06 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (extern_lang_string): Catch use of linkage specs that + aren't all naming the same language. + + * class.c (finish_struct): Delete accidental duplicate code. + +Tue Mar 21 14:00:57 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Disable pedwarns about + comparing functions and incomplete types. + + * decl.c (finish_function): Only unset current_function_decl if + !nested. + (duplicate_decls): Last change went too far; we only want to stop + checking for value/reference ambiguity. + +Tue Mar 21 01:26:39 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (build_generic_desc): Zap the DECL_SIZE so that we can lay it + out fresh, as the new type may be larger. + +Mon Mar 20 19:01:10 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * expr.c (extract_init): Try to expand the RTL for the + initialization and figure out what it will look like so we can avoid + run-time initialization. Disabled for now. + (extract_scalar_init): Helper for scalar initialization. + (extract_aggr_init): Helper for aggregate initialization. + + * decl.c (duplicate_decls): Don't complain about ambiguous + declarations. + (obscure_complex_init): Now returns a tree. Call extract_init if + we're optimizing and this is a toplevel decl. + (finish_decl): Update accordingly. + + * lex.c (check_newline): If we're just changing files (not pushing + or popping), update input_file_stack->name. + +Mon Mar 20 17:55:04 1995 Mike Stump <mrs@cygnus.com> + + * pt.c (type_unification): Only TEMPLATE_DECLs are handled right now + in the transitive unification code. + +Mon Mar 20 16:07:50 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (shadow_tag): Don't allow inline, virtual, or explicit on + non-functions. + (grokdeclarator): Don't allow friends to be defined in local classes. + +Sat Mar 18 04:03:33 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_prevtable_vardecl): Use DECL_DECLARED_STATIC + rather than DECL_SAVED_INSNS to decide whether or not this method + was declared inline. + + * method.c (synthesize_method): Turn off DECL_INLINE if + function_cannot_inline_p thinks we're too large. + + * typeck.c (build_indirect_ref): Use build_expr_type_conversion. + +Fri Mar 17 17:47:36 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (instantiate_type): Handle pmfs. + + * typeck.c (convert_for_assignment): Check types when assigning one + pmf to another. + + * decl.c (define_label): Fix logic for printing out the name of the + label in an error message. + + * error.c (dump_expr): Support ARRAY_REF. + +Fri Mar 17 17:43:02 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl2.c (finish_vtable_vardecl): Call build_t_desc here. + (finish_prevtable_vardecl): Instead of here. + +Fri Mar 17 14:40:45 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (expand_static_init): Also use expand_aggr_init if the + initializer is a TREE_LIST. + (grokdeclarator): Only pedwarn about extra qualification if -pedantic. + + * pt.c (unify): Fix unification of return type. + + * expr.c (fixup_result_decl): Use store_expr, rather than + emit_move_insn, to move the return value into the place where + callers will expect it. + +Thu Mar 16 22:05:25 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_offset_ref): Call assmble_external on functions. + * typeck.c (build_component_ref): Likewise. + +Thu Mar 16 20:28:16 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (struct saved_scope): Add members base_init_list and + member_init_list. + (push_to_top_level): Save current_base_init_list and + current_member_init_list to them. + (pop_from_top_level): Put it back. + +Thu Mar 16 19:21:14 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (instantiate_template): Call assemble_external. + +Thu Mar 16 18:07:54 1995 Brendan Kehoe <brendan@phydeaux.cygnus.com> + + * class.c: Include rtl.h, to get NULL_RTX. + (finish_struct): Also zero out DECL_SAVED_INSNS, to avoid problems + on hosts with different sizes for each part of the union. + * tree.c: Also include rtl.h. + (layout_basetypes): Same change for DECL_SAVED_INSNS. + +Thu Mar 16 13:57:36 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (unify): Fix array domain unification for 64-bit targets. + + * decl2.c (finish_file): Push bizarre type decl before walking the + vtables the first time. + (walk_vtables): OK, don't set prev to vars if the vardecl_fn messed + with TREE_CHAIN (prev). + + * init.c (emit_base_init): Use convert_pointer_to_real instead of + convert_pointer_to when converting to a direct base. + +Wed Mar 15 20:26:29 1995 Mike Stump <mrs@cygnus.com> + + * pt.c (type_unification): Handle transitive unification better. + +Wed Mar 15 13:56:16 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (walk_vtables): Always set prev to vars. + (mark_vtable_entries): Call assemble_external on the vtable entries. + + * class.c (finish_struct): Set the vtable's size to NULL_TREE before + calling layout_decl, so that it gets updated properly. + + Finally re-enable dynamic synthesis. This time it works. + * method.c (synthesize_method): Pass decl_function_context (fndecl) + to {push,pop}_cp_function_context. + * decl.c (push_cp_function_context): Now takes a tree argument. + (pop_cp_function_context): Likewise. + * call.c (build_method_call): Enable synthesis. + * lex.c (cons_up_default_function): Likewise. + +Tue Mar 14 19:14:19 1995 Doug Evans <dje@chestnut.cygnus.com> + + * parse.y (setattrs): Chain onto prefix_attributes rather than + setting it. + +Wed Mar 15 13:00:00 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (pushdecl): Check if the type of the VAR_DECL is an + error_mark_node before trying to read TYPE_LANG_SPECIFIC. + +Mon Mar 13 21:00:28 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold, + and convert the size and integer_one_node to the index type. + +Mon Mar 13 08:01:02 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (get_member_function_from_ptrfunc): Save the instance + argument, and tack it onto the front of the COND_EXPR to make the + semantics come out right. Grab the instance argument from + '*instance_ptrptr', rather than having it passed in separately. + + * various: Change various consed-up comparison operations to have + boolean type. Remove the instance argument in calls to + get_member_function_from_ptrfunc. + + * error.c (dump_expr): Dump true and false as "true" and "false". + + * decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the + global init function. + + * decl.c (finish_function): Only set DECL_EXTERNAL here if the + inline function is public. + +Sat Mar 11 00:58:03 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (is_friend): Be more careful about checking + DECL_CLASS_CONTEXT on non-member functions. + + * decl2.c (finish_vtable_vardecl): Don't bother calling + assemble_external here. + (prune_vtable_vardecl): New function that just splices out the + vtable decl from the top-level decls. + (import_export_inline): Unset DECL_EXTERNAL at first. + (finish_file): Don't bother calling assemble_external here. Do + splice out all of the vtables. + +Fri Mar 10 14:42:29 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (finish_function): If we're not emitting the function yet, + call assemble_external for it. + + * decl2.c (finish_prevtable_vardecl): Don't call mark_vtable_entries + here. + (finish_vtable_vardecl): Don't do the linkage deduction thing here. + Also don't splice out the current vtable if it is unused. + (finish_file): Move the second walk_vtables and the synthesis check + inside the 'reconsider' loop. Move thunk emission after the + 'reconsider' loop. + +Thu Mar 9 16:28:16 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * pt.c (tsubst): Don't bother calling cp_build_type_variant, since it + was passing bogus values for readonly and volatile from the original + template decl, not the resultant type of the tsubst call. + + * class.c (duplicate_tag_error): Use cp_error_at to point out the + previous definition of the tag. + +Thu Mar 9 10:46:17 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (start_function): Clear base_init_insns and protect_list. + (struct cp_function): Add base_init_insns field. + (push_cp_function_context): Also save base_init_insns. + (pop_cp_function_context): Also restore base_init_insns. + +Wed Mar 8 13:31:44 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (member_init_ok_or_else): Check for initializing a static + member here. + (emit_base_init): Instead of here. + +Tue Mar 7 16:03:26 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Disable synthesis as needed. + * lex.c (cons_up_default_function): Likewise. + +Tue Mar 7 10:14:29 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y: New rules to allow attributes in a prefix position. + (prefix_attributes): New variable. Pass it into cplus_decl_attributes. + (setattr): New rule. + (reserved_declspecs, declmods): Catch attributes here. + * decl2.c (cplus_decl_attributes): Add PREFIX_ATTRIBUTES argument. + * decl.c (duplicate_decls): Pass DECL_MACHINE_ATTRIBUTES to + descendent typedef. + (grokdeclarator): Added code to support machine attributes. + * Makefile.in (stamp-parse): Expect 5 shift/reduce failures. + +Mon Mar 6 15:07:02 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Don't synthesize methods outside of a + function. + + Make base initialization more re-entrant so that synthesis on the + fly will work (and, eventually, template instantation on the fly). + * init.c (sort_member_init): Don't bother with members that can't be + initialized. Reorganize a bit. Don't initialize base members here. + (sort_base_init): New function, like sort_member_init, but for base + classes. Steals some code from emit_base_init. + (emit_base_init): Simplify. Call sort_{member,base}_init before + doing any initialization, so we don't have to save + current_{member,base}_init_list in push_cp_function_context. + (expand_aggr_vbase_init_1): Adjust for sort_base_init. + (expand_aggr_vbase_init): Simplify. + * decl.c (struct cp_function): Add protect_list field. + (push_cp_function_context): Also save protect_list. + (pop_cp_function_context): Also restore protect_list. + * call.c (build_method_call): Enable synthesis at point of call. + * lex.c (cons_up_default_function): Likewise. + + * parse.y: Turn -ansi checks back into -pedantic checks. + + * init.c (build_new): Fix -fcheck-new for array new. + +Sat Mar 4 15:55:42 1995 Fergus Henderson <fjh@cs.mu.oz.au> + + * typeck.c (build_compound_expr): warn if left-hand operand of + comma expression has no side-effects. + +Fri Mar 3 15:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y (primary): Change 'object qualified_id *' rules to 'object + overqualified_id *'. + +Fri Mar 3 12:48:17 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (unary_expr): Catch doing sizeof an overloaded function. + Make the error look the same as the one we issue in c_sizeof. + + * typeck.c (build_binary_op_nodefault): Give an error for trying + to compare a pointer-to-member to `void *'. + +Fri Mar 3 11:28:50 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_unary_op): Handle bool increment with smoke and + mirrors here, rather than in expand_increment where it belongs, + because Kenner doesn't agree with me. + +Fri Mar 3 00:08:10 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokparms): Catch a PARM_DECL being used for a default + argument as well. + +Thu Mar 2 20:05:54 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * init.c (build_new): Don't allow new on a function type. + + * parse.y (primary): Avoid a crash when seeing if the arg is of + the same type as that given for the typespec in an explicit dtor call. + +Thu Mar 2 00:49:38 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (finish_function): Change test for calling + mark_inline_for_output. + +Wed Mar 1 11:23:46 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_modify_expr): Complain if + build_default_binary_type_conversion fails. + + * init.c (expand_default_init): Handle arguments of unknown type + properly. + + * cvt.c (build_expr_type_conversion): Only complain about ambiguity + if 'complain'. + * various: Pass 'complain'. + + * typeck.c (comptypes): Be more picky about comparing UPTs. + +Wed Mar 1 11:03:41 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): If declarator is null, say that the + type used has an incomplete type. + +Wed Mar 1 10:06:20 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (instantiate_template): Copy the template arguments to the + permanent_obstack. Also use simple_cst_equal to compare them when + looking for a previous instantiation. + + * tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming + they are array domain types). + +Tue Feb 28 23:24:55 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cp-tree.h: Define WANT_* constants for passing to + build_expr_type_conversion. + * cvt.c (build_expr_type_conversion): New function to build + conversion to one of a group of suitable types. + (build_default_binary_type_conversion): Use it. + * decl2.c (grok_array_decl): Likewise. + * typeck.c (build_unary_op): Likewise. + (build_array_ref): Tidy up a bit. + (build_binary_op): Likewise. + +Tue Feb 28 19:57:31 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Don't allow decl of an argument as `void'. + +Tue Feb 28 17:23:36 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals + reserved_declspecs' rule. + + * parse.y (expr_or_declarator): Remove notype_qualified_id rule. + (direct_notype_declarator): Likewise. + (complex_direct_notype_declarator): Add notype_qualified_id rule. + + * lex.c (real_yylex): Handle :> digraph properly. + +Tue Feb 28 12:26:29 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Check if it's a friend, not if it's + non-virtual, that's being initialized. Move the check up to + before FRIENDP would get cleared. Catch an unnamed var/field + being declared void. Say just `field' instead of `structure field' + in the error message. Only go for the operator name if DECLARATOR + is non-null. + +Tue Feb 28 00:08:01 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (start_function): Complain about abstract return type. + (grokdeclarator): Complain about declaring constructors and + destructors to be const or volatile. Complain about declaring + destructors to be static. + + * pt.c (uses_template_parms): Handle pmfs. + + * decl.c (grokdeclarator): Don't call variable_size for array bounds + that only depend on template constant parameters. + +Mon Feb 27 15:38:16 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * error.c (dump_decl): Only look to see if it's a vtable if we + actually have a name to check out. + +Mon Feb 27 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (convert_to_aggr): Lose misleading shortcut. + +Sun Feb 26 17:27:32 1995 Doug Evans <dje@canuck.cygnus.com> + + * decl.c (set_nested_typename): Always set DECL_IGNORED_P, + not just for dwarf. + +Sun Feb 26 00:10:18 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Don't allow a static member to be + declared `register'. + + * init.c (make_friend_class): Move up to a pedwarn for the warning + about a class declaring friends with itself. + + * decl.c (grokdeclarator): You can't do `volatile friend class foo' + or `inline friend class foo'. Only try to make a friend out of + TYPE if we didn't already reset it to integer_type_node. + +Sat Feb 25 22:32:03 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Don't allow initialization of a + non-virtual function. + + * decl.c (start_function): Do a pedwarn if we're changing `main' + to have an int return type. + +Sat Feb 25 00:02:05 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_modify_expr): Handle simple assignment from + TARGET_EXPRs by building up an RTL_EXPR to force expansion. Whew. + +Fri Feb 24 18:27:14 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Also don't allow virtual outside of a + class decl for a scope method definition performed at global binding. + + * init.c (build_offset_ref): Don't allow creation of an OFFSET_REF + of a bitfield. + + * decl.c (grokdeclarator): Don't allow a const to be declared mutable. + + * typeck.c (build_binary_op): Return an error_mark_node if either + one of the args turned into an error_mark_node when we tried to + use default_conversion. + + * typeck.c (build_unary_op): Forbid using postfix -- on a bool. + + * decl.c (grokdeclarator): Allow `signed' and `unsigned' to be + used on `__wchar_t'. + +Fri Feb 24 13:59:53 1995 Mike Stump <mrs@cygnus.com> + + * except.c (end_protect_partials): Do it the right way. + +Wed Feb 22 15:42:56 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Upgrade warning about + comparing distinct pointer types to pedwarn. + + * typeck2.c (digest_init): Cope with extra braces. + + * typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead + of INT_CST_LT (..., interger_zero_node). + +Wed Feb 22 14:45:52 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy + function for systems that don't have EH. + +Tue Feb 21 19:18:31 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (can_convert_arg): Like can_convert, but takes an arg as + well. + + * pt.c (type_unification): Allow implicit conversions for parameters + that do not depend on template parameters. + +Tue Feb 21 18:43:48 1995 Douglas Rupp <drupp@cs.washington.edu> + + * Make-lang.in, config-lang.in: ($exeext): New macro. + * Make-lang.in: Try a "cp" if "ln" fails. + * cp-tree.h (decl_attributes): Added argument. + * decl2.c (cplus_decl_attribute): Add arg to decl_attributes. + * cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT. + Modified spawnvp to have to correct number of arguments for OS/2, NT. + +Tue Feb 21 18:36:55 1995 Mike Stump <mrs@cygnus.com> + + * decl.c (finish_function): Add calls to end_protect_partials to end + the exception region that protects constructors so that partially + constructed objects can be partially destructed when the constructor + throws an exception. + * init.c (perform_member_init, sort_member_init, emit_base_init): + Added support for partially constructed objects. + * init.c (build_partial_cleanup_for): New routine to do partial + cleanups of a base class. + * decl2.c (finish_file): Move the emitting of the exception table + down, after we emit all code that might have exception regions in + them. + * except.c (end_protect_partials, might_have_exceptions_p): New + routines. + (emit_exception_table): Always output table if called. + * cp-tree.h (protect_list, end_protect_partials, + might_have_exceptions_p, emit_exception_table): Added. + +Tue Feb 21 16:05:59 1995 Brendan Kehoe <brendan@lisa.cygnus.com> + + * gc.c (build_typeid): Pass a NULL_TREE, not the bogus, unused + address of a local variable. + * class.c (build_vfn_ref): Only try to build the PLUS_EXPR if we + were given a non-null PTR_TO_INSTPTR. + +Tue Feb 21 01:53:18 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (duplicate_decls): Always lay out the merged decl. + + * decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates. + (finish_prevtable_vardecl): Likewise. + + * method.c (synthesize_method): Set interface_{unknown,only} + according to the settings for our class, not the file where it comes + from. + +Sat Feb 18 12:26:48 1995 Mike Stump <mrs@cygnus.com> + + * except.c: Handle systems that define __i386__ but not __i386. + +Fri Feb 17 15:31:31 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (reparse_decl_as_expr): Support being called without a + type argument. + + * parse.y (primary): Add '(' expr_or_declarator ')'. Adds 4 r/r + conflicts. Sigh. + +Fri Feb 17 12:02:06 1995 Mike Stump <mrs@cygnus.com> + + * parse.y (template_def, fndef, fn.def1, return_init, condition, + initdcl0, initdcl, notype_initdcl0, nomods_initdcl0, + component_decl_1, after_type_component_declarator0, + notype_component_declarator0, after_type_component_declarator, + notype_component_declarator, after_type_component_declarator, + full_parm, maybe_raises, exception_specification_opt): Fix up, + include exception_specification_opt maybeasm maybe_attribute and + maybe_init if missing. Rename maybe_raises to + exception_specification_opt to match draft wording. Use maybe_init + to simplify rules. + +Fri Feb 17 01:54:46 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_new): Set TREE_NO_UNUSED_WARNING on COMPOUND_EXPRs + built for news of scalar types. + +Thu Feb 16 17:48:28 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Update code for warning + about signed/unsigned comparisons from C frontend. Realize that the + code in the C frontend is, if anything, even more bogus. Fix it. + (build_binary_op): Undo default_conversion if it wasn't useful. + + * typeck.c (build_unary_op, ADDR_EXPR): Lose bogus special case for + PRE*CREMENT_EXPR. + + * decl2.c (import_export_vtable): Don't try the vtable hack + if the class doesn't have any real non-inline virtual functions. + (finish_vtable_vardecl): Don't bother trying to find a non-inline + virtual function in a non-polymorphic class. + (finish_prevtable_vardecl): Likewise. + + * decl2.c (import_export_vtable): Use and set DECL_INTERFACE_KNOWN. + + * cp-tree.h (DECL_INTERFACE_KNOWN): Use DECL_LANG_FLAG_5. + + * init.c (expand_virtual_init): Always call assemble_external. + + * class.c (build_vfn_ref): Always call assemble_external. + (build_vtable): Always call import_export_vtable. + (prepare_fresh_vtable): Likewise. + (add_virtual_function): Don't bother setting TREE_ADDRESSABLE. + +Thu Feb 16 03:28:49 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine + whether an enumerated type fits in a bitfield. + +Wed Feb 15 15:38:12 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (grow_method): Update method_vec after growing the class + obstack. + +Wed Feb 15 13:42:59 1995 Mike Stump <mrs@cygnus.com> + + * parse.y (handler_seq): Push a level for the catch parameters. + +Wed Feb 15 12:42:57 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my + bases, in case they've been clobbered. + +Wed Feb 15 12:07:29 1995 Mike Stump <mrs@cygnus.com> + + * class.c (finish_base_struct): Set up BINFO_INHERITANCE_CHAIN here, + so that one day it will always be valid. + * tree.c (propagate_binfo_offsets, layout_vbasetypes): Likewise. + + * cp-tree.h (copy_binfo): Removed, unused. + * tree.c (copy_binfo): Likewise. + +Wed Feb 15 00:05:30 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_new): Save the allocation before calling + expand_vec_init on it. + + * decl.c (finish_enum): The TYPE_PRECISION of the enum type mush + match the TYPE_PRECISION of the underlying type for constant folding + to work. + +Tue Feb 14 15:31:25 1995 Mike Stump <mrs@cygnus.com> + + * except.c (push_eh_entry, expand_start_all_catch, + expand_leftover_cleanups, expand_end_catch_block): Keep track of + the context in which the exception region occurs. + (build_exception_table): If the region was not output, don't output + the entry in the eh table for it. + +Tue Feb 14 02:15:43 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (expand_default_init): Only use a previous constructor call + if it's a call to our constructor. Does the word "Duh" mean + anything to you? + + * decl.c (grokparms): Fine, just don't call + convert_for_initialization at all. OK? Happy now? + +Mon Feb 13 02:23:44 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class + method vector has a second element before returning it. + + * decl.c (grokparms): Don't strip REFERENCE_TYPE before calling + convert_for_initialization. + +Sun Feb 12 03:57:06 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_modify_expr): Compare function name to + constructor_name (current_class_type) instead of current_class_name. + + * decl.c (grokparms): Don't do anything with the return value of + convert_for_initialization. + + * error.c (dump_decl): Also dump_readonly_or_volatile on the decl. + + * decl.c (duplicate_decls): Tweak error message. + + * typeck.c (build_const_cast): Implement checking. + (build_reinterpret_cast): Implement some checking. + + * cp-tree.h (CONV_FORCE_TEMP): Require a new temporary when + converting to the same aggregate type. + (CONV_STATIC_CAST): Include it. + (CONV_C_CAST): Likewise. + * cvt.c (convert_force): Use CONV_C_CAST instead of CONV_OLD_CONVERT. + (cp_convert): Only force a new temporary if CONV_FORCE_TEMP. + +Fri Feb 10 16:18:52 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_c_cast): Use non_lvalue to tack something on + where necessary. + + * decl.c (auto_function): Now a function. + * except.c (init_exception_processing): terminate, unexpected, + set_terminate, and set_unexpected have C++ linkage. + + * typeck.c (build_unary_op, TRUTH_NOT_EXPR): Use convert instead of + truthvalue_conversion for converting to bool, as it handles + user-defined conversions properly. + (condition_conversion): Likewise. + + * except.c (expand_throw): Don't call convert_to_reference. + Pass the correct parameters to build_new. + + * method.c (do_build_assign_ref): Don't use access control when + converting to a base reference here. + (do_build_copy_constructor): Or here. + + * init.c (build_new): Unset TREE_READONLY on the dereferenced + pointer before assigning to it. + + * decl.c (maybe_build_cleanup): Don't bother stripping const here. + + * decl2.c (delete_sanity): You can now delete pointer to const. + +Fri Feb 10 13:28:38 1995 Jason Merrill <jason@python.cygnus.com> + + * decl.c (finish_function): Don't rely on actual parameters being + evaluated left-to-right. + * except.c (expand_end_catch_block): Likewise. + +Fri Feb 10 00:52:04 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * tree.c (real_lvalue_p): Like lvalue_p, but class temps aren't + considered lvalues. + * cvt.c (convert_to_reference): Use real_lvalue_p instead of + lvalue_p. + + * cvt.c (build_type_conversion_1): Don't call convert on aggregate + types. + (convert_to_reference): Fix erroneous text substitution. + + * typeck2.c (initializer_constant_valid_p): Update from C frontend. + Add new argument to all callers. + + * typeck.c (convert_arguments): Check for error_mark_node before + trying to do anything with the actual parameter. + + * typeck.c (condition_conversion): Build up a CLEANUP_POINT_EXPR and + fold it. + (bool_truthvalue_conversion): Remove. Fix all callers to call + truthvalue_conversion instead. + (various): Fold CLEANUP_POINT_EXPRs. + + * parse.y (conditions): Call condition_conversion rather than + building up a CLEANUP_POINT_EXPR. + + * pt.c (end_template_decl): Don't warn_if_unknown_interface here + under -falt-external-templates. + +Thu Feb 9 05:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_new): Complain about new of const type without + initializer. Other cleanup. + + * call.c (compute_conversion_costs): Don't call + build_type_conversion with a reference type; convert to the target + type and check its lvaluetude. + * cvt.c (convert_to_reference): Likewise. + + * cvt.c (build_type_conversion_1): There will never be any need to + dereference references here now. + +Thu Feb 9 00:37:47 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_builtin_throw): Make sure we only `use' the + value of return_val_rtx. + +Wed Feb 8 15:45:55 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y (structsp): Don't complain about declaring a type being + defined to be a friend. + + * decl2.c (warn_if_unknown_interface): Note the template in question + and the point of instantiation, for -falt-external-templates. + * lex.c (reinit_parse_for_method): Pass the decl to + warn_if_unknown_interface. + * pt.c (instantiate_template): Likewise. + (end_template_decl): Likewise. + + * decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the + nested name again, to make local classes work a bit better. + + * typeck.c (build_function_call_real): Dereference reference after + checking for incomplete type. + + * init.c (build_new): Accept new of const and volatile types. + +Wed Feb 8 14:04:16 1995 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Fix error message. + +Wed Feb 8 03:16:15 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (convert_for_initialization): Do bash arrays when + converting to a reference to non-array. + +Tue Feb 7 15:50:33 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (cp_convert): Don't call convert_to_reference, or + automatically dereference references. Do pass reference conversions + to cp_convert_to_pointer. + (cp_convert_to_pointer): Support references. + + * call.c (build_method_call): Don't build up a reference to the + parameter here; let build_overload_call handle that. + + * typeck.c (build_c_cast): Call convert_to_reference directly if + converting to a reference type. + * method.c (do_build_copy_constructor): Likewise. + * method.c (do_build_copy_constructor): Likewise. + (do_build_assign_ref): Likewise. + + * call.c (build_method_call): Dereference a returned reference. + * typeck.c (build_function_call_real): Likewise. + + * decl.c (xref_basetypes): Check for unions with basetypes here. + (xref_tag): Instead of here. + + * pt.c (process_template_parm): Template type parm decls are + artificial. + +Mon Feb 6 04:32:09 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y (typed_declspecs): Add missing semicolon. + (do_xref_defn): Resurrect. + (named_class_head_sans_basetype): Move template specialization + definition cases to named_class_head_sans_basetype_defn. + + * decl2.c (grokfield): Call pushdecl_class_level after setting the + TYPE_NAME, not before. + +Sun Feb 5 02:50:45 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (convert_harshness): Don't call sorry here. Don't allow + conversions between function pointer types if pedantic. + + * pt.c (overload_template_name): Pass globalize=1 to xref_tag. + + * lex.c (cons_up_default_function): Use the full name for the return + type of op=. + + * decl.c (set_nested_typename): Don't worry about anonymous types, + as they already have a unique name. + (pushdecl): Remove redundant set_nested_typename + (xref_tag): Split out base handling into xref_basetypes. + + * cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are + not considered incomplete even though their definition is unknown. + + * decl.c (xref_defn_tag): Lose. + (xref_tag): xref_next_defn = ! globalize. + (pushdecl): Don't set DECL_NESTED_TYPENAME on artificial decls. The + ones that should have it set will have it set by pushtag. + (pushdecl_class_level): Likewise. + (pushtag): Tidy up a bit. + (set_nested_typename): Push a decl for the nested typename from + here, rather than from xref_defn_tag. + + * parse.y (do_xref): Lose. + (named_class_head): If we see 'class foo:' we know it's a + definition, so don't worry about base lists for non-definitions. + + * pt.c (push_template_decls): Template parm decls are artificial. + + * decl.c (duplicate_decls): Restore check for qualifier + disagreement for non-functions. + (decls_match): Remove check for qualifier disagreement. + +Fri Feb 3 14:58:58 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (grok_reference_init): Convert initializer from + reference. + * typeck.c (convert_for_initialization): Likewise. + + * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME. + + * cvt.c (cp_convert): Don't convert to the same class type by just + tacking on a NOP_EXPR. + (convert_to_reference): Use comp_target_types instead of comptypes + so that we don't allow conversions two levels down. + +Thu Feb 2 15:07:58 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (build_vbase_path): Bash types to make the backend happy. + * cvt.c (build_up_reference): Bash the types bashed by + build_vbase_path to be reference types instead of pointer types. + (convert_to_reference): Likewise. + + * typeck.c (build_c_cast): Don't strip NOPs if we're converting to a + reference type. + + * parse.y (structsp): Put back error for 'struct B: public A;'. + +Wed Feb 1 23:02:06 1995 Mike Stump <mrs@cygnus.com> + + * except.c: Add support for mips systems that don't define __mips + but do define mips, like Ultrix. + +Wed Feb 1 22:39:07 1995 Mike Stump <mrs@cygnus.com> + + * except.c: Add support for exception handling on the Alpha. + +Wed Feb 1 10:12:14 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_file): Fix bug in Jan 31st change. + +Tue Jan 31 16:59:15 1995 Gerald Baumgartner <gb@lorenzo.cs.purdue.edu> + + * sig.c (build_signature_pointer_or_reference_type): Don't set + IS_AGGR_TYPE for signature pointers/reference so expand_default_init + doesn't expect to find a copy constructor. + * call.c (build_method_call): Treat signature pointers/reference + as if IS_AGGR_TYPE were set. + +Tue Jan 31 13:28:56 1995 Mike Stump <mrs@cygnus.com> + + * gc.c (get_typeid): Pawn off error messages to build_t_desc. + (build_t_desc): Inform the user here if they try and build + with -frtti and don't include <typeinfo.h>. + + * decl2.c (finish_prevtable_vardecl): Support rescanning. + (finish_file): Move finish_prevtable_vardecl up to before the global + initializers are done as tdecls are initialized in the global + initializer. Also Pick up any new tdecls or vtables needed by + synthesized methods. + + * class.c (finish_struct): Simplify. We have to do rtti scanning at + end, so we might as well do all of it there. + +Tue Jan 31 05:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Fix -fthis-is-variable for 32-bit + targets, too. + +Tue Jan 31 00:11:04 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_prevtable_vardecl): New routine, mostly split from + finish_vtable_vardecl. It has the first half functionality from + that routine. + * decl2.c (finish_vtable_vardecl): Update to not include stuff not + in finish_prevtable_vardecl. + * decl2.c (finish_file): Call finish_prevtable_vardecl. + * gc.c (build_generic_desc): Allow it to be called when not at the + global binding layer, but behave as if we were. + (build_t_desc): Rearrange a bit so that it really works and is + easier to follow. + * class.c (finish_struct): Don't decide on tdecls here, as we have + to wait until the end of the file in general to decide whether or + not they come out. + +Mon Jan 30 01:00:40 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_delete): Check access to operator delete before + calling the destructor. + * method.c (build_opfncall, DELETE_EXPR): build_method is allowed to + return error_mark_node. + * call.c (build_method_call): Use the one-argument op delete even if + it's an error. + + * init.c (build_new): Fix -fthis-is-variable support. + * call.c (build_method_call): Likewise. + + * call.c (convert_harshness): Make conversion from a pointer to bool + worse than conversion to another pointer. + +Sat Jan 28 16:46:10 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (build_new): Check new return value if -fcheck-new. + + * lex.c (check_newline): Clear end_of_file when we're done, too. + +Sat Jan 28 10:38:39 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_vtable_vardecl): Make rtti TD tables follow + vtables whereever they go. + + * gc.c (build_t_desc): Remove old way of setting it up, as it wasn't + right. + +Sat Jan 28 09:10:44 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (finish_vtable_vardecl): Now set the + interface/implementation of vtables on the first virtual function, + if one exists, otherwise we use the old method. This is a major win + in terms of cutting down the size of objects and executables in + terms of text space and data space. Now most of the savings that + #pragma interface/implementation gives is automatic in a fair number + of cases. + +Sat Jan 28 04:57:33 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (grokdeclarator): Discard the template parameters in a + template constructor declaration so that the function is always + named constructor_name (ctype). + + * lex.c (check_newline): Use ungetc to put back the character before + calling HANDLE_PRAGMA. + +Fri Jan 27 17:23:47 1995 Mike Stump <mrs@cygnus.com> + + * decl2.c (check_classfn): If the cname is T<int> and fn_name is T, + make sure we still match them. + +Fri Jan 27 16:32:10 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y: Add END_OF_LINE token. + + * lex.c (check_newline): Set linemode when we see a # directive, and + unset it when we're done. Turn all 'return's into 'goto skipline'. + Fix all uses of '\n', since we won't see it anymore. Put back the + character we read before checking for a sysv or target pragma. + (real_yylex): If we see an EOF in linemode, return END_OF_LINE. + (handle_sysv_pragma): Don't look at the input stream; quit when we + see an END_OF_LINE token. + + * input.c (getch): Return EOF if we're in line mode and at the end + of a line. + (put_back): Don't put back an EOF. + +Thu Jan 26 19:26:34 1995 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Do the newing of the exception object + before we load the type descriptor or the address so that we don't + wipe any of the values out. + +Thu Jan 26 19:20:00 1995 Mike Stump <mrs@cygnus.com> + + * except.c (init_exception_processing): Don't use r12 on the rs6000. + +Tue Jan 24 16:36:31 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (grokparms): Don't try to build up a reference at this point. + + * typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR + will suffice to convert from integer_zero_node. + +Wed Jan 25 15:02:09 1995 David S. Miller <davem@nadzieja.rutgers.edu> + + * class.c (instantiate_type): Change error message text. + * typeck2.c (store_init_value): Likewise. + +Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com> + + * pt.c (tsubst): When we copy a node, don't forget to copy + TREE_CHAIN, we use it later. + +Mon Jan 23 03:33:47 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (convert_for_assignment): Initialize variable before use. + +Fri Jan 20 01:17:59 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * g++.c (main): Link with both libstdc++ and libg++ if called as + something ending with "g++", otherwise only libstdc++. Move -lm to + the end of the line. + +Thu Jan 19 15:43:11 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Don't mess with 'this' before calling + compute_conversion_costs. + +Wed Jan 18 15:40:55 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * search.c (get_matching_virtual): Give line number for previous + declaration. + + * call.c (convert_harshness): Handle conversions to references + better. + + * cvt.c (build_up_reference): OK, handle {MIN,MAX}_EXPR *properly*. + +Wed Jan 18 15:21:38 1995 Mike Stump <mrs@cygnus.com> + + * class.c (instantiate_type): Use DECL_CHAIN to walk lists instead, + as the TREE_CHAIN for methods will take us to the next differently + named function, DECL_CHAIN won't. + +Wed Jan 18 14:26:59 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * tree.c (lvalue_p): Handle {MIN,MAX}_EXPR. + + * decl2.c (lang_decode_option): -Wall implies -Wparentheses. + warn_parentheses defaults to 0. + + * decl.c (grokparms): Put back call to require_instantiated_type. + +Tue Jan 17 19:56:15 1995 Mike Stump <mrs@cygnus.com> + + * except.c (exception_section): Use the data section on the rs6000. + Change calling convention for named_section. + +Wed Jan 17 18:20:57 1994 Fergus Henderson <fjh@munta.cs.mu.oz.au> + + * cp-tree.h : Make if (x=0) warn with wall + * parse.y : Make if (x=0) warn with wall + +Tue Jan 17 14:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (BOOL_TYPE_SIZE): BITS_PER_WORD if SLOW_BYTE_ACCESS, + BITS_PER_UNIT otherwise. + + * search.c (get_matching_virtual): Don't check the binfo if the + types are the same. + + * cvt.c (cp_convert): Just call truthvalue_conversion to convert to + bool. + +Mon Jan 16 13:28:48 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * various: Use boolean_type_node, boolean_true_node, + boolean_false_node. + + * search.c (get_matching_virtual): Allow covariant returns that + don't require pointer adjustment. + + * typeck.c (build_conditional_expr): Don't call default_conversion + on ifexp. + + * cvt.c (build_up_reference): Handle MIN_EXPR and MAX_EXPR. + + * decl.c (grokdeclarator): Upgrade warning about &const to pedwarn. + +Sun Jan 15 22:17:32 1995 David Binderman <dcb@lovat.fmrco.COM> + + * pt.c (do_function_instantiation): Free targs once we're done. + +Sun Jan 15 22:17:32 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD. + (init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE + for bool. + +Sat Jan 14 05:33:55 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_file): We need to mess up if there are any + variables in the list, not just if there is one with a constructor. + +Fri Jan 13 14:42:55 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (duplicate_decls): Propagate DECL_STATIC_{CON,DE}STRUCTOR. + (finish_function): Handle DECL_STATIC_{CON,DE}STRUCTOR. + (finish_function): Trust rest_of_compilation. + + * decl2.c (finish_file): Also call functions designated as static + constructors/destructors. + + * decl.c (grokdeclarator): Allow access decls of operator functions. + (grokparms): Only do convert_for_initialization if the initializer + has a type. + (duplicate_decls): Put back push_obstacks_nochange call. + + * lex.c (real_yylex): Downgrade complaint about the escape sequence + being too large from pedwarn to warning. + + * decl.c (grokdeclarator): Don't complain about long long in system + headers. + + * lex.c (real_yylex): Handle digraphs. + +Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (init_decl_processing): -f{no-,}strict-prototype only + affects C linkage declarations now. + + * typeck.c (comp_target_types): Grok simple contravariant conversions. + (common_type): t1 and t2 are interchangeable. + + * various: Test return value of comp_target_types differently in + different places; it now returns -1 for a contravariant conversion + (which is fine in symmetric cases). + + (common_type): Prefer long double to double even when + they have the same precision. + + * decl.c (grokparms): Call convert_for_initialization to check + default arguments. + + * init.c (build_new): void_type_node has a size (of 0). + + * decl.c (decls_match): Also check for agreement of TREE_READONLY + and TREE_THIS_VOLATILE. + (push_class_level_binding): Properly handle shadowing of + nested tags by fields. + + * search.c (dfs_pushdecls): Likewise. + + * decl2.c (finish_file): Don't second-guess self-initialization. + + * cvt.c (convert_to_reference): Work with expr directly, rather than + a copy. + + * decl.c (push_overloaded_decl): Only shadow artificial TYPE_DECLs. + + * init.c (add_friend): Downgrade duplicate friend message from + pedwarn to warning. + + * decl.c (duplicate_decls): Push obstacks before calling common_type. + +Thu Jan 12 17:15:21 1995 Michael Ben-Gershon <mybg@cs.huji.ac.il> + + * except.c (push_eh_entry): set LABEL_PRESERVE_P flag for + exception table labels. + (expand_start_all_catch): Likewise. + (expand_leftover_cleanups): Likewise. + (expand_end_catch_block): Likewise. + * except.c (make_first_label): new function. + (expand_start_all_catch): add a call to make_first_label() before + using a label as a jump destination. + (expand_end_all_catch): Likewise. + (expand_leftover_cleanups): Likewise. + (expand_end_catch_block): Likewise. + (expand_builtin_throw): Likewise. + (expand_throw): Likewise. + * except.c: Add ARM processor support for exception handling. + +Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + (complete_array_type): Copy code from C frontend. + + * lex.c (real_yylex): Don't multiply the length of a wide string + literal by WCHAR_BYTES. + + * decl.c (pushdecl): Check for redeclaration of wchar_t here. + (duplicate_decls): Instead of here. + (define_label): Complain about a label named wchar_t. + (grokdeclarator): Complain about declarations of + operator-function-ids as non-functions. + + * typeck.c (unary_complex_lvalue): Also wrap prefix -- and ++ in + COMPOUND_EXPRs. + (build_unary_op): Wrap unary plus in a NON_LVALUE_EXPR. + + * lex.c (real_yylex): Don't skip whitespace when reading the next + character after ->. + +Wed Jan 11 16:32:49 1995 Mike Stump <mrs@cygnus.com> + + * except.c: Allow cc1plus to be built with native compiler on rs6000. + (expand_start_all_catch): Add assemble_external calls for various + routines we call. + (expand_leftover_cleanups): Likewise. + (expand_start_catch_block): Likewise. + (do_unwind): Likewise. + (expand_builtin_throw): Likewise. + +Wed Jan 11 01:05:42 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (pushtag): Only look for a previous decl in the current + binding level. Use explicit global scope in DECL_NESTED_TYPENAME. + + * gxx.gperf: Add __signature__ and __sigof__ keywords. + + * decl2.c (lang_decode_option): -ansi does not set flag_no_asm. It + does set flag_no_gnu_keywords and flag_operator_names. + + * lex.c (init_lex): 'overload' is not a keyword unless -traditional. + Unset extension keywords if -fno-gnu-keywords. + Allow operator names ('bitand') if -foperator-names. + Never unset 'asm'; -fno-asm only affects 'typeof'. + + * decl.c (lookup_name_real): The got_object special lookup only + applies to types. + +Tue Jan 10 18:07:51 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set. + + * parse.y (primary): Unset got_object after all rules that use the + 'object' nonterminal. + (object): Set got_object. + + * lex.h: Declare got_object. + + * decl.c (lookup_name_real): Also lookup names in the context of an + object specified. + +Tue Jan 10 14:30:30 1995 Mike Stump <mrs@cygnus.com> + + * typeck.c (get_member_function_from_ptrfunc): Use ptrdiff_type_node + for things that have to be added to pointers, not size_type. Cures + problems with pointer to members on Alphas. + (build_binary_op_nodefault): Likewise. + (get_delta_difference_: Likewise. + (build_ptrmemfunc): Likewise. + +Tue Jan 10 01:49:25 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (pushtag): Stick the new decl in TYPE_NAME before pushing + it. + + * typeck.c (build_component_ref): Don't build up a COMPONENT_REF + when dealing with overloaded member functions; just act like + build_offset_ref. + (commonparms): Remove misleading comment. + + * decl.c (duplicate_decls): Complain about repeated default + arguments here. + (redeclaration_error_message): Instead of here. + (pushdecl): Complain about missing default arguments here. + (grokparms): Instead of here. + (lookup_name_current_level): Also match on DECL_ASSEMBLER_NAME. + (grok_reference_init): Do not complain about missing initializer if + declared 'extern'. + + * search.c (lookup_field): Don't return a TYPE_DECL if there is a + function alternative and want_type is not set. + +Mon Jan 9 18:16:23 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (pushtag): Don't set TYPE_NAME to an identifier. Do push + the decl when the type has no TYPE_NAME. + (lookup_nested_type): Don't assume that type has TYPE_NAME set. + (lookup_name_real): Call lookup_field with want_type = + prefer_type. + + * search.c (lookup_field): Handle want_type properly in the presence + of fields with the same name. + + * decl.c (set_nested_typename): Set nested name for file-scope types + to include leading ::. + (pushdecl): Set the nested typename if the decl doesn't have one, + rather than if the type's canonical decl doesn't have one. + +Mon Jan 9 03:44:33 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (convert_for_assignment): Complain about contravariance + violation here. + (comp_target_types): Instead of here. + (build_unary_op): resolve_offset_ref before checking for a valid + type. + + * spew.c (yylex): Decrement looking_for_typename after we see a + _DEFN. + + * decl.c (pushdecl): Don't install an artificial TYPE_DECL in + IDENTIFIER_LOCAL_VALUE if we already have a decl with that name. + + * typeck.c (convert_for_assignment): Converting pointers to bool + does not need a cast. + +Sun Jan 8 18:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (instantiate_type): Initialize nsubsts parm. + + * pt.c (do_function_instantiation): Likewise. + +Sat Jan 7 14:37:05 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (tsubst): Use TREE_STATIC instead of DECL_INLINE && + DECL_SAVED_INSNS to determine whether or not we've seen a definition + of this function. + (instantiate_template): Likewise. + + * call.c (convert_harshness): Allow const reference binding when + called from the overloading code, but not when called from + can_convert (since it isn't a conversion). + (convert_harshness): Put back some disabled code. + +Fri Jan 6 14:10:57 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (convert_harshness): There is no implicit conversion from + void* to other pointer types (unless the parameter is (void*)0). + (convert_harshness): Non-lvalues do not convert to reference types. + + * class.c (finish_struct_methods): Still set + TYPE_HAS_{INT,REAL}_CONVERSION. + + * call.c (can_convert): Don't use aggregate initialization. + + * cp-tree.h: Declare lookup_conversions. + +Thu Jan 5 21:08:00 1995 Mike Stump <mrs@cygnus.com> + + * parse.y (simple_stmt): Fix duplicate case value error messages to + be more readable. + +Wed Jan 4 16:44:19 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (build_type_conversion): Total rewrite to use + convert_harshness instead of reproducing conversion logic here. Now + much shorter. + + * call.c (convert_harshness): Support conversions to bool. + (can_convert): Checks whether a conversion is less harsh + than USER_CODE, for build_type_conversion. + + * search.c (add_conversions): Function for passing to dfs_walk which + adds all the type conversion operators in the current type to a list. + (lookup_conversions): Calls dfs_walk with add_conversions and return + the list. + (dfs_walk): Don't require a qfn. + + * cp-tree.h: Lose CLASSTYPE_CONVERSIONS hackery. + (CLASSTYPE_FIRST_CONVERSION): Points to elt 1 of CLASSTYPE_METHOD_VEC. + + * class.c (finish_struct_bits): Lose CLASSTYPE_CONVERSIONS hackery. + (grow_method): A separate function for building onto the growing + method vector. + (finish_struct_methods): Use it. Put all type conversion operators + right after the constructors. Perhaps we should sort the methods + alphabetically? + +Mon Jan 2 14:42:58 1995 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Lose another misleading shortcut. + +Fri Dec 30 17:57:30 1994 Mike Stump <mrs@cygnus.com> + + * gc.c (build_bltn_desc): Handle bool as a built-in type. + +Fri Dec 30 14:20:21 1994 Mike Stump <mrs@cygnus.com> + + * tree.c (layout_vbasetypes): Ensure that we don't loose alignment + on the complete type because of small virtual bases. + +Fri Dec 30 12:22:29 1994 Mike Stump <mrs@cygnus.com> + + * decl.c (n_incomplete): Bump n_incomplete up to int to match C + front end. + (pushdecl): Also count decls pushed that are of a type being defined + as incomplete things. + * class.c (finish_struct): Move hack_incomplete_structures up to + just after we set it as not being defined, so that the decls we + build for RTTI don't count as incomplete. + +Thu Dec 29 18:20:57 1994 Mike Stump <mrs@cygnus.com> + + * pt.c (tsubst): Fix problem with defining constructors in templated + classes with virtual bases. + +Wed Dec 28 08:31:00 1994 Mike Stump <mrs@cygnus.com> + + * parse.y (TYPEID): Strip top-level cv-qualifiers on typeid + expressions. + * gc.c (build_typeid): Likewise. + +Thu Dec 22 17:26:33 1994 Mike Stump <mrs@cygnus.com> + + * cvt.c (build_up_reference): Fix breakage introduced on Nov 29, + don't assert on complex AGGR inits. + +Thu Dec 22 14:32:31 1994 Mike Stump <mrs@cygnus.com> + + * method.c (build_overload_value): Handle pointer to members as + template arguments. + +Thu Dec 22 13:09:07 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (unary_complex_lvalue): Don't call sorry if we know how + to do take the address of a data member for a pointer to data + member. + +Thu Dec 22 10:04:19 1994 Mike Stump <mrs@cygnus.com> + + * decl.c (grokdeclarator): Use the typedef name for linkage if the + type doesn't otherwise have a name. + + * decl2.c (grokfield): Likewise. + + * class.c (finish_struct): Since we reuse the TYPE_DECL for the + DECL_NAME of enums, structs and classes, we have to avoid trying to + put it in the TYPE_FIELDS again. + +Wed Dec 21 11:07:05 1994 Mike Stump <mrs@cygnus.com> + + * decl2.c (check_classfn): Ignore this parameter on static functions + when checking to see if we match. + +Tue Dec 20 17:47:02 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (unary_complex_lvalue): Handle address of non-left most + pointers to members by calling get_delta_difference. + +Mon Dec 19 22:40:53 1994 Mike Stump <mrs@cygnus.com> + + * decl2.c (check_classfn): Don't use decls_match yet, as it modifies + static functions to early. + +Thu Dec 19 22:37:48 1994 Mike Stump <mrs@cygnus.com> + + * method.c (make_thunk): Handle encoding of positive thunk offsets. + +Sat Dec 17 13:29:50 1994 Doug Evans <dje@canuck.cygnus.com> + + * Make-lang.in (.PHONY): Tell GNU make C++ and c++ are phony targets. + +Thu Dec 15 16:32:12 1994 Mike Stump <mrs@cygnus.com> + + * decl2.c (check_classfn): Use decls_match to check if this has + already been declared, as the DECL_ASSEMBLER_NAME may have been + changed via asm("new_name"). + * decl.c (decls_match): Make public. + +Thu Dec 15 15:17:55 1994 Mike Stump <mrs@cygnus.com> + + * *.[chy] (expand_aggr_init) Add fourth argument to handle + distinction between = init and (init) style of initializations. + * *.[chy] (finish_decl): Add fifth argument to to handle + distinction between = init and (init) style of initializations. + +Tue Dec 13 19:16:05 1994 Mike Stump <mrs@cygnus.com> + + Fix some random `explicit' bugs. + + * cvt.c (convert_to_reference): Add third parameter to + convert_force. + (convert_force): Likewise. + * call.c (build_method_call): Likewise. + * decl2.c (setup_vtbl_ptr): Likewise. + * init.c (expand_virtual_init): Likewise. + (build_member_call): Likewise. + (build_delete): Likewise. + (build_vbase_delete): Likewise. + * typeck.c (build_component_addr): Likewise. + (build_c_cast): Likewise. + (build_modify_expr): Likewise. + * cp-tree.h (CONV_NONCONVERTING): Likewise. Add so that we can + distinguish the context in which the conversion appears. Add thrid + argument to build_c_cast. + * cvt.c (cp_convert): Pass whether or not we want to consider + non-converting constructors down to build_method_call. + * decl2.c (reparse_absdcl_as_casts): Add third argument to + build_c_cast. + * gc.c (build_m_desc): Likewise. + * init.c (build_new): Likewise. + * parse.y (expr_no_commas): Likewise. + (primary): Likewise. + * typeck.c (build_x_function_call): Likewise. + (build_static_cast): Likewise. + (build_reinterpret_cast): Likewise. + (build_const_cast): Likewise. + (build_c_cast): Likewise. + (build_ptrmemfunc): Likewise. + * typeck2.c (build_functional_cast): Likewise. + * init.c (expand_aggr_init): Added LOOKUP_ONLYCONVERTING to + expand_aggr_init_1 as inits are converted to the destination type. + +Tue Dec 13 16:18:57 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * Make-lang.in (cc1plus): Depends on c-pragma.o. + + * Makefile.in (OBJ{DEP,}S): Add ../c-pragma.o. + + * lex.c (check_newline): If the #pragma is not recognized by g++, + try machine-specific ones too. + (handle_sysv_pragma): Copied from c-lex.c. + +Mon Dec 12 23:53:06 1994 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Fix Dec 6th change, build_new likes a + reference better. + +Mon Dec 12 18:01:00 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_binary_op): Lose checks on TYPE_PTRMEMFUNC_P with + IS_AGGR_TYPE, since now they will not both be set on the same type. + + * pt.c (do_pending_expansions): Don't clear TREE_PUBLIC on + instantiations controlled by -fexternal-templates. + + * decl.c (duplicate_decls): Don't complain about different values of + __attribute__ ((const)) and ((noreturn)). + +Fri Dec 9 18:17:37 1994 Doug Evans <dje@cygnus.com> + + * Makefile.in (BISONFLAGS): Delete --yacc. + (PARSE_H): Depend on $(PARSE_C), for parallel makes. + (PARSE_C): Undo last patch. + +Fri Dec 2 10:44:36 1994 Mike Stump <mrs@cygnus.com> + + * Makefile.in (BISONFLAGS): Add --yacc so that output winds up in + y.tab.c. + +Thu Dec 8 17:39:46 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (finish_decl): Don't call obscure_complex_init for decls + of indeterminate size. + +Wed Dec 7 16:49:22 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (obscure_complex_init): Function to tweak the decl to + prevent expand_decl from tring to initialize it. + (finish_decl): Use it rather than writing the same code in three + different places. + + * parse.y (bad_parm): Stop trying to support parms without types. + +Wed Dec 7 12:06:56 1994 Mike Stump <mrs@cygnus.com> + + * decl2.c (grokfield): Make asm specs on static member functions + work. + +Tue Dec 6 15:43:20 1994 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Make a copy of the thrown object. + +Tue Dec 6 14:16:34 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * parse.y: : has lower precedence than =. + +Tue Dec 6 12:46:17 1994 Mike Stump <mrs@cygnus.com> + + * decl.c (pushdecl): Use DECL_NAME of VAR_DECLs to avoid namespace + manglings. + (grokvardecl): Add namespace into variable name. + +Tue Dec 6 11:26:55 1994 Mike Stump <mrs@cygnus.com> + + * decl2.c (current_namespace_id): New routine to transform a simple + name into a name in a namespace. + * decl.c (grokdeclarator): Use it. + * decl2.c (get_namespace_id): Find the name of the current + namespace. + (push_namespace, pop_namespace): Complete out missing + functionality. + +Mon Dec 5 17:11:51 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * class.c (finish_struct): Don't use LONG_LONG_TYPE_SIZE, as it may + not be defined. Fix warning message for enums and restore warning + for non-enums. + + * decl2.c (push_namespace): Dummy function. + (pop_namespace): Likewise. + (do_namespace_alias): Likewise. + (do_using_decl): Likewise. + (do_using_directive): Likewise. + + * parse.y: New token NSNAME for namespace names. + (extdef): Add namespace, using definitions. + (using_decl): New rule for using declarations. + (any_id): New rule for identifiers with any degree of scoping. + (identifier): Add NSNAME. + (notype_identifier): Likewise. + (component_decl): Add using_decl. + (nested_name_specifier): Add NSNAME SCOPE. + + * typeck.c (convert_for_assignment): Handle conversions between + enums and bool. + + * decl.c (duplicate_decls): Only propagate DECL_MAIN_VARIANT on + FUNCTION_DECLs. + +Mon Dec 5 13:03:16 1994 Mike Stump <mrs@cygnus.com> + + * class.c (finish_struct): Give an error if one tries to declare a + bit-field's size greater than a long long, as the backend will dump. + It is not an error to declare an enum bit-field greater than its + precision. Warn if an enum bit-field is too small to hold all + its values. + +Mon Dec 5 11:41:50 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (convert_for_assignment): Use cp_convert instead of + convert so that we don't get static casts. + +Sun Dec 4 11:59:01 1994 Mike Stump <mrs@cygnus.com> + + * cvt.c (cp_convert): Don't complain about int->enum conversion if + we are doing static casts. + +Fri Dec 2 18:32:41 1994 Mike Stump <mrs@cygnus.com> + + * error.c (dump_expr): Do something more intelligent with SAVE_EXPRs + when dumping expressions in error messages. + +Fri Dec 2 17:04:27 1994 Mike Stump <mrs@cygnus.com> + + * gc.c (build_dynamic_cast): Change interface to libg++, ensure that + the return type is the right type, and make references work. + +Fri Dec 2 16:36:43 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (poplevel): Don't be confused by function-scope + declarations of non-nested functions. + (duplicate_decls): Propagate DECL_MAIN_VARIANT. + (pushdecl): Use duplicate_decls to copy info from old decl into new + function-scope one rather than doing it here. + + * decl2.c (mark_inline_for_output): Deal with the DECL_MAIN_VARIANT + of this decl, in case this is a function-scope declaration. + + * decl.c (finish_enum): Make sure that the type has the right + precision when we call fixup_*_type. + +Tue Nov 29 19:12:07 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (build_up_reference): Strip superfluous NOP_EXPRs; we do + want to build up references to rvalues if possible. + (cp_convert): Stick on a NOP_EXPR when converting to the same type. + +Tue Nov 29 11:28:59 1994 Mike Stump <mrs@cygnus.com> + + * parse.y (maybe_raises): Handle throw (). + * parse.y (ansi_raise_identifier): grok type-ids in exception + specifications. + * tree.c (build_exception_variant): Use list compare to check if + two exception specifications match. + * decl.c (duplicate_decls, bad_specifiers): Enhance wording on error + messages. + * call.c (build_method_call): Remove TREE_RAISES. + * cvt.c (convert_to_aggr): Likewise. + * typeck.c (build_function_call_real, convert_arguments): Likewise. + * init.c (expand_aggr_init_1): Likewise. + +Tue Nov 29 09:50:39 1994 Mike Stump <mrs@cygnus.com> + + * except.c: Add support for m68k and mips exception handling + support. + +Tue Nov 29 08:48:33 1994 Mike Stump <mrs@cygnus.com> + + * except.c (expand_end_all_catch): Throw into outer context, if we + fall off end of catch handlers. + +Mon Nov 28 16:44:41 1994 Mike Stump <mrs@cygnus.com> + + * Makefile.in: Make is easier to decide where parse.[ch] will be + built. + +Thu Nov 17 20:11:24 1994 Doug Evans <dje@cygnus.com> + + * cp/Make-lang.in (CXX_INSTALL_NAME) Use program_transform_name. + (GXX_INSTALL_NAME) Likewise. + (CXX_CROSS_NAME) Use program_transform_cross_name. + (GXX_CROSS_NAME) Likewise. + (c++.install-man): Use program_transform_name on g++.1. + (c++.uninstall): Likewise. + +Mon Nov 28 13:53:03 1994 Mike Stump <mrs@cygnus.com> + + * parse.y (THROW): Fix precedence of throw expressions. + +Mon Nov 28 13:15:16 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (build_unary_op): Allow promotions from bool to int on + unary ~. + +Sun Nov 27 00:16:21 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * method.c (build_overload_name): Use DECL_ASSEMBLER_NAME for + classes when appropriate. + (build_overload_nested_name): When dealing with a function context, + use ASM_FORMAT_PRIVATE_NAME to tweak the name of the function to + avoid conflicts between local classes of the same name. + +Wed Nov 23 17:59:42 1994 Mike Stump <mrs@cygnus.com> + + * gxx.gperf, parse.y, lex.h, hash.h, lex.c (init_lex), delc.c + (duplicate_decls, grokdeclarator), cp-tree.h: Add support for + `explicit'. + * cvt.c (convert_to_reference, cp_convert, build_type_conversion_1, + build_type_conversion): Use LOOKUP_ONLYCONVERTING in + build_method_calls so that non-converting constructors are not used. + * call.c (build_method_call): If we shouldn't use a non-converting + constructor, then don't. + +Wed Nov 23 14:46:56 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_method_call): Don't try to synthesize methods yet. + +Tue Nov 22 12:45:21 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (push_template_decls): Create CONST_DECLs for template + constant parameters, not VAR_DECLs. + +Sat Nov 19 15:28:31 1994 Jim Wilson <wilson@chestnut.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Can shorten shift only if + shift count is less than size in bits of arg0. + +Thu Nov 17 15:30:50 1994 Mike Stump <mrs@cygnus.com> + + * gxx.gperf, hash.h, lex.c (init_lex, real_yylex), parse.y: Add new + ANSI keywords and, and_eq, bitand, bitor, explicit, namespace, not, + not_eq, or, or_eq, typename, using, xor, xor_eq to g++. Still need + to add support for explicit, namespace, typename, and using, support + for the rest is already in. + +Fri Nov 4 19:04:18 1994 Mike Stump <mrs@cygnus.com> + + * gc.c (get_bad_cast_node): New routine to support compile time + throws of bad_cast. + * gc.c (build_dynamic_cast): Support throwing of bad_cast at compile + time. + +Fri Nov 4 11:12:00 1994 Mike Stump <mrs@cygnus.com> + + * except.c: Add hppa support. + +Fri Nov 4 10:50:50 1994 Mike Stump <mrs@cygnus.com> + + * except.c: Add rs6000 support. + +Thu Nov 3 14:24:23 1994 Mike Stump <mrs@cygnus.com> + + * except.c (do_unwind): Add i[34]86 support. + +Thu Nov 3 00:10:46 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (do_pending_expansions): Unset TREE_PUBLIC on implicit + instantiations. + +Wed Nov 2 15:08:24 1994 Kung Hsu <kung@mexican.cygnus.com> + + * decl.c (finish_function): Emit types used in method parameters + into symbol table. + +Wed Nov 2 15:05:47 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (process_template_parm): Allow pointer to member function + template parameter types. + (uses_template_parms): Handle pointer to member function + CONSTRUCTORs. + + * g++.c (main): Cast first argument of bzero to (char *). + Pass -lstdc++ instead of -lg++ unless we are invoked as 'g++'. + +Mon Oct 31 14:50:48 1994 Kung Hsu <kung@mexican.cygnus.com> + + * gc.c (build_dynamic_cast): rewrite to make it work. + * class.c (finish_vtbls): build more vtables if flag_rtti is on. + * class.c (modify_all_direct_vtables): ditto. + * init.c (expand_direct_vtbls_init): expand more vtables if + flag_rtti is on. + * decl.c (init_type_desc): add default return. + +Tue Oct 25 17:13:09 1994 Kung Hsu <kung@mexican.cygnus.com> + + * tree.c (debug_binfo): get rid of the initial size entry of + vtable. + * cp-tree.h: change flag_dossier to flag rtti, define type + descriptor type nodes. + * decl.c (init_type_desc): new function to initialize type + descriptor type nodes. + * decl.c (record_builtin_type): change flag_dossier to flag_rtti. + * lex.c (init_lex): ditto. + * decl.c : change variable flag_dossier to flag_rtti. + * decl.c (duplicate_decls): get rid initial size entry of vtable. + * decl.c (hack_incomplete_structures): take out assert 164. + * search.c (get_abstract_virtuals_1): ditto. + * search.c (dfs_init_vbase_pointers): change CLASSTYPE_DOSSIER to + CLASSTYPE_RTTI. + * parse.y: ditto. + * class.c (prepare_fresh_vtable): for virtual bases, get right + offset. + * class.c (add_virtual_function): change flag_dossier to + flag_rtti. + * class.c (modify_one_vtable): modify the right rtti entry. + * class.c (override_one_vtable): get rid of size entry. + * class.c (finish_struct): change flag_dossier to flag_rtti, and + build extra vtables, build type descriptors for polymorphic + classes. + * gc.c (build_headof): make headof() works correctly with new + rtti. + * gc.c (build_typeid): make this function work with new rtti. + * gc.c (get_typeid): make this function work with new rtti. + * gc.c (build_bltn_desc): new function for new rtti. + * gc.c (build_user_desc): ditto. + * gc.c (build_class_desc): ditto. + * gc.c (build_ptr_desc): ditto. + * gc.c (build_attr_desc): ditto. + * gc.c (build_func_desc): ditto. + * gc.c (build_ptmf_desc): ditto. + * gc.c (build_ptmd_desc): ditto. + * gc.c (build_t_desc): ditto. + * gc.c : comment out old build_t_desc, build_i_desc, build_m_desc. + +Tue Oct 25 13:37:41 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (convert_harshness): Check for TREE_UNSIGNED differences + after checking for integral conversions. + +Wed Nov 30 19:13:50 1994 Mike Stump <mrs@cygnus.com> + + * Version 2.6.3 released. + +Thu Nov 17 10:56:50 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck2.c (build_m_component_ref): Check the basetype of the + member pointer against the main variant of the object type. + +Mon Nov 14 14:21:52 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (convert_to_reference): Make sure that the original expr + gets its type back when converting a reference. + + * method.c (build_overload_name): Clear numeric_outputed_need_bar here. + (build_decl_overload): Instead of here. + +Tue Nov 8 17:11:24 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (cp_convert): Don't build a TARGET_EXPR if we're not in a + function. + + * typeck.c (convert_for_initialization): Handle initialization from + a TARGET_EXPR. + +Sun Nov 6 01:34:24 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (lookup_nested_type_by_name): Fix list-walking logic. + (tsubst): When replacing a TEMPLATE_TYPE_PARM, propagate + TYPE_READONLY and TYPE_VOLATILE from the argument. + (unify): When unifying with a TEMPLATE_TYPE_PARM, remove cv-quals + present in parm from arg. + (type_unification): Strip REFERENCE_TYPE from the argument type. + (unify): Don't strip REFERENCE_TYPE from the argument type. + +Sat Nov 5 22:42:15 1994 Greg McGary <gkm@magilla.cichlid.com> + + * pt.c (do_type_instantiation): Check to see if there's a + IDENTIFIER_TEMPLATE on a class before calling + instantiate_member_templates(). + +Sat Nov 12 06:35:42 1994 Mike Stump <mrs@cygnus.com> + + * Version 2.6.2 released. + +Thu Nov 3 18:48:19 1994 Paul Eggert <eggert@twinsun.com> + + * Makefile.in (spew.o, lex.o, pt.o): + Depend on $(srcdir)/parse.h, not parse.h. + +Tue Nov 1 19:19:41 1994 Mike Stump <mrs@cygnus.com> + + * Version 2.6.1 released. + +Sun Oct 23 13:19:55 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c: Declare flag_access_control. + (struct lang_f_options): Add access-control. + * expr.c (cplus_expand_expr, NEW_EXPR): Unset flag_access_control + for the call to expand_aggr_init to copy the object out of the + pcc_struct_return slot. + * search.c (compute_access): if (!flag_access_control) return + access_public. + +Fri Oct 21 00:32:54 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * lex.c (cons_up_default_function): Don't try to defer method + synthesis now. + + * decl.c (init_decl_processing): Use __pure_virtual for abort_fndecl + instead of abort, since the OSF/1 dynamic linker doesn't like to see + relocation entries for abort. + + * tree.c (array_type_nelts_total): Use sizetype, not + integer_type_node. + (array_type_nelts_top): Likewise. + +Thu Oct 20 15:48:27 1994 Mike Stump <mrs@cygnus.com> + + * decl.c (grokdeclarator): Added handling for catch parameters + (CATCHPARM). + * except.c (expand_start_catch_block): Use the new CATCHPARM context + instead of NORMAL. + * except.c (expand_throw): Don't let convert_to_reference complain + about what we are doing. + +Thu Oct 20 12:55:24 1994 Jim Wilson <wilson@cygnus.com> + + * method.c (emit_thunk): Call instantiate_virtual_regs. + +Wed Oct 19 14:15:33 1994 Mike Stump <mrs@cygnus.com> + + * except.c (expand_exception_blocks): Make sure throw code doesn't + get put in function that won't be output. + +Mon Oct 17 18:03:15 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (init_decl_processing): Make alloca a builtin. + +Thu Oct 27 21:10:25 1994 Craig Burley <craig@burley> + + * g++.c (main): Only decrement "added" and set "library" to + NULL when "library" != NULL (just like 940829 fix). + +Mon Oct 17 15:56:11 1994 Mike Stump <mrs@cygnus.com> + + * except.c (expand_start_catch_block): Make sure the false label + gets onto the permanent obstack, as it is used for the exception + table. + +Fri Oct 14 18:54:48 1994 Mike Stump <mrs@cygnus.com> + + * class.c (modify_one_vtable): Since the DECL_CONTEXT of fndecl can + be set just below, use current_fndecl instead. + +Fri Oct 14 15:12:22 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * init.c (expand_aggr_vbase_init_1): Don't call expand_aggr_init_1 + with LOOKUP_SPECULATIVELY. + (expand_default_init): Abort if build_method_call returns NULL_TREE. + + * typeck.c (build_modify_expr): Don't just build a MODIFY_EXPR if + the rhs is a TARGET_EXPR. + + * parse.y (left_curly): Anonymous types are not affected by #pragma + interface/implementation. + + * method.c (synthesize_method): Don't call setup_vtbl_ptr for the + default constructor if it isn't needed. + + * lex.c (cons_up_default_function): Do synthesize methods for + anonymous types if necessary. + +Thu Oct 13 17:44:55 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * method.c (build_decl_overload): Set numeric_outputed_need_bar to 0. + +Wed Oct 12 13:27:57 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * typeck.c (build_modify_expr): Understand how to copy an aggregate. + + * init.c (expand_default_init): Likewise. Also remove some of the + crufty code that assumes methods will not be synthesized properly. + + * lex.c (cons_up_default_function): If the containing type has no + name, these functions should never need to be called, so just + declare them. + + * lex.c (real_yylex): Use HOST_BITS_PER_WIDE_INT to determine the + bitmask for lexing character constants. + + * call.c (build_method_call): Disable code that tries to do tricky + stuff with a default parameter that is a constructor call, but + actually does other tricky stuff that breaks things. + +Wed Oct 12 16:14:01 1994 Benoit Belley <belley@cae.ca> + + * decl.c (finish_enum): Disable code which forces enums to be signed, + since this conflicts with their use as bitfields. type_promotes_to + handles promotion of enums of underlying unsigned types to signed + integer types. + +Wed Oct 12 13:24:03 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * cvt.c (type_promotes_to): Also promote enums to long if + appropriate. + + * typeck.c (default_conversion): Don't expect type_promotes_to to + return a main variant. + +Wed Oct 12 12:19:45 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_scoped_method_call): Don't lose side effects in the + object expression when calling a non-existent destructor. + +Fri Sep 2 19:05:21 1994 Rohan Lenard <rjl@iassf.easams.com.au> + + * call.c (build_scoped_method_call): Remove erroneous error message + when destructor call is written as a scoped call. + +Tue Oct 11 23:48:31 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * various: Cast pointer arguments to bzero and bcopy to char *. + +Tue Oct 11 19:34:32 1994 Mike Stump <mrs@cygnus.com> + + * class.c (get_derived_offset): Added a type parameter to limit how + far up the CLASSTYPE_VFIELD_PARENT chain we search. + * class.c (modify_one_vtable, fixup_vtable_deltas): When forming the + offset to put into the vtable for the this parameter, make sure we + don't offset from a parent of the DECL_CONTEXT of the function. + +Tue Oct 11 16:10:52 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * pt.c (do_function_instantiation): Set DECL_EXTERNAL and + TREE_STATIC when setting DECL_INTERFACE_KNOWN. + (do_type_instantiation): Likewise. + + * lex.c (cons_up_default_function): Set DECL_INTERFACE_KNOWN, + DECL_EXTERNAL and TREE_STATIC as appropriate. + + * decl2.c (finish_file): Also synthesize methods that don't have + DECL_EXTERNAL set. Set interface_unknown before doing so. + + * decl.c (start_function): If DECL_INTERFACE_KNOWN is set on the + function decl, don't muck with TREE_PUBLIC and DECL_EXTERNAL. + +Mon Oct 10 00:56:53 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * lex.c (cons_up_default_function): Mark methods in a template class + as template instances. Store the values of interface_unknown and + interface_only for do_pending_inlines. + (do_pending_inlines): Use them. + + * decl2.c (finish_file): If we haven't seen a definition of a + function declared static, make the decl non-PUBLIC so compile_file + can give an error. + +Sun Oct 9 02:42:29 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * method.c (do_build_copy_constructor): Handle anonymous unions. + (do_build_assign_ref): Likewise. + (largest_union_member): Move from lex.c. + +Sat Oct 8 14:59:43 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + Re-implement g++'s vague linkage independent of TREE_PUBLIC. + * pt.c (instantiate_member_templates): Lose redundant + -fexternal-templates handling. + (tsubst): Set TREE_PUBLIC and DECL_EXTERNAL on new decls. Don't set + TREE_STATIC or DECL_INTERFACE_KNOWN. + (do_pending_expansions): Predicate on DECL_INTERFACE_KNOWN instead + of DECL_EXTERNAL for explicit instantiations. + (do_function_instantiation): Do the new thing. + (do_type_instantiation): Likewise. + (instantiate_template): Deal with member templates defined in a .cc + file with -fexternal-templates. + * except.c (expand_exception_blocks): Use DECL_LINKAGE_KNOWN to + decide whether to stick builtin_throw here. + * decl2.c (import_export_inline): Predicate on DECL_INTERFACE_KNOWN + rather than TREE_PUBLIC. Generally fix rules. + (finish_file): Use DECL_INITIAL to determine whether or not a method + has been synthesized, rather than TREE_ASM_WRITTEN. + * decl.c (warn_extern_redeclared_static): Use DECL_PUBLIC instead of + TREE_PUBLIC. + (pushdecl): Likewise. + (duplicate_decls): Likewise. Deal with DECL_DECLARED_STATIC and + DECL_INTERFACE_KNOWN. + (redeclaration_error_message): Fix checking for conflicting linkage. + (define_function): Set DECL_INTERFACE_KNOWN. + (grokfndecl): Function decls are PUBLIC until we are sure about + their linkage. Set DECL_DECLARED_STATIC as needed. + (start_function): Deal with linkage. Move pushdecl after linkage + magic. + (finish_function): Don't set TREE_ASM_WRITTEN on discarded inlines. + * cp-tree.h (lang_decl_flags): Add interface_known and + declared_static. + (DECL_INTERFACE_KNOWN): New macro. + (DECL_DECLARED_STATIC): New macro. + (DECL_PUBLIC): New macro. + + Clean up bogus use of TREE_PUBLIC. + * class.c (alter_access): Fix mistaken use of TREE_PUBLIC (it + doesn't correspond to TREE_PROTECTED and TREE_PRIVATE). + * init.c (do_friend): Don't arbitrarily set TREE_PUBLIC. + +Wed Oct 5 13:44:41 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * call.c (build_overload_call_real): Don't immediately do + array->pointer conversion. + + * pt.c (type_unification): If not passing to a reference, strip + cv-quals. Also handle array->pointer conversion. + +Tue Oct 4 17:45:37 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (grokdeclarator): Don't warn about applying const to a + const typedef or template type parameter. + + * decl2.c (finish_file): Also synthesize methods after walking the + vtables. Ugly ugly ugly. + +Mon Oct 3 15:02:41 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * various: Remove lingering remnants of old exception handling code. + + * decl2.c (finish_file): Synthesize methods before walking the + vtables, so that the vtables get emitted as needed. + + * decl.c (shadow_tag): Remove obsolete code for pushing tags and + dealing with exceptions. + +Mon Oct 3 13:05:27 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> + + * Make-lang.in (g++-cross): Depend upon version.o and $(LIBDEPS). + +Mon Oct 3 02:59:28 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl2.c (finish_file): Fix inline handling. + +Sun Oct 2 00:21:56 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + * decl.c (grokdeclarator): Handle redundant scope even better. + ({push,pop}_cp_function_context): Take toplev parameter. + + * method.c (synthesize_method): Pass toplev parameter to + {push,pop}_cp_function_context depending on decl_function_context + (fndecl). + + * typeck.c (build_x_unary_op): Unary & on OFFSET_REFs is always the + built-in version. + + * method.c (synthesize_method): Don't be confused by __in_chrg + parameter. + + * class.c (popclass): Set C_C_D like start_function does. + + * decl.c (grokdeclarator): Handle redundant scope better. + + * parse.y (expr_or_declarator): Add '(' expr_or_declarator ')' rule. + (direct_notype_declarator): Likewise. + (complex_direct_notype_declarator): Remove it here. + +Sat Oct 1 21:42:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (resolve_offset_ref): Fix types used in resolving .* + expressions. + +Sat Oct 1 15:18:49 1994 Jason Merrill <jason@phydeaux.cygnus.com> + + Beginnings of work to synthesize methods only when needed. + * call.c (build_method_call): Synthesize methods as necessary + (currently never necessary). + * class.c (popclass): Don't try to set C_C_D here, as it'll end up + on the wrong obstack. + * decl.c (push_cp_function_context): Mostly copied from + push_c_function_context. + (pop_cp_function_context): Similarly. + (finish_function): Reverse order of poplevel and pop_nested_class so + that current_class_decl is restored properly. + (start_function): Likewise. + (finish_function): Add parameter 'nested'. Don't call + permanent_allocation if (nested). + * various: Pass extra parameter to finish_function. + * decl2.c (finish_file): Reorganize end-of-file inline handling, + synthesizing methods as necessary. + * lex.c (cons_up_default_function): Call mark_inline_for_output. + Only synthesize methods immediately if #pragma implementation + (currently disabled). + (do_pending_inlines): Call synthesize_method. + * method.c (synthesize_method): New function; all method synthesis + goes through here. Calls do_build_assign_ref and + do_build_copy_constructor. + (build_default_constructor): Remove. + (build_dtor): Likewise. + (build_assign_ref): Rename to do_build_assign_ref and remove stuff + done by synthesize_method. + (build_copy_constructor): Similarly. + +Thu Sep 29 16:58:52 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (c_expand_return): Use magic so the backend can fixup the + assignment into the return register, so cleanups won't clobber it. + +Thu Sep 29 13:08:50 1994 Jason Merrill <jason@deneb.cygnus.com> + + * method.c (hack_identifier): Don't call assemble_external for + template decls. + + * decl.c (finish_decl): Also end temporary allocation if the decl in + question has a type of error_mark_node. + +Wed Sep 28 21:45:00 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (build_modify_expr): When optimizing ?: on lhs, make sure + that if the ?: was a reference type, that the subparts will be also. + +Wed Sep 28 16:14:04 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * except.c (register_exception_table): Use Pmode, not PTRmode. + +Fri Sep 23 13:54:27 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (do_pending_inlines): Do method synthesis after the + pending_inlines have been reversed. + +Thu Sep 22 12:53:03 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl2.c (finish_file): Fix Brendan's fix: Only call + register_exception_table if there is a non-empty exception table. + +Thu Sep 22 12:03:46 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl2.c (finish_file): Only do register_exception_table if + -fhandle-exceptions is being used. + +Wed Sep 21 19:01:51 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * except.c (output_exception_table_entry): Simplify + by using assemble_integer. + (build_exception_table): Change to return a count. + Cleanup to use standard macros, instead of hard-wired + sparc asm format. Don't make __EXCEPTION_TABLE__ global. + (register_exception_table): New function. Generate call to builtin. + * decl2.c (finish_file): Call register_exception_table. + * cp-tree.h (build_exception_table): Fix prototype. + +Wed Sep 21 13:20:42 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * tree.c (break_out_calls): Don't try to duplicate the DECL_INITIAL. + + * decl2.c (delete_sanity): Give an error at trying to delete a + function. + +Wed Sep 21 11:47:10 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (cons_up_default_function): Mark synthesized destructors + inline. + + * decl.c (duplicate_decls): Ignore redeclarations of wchar_t as + something other than __wchar_t, complaining if -pedantic and not in + a system header. + +Tue Sep 20 09:43:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (xref_tag): Set up BINFO_INHERITANCE_CHAIN on base binfos + here. + + * typeck.c (build_modify_expr): Require complete type after checking + for error_mark_node. + + * call.c (build_method_call): Print parmtypes when complaining of + ambiguous call. + + * typeck.c (build_modify_expr): Handle assignment to array from + non-array. + + * decl.c (lookup_name_real): Deal with got_scope == error_mark_node. + + * call.c (build_method_call): Don't bother with the exact match. + +Mon Sep 19 00:51:39 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (expand_aggr_init): If we munge the type of the variable, + also munge the type of the initializer. + + * decl.c (grokdeclarator): Use <= when comparing to RID_LAST_MODIFIER. + (init_decl_processing): Push artificial declaration of wchar_t so + people don't have to declare it before they can use it. + + * error.c (cp_line_of): return lineno in lieu of 0. + + * typeck.c (convert_for_assignment): Handle conversion of pmfs to + int and bool. + (build_component_ref): Fold the COMPONENT_REF in case it can be + reduced. + + * typeck2.c (store_init_value): Don't pedwarn about non-constant + bracketed initializers for automatic variables. + +Sun Sep 18 10:12:12 1994 Jason Merrill <jason@deneb.cygnus.com> + + * error.c (dump_decl): Don't say `typedef enum foo foo'. + + * decl.c (start_decl): Don't set TREE_PUBLIC on template decls just + because they're affected by #pragma i/i. We'll deal with that when + they get instantiated. + + * typeck.c (build_unary_op): Clean up cruft in ADDR_EXPR case. + + * class.c (instantiate_type): Set TREE_CONSTANT on instantiated + ADDR_EXPRs if appropriate. + + * decl.c (build_ptrmemfunc_type): Unset IS_AGGR_TYPE on pmf types. + + * typeck.c (build_ptrmemfunc): Handle &overloaded_method as an + initializer properly. + * typeck2.c (digest_init): Likewise. + + * tree.c (cp_build_type_variant): Like c_build_type_variant, except + it uses build_cplus_array_type. + * *.c: Use cp_build_type_variant instead of c_build_type_variant. + + * pt.c (do_type_instantiation): Don't try to instantiate nested + enums. + +Tue Sep 13 10:56:58 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (build_up_reference): Handle preincrement and predecrement + properly. + +Tue Sep 13 09:51:59 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (finish_decl): Only lay out the rtl for DECL if it is, in + fact, static. + +Mon Sep 12 14:40:30 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (finish_decl): Lay out the rtl for DECL before doing + grok_reference_init, in case it's static. + +Mon Sep 12 12:45:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Don't synthesize constructors if the + class has a field with the same name as the class. Don't die on + classes with no constructors or destructors. Don't die if the head + and tail of the class are in different files. + + * decl.c (grokdeclarator): Don't treat a function pointer field + with the same name as the class as a constructor. + +Fri Sep 9 13:17:00 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_c_cast): Pull constant values out of their + variables here. + + * decl.c (duplicate_decls): Only propagate DECL_CHAIN in + FUNCTION_DECLs and TEMPLATE_DECLs. + +Thu Sep 8 10:07:48 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (duplicate_decls): Propagate DECL_CHAIN in all DECLs that + have it. + + * pt.c (unify): REALs and INTEGERs only unify with their own genus. + (instantiate_member_templates): Don't muck with DECL_EXTERNAL and + TREE_PUBLIC unless -fexternal-templates. + +Wed Sep 7 13:17:10 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (do_type_instantiation): Call instantiate_member_templates. + Deal with specializations. + (tsubst): Don't stick the mangled name in DECL_NAME for function + instantiations. Don't push them, either. + + * decl2.c (grokfield): Move code for generating the + DECL_ASSEMBLER_NAME for static members from here. + * method.c (build_static_name): To here. + * decl.c (grokvardecl): Call build_static_name. + (duplicate_decls): Keep old DECL_ASSEMBLER_NAME. + +Mon Sep 5 12:49:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): if -Wsynth, warn when selecting + synthesized op= over user-supplied one cfront would select. + * decl2.c (lang_decode_option): Handle -Wsynth. + +Fri Sep 2 15:11:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (finish_enum): Overhaul to fix several bugs. + (start_enum): Disable useless code. + +Thu Sep 1 16:04:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (c_expand_return): Warn about returning a reference to a + temporary. + (convert_arguments): Increment argument counter when using default + arguments, too. + +Wed Aug 31 14:29:22 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (finish_decl): If the type of decl is error_mark_node, + don't bother trying to do anything. + + * typeck.c (convert_for_initialization): If the rhs contains a + constructor call, pretend the lhs type needs to be constructed. + + * init.c (expand_default_init): If we stick the object inside the + initializer, mark the initializer used. + +Tue Aug 30 13:50:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * method.c (build_assign_ref): return *this; + (build_assign_ref): Fix base assignment order. + (build_copy_constructor): Fix member init order. + +Mon Aug 29 13:54:39 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * g++.c (main): Remember to clear out SAW_SPECLANG after we see + its argument. + +Sat Aug 27 09:36:03 1994 Jason Merrill <jason@deneb.cygnus.com> + + * method.c (build_copy_constructor): Also copy virtual bases. + +Fri Aug 26 17:05:15 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (do_pending_inlines): Clear out pending_inlines before doing + any synthesis. Also first set deja_vu on all pending_inlines. + + * method.c (build_assign_ref): Use build_member_call to invoke base + operator=, rather than build_modify_expr. And use + build_reference_type instead of TYPE_REFERENCE_TO. + (build_copy_constructor): Use TYPE_NESTED_NAME to identify the + basetype. + + * decl2.c (grokfield): Don't complain about undefined local class + methods. + + * class.c (finish_struct): Don't try to synthesize methods here. + * lex.c (do_pending_inlines): Instead, synthesize them here. + (init_lex): Initialize synth_obstack. + (cons_up_default_function): Stick synthesis request on + pending_inlines. + +Fri Aug 26 12:24:14 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * call.c (build_method_call) [PCC_STATIC_STRUCT_RETURN]: Also + accept an RTL_EXPR in what we're about to use for the instance, + since anything which would end up with pcc_struct_return set + inside cplus_expand_expr. + + * cp-tree.h (cons_up_default_function): Note change of prototype. + +Thu Aug 25 23:05:30 1994 Gerald Baumgartner <gb@cs.purdue.edu> + + * class.c (finish_struct): Undid change from Aug 21 testing + CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING. + * parse.y (left_curly): Likewise, undid change from Aug 21. + * decl.c (xref_tag): Undid change from Aug 21, set + CLASSTYPE_INTERFACE correctly, and added comments. + +Thu Aug 25 00:36:31 1994 Jason Merrill <jason@deneb.cygnus.com> + + Rework approach to synthesized methods; don't go through the parser + anymore. + * class.c (finish_struct): Use new synthesis approach. + * lex.c (cons_up_default_function): Now just creates declaration, + not code. + (largest_union_member): #if 0 out. + (default_assign_ref_body): Likewise. + (default_copy_constructor_body): Likewise. + * method.c (build_default_constructor): New function to synthesize X(). + (build_copy_constructor): Synthesize X(X&). + (build_assign_ref): Synthesize X::operator=(X&). + (build_dtor): Synthesize ~X(). + + * error.c (cp_line_of): If we're dealing with an artificial + TYPE_DECL, look at the type instead. + +Wed Aug 24 11:11:50 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (sort_member_init): Check warn_reorder. + * decl2.c (lang_decode_option): Handle -W{no-,}reorder. + + * cp-tree.h (CLASSTYPE_SOURCE_LINE): New macro. + * error.c (cp_line_of): Use CLASSTYPE_SOURCE_LINE for aggregates. + * class.c (finish_struct): Set CLASSTYPE_SOURCE_LINE. + +Tue Aug 23 09:28:35 1994 Mike Stump <mrs@cygnus.com> + + * error.c (dump_decl): Improve wording, so that error messages + dont't read template<, class foo>... + +Mon Aug 22 15:30:51 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (label_colon): Also match a TYPENAME as a label name, + since they may have declared a class by that name but have also + tried to have a local label under the same name. + + * pt.c (coerce_template_parms): Call cp_error, not cp_error_at, + for the message so they know at what point it was instantiated. + +Sun Aug 21 23:07:35 1994 Gerald Baumgartner <gb@cs.purdue.edu> + + * class.c (finish_struct): Move setting of CLASSTYPE_INTERFACE and + CLASSTYPE_VTABLE_NEEDS_WRITING for signatures up to left_curly time. + * decl.c (xref_tag): Move setting of CLASSTYPE_INTERFACE and + CLASSTYPE_VTABLE_NEEDS_WRITING for signatures down to left_curly time. + * parse.y (left_curly): New final resting place for setting + CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING for signatures. + + * class.c (finish_struct): Don't test for function/field name + conflicts in signatures, since all the fields are compiler-constructed. + +Fri Aug 19 14:04:47 1994 Kung Hsu <kung@mexican.cygnus.com> + + * method.c (build_overload_nested_name): in qualified name + mangling, the template with value instantiation will have numeric + at end and may mixed with the name length of next nested level. + Add a '_' in between. + * method.c (build_overload_name): ditto. + * method.c (build_overload_identifier): ditto. + +Thu Aug 18 16:24:43 1994 Mike Stump <mrs@cygnus.com> + + * error.c (dump_decl): Handle NULL args. + +Thu Sep 29 16:15:36 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu> + + * g++.c: Rework last change so it's done like collect.c (and + gcc.c). + +Wed Sep 14 10:17:27 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu> + + * g++.c: Include <sys/errno.h> in case `errno' is a macro + as permitted by ANSI C. + +Thu Aug 18 12:48:09 1994 Mike Stump <mrs@cygnus.com> + + * class.c (finish_struct): Move setting of CLASSTYPE_INTERFACE and + CLASSTYPE_VTABLE_NEEDS_WRITING up to left_curly time. + * decl.c (xref_tag): Move setting of CLASSTYPE_INTERFACE and + CLASSTYPE_VTABLE_NEEDS_WRITING down to left_curly time. + * parse.y (left_curly): New final resting place for setting + CLASSTYPE_INTERFACE and CLASSTYPE_VTABLE_NEEDS_WRITING. + +Thu Aug 11 11:32:42 1994 H.J. Lu <hjl@nynexst.com> + + * g++.c (main): Only decrement "added" and set "library" to + NULL when "library" != NULL. + +Sat Aug 13 00:14:52 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Don't set TREE_PUBLIC on a function decl + just because its class has a known interface. + (decls_match): Deal with new format of template parms. + + * lex.c (cons_up_default_function): Don't play with TREE_PUBLIC and + DECL_EXTERNAL here. + +Fri Aug 12 01:55:15 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (pushtag): SET_DECL_ARTIFICIAL on gratuitous typedefs. + (xref_defn_tag): Likewise. + (pushdecl): Only allow artificial typedefs to be shadowed. + + * init.c (emit_base_init): Pass the right binfos to + expand_aggr_init_1. + + * class.c (delete_duplicate_fields_1): Make it work right. + (finish_struct): Catch function/field name conflict. + + * decl2.c (check_classfn): Pass the function to cp_error, not just + the name. + + * init.c (sort_member_init): Warn when order of member initializers + does not match order of member declarations. + (emit_base_init): Call expand_aggr_init_1 with LOOKUP_PROTECT. + + * error.c (dump_expr): Handle lists of functions. + + * decl.c (start_function): #pragma interface only affects functions + that would otherwise be static. + (finish_decl): Don't warn about an unused variable if it has both + constructor and destructor, since the 'resource allocation is + initialization' idiom is relatively common. + + * typeck.c (comp_target_types): Don't handle TEMPLATE_TYPE_PARMs. + (comp_target_parms): Likewise. + (compparms): Never consider default parms. + (common_base_type): Don't choose a virtual baseclass if there is a + more derived class in common. + (build_conditional_expr): If pedantic, pedwarn about conversion to + common base in conditional expr. + + * class.c (instantiate_type): Handle template instantiation better. + + * typeck.c (convert_arguments): Don't try to get tricky and convert + to int directly when PROMOTE_PROTOTYPES is set, as it breaks + user-defined conversions. + + * lex.c (check_for_missing_semicolon): Also give error at end of + file. + + * call.c (build_method_call): Don't promote arrays to pointers here. + + * typeck.c (convert_arguments): Don't require the actual parameter + to be of a complete type if the formal parameter is a reference. + +Thu Aug 11 15:21:40 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Soften 'static' on member function error + to pedwarn. + + * init.c (build_new): Don't automatically save rval. + (build_offset_ref): Do field lookup with proper basetype_path. + +Thu Aug 11 12:46:54 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * errfn.c (cp_silent): Declare to mark when we should avoid + emitting warnings and errors. + (cp_error): Check it. + (cp_warning): Likewise. + (cp_pedwarn): Likewise. + (cp_compiler_error): Likewise. + (cp_error_at): Likewise. + (cp_warning_at): Likewise. + (cp_pedwarn_at): Likewise. + * call.c (compute_conversion_costs): Set CP_SILENT when we start + out, and make sure we turn it off before we leave. + +Thu Aug 11 00:02:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (grok_array_decl): Try computing *(A+B) if neither + argument is obviously an array. + +Wed Aug 10 15:32:04 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (c_expand_start_case): Do cleanups here. + + * parse.y (xcond): Do bool conversion here, too. + (simple_stmt, SWITCH case): Don't do cleanups here. + + * decl.c (duplicate_decls): Don't treat builtins that have been + explicitly declared specially. + +Tue Aug 9 01:16:09 1994 Jason Merrill <jason@deneb.cygnus.com> + + * tree.c (make_deep_copy): Support copying pointer, reference, + function, array, offset and method types. + + * decl.c (init_decl_processing): Mark exit and abort as + BUILT_IN_NONANSI so that duplicate_decls is kinder about + redeclaration. + (duplicate_decls): Don't give two errors for redeclaring a C + function with the same parms but a different return type. + + * parse.y (paren_cond_or_null): Do cleanup and bool conversion here. + (condition): Instead of here. + (simple_stmt, SWITCH case): Also do cleanup here. + + * decl2.c (finish_anon_union): Only break out FIELD_DECLs. + + * call.c (build_method_call): Don't throw away the side effects of + the object in a call to a non-existent constructor. + * parse.y (primary): Likewise. + + * method.c (build_decl_overload): Oop. + + * decl2.c (lang_decode_option): Deal with flag_no_nonansi_builtin, + warn about uselessness of specifying -fansi-overloading. + + * method.c (build_decl_overload): Treat any non-member new with one + parameter as __builtin_new. + + * decl.c (init_decl_processing): Setup built-in meanings of exit, + _exit and abort. + +Mon Aug 8 15:03:30 1994 Jason Merrill <jason@deneb.cygnus.com> + + * error.c (dump_readonly_or_volatile): Put a space between const and + volatile if both apply. + + * init.c (perform_member_init): Clean up after this initialization. + (emit_base_init): Clean up after each base init, not after all have + been done. + (expand_aggr_vbase_init_1): Clean up after this init. + +Sun Aug 7 14:55:05 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Deal with destroying references. + + * parse.y (condition): Do bool_truthvalue_conversion here. + (paren_expr_or_null): And here. + (simple_if): Not here. + (simple_stmt): Or here. + +Sat Aug 6 22:29:45 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (paren_expr_or_null): Wrap the expression in a + CLEANUP_POINT_EXPR. + (condition): Likewise. + +Sat Aug 6 19:46:37 1994 Rohan Lenard <rjl@easams.com.au> + + * call.c (build_scoped_method_call): Fix error message when + destructor call refers to a nonexistent type. + +Sat Apr 16 22:43:30 1993 Gerald Baumgartner <gb@cs.purdue.edu> + + * lex.h (rid): Deleted RID_RAISES, it's never used. + Moved RID_PUBLIC, RID_PRIVATE, RID_PROTECTED, RID_EXCEPTION, + RID_TEMPLATE and RID_SIGNATURE to the end of the enumeration, + they don't need to be touched in `grokdeclarator.' + (RID_LAST_MODIFIER): Defined macro to be RID_MUTABLE. + + * decl.c (grokdeclarator): Use RID_LAST_MODIFIER instead of + RID_MAX as loop limit for finding declaration specifiers. + +Sat Apr 3 21:59:07 1993 Gerald Baumgartner <gb@cs.purdue.edu> + + * lex.c (debug_yytranslate): Moved to parse.y since it needs to + access `yytname,' which is static in parse.c. + +Fri Apr 2 23:36:57 1993 Gerald Baumgarnter <gb@cs.purdue.edu> + + * cp-tree.h (GNU_xref_ref): Fixed typo in extern declaration, it + was `GNU_xref_def' instead of `GNU_xref_ref.' + +Fri Aug 5 14:20:16 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (do_function_instantiation): Don't set TREE_PUBLIC and + DECL_EXTERNAL on 'extern' instantiations; wait until EOF to do that. + (do_type_instantiation): Likewise. + + * decl2.c (import_export_inline): Decides at EOF what an inline's + linkage should be. + (finish_file): Call it. + + * decl.c (start_function): Don't rely on the settings of TREE_PUBLIC + and DECL_EXTERNAL from do_*_instantiation. Only set + DECL_DEFER_OUTPUT on inlines whose linkage might actually change. + (finish_function): Use DECL_DEFER_OUTPUT to decide which inlines to + mark for later consideration, rather than DECL_FUNCTION_MEMBER_P. + +Fri Aug 5 01:12:20 1994 Mike Stump <mrs@cygnus.com> + + * class.c (get_class_offset_1, get_class_offset): New routine to + find the offset of the class where a virtual function is defined, + from the complete type. + * class.c (modify_one_vtable, fixup_vtable_deltas): Use + get_class_offset instead of virtual_offset as get_class_offset will + always provide the right answer. + * tree.c (virtual_offset): Remove. It only ever worked some of the + time. + +Tue Aug 2 12:44:21 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Put back unary_complex_lvalue call + that I thought was redundant. + + * typeck.c (c_expand_return): Fix a case I missed before. + +Sun Jul 31 17:54:02 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (unify): Strip cv-quals from template type arguments (when + 'const T*' is matched to 'const char*', that does not mean that T is + 'const char'). + +Fri Jul 29 01:03:06 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (do_type_instantiation): Instantiate nested TAGS, not + typedefs. Third time's the charm? + + * parse.y (template_parm): Support default template parms. + * pt.c (process_template_parm): Likewise. + (end_template_parm_list): Likewise. + (coerce_template_parms): Likewise. + (mangle_class_name_for_template): Likewise. + (push_template_decls): Likewise. + (unify): Likewise. + * method.c (build_overload_identifier): Likewise. + * error.c (dump_decl): Likewise. + +Wed Jul 27 17:47:00 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (do_type_instantiation): Only instantiate nested *classes*. + +Tue Jul 26 13:22:40 1994 Jason Merrill <jason@deneb.cygnus.com> + + * search.c (note_debug_info_needed): Also emit debugging information + for the types of fields. + +Mon Jul 25 00:34:44 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (lookup_template_class): Pass 'template' to + coerce_template_parms instead of 'in_decl', since it's a more + meaningful context. + + * typeck.c (c_expand_return): Make sure any cleanups for the return + expression get run. + (build_c_cast): Use CONVERT_EXPR for conversion to void. + + * pt.c (do_type_instantiation): Also instantiate nested types. + + * typeck.c (convert_for_assignment): Don't die when comparing + pointers with different levels of indirection. + + * decl.c (grokdeclarator): The sub-call to grokdeclarator for + class-local typedefs sets DECL_ARGUMENTS, so we need to clear it + out. + + * decl2.c (finish_anon_union): Don't die if the union has no + members. + + * decl.c (grokdeclarator): Undo changes to declspecs when we're done + so that 'typedef int foo, bar;' will work. + + * decl2.c (finish_file): Don't call expand_aggr_init for + non-aggregates. + +Mon Jul 25 00:03:10 1994 Teemu Torma <tot@trema.fi> + + * decl.c (finish_function): We can't inline constructors and + destructors under some conditions with -fpic, but don't unset + DECL_INLINE. + +Mon Jul 25 00:03:10 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_object_ref): Make sure 'datum' is a valid object. + +Sun Jul 24 14:19:31 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Don't set DECL_FIELD_BITPOS on + non-fields. + (finish_struct_methods): Use copy_assignment_arg_p. + + * cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead + of giving an error. + + * typeck.c (build_binary_op_nodefault): Don't set result_type if we + don't know how to compare the operands. + + * decl.c (grokdeclarator): Avoid seg fault when someone uses '__op' + as a declarator-id in their program. Like the Linux headers do. + Arrgh. + + * tree.c (lvalue_p): Treat calls to functions returning objects by + value as lvalues again. + + * typeck.c (build_component_addr): Use convert_force to convert the + pointer in case the component type is also a private base class. + + * search.c (get_matching_virtual): Fix bogus warning of overloaded + virtual. + + * pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created + TYPE_DECL to fix bogus shadowing warnings. + +Fri Jul 22 01:15:32 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (expand_aggr_init_1): const and volatile mismatches do not + prevent a TARGET_EXPR from initializing an object directly. + +Tue Jul 19 17:55:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (build_up_reference): Allow building up references to + `this', don't warn about making references to artificial variables + (like `this'). + + * tree.c (lvalue_p): `this' is not an lvalue. + + * call.c (build_method_call): Accept using a typedef name (or + template type parameter) for explicit destructor calls. + +Thu Jul 14 09:42:23 1994 Mike Stump <mrs@cygnus.com> + + * Version 2.6.0 released. + +Wed Jul 13 03:57:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * method.c (hack_identifier): Put back old code so lists of + non-functions will be handled properly. + + * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now + defined in the language-independent tree.h. + + * tree.c (count_functions): Avoid bogus warning when compiling this + function. + +Mon Jul 11 18:37:20 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grok_reference_init): Always save the initializer of a + reference. + +Fri Jul 8 17:41:46 1994 Mike Stump <mrs@cygnus.com> + + * decl.c (cplus_expand_expr_stmt): Wrap statement expressions inside + CLEANUP_POINT_EXPRs so that the stack slots can be reused. + (disabled for now) + +Fri Jul 8 12:59:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * method.c (hack_identifier): Fix for new overloading. + + * typeck.c (build_binary_op_nodefault): Don't mess with division by + zero. + +Fri Jul 8 13:20:28 1994 Gerald Baumgartner <gb@cs.purdue.edu> + + * decl2.c (finish_file): Only call walk_sigtables, if + flag_handle_signatures is turned on, don't waste time otherwise. + +Fri Jul 8 02:27:41 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (push_overloaded_decl): Don't create overloads of one when + shadowing a class type. + * typeck.c (build_x_function_call): Complain about overloads of one. + + * decl.c (grokdeclarator): Don't try to treat a char* as a tree. + (grokdeclarator): Fix setting of TREE_STATIC. + (start_decl): Clear DECL_IN_AGGR_P after calling duplicate_decls. + +Thu Jul 7 22:20:46 1994 Gerald Baumgartner <gb@andros.cygnus.com> + + * cp-tree.h (walk_sigtables): Created extern declaration. + * decl2.c (walk_sigtables): Created function, patterned after + walk_vtables, even though we only need it to write out sigtables. + (finish_sigtable_vardecl): Created function. + (finish_vtable_vardecl): Changed 0 to NULL_PTR. + (finish_file): Call walk_sigtables. + + * sig.c (build_signature_table_constructor): Mark class member + function pointed to from signature table entry as addressable. + +Thu Jul 7 13:39:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (start_decl): Check new decl of static member variable + against the declaration in the class here. + (grokvardecl): Instead of here. + + * class.c (prepare_fresh_vtable): Call import_export_vtable if not + -fvtable-thunks. + (build_vtable): Likewise. + + * decl2.c (import_export_vtable): Move logic for deciding the + interface of a template class from here. + (import_export_template): To here. + (finish_vtable_vardecl): Call import_export_template before + import_export_vtable. + +Wed Jul 6 20:25:48 1994 Mike Stump <mrs@cygnus.com> + + * except.c (init_exception_processing): Setup interim_eh_hook to + call lang_interim_eh. + * except.c (do_unwind): Propagate throw object value across + stack unwinding. + * except.c (saved_throw_value): Used to hold the value of the object + being thrown. It is always a reference to the real value. + * except.c (expand_start_catch_block): Add handling for the + value of the exception object. + * except.c (expand_start_catch_block): Add handler for the handler, + so that throws inside the handler go to the outer block. + * except.c (expand_end_catch_block): Likewise. + * parse.y (handler_args): Use parm instead, as the other doesn't yet + handle references correctly. + +Wed Jul 6 17:55:32 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl2.c (mark_vtable_entries): If -ftable-thunks, set the + vtable entry properly to abort. + +Tue Jul 5 14:07:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Downgrade division by zero + errors to warnings. + + * call.c (build_overload_call_real): Handle fnname being a list of + functions. + * typeck.c (build_x_function_call): Pass list of functions to + build_overload_call, not just the name. + * tree.c (count_functions): Complain when called for invalid + argument. + + * decl.c (grokdeclarator): Fix settings of TREE_STATIC, TREE_PUBLIC + and DECL_EXTERNAL on static members and initialized const members. + * decl2.c (grokfield): Reflect this change. + +Fri Jul 1 09:35:51 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (init): ANSI C++ does not forbid { }. + +Thu Jun 30 00:35:22 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (lang_decode_option): Set warn_nonvdtor along with -Wall. + warn_nonvdtor defaults to off. + + * class.c (instantiate_type): Use comptypes rather than relying on + types to satisfy ==. + + * decl.c (start_function): Set DECL_DEFER_OUTPUT on all inlines that + might be static. + + * tree.c (build_cplus_new): Never build WITH_CLEANUP_EXPRs. + + * decl.c (grok_reference_init): Deal with ADDR_EXPRs of TARGET_EXPRs. + + * cvt.c (cp_convert): Pass 0 to with_cleanup_p arg of + build_cplus_new. + +Wed Jun 29 22:31:09 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (finish_file): Maybe consider static inlines multiple + times, in case they reference each other. + +Tue Jun 28 11:58:38 1994 Gerald Baumgartner <gb@cs.purdue.edu> + + * class.c (finish_struct): Don't `cons_up_default_function's + for signatures. + (finish_struct): Handle an empty method_vec correctly. + + * decl.c (grokdeclarator): Don't warn about a signature being + empty in a signature pointer declaration if we only saw a + forward declaration of the signature. Changed `warning's into + `cp_warning's. + + * sig.c (build_sigtable): Don't die if a null signature table + constructor is returned. + (build_signature_pointer_constructor): If the signature table + constructor is null, the _sptr field is set to a null pointer + and cast to the appropriate type. Make copies of all null + pointers so that the type null_pointer_node doesn't get changed. + (build_signature_table_constructor): Added comments. + + * sig.c (build_signature_pointer_constructor): Complain if we + try to assign to/initialize a signature pointer/reference of + an undefined signature. + +Mon Jun 27 14:05:16 1994 Gerald Baumgartner <gb@cs.purdue.edu> + + * typeck2.c (store_init_value): Don't be pedantic about + non-constant initializers of signature tables/pointers/references. + +Fri Jun 24 16:49:41 1994 Gerald Baumgartner <gb@cs.purdue.edu> + + * decl.c (grokdeclarator): If we are grokking an opaque typedef + in a signature, don't complain about it begin static. + +Wed Jun 29 16:44:45 1994 Mike Stump <mrs@cygnus.com> + + Fixes a problem of the this pointer being wrong in virtual calls to + methods that are not overridden in more derived classes. + + * class.c (fixup_vtable_delta): New routine. It will fixup the + delta entries in vtables, wheever they need updating. + * class.c (finish_struct): Call the new routine for all virtual + bases, as they can have different offsets, than those used in base + classes that we derive our vtable from. + +Tue Jun 28 23:49:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_binary_op): Use the types before default + conversions in the error message. + + * *.c: Use c_build_type_variant instead of build_type_variant where + the type might be an array. + + * call.c (build_method_call): Call build_type_variant and + build_reference_type in the right order. + * decl.c (record_builtin_type): Likewise. + +Wed Jun 29 16:58:53 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Call build_type_variant and + build_reference_type in the right order. + * decl.c (record_builtin_type): Likewise. + +Tue Jun 28 23:49:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_binary_op): Use the types before default + conversions in the error message. + + * *.c: Use c_build_type_variant instead of build_type_variant where + the type might be an array. + +Sat Jun 25 11:50:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): Try UDC's before doing the + reinterpret_cast thang, though. + +Fri Jun 24 01:24:01 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (c_expand_return): Don't USE the return value location + after we've expanded the jump. + + * decl2.c (finish_file): Make sure DECL_SAVED_INSNS is not 0 before + trying to write out an inline. + + * cvt.c (build_up_reference): Also do address adjustment when the + target type uses MI. + (convert_to_reference): Try UDCs only after built-in conversions. + (build_type_conversion_1): Don't play games with the argument to the + method. + (build_type_conversion): #if 0 out code for binding to reference. + +Thu Jun 23 00:22:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (finish_file): Use TREE_SYMBOL_REFERENCED to decide + whether to emit inlines. + + * decl.c (grokdeclarator): Set explicit_int for decls that just + specify, say, 'long'. + + * init.c (do_friend): Do overload C functions (or call pushdecl, + anyaway). + +Wed Jun 22 13:40:49 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (build_up_reference): Don't call readonly_error. + (convert_to_reference): Propagate const and volatile from expr to + its type. + + * tree.c (lvalue_p): Random CALL_EXPRs are not lvalues. + + * cvt.c (build_up_reference): Break out WITH_CLEANUP_EXPR when + creating a temporary. + (convert_to_reference): Lose excessive and incorrect trickiness. + (cp_convert): Call build_cplus_new with with_cleanup_p set. + + * typeck2.c (build_functional_cast): Likewise. + +Tue Jun 21 17:38:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): signed, unsigned, long and short all + imply 'int'. + + * decl.c (grokdeclarator): Allow "this is a type" syntax. + (grok_reference_init): Simplify and fix. + +Sun Jun 19 17:08:48 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): pedwarn about a typedef that specifies no + type. + +Sat Jun 18 04:16:50 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (start_function): Move TREE_PUBLIC and DECL_EXTERNAL + tinkering to after call to pushdecl. + +Fri Jun 17 14:48:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Handle destructors for non-aggregate + types properly. + +Thu Jun 16 16:48:05 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Make sure that the name given for the + destructor matches the constructor_name of the instance. + + * pt.c (do_function_instantiation): A non-extern instantiation + overrides a later extern one. + (do_type_instantiation): Likewise. + +Wed Jun 15 19:34:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (expand_aggr_init): Use TYPE_MAIN_VARIANT to get the + unqualified array type. + + * cp-tree.h (EMPTY_CONSTRUCTOR_P): Tests whether NODE is a + CONSTRUCTOR with no elements. + + * decl.c (various): Lose empty_init_node. + (finish_decl): Use EMPTY_CONSTRUCTOR_P, do the empty CONSTRUCTOR + thing depending on the value of DECL_COMMON instead of + flag_conserve_space, do the empty CONSTRUCTOR thing for types that + don't have constructors, don't treat a real empty CONSTRUCTOR + specially. + + * typeck2.c (process_init_constructor): Don't treat empty_init_node + specially. + +Wed Jun 15 19:05:25 1994 Mike Stump <mrs@cygnus.com> + + * class.c (override_one_vtable): Don't forget to merge in an old + overrider when we wanted to reuse a vtable, but couldn't. + +Wed Jun 15 15:03:16 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (start_decl): Put statics in common again. + + * decl.c (grokdeclarator): Return NULL_TREE for an error rather than + setting the type to error_mark_node. + + * typeck.c (build_modify_expr): Build up a COMPOUND_EXPR for enum + bitfield assignments. + +Tue Jun 14 12:23:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grok_op_properties): Const objects can be passed by value. + +Mon Jun 13 03:10:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (import_export_vtable): Force implicit instantiations to + be interface_only when -fno-implicit-templates. + + * decl.c (duplicate_decls): Redeclaring a class template name is an + error. + + * pt.c (end_template_decl): Call GNU_xref_decl for class templates. + * xref.c (GNU_xref_decl): Support templates. + +Sat Jun 11 17:09:05 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grok_op_properties): Split out checking for whether this + function should suppress the default assignment operator. + * decl2.c (grok_function_init): Likewise. + (copy_assignment_arg_p): New function do do just that. + Now considers virtual assignment operators that take a base as an + argument to count as copy assignment operators. + + * search.c (dfs_debug_mark): Lose checks for DWARF_DEBUG and + TREE_ASM_WRITTEN, as they are redundant. + + * pt.c (end_template_decl): Don't try to set DECL_CLASS_CONTEXT on a + decl that has no LANG_SPECIFIC part. + (do_type_instantiation): Force the debugging information for this + type to be emitted. + + * decl.c (start_decl): Clear up uses of various types of templates + (say sorry for static data members, rather than "invalid template"). + (expand_static_init): Fix initialization of static data members of + template classes. + +Fri Jun 10 00:41:19 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Set DECL_CONTEXT on static data members. + + * g++.c (main): Use -xc++-cpp-output for .i files. + + * pt.c (tsubst): Give meaningful error about declaring template for + a copy constructor which was not declared in the class template. + (do_type_instantiation): Explicit instantiation before the class + template is an error. + (instantiate_template): Don't die if tsubst returns error_mark_node. + +Thu Jun 9 19:04:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + Don't synthesize the copy assignment operator if the one in a base + class is pure virtual. + * cp-tree.h (TYPE_HAS_ABSTRACT_ASSIGN_REF): New macro to indicate + whether the type has a pure virtual copy assignment operator. + * class.c (finish_base_struct): Don't generate the copy assignment + operator if a base class has a pure virtual one. + * decl.c (grok_op_properties): Add disabled code to set + TYPE_HAS_ABSTRACT_ASSIGN_REF with comment pointing to where it is + actually set. + * decl2.c (grok_function_init): Set TYPE_HAS_ABSTRACT_ASSIGN_REF. + + * decl2.c (import_export_vtable): Always treat template + instantiations as if write_virtuals >= 2, and treat implicit + instantiations as external if -fno-implicit-templates. + (finish_file): Output all pending inlines if + flag_keep_inline_functions. + +Wed Jun 8 20:48:02 1994 Mike Stump <mrs@cygnus.com> + + * tree.c (layout_vbasetypes): Align virtual base classes inside + complete objects, so that we don't core dump on machines such as + SPARCs when we access members that require larger than normal + alignments, such as a double. Also, we bump up the total alignment + on the complete type, as necessary. + +Wed Jun 8 16:18:14 1994 Jason Merrill <jason@deneb.cygnus.com> + + * gxxint.texi (Free Store): New section with code for examining + cookie. + (Limitations of g++): Remove operator delete entry, since it is no + longer accurate. Fix access control entry. + + * typeck.c (build_unary_op): Pedwarn about taking the address of or + incrementing a cast to non-reference type. + (build_modify_expr): Use convert instead of convert_force again. + + * search.c (get_base_distance): Use IS_AGGR_TYPE_CODE to check for + class type, not == RECORD_TYPE. + + * decl.c (grokdeclarator): Cope with grokfndecl returning NULL_TREE. + + * typeck2.c (report_case_error): #if 0 out. + * lex.c (real_yylex): Lose RANGE. + * parse.y: Likewise. + +Tue Jun 7 18:17:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (simple_stmt, case ranges): Use ELLIPSIS instead of RANGE. + +Mon Jun 6 19:39:57 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_c_cast): Don't shortcut conversions to the same + type. Don't replace consts with their values here, since that's now + done in cp_convert. + + * cvt.c (cp_convert): When converting to bool, take + integer_zero_node to false_node and all other INTEGER_CSTs to + true_node. + (build_type_conversion): Don't complain about multiple conversions + to float if we're not really converting. + +Fri Jun 3 02:10:56 1994 Jason Merrill <jason@deneb.cygnus.com> + + Implement 'extern template class A<int>;' syntax for suppressing + specific implicit instantiations. + * cp-tree.h: Update prototypes for do_*_instantiation. + * pt.c (do_pending_expansions): Don't compile 'extern' explicit + instantiations. + (do_function_instantiation): Set DECL_EXTERNAL on 'extern' explicit + instantiations. + (do_type_instantiation): Likewise. + * parse.y (explicit_instantiation): Support 'extern template class + A<int>;' syntax. + * decl.c (start_function): Don't modify the settings of TREE_PUBLIC + and DECL_EXTERNAL on explicit instantiations. + + * cvt.c (cp_convert): Replace constants with their values before + converting. + (cp_convert): Consistently use 'e' instead of 'expr'. + +Thu Jun 2 03:53:30 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck2.c (build_x_arrow): Resolve OFFSET_REFs first. + +Wed Jun 1 18:57:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck2.c (digest_init): Handle initializing a pmf with an + overloaded method. + * typeck.c (build_ptrmemfunc): Handle overloaded methods. + + * decl.c (pushtag): Use build_decl to make TYPE_DECLs. + (xref_defn_tag): Likewise. + * pt.c (process_template_parm): Likewise. + (lookup_template_class): Likewise. + (push_template_decls): Likewise. + (instantiate_class_template): Likewise. + (create_nested_upt): Likewise. + * class.c (finish_struct): Don't try to set DECL_CLASS_CONTEXT on + TYPE_DECLs. + + * typeck.c (convert_arguments): Make sure type is not NULL before + checking its TREE_CODE. + +Wed Jun 1 17:40:39 1994 Mike Stump <mrs@cygnus.com> + + * class.c (get_derived_offset): New routine. + * class.c (finish_base_struct): Make sure we set BINFO_VTABLE and + BINFO_VIRTUALS when we choose a new base class to inherit from. + * class.c (modify_one_vtable): Use get_derived_offset to get the + offset to the most base class subobject that we derived this binfo + from. + * class.c (finish_struct): Move code to calculate the + DECL_FIELD_BITPOS of the vfield up, as we need might need it for + new calls to get_derived_offset in modify_one_vtable. + +Wed Jun 1 16:50:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (build_member_call): Use build_pointer_type instead of + TYPE_POINTER_TO. + +Wed Jun 1 11:11:15 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (grokdeclarator): Make sure we have a DNAME set before we + try to use it in an error. + +Wed Jun 1 09:48:49 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (convert_arguments, convert_for_initialization): Don't + strip NOP_EXPRs, when we are converting to a reference. + +Wed Jun 1 01:11:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_modify_expr): Don't dereference references when + initializing them. + + * decl2.c (grokfield): Don't check for grokdeclarator returning + error_mark_node any more. + + * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node. + (start_method): Return void_type_node instead of error_mark_node. + + * typeck.c (build_modify_expr): Resolve offset refs earlier. + +Tue May 31 16:06:58 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Resolve OFFSET_REFs in the object. + + * typeck.c (build_modify_expr): Dereference references before trying + to assign to them. + + * call.c (build_method_call): Don't confuse type conversion + operators with constructors. + * typeck2.c (build_functional_cast): Just call build_c_cast if there + was only one parameter. + * method.c (build_typename_overload): Don't set + IDENTIFIER_GLOBAL_VALUE on these identifiers. + * decl.c (grok_op_properties): Warn about defining a type conversion + operator that converts to a base class (or reference to it). + * cvt.c (cp_convert): Don't try to use a type conversion operator + when converting to a base class. + (build_type_conversion_1): Don't call constructor_name_full on an + identifier. + * cp-tree.h (DERIVED_FROM_P): Should be self-explanatory. + + * decl.c (start_decl): Don't complain that error_mark_node is an + incomplete type. + (finish_decl): Check for type == error_mark_node. + +Mon May 30 23:38:55 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (start_function): Set DECL_DEFER_OUTPUT on implicit + instantiations and inline members. + + * spew.c (yylex): Set looking_for_template if the next token is a '<'. + + * lex.h: Declare looking_for_template. + + * decl.c (lookup_name_real): Use looking_for_template to arbitrate + between type and template interpretations of an identifier. + +Sat May 28 04:07:40 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (instantiate_template): Zero out p if we found a + specialization. + + * decl.c (grokdeclarator): Elucidate warning. + (grokdeclarator): If pedantic AND -ansi, complain about long long. + + Make explicit instantiation work reasonably. It is now appropriate + to deprecate the use of -fexternal-templates. + * pt.c (instantiate_template): Set DECL_TEMPLATE_SPECIALIZATION or + DECL_IMPLICIT_INSTANTIATION on fndecl as appropriate. + (end_template_instantiation): Reflect changes in USE_TEMPLATE + semantics. + (do_pending_expansions): if (!flag_implicit_templates) DECIDE(0); + (do_function_instantiation): Don't set EXPLICIT_INST if + flag_external_templates is set. Do set TREE_PUBLIC and DECL_EXTERN + appropriately otherwise. + (do_type_instantiation): Set interface info for class. Set + TREE_PUBLIC and DECL_EXTERN for methods. Do none of this if + flag_external_templates is set. + * parse.y: Reflect changes in USE_TEMPLATE semantics. + * decl2.c: New flag flag_implicit_templates determines whether or + not implicit instantiations get emitted. This flag currently + defaults to true, and must be true for -fexternal-templates to work. + (finish_file): Consider flag_implement_inlines when + setting DECL_EXTERNAL. Consider flag_implicit_templates when + deciding whether or not to emit a static copy. + * decl.c (start_function): Set TREE_PUBLIC and DECL_EXTERNAL + properly for template instantiations. + (start_method): Set DECL_IMPLICIT_INSTANTIATION on methods of a + template class. + * cp-tree.h (CLASSTYPE_USE_TEMPLATE): Change semantics. + (DECL_USE_TEMPLATE): Parallel macro for FUNCTION and VAR_DECLs. + (various others): Accessor macros for the above. + +Fri May 27 13:57:40 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Division by constant zero is + an error. + +Fri May 27 13:50:15 1994 Mike Stump <mrs@cygnus.com> + + * class.c (override_one_vtable): Don't modify things we don't own. + +Fri May 27 01:42:58 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (finish_decl): Don't postpone processing the initializer of + a decl with DECL_EXTERNAL set, and do call rest_of_compilation for a + PUBLIC const at toplevel. + (grokdeclarator): pedwarn about initializing non-const or + non-integral statics in the class body. + + * decl.c (pushtag): Don't try to set DECL_CLASS_CONTEXT on a + TYPE_DECL. + + * call.c (convert_harshness): Dereference reference on rhs before + proceeding, properly grok passing const things to non-const + references. + + * typeck.c (build_unary_op): Soften error about taking the address + of main() to a pedwarn. + + * lex.c (default_copy_constructor_body): Unambiguously specify base + classes (i.e. A((const class ::A&)_ctor_arg) ). + (default_assign_ref_body): Likewise. + +Thu May 26 13:13:55 1994 Gerald Baumgartner <gb@mexican.cygnus.com> + + * decl2.c (grokfield): Don't complain about local signature + method declaration without definition. + + * call.c (convert_harshness): If `type' is a signature pointer + and `parmtype' is a pointer to a signature, just return 0. We + don't really convert in this case; it's a result of making the + `this' parameter of a signature method a signature pointer. + + * call.c (build_method_call): Distinguish calling the default copy + constructor of a signature pointer/reference from a signature + member function call. + +Thu May 26 12:56:25 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (grokfield): Don't set TREE_PUBLIC on member function + declarations. + + * decl.c (duplicate_decls): A previous function declaration as + static overrides a subsequent non-static definition. + (grokdeclarator): Don't set TREE_PUBLIC on inline method + declarations. + +Wed May 25 14:36:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Handle initialization of static const + members. + (finish_decl): Likewise. + + * decl2.c (grokfield): Allow initialization of static const members + even when pedantic. + + * decl2.c (grokfield): Deal with grokdeclarator returning + error_mark_node. + + * decl.c (grok_ctor_properties): Return 0 for A(A) constructor. + (grokfndecl): Check the return value of grok_ctor_properties. + (start_method): Likewise. + + * parse.y (absdcl): Expand type_quals inline. + +Tue May 24 19:10:32 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (pushtag): Use IS_AGGR_TYPE rather than checking for a + RECORD_TYPE. + +Tue May 24 18:09:16 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks, + always use "__vt_%s". + * decl2.c (finish_vtable_vardecl): Don't consider abstract virtuals + when looking for a "sentinal" method (to decide on emitting vtables). + * decl2.c (finish_file): Scan all decls for thunks that need + to be emitted. + * decl2.c (finish_vtable_vardecl): Don't bother calling emit_thunk. + * method.c (make_thunk): Use a more meaningful label. If there + exists a matching top-level THUNK_DECL re-use it; otherwise + create a new THUNK_DECL (and declare it). + * method.c (emit_thunk): Make thunk external/public depending + on the underlying method. + +Tue May 24 00:22:04 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (tsubst): Use lookup_name_nonclass to find guiding decls, not + lookup_name. + + * call.c (build_overload_call_real): Don't immediately pick a + function which matches perfectly. + + * decl.c (grokdeclarator): Use c_build_type_variant for arrays. + (grokdeclarator): Warn about, and throw away, cv-quals attached to a + reference (like 'int &const j'). + + * typeck.c (convert_arguments): Don't mess with i for methods. + * call.c (build_method_call): Pass the function decl to + convert_arguments. + + * typeck.c (comp_ptr_ttypes_real): New function. Implements the + checking for which multi-level pointer conversions are allowed. + (comp_target_types): Call it. + (convert_for_assignment): Check const parity on the ultimate target + type, too. And make those warnings pedwarns. + +Mon May 23 14:11:24 1994 Jason Merrill <jason@deneb.cygnus.com> + + * error.c (dump_char): Use TARGET_* for character constants. + +Mon May 23 13:03:03 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * tree.c (debug_no_list_hash): Make static. + + * decl.c (decls_match): Say the types don't match if newdecl ends up + with a null type, after we've checked if olddecl does. + (pushdecl): Check if the decls themselves match before looking for + an extern redeclared as static, to avoid inappropriate and incorrect + warnings. + +Fri May 20 14:04:34 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Make warning about duplicate short, etc. + a pedwarn. + + * typeck.c (build_c_cast): Casting to function or method type is an + error. + + * class.c (finish_struct): Make warning for anonymous class with no + instances a pedwarn. + + * Makefile.in (stamp-parse): Expect a s/r conflict. + + * typeck.c (build_modify_expr): pedwarn about using a non-lvalue + cast as an lvalue. + +Thu May 19 12:08:48 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (type_promotes_to): Make sure bool promotes to int rather + than unsigned on platforms where sizeof(char)==sizeof(int). + +Wed May 18 14:27:06 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_c_cast): Tack on a NOP_EXPR when casting to + another variant. + (build_modify_expr): Don't strip NOP_EXPRs, and don't get tricky + and treat them as lvalues. + + * decl.c (shadow_tag): Do complain about forward declarations of + enums and empty declarations. + * parse.y: Don't complain about forward declarations of enums and + empty declarations. + + * typeck.c (convert_for_assignment): Complain about changing + the signedness of a pointer's target type. + + * parse.y (stmt): Move duplicated code for checking case values from + here. + * decl2.c (check_cp_case_value): To here. And add a call to + constant_expression_warning. + + * typeck.c (convert_for_assignment): Don't complain about assigning + a negative value to bool. + + * decl.c (init_decl_processing): Make bool unsigned. + + * class.c (finish_struct): Allow bool bitfields. + +Wed May 18 12:35:27 1994 Ian Lance Taylor <ian@tweedledumb.cygnus.com> + + * Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp. + +Wed May 18 03:28:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (build_type_conversion): Lose special handling of + truthvalues. + + * search.c (dfs_pushdecls): Improve shadowing warning. + +Tue May 17 13:34:46 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (build_delete): Throw away const and volatile on `this'. + + * decl.c (finish_enum): Put the constants in TYPE_VALUES again, + rather than the enumerators. + (pushtag): s/cdecl/c_decl/g + +Mon May 16 23:04:01 1994 Stephen R. van den Berg <berg@pool.informatik.rwth-aachen.de> + + * cp/typeck.c (common_type): Attribute merging. + (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro. + + * cp/parse.y: Revamp attribute parsing. + +Mon May 16 01:40:34 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (shadow_tag): Also check for inappropriate use of auto and + register. + + * method.c (build_overload_name): Clarify that the illegal case is a + pointer or reference to array of unknown bound. + + * error.c (dump_type_prefix): Print references to arrays properly. + + * typeck.c (various): Be more helpful in pointer + comparison diagnostics. + + * tree.c (lvalue_p): MODIFY_EXPRs are lvalues again. Isn't this + fun? + + * parse.y: Also catch an error after valid stmts. + + * search.c (dfs_init_vbase_pointers): Don't abort because `this' is + const. + + * typeck.c (convert_for_initialization): If call to + convert_to_reference generated a diagnostic, print out the parm + number and function decl if any. + + * errfn.c (cp_thing): Check atarg1 to determine whether or not we're + specifying a line, not atarg. + + * tree.c (build_cplus_method_type): Always make `this' const. + + * decl2.c (grokclassfn): If -fthis-is-variable and this function is + a constructor or destructor, make `this' non-const. + + * typeck.c (build_modify_expr): Don't warn specially about + assignment to `this' here anymore, since it will be caught by the + usual machinery. + + * various: Disallow specific GNU extensions (variable-size arrays, + etc.) when flag_ansi is set, not necessarily when pedantic is set, + so that people can compile with -pedantic-errors for tighter const + checking and such without losing desirable extensions. + + * typeck2.c (build_functional_cast): Call build_method_call with + LOOKUP_PROTECT. + (process_init_constructor): Only process FIELD_DECLs. + + * decl.c (finish_decl): Also force static consts with no explicit + initializer that need constructing into the data segment. + + * init.c (build_delete): Undo last patch, as it interferes with + automatic cleanups. + +Sat May 14 01:59:31 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c, class.h, cp-tree.h, cvt.c, decl2.c: Lose old overloading + code. + + * init.c (build_delete): pedwarn about using plain delete to delete + an array. + +Fri May 13 16:45:07 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (comp_target_types): Be more helpful in contravariance + warnings, and make them pedwarns. + + * decl.c (grokdeclarator): Use decl_context to decide whether or not + this is an access declaration. + + * class.c (finish_struct_bits): Set TYPE_HAS_INT_CONVERSION if it + has a conversion to enum or bool, too. + +Fri May 13 16:31:27 1994 Mike Stump <mrs@cygnus.com> + + * method.c (emit_thunk): Make declaration for + current_call_is_indirect local (needed for hppa). + +Fri May 13 16:16:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (uses_template_parms): Grok BOOLEAN_TYPE. + (tsubst): Likewise. + +Fri May 13 16:23:32 1994 Mike Stump <mrs@cygnus.com> + + * pt.c (tsubst): If there is already a function for this expansion, + use it. + * pt.c (instantiate_template): Likewise. + +Fri May 13 10:30:42 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * parse.y (implicitly_scoped_stmt, simple_stmt case): Use + kept_level_p for MARK_ENDS argument to expand_end_bindings, to avoid + generating debug info for unemitted symbols on some systems. + + * cp-tree.h (build_static_cast, build_reinterpret_cast, + build_const_cast): Add declarations. + +Fri May 13 09:50:31 1994 Mike Stump <mrs@cygnus.com> + + * search.c (expand_indirect_vtbls_init): Fix breakage from Apr 27 + fix. We now try get_binfo, and if that doesn't find what we want, + we go back to the old method, which still sometimes fails. + +Fri May 13 01:43:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (initdcl): Call cplus_decl_attributes on the right + variable. + * decl2.c (cplus_decl_attributes): Don't call decl_attributes for + void_type_node. + + * typeck.c (build_binary_op_nodefault): Change result_type for + comparison ops to bool. + (build_binary_op): Convert args of && and || to bool. + * cvt.c (build_default_binary_type_conversion): Convert args of && + and || to bool. + (build_default_unary_type_conversion): Convert arg of ! to bool. + (type_promotes_to): bool promotes to int. + +Fri May 13 01:43:18 1994 Mike Stump <mrs@cygnus.com> + + Implement the new builtin `bool' type. + * typeck.c (build_binary_op_nodefault): Convert args of && and || to + bool. + (build_unary_op): Convert arg of ! to bool. + * parse.y: Know true and false. Use bool_truthvalue_conversion. + * method.c (build_overload_value): Know bool. + (build_overload_name): Likewise. + * lex.c (init_lex): Set up RID_BOOL. + * gxx.gperf: Add bool, true, false. + * error.c (*): Know bool. + * decl.c (init_decl_processing): Set up bool, true, false. + * cvt.c (cp_convert): Handle conversion to bool. + (build_type_conversion): Likewise. + * *.c: Accept bool where integers and enums are accepted (use + INTEGRAL_CODE_P macro). + +Thu May 12 19:13:54 1994 Richard Earnshaw <rwe11@cl.cam.ac.uk> + + * g++.c: Use #ifdef for __MSDOS__, not #if. + +Thu May 12 18:05:18 1994 Mike Stump <mrs@cygnus.com> + + * decl2.c (lang_f_options): Handle -fshort-temps. -fshort-temps + gives old behavior , and destroys temporaries earlier. Default + behavior now conforms to the ANSI working paper. + +Thu May 12 14:45:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_modify_expr): Understand MODIFY_EXPR as an lvalue. + Use convert_force to convert the result of a recursive call when we + are dealing with a NOP_EXPR. Don't automatically wrap MODIFY_EXPRs + in COMPOUND_EXPRs any more. + (various): Lose pedantic_lvalue_warning. + (unary_complex_lvalue): Understand MODIFY_EXPR. + + * cvt.c (convert_to_reference): Allow DECL to be error_mark_node if + we don't know what we're initializing. + +Wed May 11 01:59:36 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): Modify to use convtype parameter. + Only create temporaries when initializing a reference, not when + casting. + (cp_convert): New main function. + (convert): Call cp_convert. + * cvt.c, decl.c, typeck.c: Fix calls to convert_to_reference. + * cp-tree.h (CONV_*): New constants used by conversion code for + selecting conversions to perform. + + * tree.c (lvalue_p): MODIFY_EXPRs are no longer lvalues. + + * typeck.c (build_{static,reinterpret,const_cast): Stubs that just + call build_c_cast. + * parse.y: Add {static,reinterpret,const}_cast. + * gxx.gperf: Likewise. + + * typeck.c (common_type): Allow methods with basetypes of different + UPTs. + (comptypes): Deal with UPTs. + (build_modify_expr): Wrap all MODIFY_EXPRs in a COMPOUND_EXPR. + + * pt.c (end_template_decl): Check for multiple definitions of member + templates. + + * call.c (build_method_call): Complain about calling an abstract + virtual from a constructor. + + * typeck.c (pointer_int_sum): Check for the integer operand being 0 + after checking the validity of the pointer operand. + + * typeck2.c (digest_init): Pedwarn about string initializer being + too long. + +Tue May 10 12:10:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (push_overloaded_decl): Only throw away a builtin if the + decl in question is the artificial one. + + * parse.y (simple_stmt, switch): Use implicitly_scoped_stmt because + expand_{start,end}_case cannot happen in the middle of a block. + + * cvt.c (build_type_conversion_1): Use convert again. + +Tue May 10 11:52:04 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * typeck2.c (digest_init): Make sure we check for signed and + unsigned chars as well when warning about string initializers. + + * init.c (emit_base_init): Check if there's a DECL_NAME on the + member before trying to do an initialization for it. + +Tue May 10 11:34:37 1994 Mike Stump <mrs@cygnus.com> + + * except.c: Don't do anything useful when cross compiling. + +Tue May 10 03:04:13 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (duplicate_decls): Fix up handling of builtins yet again. + (push_overloaded_decl): Likewise. + + * cvt.c (convert): Don't look for void type conversion. + +Mon May 9 18:05:41 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (do_friend): Only do a pushdecl for friends, not + pushdecl_top_level. + +Mon May 9 13:36:34 1994 Jim Wilson <wilson@sphagnum.cygnus.com> + + * decl.c (lookup_name_current_level): Put empty statement after + the label OUT to make the code valid C. + +Mon May 9 12:20:57 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_binary_op_nodefault): Only complain about + comparing void * and a function pointer if void * is smaller. + +Sun May 8 01:29:13 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (lookup_name_current_level): Move through temporary binding + levels. + + * parse.y (already_scoped_stmt): Revive. + (simple_stmt): Use it again. + + * decl.c (poplevel): Always call poplevel recursively if we're + dealing with a temporary binding level. + +Sat May 7 10:52:28 1994 Mike Stump <mrs@cygnus.com> + + * decl.c (finish_decl): Make sure we run cleanups for initial values + of decls. Cures memory leak. + * decl.c (expand_static_init): Likewise for static variables. + * decl2.c (finish_file): Likewise for globals. + +Sat May 7 03:57:44 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (commonparms): Don't complain about redefining default + args. + + * decl.c (duplicate_decls): Don't complain twice about conflicting + function decls. + (decls_match): Don't look at default args. + (redeclaration_error_message): Complain about redefining default + args. + + * call.c (build_overload_call_real): Also deal with guiding + declarations coming BEFORE the template decl. + + * pt.c (unify): Allow different parms to have different + cv-qualifiers. + (unify): Allow trivial conversions on non-template parms. + +Fri May 6 03:53:23 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (tsubst): Support OFFSET_TYPEs. + (unify): Likewise. + + * decl2.c (finish_decl_parsing): Call push_nested_class with a type. + + * init.c (build_offset_ref): Fix error message. + * search.c (lookup_field): Likewise. + + * call.c (build_scoped_method_call): Pass binfo to + build_method_call. + * typeck.c (build_object_ref): Likewise. + + * typeck2.c (binfo_or_else): Don't return a _TYPE. + + * class.c (finish_struct): Don't complain about re-use of inherited + names or shadowing of type decls. + * decl.c (pushdecl_class_level): Likewise. + + * decl.c (finish_enum): Set the type of all the enums. + + * class.c (finish_struct): Don't get confused by access decls. + + * cp-tree.h (TYPE_MAIN_DECL): New macro to get the _DECL for a + _TYPE. You can stop using TYPE_NAME for that now. + + * parse.y: Lose doing_explicit (check $0 instead). + * gxx.gperf: 'template' now has a RID. + * lex.h (rid): Likewise. + * lex.c (init_lex): Set up the RID for 'template'. + + * parse.y (type_specifier_seq): typed_typespecs or + nonempty_type_quals. Use it. + (handler_args): Fix bogus syntax. + (raise_identifier{,s}, optional_identifier): Lose. + * except.c (expand_start_catch_block): Use grokdeclarator to parse + the catch variable. + (init_exception_processing): The second argument to + __throw_type_match is ptr_type_node. + + Fri May 6 07:18:54 1994 Chip Salzenberg <chip@fin.uucp> + + [ change propagated from c-decl.c of snapshot 940429 ] + * cp/decl.c (finish_decl): Setting asmspec_tree should not + zero out the old RTL. + +Fri May 6 01:25:38 1994 Mike Stump <mrs@cygnus.com> + + Add alpha exception handling support to the compiler. + Quick and dirty backend in except.c. + + * cp/*: Remove most remnants of old exception handling support. + * decl.c (finish_function): Call expand_exception_blocks to put + the exception hanlding blocks at the end of the function. + * dec.c (hack_incomplete_structures): Make sure expand_decl_cleanup + comes after expand_decl_init. + * except.c: Reimplementation. + * expr.c (cplus_expand_expr): Handle THROW_EXPRs. + * lex.c (init_lex): Always have catch, try and throw be reserved + words, so that we may always parse exception handling. + * parse.y: Cleanup to support new interface into exception handling. + * tree.def (THROW_EXPR): Add. + +Thu May 5 17:35:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (simple_stmt, for loops): Use implicitly_scoped_stmt. + (various): Lose .kindof_pushlevel and partially_scoped_stmt. + +Thu May 5 16:17:27 1994 Kung Hsu <kung@mexican.cygnus.com> + + * parse.y (already_scoped_stmt): move expand_end_binding() to + fix the unmatched LBB/LBE in stabs. + +Thu May 5 14:36:17 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (set_nested_typename): Set TREE_MANGLED on the new + identifiers. + (pushdecl): Check TREE_MANGLED. + (xref_tag): Likewise. + * cp-tree.h (TREE_MANGLED): This identifier is a + DECL_NESTED_TYPENAME (named to allow for future use to denote + mangled function names as well). + + Implement inconsistency checking specified in [class.scope0]. + * decl.c (lookup_name_real): Don't set ICV here after all. + (finish_enum): Also set the type of the enumerators themselves. + (build_enumerator): Put the CONST_DECL in the list instead of its + initial value. + (pushdecl_class_level): Check inconsistent use of a name in the + class body. + * class.c (finish_struct): Check inconsistent use of a name in the + class body. Don't set DECL_CONTEXT on types here anymore. + * parse.y (qualified_type_name): Note that the identifier has now + been used (as a type) in the class body. + * lex.c (do_identifier): Note that the identifier has now been used + (as a constant) in the class body. + * error.c (dump_decl): Print type and enum decls better. + +Thu May 5 09:35:35 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * typeck.c (build_modify_expr): Warn about assignment to `this'. + +Wed May 4 15:55:49 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (build_delete): Use the global operator delete when + requested. + + * decl.c (lookup_name_real): If we find the type we're looking in a + base class while defining a class, set IDENTIFIER_CLASS_VALUE for + the type. + + * class.c (finish_struct): Remove a couple of dependencies on + language linkage. + + * decl.c (pushtag): Classes do nest in extern "C" blocks. + (pushdecl): Only set DECL_NESTED_TYPENAME on the canonical one for + the type. + (pushtag): Remove another dependency on the language linkage. + + * lex.c (cons_up_default_function): Don't set DECL_CLASS_CONTEXT to + a const-qualified type. + + * decl.c (push_overloaded_decl): Throw away built-in decls here. + (duplicate_decls): Instead of here. + +Wed May 4 15:27:40 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * typeck.c (get_member_function_from_ptrfunc): Do The Right + Thing (I hope) if we're using thunks. + +Wed May 4 13:52:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (specialization): aggr template_type_name ';'. + (named_class_head_sans_basetype): Use it. + (explicit_instantiation): Likewise. + (tmpl.2): Revert. + + * cvt.c (build_type_conversion_1): Use convert_for_initialization, + rather than convert, to do conversions after the UDC. + + * cp-tree.h (SHARED_MEMBER_P): This member is shared between all + instances of the class. + + * search.c (lookup_field): If the entity found by two routes is the + same, it's not ambiguous. + +Wed May 4 12:10:00 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (lookup_name_real): Check for a NULL TREE_VALUE, + to prevent the compiler from crashing ... + +Wed May 4 11:19:45 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): If we don't have an object, check + basetype_path to figure out where to look up the function. + + * typeck.c (convert_for_initialization): Pass TYPE_BINFO (type) to + build_method_call in case exp is NULL_TREE. + +Tue May 3 16:02:53 1994 Per Bothner <bothner@kalessin.cygnus.com> + + Give a vtable entries a unique named type, for the sake of gdb. + * class.c (build_vtable_entry): The addres of a thunk now has + type vtable_entry_type, not ptr_type_node. + * method.c (make_thunk): Fix type of THUNK_DECL. + * class.c (add_virtual_function, override_one_vtable): Use + vfunc_ptr_type_node, instead of ptr_type_node. + * cp-tree.h (vfunc_ptr_type_node): New macro. + * decl.c (init_decl_processing): Make vtable_entry_type + be a unique type of pointer to a unique function type. + +Tue May 3 09:20:44 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (do_explicit): Sets doing_explicit to 1. + (explicit_instantiation): Use do_explicit rather than TEMPLATE + directly, add "do_explicit error" rule. + (datadef): Set doing_explicit to 0 after an explicit instantiation. + (tmpl.2): Don't instantiate if we see a ';' unless we're doing an + explicit instantiation. + (named_class_head_sans_basetype): Remove aggr template_type_name + ';' again. + +Mon May 2 23:17:21 1994 Jason Merrill <jason@deneb.cygnus.com> + + * search.c (lookup_nested_tag): Lose. + + * decl2.c (grokfield): Set DECL_CONTEXT on TYPE_DECLs. + (lookup_name_nonclass): Lose. + + * decl.c (poplevel_class): Add force parameter. + (lookup_name_real): Fix handling of explicit scoping which specifies + a class currently being defined. Add 'nonclass' argument. + (lookup_name, lookup_name_nonclass): Shells for lookup_name_real. + + * class.c (finish_struct): Don't unset IDENTIFIER_CLASS_VALUEs here. + (popclass): Force clearing of IDENTIFIER_CLASS_VALUEs if we're being + called from finish_struct. + +Mon May 2 19:06:21 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (init_decl_processing), cp-tree.h: Removed memptr_type. + (It seeems redundant, given build_ptrmemfunc_type.) + * typeck.c (get_member_function_from_ptrfunc), gc.c (build_headof, + build_classof): Use vtable_entry_type instead of memptr_type. + * method.c (emit_thunk): Call poplevel with functionbody==0 + to prevent DECL_INITIAL being set to a BLOCK. + +Mon May 2 15:02:11 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (named_class_head_sans_basetype): Add "aggr + template_type_name ';'" rule for forward declaration of + specializations. + +Mon May 2 15:02:11 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (instantiate_type): Deal with pmf's. + + * Make-lang.in (cc1plus): Don't depend on OBJS or BC_OBJS, since + stamp-objlist does. + + * Makefile.in (../cc1plus): Depend on OBJDEPS. + (OBJDEPS): Dependency version of OBJS. + +Mon May 2 12:51:31 1994 Kung Hsu <kung@mexican.cygnus.com> + + * search.c (dfs_debug_mark): unmark TYPE_DECL_SUPPRESS_DEBUG, not + DECL_IGNORED_P. + +Fri Apr 29 12:29:56 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Clear out memory of local tags. And + typedefs. + + * decl2.c (grokclassfn): Don't set DECL_CONTEXT to a cv-qualified + type. + * search.c (get_matching_virtual): Be more helpful in error message. + + * *: Use DECL_ARTIFICIAL (renamed from DECL_SYNTHESIZED). + + * lex.c (default_assign_ref_body): Expect TYPE_NESTED_NAME to work. + (default_copy_constructor_body): Likewise. + + * class.c (finish_struct): Don't gratuitously create multiple decls + for nested classes. + +Thu Apr 28 23:39:38 1994 Jason Merrill <jason@deneb.cygnus.com> + + Avoid clobbering the arg types of other functions when reverting + static member functions. + * decl.c (revert_static_member_fn): Rearrange arguments, don't + require values for 'fn' and 'argtypes', add warning to comment + above. + (decls_match): Rearrange arguments in call to rsmf. + (grok_op_properties): Don't pass values for fn and argtypes. + * pt.c (instantiate_template): Don't pass values for fn and argtypes. + +Thu Apr 28 16:29:11 1994 Doug Evans <dje@canuck.cygnus.com> + + * Make-lang.in (cc1plus): Depend on stamp-objlist. + * Makefile.in (BC_OBJS): Delete. + (OBJS): Cat ../stamp-objlist to get language independent files. + Include ../c-common.o. + (../cc1plus): Delete reference to BC_OBJS. + +Thu Apr 28 02:12:08 1994 Jason Merrill <jason@deneb.cygnus.com> + + * search.c (compute_access): No really, deal with static members + properly. Would I lie to you? + + Implement lexical hiding of function declarations. + * pt.c (tsubst): Use lookup_name to look for function decls to guide + instantiation. + * method.c (build_opfncall): Use lookup_name_nonclass to look for + non-member functions. + * init.c (do_friend): Use lookup_name_nonclass to look for + functions. + * error.c (ident_fndecl): Use lookup_name to look for functions. + * decl2.c (lookup_name_nonclass): New function, skips over + CLASS_VALUE. + * decl.c (struct binding_level): Lose overloads_shadowed field. + (poplevel): Don't deal with overloads_shadowed. + (push_overloaded_decl): Do lexical hiding for functions. + * class.c (instantiate_type): Don't check non-members if we have + members with the same name. + * call.c (build_method_call): Use lookup_name_nonclass instead of + IDENTIFIER_GLOBAL_VALUE to check for non-member functions. + (build_overload_call_real): Likewise. + + * decl.c (duplicate_decls): Check for ambiguous overloads here. + (push_overloaded_decl): Instead of here. + + * decl.c (pushdecl): Back out Chip's last change. + + * decl.c (grok_op_properties): operators cannot be static members. + + * cp-tree.h (DECL_SYNTHESIZED): DECL_SOURCE_LINE == 0 + (SET_DECL_SYNTHESIZED): DECL_SOURCE_LINE = 0 + * lex.c (cons_up_default_function): Use SET_DECL_SYNTHESIZED. + + * method.c (do_inline_function_hair): Don't put friends of local + classes into global scope, either. + + * typeck2.c (build_functional_cast): Don't look for a function call + interpretation. + +Thu Apr 28 15:19:46 1994 Mike Stump <mrs@cygnus.com> + + * cp-tree.h: disable use of backend EH. + +Wed Apr 27 21:01:24 1994 Doug Evans <dje@canuck.cygnus.com> + + * Make-lang.in (c++.distdir): mkdir tmp/cp first. + * Makefile.in (INCLUDES): Move definition to same place as + parent makefile. + (ALLOCA): Define. + (OLDAR_FLAGS): Delete. + (OLDCC): Define. + (DIR): Delete. + (CLIB): Define. + (####site): Delete. + (SUBDIR_USE_ALLOCA): Don't use ALLOCA if compiling with gcc. + +Wed Apr 27 19:10:04 1994 Kung Hsu <kung@mexican.cygnus.com> + + * decl.c (xref_tag): not to use strstr(), it's not available on + all platforms. + +Wed Apr 27 18:10:12 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Resolve yet another class/pmf confusion. + + * call.c (build_overload_call_real): Don't take the single-function + shortcut if we're dealing with an overloaded operator. + +Wed Apr 27 17:35:37 1994 Mike Stump <mrs@cygnus.com> + + * search.c (get_base_distance): Search the virtual base class + binfos, incase someone wants to convert to a real virtual base + class. + * search.c (expand_indirect_vtbls_init): Use convert_pointer_to_real + instead of convert_pointer_to, as it now will work. + +Wed Apr 27 15:36:49 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): Don't complain about casting away + const and volatile. + + * typeck.c (build_unary_op): References are too lvalues. + +Wed Apr 27 13:58:05 1994 Mike Stump <mrs@cygnus.com> + + * class.c (override_one_vtable): We have to prepare_fresh_vtable + before we modify it, not after, also, we cannot reuse an old vtable, + once we commit to a new vtable. Implement ambiguous overrides in + virtual bases as abstract. Hack until we make the class + ill-formed. + +Wed Apr 27 01:17:08 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (unary_expr): Expand new_placement[opt] and + new_initializer[opt] inline. + + * search.c (lookup_fnfields): Don't throw away the inheritance + information here, either. + (compute_access): Handle static members properly. + + * init.c (build_member_call): Always set basetype_path, and pass it + to lookup_fnfields. + + * search.c (lookup_field): Deal properly with the case where + xbasetype is a chain of binfos; don't throw away the inheritance + information. + (compute_access): protected_ok always starts out at 0. + + * init.c (resolve_offset_ref): Don't cast `this' to the base type + until we've got our basetype_path. + + * cp-tree.h (IS_OVERLOAD_TYPE): aggregate or enum. + + * cvt.c (build_up_reference): Use build_pointer_type rather than + TYPE_POINTER_TO. + + * call.c (convert_harshness_ansi): Call type_promotes_to for reals + as well. + + * cvt.c (type_promotes_to): Retain const and volatile, add + float->double promotion. + + * decl.c (grokdeclarator): Don't bash references to arrays into + references to pointers in function parms. Use type_promotes_to. + +Tue Apr 26 23:44:36 1994 Mike Stump <mrs@cygnus.com> + + Finish off Apr 19th work. + + * class.c (finish_struct_bits): Rename has_abstract_virtuals to + might_have_abstract_virtuals. + * class.c (strictly_overrides, override_one_vtable, + merge_overrides): New routines to handle virtual base overrides. + * class.c (finish_struct): Call merge_overrides to handle overrides + in virtual bases. + +Tue Apr 26 12:45:53 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_function_call): Call build_function_call_real with + LOOKUP_NORMAL. + + * *: Don't deal with TYPE_EXPRs. + + * tree.c (lvalue_p): If the type of the expression is a reference, + it's an lvalue. + + * cvt.c (convert_to_reference): Complain about passing const + lvalues to non-const references. + (convert_from_reference): Don't arbitrarily throw away const and + volatile on the target type. + + * parse.y: Simplify and fix rules for `new'. + + * decl.c (grok_op_properties): operator void is illegal. + +Mon Apr 25 02:36:28 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (components): Anonymous bitfields can still have declspecs. + + * decl.c (pushdecl): Postpone handling of function templates like we + do C functions. + + * search.c (expand_indirect_vtbls_init): Fix infinite loop when + convert_pointer_to fails. + + * call.c (compute_conversion_costs_ansi): A user-defined conversion + by itself is better than that UDC followed by standard conversions. + Don't treat integers and reals specially. + + * cp-tree.h: Declare flag_ansi. + + * typeck.c (c_expand_return): pedwarn on return in void function + even if the expression is of type void. + (build_c_cast): Don't do as much checking for casts to void. + (build_modify_expr): pedwarn about array assignment if this code + wasn't generated by the compiler. + + * tree.c (lvalue_p): A comma expression is an lvalue if its second + operand is. + + * typeck.c (default_conversion): Move code for promoting enums and + ints from here. + * cvt.c (type_promotes_to): To here. + * call.c (convert_harshness_ansi): Use type_promotes_to. Also fix + promotion semantics for reals. + +Sun Apr 24 16:52:51 1994 Doug Evans <dje@canuck.cygnus.com> + + * Make-lang.in (c++.install-common): Check for g++-cross. + * Makefile.in: Remove Cygnus cruft. + (config.status): Delete. + (RTL_H): Define. + (TREE_H): Use complete pathname, some native makes have minimal + VPATH support. + (*.o): Use complete pathname to headers in parent dir. + (doc, info, dvi): Delete. + +Sun Apr 24 16:52:51 1994 Doug Evans <dje@canuck.cygnus.com> + + * Make-lang.in (c++.install-common): Check for g++-cross. + * Makefile.in: Remove Cygnus cruft. + (config.status): Delete. + (RTL_H): Define. + (TREE_H): Use complete pathname, some native makes have minimal + VPATH support. + (*.o): Use complete pathname to headers in parent dir. + (doc, info, dvi): Delete. + +Sun Apr 24 00:47:49 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (pushdecl): Avoid redundant warning on redeclaring function + with different return type. + (decls_match): Compare return types strictly. + +Fri Apr 22 12:55:42 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (build_type_conversion): Do try to convert through other + pointers. This will fail if the class defines multiple pointer + conversions. + + * error.c (dump_type_prefix): Print out pointers to arrays properly. + (dump_type_suffix): Likewise. (was 'int *[]', now 'int (*)[]') + + * typeck.c (build_unary_op): Disallow ++/-- on pointers to + incomplete type. + + * decl.c (duplicate_decls): Check mismatched TREE_CODES after + checking for shadowing a builtin. If we're redeclaring a builtin + function, bash the old decl to avoid an ambiguous overload. + + * cvt.c (convert_to_reference): Don't force arrays to decay here. + + * tree.c (lvalue_p): A MODIFY_EXPR is an lvalue. + + * decl.c (duplicate_decls): Don't assume that the decls will have + types. + + Mon Apr 18 11:35:32 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940318 snapshot ] + * c-decl.c (pushdecl): Warn if type mismatch with another external decl + in a global scope. + + Fri Apr 22 06:38:56 1994 Chip Salzenberg <chip@fin.uucp> + + * cp/typeck2.c (signature_error): Use cp_error for "%T". + + Mon Apr 18 11:59:59 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940415 snapshot ] + * cp/decl.c (duplicate_decls, pushdecl, builtin_function): + Use DECL_FUNCTION_CODE instead of DECL_SET_FUNCTION_CODE. + + Mon Apr 18 11:55:18 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940409 snapshot ] + * cp/decl.c (duplicate_decls): Put new type in same obstack as + old ones, or permanent if old ones in different obstacks. + + Mon Apr 18 11:48:49 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940401 snapshot ] + * cp/parse.y (attrib): Handle string args as expressions, + merging the two rules. `mode' attribute now takes a string arg. + Delete the rule for an identifier as arg. + + Mon Apr 18 11:24:00 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940312 snapshot ] + * cp/typeck.c (pointer_int_sum): Multiplication should be done signed. + (pointer_diff): Likewise the division. + + Sun Mar 6 19:43:39 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940304 snapshot ] + * cp/decl.c (finish_decl): Issue warning for large objects, + if requested. + + Sat Feb 19 22:20:32 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940218 snapshot ] + * cp/parse.y (attrib): Handle attribute ((section ("string"))). + * cp/decl.c (duplicate_decls): Merge section name into new decl. + + Tue Feb 8 09:49:17 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp/* changes propagated from c-* changes in 940206 snapshot ] + * cp/typeck.c (signed_or_unsigned_type): Check for any + INTEGRAL_TYPE_P not just INTEGER_TYPE. + + Mon Dec 6 13:35:31 1993 Norbert Kiesel (norbert@i3.INformatik.rwth-aachen.DE) + + * cp/decl.c (finish_enum): Start from 0 when determining precision + for short enums. + + Fri Dec 3 17:07:58 1993 Ralph Campbell (ralphc@pyramid.COM) + + * cp/parse.y (unary_expr): Look at $1 for tree_code rather than + casting $$. + + Wed Nov 17 19:22:09 1993 Chip Salzenberg <chip@fin.uucp> + + * cp/typeck.c (build_binary_op_nodefault): Propagate code + from C front-end to optimize unsigned short division. + (build_conditional_expr): Fix bug in "1 ? 42 : (void *) 8". + + Wed Nov 17 19:17:18 1993 Chip Salzenberg <chip@fin.uucp> + + * cp/call.c (convert_harshness_ansi): Given an (e.g.) char + constant, prefer 'const char &' to 'int'. + + Wed Feb 3 13:11:48 1993 Chip Salzenberg <chip@fin.uucp> + + * cp/class.c (finish_struct_methods): Handle multiple + constructors in fn_fields list. + +Fri Apr 22 12:48:10 1994 Kung Hsu <kung@mexican.cygnus.com> + + * class.c (finish_struct): use TYPE_DECL_SUPPRESS_DEBUG to flag + types not to be dumped in stabs, like types in #pragma interface. + * decl.c (init_decl_processing): use TYPE_DECL_SUPPRESS_DEBUG to + mark unknown type. + +Fri Apr 22 03:27:26 1994 Doug Evans <dje@cygnus.com> + + * Language directory reorganization. + See parent makefile. + +Thu Apr 21 18:27:57 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * cp-tree.h (THUNK_DELTA): It is normally negative, so + use signed .i variant of frame_size rather than unsigned .u. + * cp-tree.h (VTABLE_NAME_FORMAT): If flag_vtable_thunks, + use "VT" rather than "vt" due to binary incompatibility. + * class.c (get_vtable_name): Use strlen of VTABLE_NAME_FORMAT, + rather than sizeof, since it is now an expression. + * class.c (modify_one_vtable): Modify to skip initial element + containing a count of the vtable. + +Thu Apr 21 00:09:02 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (check_newline): Force interface_unknown on main input file. + + * pt.c (do_pending_expansions): Always emit functions that have been + explicitly instantiated. + (do_function_instantiation): Set DECL_EXPLICITLY_INSTANTIATED. + (do_type_instantiation): Set CLASSTYPE_VTABLE_NEEDS_WRITING and + DECL_EXPLICITLY_INSTANTIATED on all my methods. + * parse.y (explicit_instantiation): Call do_type_instantiation for + types. + * decl2.c (finish_vtable_vardecl): Call import_export_vtable. + * decl.c (start_function): Don't set DECL_EXTERNAL on a function + that has been explicitly instantiated. + * cp-tree.h (DECL_EXPLICITLY_INSTANTIATED): Alias for + DECL_LANG_FLAG_4. + * class.c: Move import_export_vtable to decl2.c, and comment out all + uses. + +Wed Apr 20 16:51:06 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (process_next_inline): Don't muck with DECL_INLINE. + (do_pending_inlines): Likewise. + +Tue Apr 19 22:25:41 1994 Mike Stump <mrs@cygnus.com> + + Reimplement vtable building, and most vtable pointer setting. + Allows for earier maintenance, easier understandability, and most + importantly, correct semantics. + + * class.c (build_vtable): Removed unneeded + SET_BINFO_VTABLE_PATH_MARKED. + * class.c (prepare_fresh_vtable): Likewise. Added argument. + * class.c (modify_vtable_entry): General cleanup. + * class.c (related_vslot, is_normal, modify_other_vtable_entries, + modify_vtable_entries): Removed. + * class.c (add_virtual_function): General cleanup. + * class.c (finish_base_struct): Setup BINFO_VTABLE and + BINFO_VIRTUALS as early as we can, so that modify_all_vtables can + work. + * class.c (finish_vtbls): New routine, mostly from + unmark_finished_struct. + * class.c (overrides): New routine. + * class.c (modify_one_vtable): New routine, mostly from + modify_other_vtable_entries and modify_vtable_entries. + * class.c (modify_all_direct_vtables, modify_all_indirect_vtables, + modify_all_vtables): New routines. + * class.c (finish_struct): Added arguemnt to prepare_fresh_vtable + call. General cleanup on how pending_hard_virtuals are handled. + General cleanup on modifying vtables. Use finish_vtbls, instead of + unmark_finished_struct. + * cp-tree.h (init_vtbl_ptrs, expand_direct_vtbls_init, + get_first_matching_virtual, get_matching_virtual, + expand_vbase_vtables_init, expand_indirect_vtbls_init): Update. + * cvt.c (convert_pointer_to_real): cleanup error message. + * decl.c (grokfndecl): General cleanup. + * decl.c (finish_function): Change init_vtbl_ptrs call to + expand_direct_vtbls_init. Change expand_vbase_vtables_init call to + expand_indirect_vtbls_init. + * init.c (expand_virtual_init): Remove unneeded argument. + * init.c (init_vtbl_ptrs): Rename to expand_direct_vtbls_init, added + two arguments to make more general. Made more general. Now can be + used for vtable pointer initialization from virtual bases. + * init.c (emit_base_init): Change expand_vbase_vtables_init call to + expand_indirect_vtbls_init. Change init_vtbl_ptrs call to + expand_direct_vtbls_init. + * init.c (expand_virtual_init): General cleanup. + * init.c (expand_default_init): Change expand_vbase_vtables_init + call to expand_indirect_vtbls_init. + * init.c (expand_recursive_init_1): Change expand_vbase_vtables_init + call to expand_indirect_vtbls_init. + * init.c (expand_recursive_init): Change expand_vbase_vtables_init + call to expand_indirect_vtbls_init. + * search.c (get_first_matching_virtual): Rename to + get_matching_virtual. General cleanup and remove setting of + DECL_CONTEXT. That is now done in a cleaner way in + modify_vtable_entry and add_virtual_function. + * search.c (expand_vbase_vtables_init): Rename to + expand_indirect_vtbls_init. General cleanup. Use + expand_direct_vtbls_init to do hard work. Ensures that _all_ vtable + pointers from virtual bases are set up. + * search.c (bfs_unmark_finished_struct, unmark_finished_struct): + Removed. + + * *.[chy]: Remove support for VTABLE_USES_MASK. + +Tue Apr 19 12:51:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): Use NOP_EXPRs to switch between + reference and pointer types instead of bashing the types directly. + + * call.c (build_overload_call_real): Use the TREE_CODE to determine + whether the function is overloaded or not, rather than + TREE_OVERLOADED. + * *: Remove all uses of TREE_OVERLOADED. + + * decl.c (grokdeclarator): Only complain about initializing const + fields when -ansi or -pedantic. + +Tue Apr 19 12:42:42 1994 Doug Evans <dje@canuck.cygnus.com> + + * cp-tree.h (THUNK_DELTA): frame_size is now a union. + +Mon Apr 18 00:17:13 1994 Jason Merrill <jason@deneb.cygnus.com> + + Do overloading on a block-by-block basis, not function-by-function. + * decl.c: Lose overloads_to_forget. + (struct binding_level): Add overloads_shadowed field. + (poplevel): Restore overloads_shadowed. + (push_overloaded_decl): Use overloads_shadowed instead of + overloads_to_forget. + (finish_function): Don't look at overloads_to_forget. + + Copy enum_overflow logic from c-decl.c. + * decl.c (start_enum): Initialize enum_overflow. + (build_enumerator): Use enum_overflow. Also use current_scope(). + + * search.c (current_scope): Move Brendan's comment from + build_enumerator here. + + * typeck.c (convert_for_assignment): Change warnings to pedwarns for + discarding const/volatile. + +Sat Apr 16 01:18:21 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (comp_target_parms): Accept TEMPLATE_TYPE_PARMs on the rhs. + (comp_target_types): Likewise. + + * decl.c (lookup_name): Don't unset got_scope here. + + * spew.c (yylex): Only replace yylval with the TYPE_NESTED_NAME if + got_scope != NULL_TREE. + +Fri Apr 15 16:36:33 1994 Jason Merrill <jason@deneb.cygnus.com> + + Horrible kludge to prevent templates from being instantiated by + their base classes. + * parse.y (template_instantiate_once): Unset TYPE_BEING_DEFINED + before we get to left_curly. + * pt.c (instantiate_class_template): Set TYPE_BEING_DEFINED. + + * error.c (dump_decl): If it's a typedef, print out the name of the + decl, not just the underlying type. + + * decl.c (pushdecl): If the old duplicate decl was a TYPE_DECL, + update the IDENTIFIER_TYPE_VALUE of its name. + + * decl2.c (finish_file): When processing the initializer for a + static member, pretend that the dummy function is a member of the + same class. + +Fri Apr 15 15:56:35 1994 Kung Hsu <kung@mexican.cygnus.com> + + * class.c (build_vtable_entry): revert Apr 4 change. + * decl2.c (mark_vtable_entries): replace pure virtual function + decl with abort's. + +Fri Apr 15 13:49:33 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_conditional_expr): Pedwarn on pointer/integer + mismatch, and don't pedwarn on 0/function pointer mismatch. + + * typeck2.c (digest_init): Lose code for special handling of unions. + (process_init_constructor): Since they're handled just fine here. + Pedwarn on excess elements. + + * decl2.c (grokfield): Complain about local class method declaration + without definition. + +Fri Apr 15 13:19:40 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * method.c (emit_thunk): Add extern declaration for + current_call_is_indirect (needed for hppa). + +Thu Apr 14 16:12:31 1994 Jason Merrill <jason@deneb.cygnus.com> + + Improve local class support; allow classes in different blocks to + have the same name. + * decl.c (pushtag): Support local classes better. + (pushdecl_nonclass_level): New function for pushing mangled decls of + nested types into the appropriate scope. + (xref_defn_tag): Use pushdecl_nonclass_level instead of + pushdecl_top_level. + (grokfndecl): Don't mess with IDENTIFIER_GLOBAL_VALUE for local + class methods. + * method.c (do_inline_function_hair): Likewise. + + * class.c (finish_struct): It is legal for a class with no + constructors to have nonstatic const and reference members. + +Thu Apr 14 07:15:11 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl.c (push_overloaded_decl): Avoid giving errors about + built-ins, since duplicate_decls will have given warnings/errors + for them. + +Thu Apr 14 03:45:12 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): Warn about casting pointer type to + reference type when this is probably not what they wanted. + +Wed Apr 13 13:12:35 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (finish_decl): Don't mindlessly set TREE_USED for + static consts any more (toplev.c has now been modified to + not emit warnings if they are unused). + +Wed Apr 13 00:22:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grok_op_properties): If op new/delete get here with + METHOD_TYPEs, do a revert_static_member_fn. + + * cp-tree.h (IDENTIFIER_CLASS_TYPE_VALUE): Lose. + * init.c (is_aggr_typedef): Don't look at + IDENTIFIER_CLASS_TYPE_VALUE. + (get_aggr_from_typedef): Likewise. + (get_type_value): Likewise. + * call.c (build_scoped_method_call): Don't rely on overloaded + template names having IDENTIFIER_CLASS_VALUE set. + + * parse.y (component_decl_1, fn.def2): Revert rules for + constructors. + (component_decl_1, fn.def2): Use $1 instead of $$, since $$ is being + clobbered. + + * decl.c (start_function): Only warn about `void main()' if pedantic + || warn_return_type. + +Tue Apr 12 02:14:17 1994 Jason Merrill <jason@deneb.cygnus.com> + + Clean up overloading of the template name. + * class.c (pushclass): overload the template name whenever pushing + into the scope of a template class, not just if it is + uninstantiated. + (popclass): Correspondingly. + * search.c (push_class_decls): Don't overload_template_name. + * pt.c (overload_template_name): Don't set IDENTIFIER_LOCAL_VALUE or + DECL_CONTEXT on things. + * parse.y (left_curly): Don't overload_template_name. + * class.c (finish_struct): Don't undo_template_name_overload. + + * method.c (build_opfncall): Only pass one argument to global op + delete. + + * call.c (build_method_call): Use TYPE_VEC_DELETE_TAKES_SIZE to + decide how many arguments to use for vec delete. + + * decl.c (grok_op_properties): Be consistent in modifying + current_class_type. + (grokdeclarator): Only complain about function decls with no return + type if we're being pedantic. + +Mon Apr 11 00:10:53 1994 Jason Merrill <jason@deneb.cygnus.com> + + Add support for operator new [] and operator delete []. + + * tree.def: Add VEC_NEW_EXPR and VEC_DELETE_EXPR. + * ptree.c (print_lang_type): Indicate vec new/delete. + * parse.y: Support vec new/delete. + * method.c (build_decl_overload): Deal with vec new/delete. + (build_opfncall): Likewise. + * lex.c (init_lex): Set up values of ansi_opname and opname_tab for + vec new/delete. vec new uses "__vn", and vec delete uses "__vd". + * init.c (init_init_processing): Set up BIVN and BIVD. + (do_friend): Don't clean up after mistaken setting of TREE_GETS_NEW, + since it doesn't happen any more. + (build_new): Support vec new. Always call something. + (build_x_delete): Support vec delete. + (build_vec_delete): Lose dtor_dummy argument, add use_global_delete, + and pass it to build_x_delete. + * decl2.c (delete_sanity): Don't change behavior by whether or not + the type has a destructor. Pass use_global_delete to + build_vec_delete. + (coerce_delete_type): Make sure that the type returned has a first + argument of ptr_type_node. + * decl.c (init_decl_processing): Also declare the global vec + new/delete. + (grokdeclarator): Also force vec new/delete to be static. + (grok_op_properties): Note presence of vec new/delete, and play with + their args. If vec delete takes the optional size_t argument, set + TYPE_VEC_DELETE_TAKES_SIZE. + * cp-tree.h (TYPE_GETS_{REG,VEC}_DELETE): New macros to simplify + checking for one delete or the other. + (lang_type): gets_new and gets_delete are now two bits long. The + low bit is for the non-array version. Lose gets_placed_new. + (TYPE_VEC_DELETE_TAKES_SIZE): New macro indicating that the vec + delete defined by this class wants to know how much space it is + deleting. + (TYPE_VEC_NEW_USES_COOKIE): New macro to indicate when vec new must + add a header containing the number of elements in the vector; i.e. + when the elements need to be destroyed or vec delete wants to know + the size. + * class.c (finish_struct_methods): Also check for overloading vec + delete. + * call.c (build_method_call): Also delete second argument for vec + delete. + + * decl.c (grokdeclarator): Correct complaints again. + (grokdeclarator): Fix segfault on null declarator. + (decls_match): Also accept redeclaration with no arguments if both + declarations were in C context. Bash TREE_TYPE (newdecl) here. + (duplicate_decls): Instead of here. + + * parse.y (nested_name_specifier_1): Lose rules for dealing with + syntax errors nicely, since they break parsing of 'const i;'. + + * decl.c (lookup_name): if (got_scope == current_class_type) + val = IDENTIFIER_CLASS_VALUE (name). + + * search.c (lookup_nested_tag): Look in enclosing classes, too. + + * spew.c (yylex): Only look one character ahead when checking for a + SCOPE. + + * lex.c (check_newline): Read first nonwhite char before + incrementing lineno. + + * decl.c (grokdeclarator): Don't claim that typedefs are variables + in warning. + + * parse.y: Divide up uses of unqualified_id into + notype_unqualified_id and unqualified_id, so that TYPENAME can be + used as an identifier after an object. + + * class.c (push_nested_class): Don't push into non-class scope. + + * decl.c (grokdeclarator): If an identifier could be a type + conversion operator, but has no associated type, it's not a type + conversion operator. + + * pt.c (unify): Check for equality of constants better. + + * decl.c (grokdeclarator): Don't complain about access decls. + +Sun Apr 10 02:39:55 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): pedwarn about data definitions without + types here. + + * parse.y (datadef): Don't pedwarn about decls without types here, + since that is valid for functions. + (fn.def2, component_decl): Support constructors with declmods again. + (nomods_initdecls): For decls without any mods, so that we don't try + to get declspecs from some arbitrary $0. + + * search.c (lookup_field): Use cp_error. + + * parse.y (nested_name_specifier_1): Don't check aggr/non-aggr type + here; it breaks destructors for non-aggr types. + + * decl.c (lookup_name): Only look for TYPE_DECLs in base classes of + a type being defined, like the comment says. + If got_scope is not an aggregate, just return NULL_TREE. + + * pt.c (create_nested_upt): Kung's code for creating types nested + within uninstantiated templates now lives here (it used to live in + hack_more_ids). It needs to be expanded. + + * parse.y: Stop calling see_typename so much. + + * decl.c (lookup_name): Deal with TTPs and UPTs. + + * lex.c (real_yylex): Don't set looking_for_typename just because we + saw a 'new'. + (dont_see_typename): #if 0 out. + + * spew.c (yylex): Increment looking_for_typename if the next + character is SCOPE, rather than setting it to 1; this way, the value + from seeing an aggr specifier will not be lost. This kinda relies + on looking_for_typename never being < 0, which is now true. + + * parse.y (nested_name_specifier_1): Accept TEMPLATE_TYPE_PARMs, + too. + (named_class_head_sans_basetype): Accept template types, too. Oops. + +Fri Apr 8 16:39:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (reparse_decl_as_expr1): Handle SCOPE_REFs. + + * parse.y: Lose START_DECLARATOR. + + * search.c (lookup_nested_tag): New function to scan CLASSTYPE_TAGS + for a class. + + * parse.y: Simplify fn.def2 and component_decl. Support 'enum + A::foo' syntax. Catch invalid scopes better. + + * parse.y, lex.c: lose TYPENAME_COLON. + + * decl2.c (groktypefield): #if 0 out. + + * decl.c (lookup_name): If the type denoted by got_scope is + currently being defined, look in CLASSTYPE_TAGS rather than FIELDS. + + * class.c (push_nested_class): Don't try to push into + error_mark_node. + +Fri Apr 8 07:26:36 1994 Brendan Kehoe <brendan@lisa.cygnus.com> + + * Makefile.in (stamp-parse): Update count of conflicts to 33. + +Thu Apr 7 17:47:53 1994 Jason Merrill <jason@deneb.cygnus.com> + + A saner implementation of nested types that treats template types + no differently from non-template types. There are still some + shortcomings of our system; most notably, it is difficult to look + for a nested type that is hidden by another name, because of the way + we keep track of hidden types. But this shouldn't be a problem for + just about anyone. Perhaps lookup_field should be fixed up a bit. + + * spew.c: Moved handling of nested types/scoping from the lexer + into the parser. Removed variable template_type_seen_before_scope. + Removed functions frob_identifier, hack_more_ids, and various cruft + that was #if 0'd out in the past, reducing the size of the file from + 1146 lines to 450 lines. We can't quite do away with spew.c yet, + though; we still need it for do_aggr () and checking for SCOPE after + the current identifier. And setting lastiddecl. + + * parse.y: Moved handling of nested types/scoping from the lexer + into the parser, using a new global variable `got_scope'. Reduced + the number of states by 53. Implemented all uses of explicit global + scope. Removed terminals SCOPED_TYPENAME and SCOPED_NAME. Removed + nonterminals tmpl.1, scoped_base_class, id_scope, typename_scope, + scoped_typename. Added nonterminals nested_type, + qualified_type_name, complete_type_name, qualified_id, ptr_to_mem, + nested_name_specifier, global_scope, overqualified_id, type_name. + Changed many others. Added 9 new reduce/reduce conflicts, which are + nested type parallels of 9 that were already in the grammar for + non-nested types. Eight of the now 33 conflicts should be removed + in the process of resolving the late binding between variable and + function decls. + + * gxxint.texi (Parser): Update. + + * cp-tree.h (IS_AGGR_TYPE_CODE): Add UNINSTANTIATED_P_TYPE. + + * lex.h: Add decl for got_scope. + + * lex.c (see_typename): Claim to be the lexer when calling + lookup_name. + + * decl.c (lookup_name): When called from the lexer, look at + got_scope and looking_at_typename; otherwise don't. + +Thu Apr 7 22:05:47 1994 Mike Stump <mrs@cygnus.com> + + 31th Cygnus<->FSF merge. + +Thu Apr 7 17:47:53 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (mark_vtable_entries): Call this to mark all the + entries in the vtable addressable. + (finish_decl_parsing): Handle SCOPE_REFs. + + * decl.c (decls_match): Always call compparms with strict == 1. + Handle the special case of C function redecl here. + (duplicate_decls): Only keep the old type if the new decl takes no + arguments. + + * typeck.c (compparms): Also allow t1 to be ... if strict == 0. + +Thu Apr 7 16:17:50 1994 Mike Stump <mrs@cygnus.com> + + * class.c (build_vtable_entry): Fix breakage introduced Apr 5 + 17:48:41. + +Wed Apr 6 16:05:10 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * init.c (build_virtual_init), search.c (build_vbase_vtables_init), + ch-tree.h: Every place these functions were called, the result was + immediately passed to expand_expr_stmt. Reduce redundancy by + calling expand_expr_init *inside* these functions. These + makes for a simpler interface, and we don't have to build + compound expressions. Hence, rename these function to: + expand_virtual_init and expand_vbase_vtables_init respectively. + * init.c, decl.c: Change callers of these functions. + * init.c, cp-tree.h (expand_virtual_init): Make static. + + * decl2.c (finish_file): Check TREE_PUBLIC||TREE_ADDRESSABLE + rather than DECL_SAVED_INSNS before emitting inlines. + +Wed Apr 6 13:06:39 1994 Jason Merrill <jason@deneb.cygnus.com> + + * spew.c (init_spew): #if 0 out stuff used by arbitrate_lookup. + + * decl.c (duplicate_decls): If this is a new declaration of an + extern "C" function, keep the type (for the argtypes). + (redeclaration_error_message): Don't check DECL_LANGUAGE here. + (decls_match): Call compparms with a value of strict dependent on + the value of strict_prototypes for DECL_LANGUAGE (oldecl). + + * typeck.c (compparms): ... is only equivalent to non-promoting + parms if we're not being strict. + + * parse.y (empty_parms): Don't check flag_ansi || pedantic here. + + * decl.c (init_decl_processing): if (flag_ansi || pedantic) + strict_prototypes_lang_c = strict_prototypes_lang_cplusplus; + + * decl2.c (grok_function_init): Don't set DECL_INITIAL on pure + virtuals. + +Tue Apr 5 17:48:41 1994 Per Bothner <bothner@kalessin.cygnus.com> + + Support for implementing vtables with thunks. + * tree.def (THUNK_DECL): New TREE_CODE. + * cp-tree.h (FNADDR_FROM_VTABLE_ENTRY), tree.c + (fnaddr_from_vtable_entry): Handle flag_vtable_thunks case. + * cp-tree.h (memptr_type): New variable. + * class.c (build_vtable_entry): Build thunk if necessary. + * class.c (build_vfn_ref): If using thunks, don't need + to add delta field from vtable (there is none!). + * decl.c: Add memptr_type as well as vtable_entry_type. + If using thunks, the latter is just ptr_type_node. + * gc.c, typeck.c: Use memptr_typeChange, not vtable_entry_type. + * decl2.c (finish_vtable_vardecl): Handle thunks. + * expr.c (cplus_expand_expr): Support THUNK_DECL. + + * decl.c (grokdeclarator): Set DECL_THIS_EXTERN if "extern". + * decl.c (start_function): Set current_extern_inline based on + DECL_THIS_EXTERN, not TREE_PUBLIC. + * decl.c (finish_function): Call mark_inline_for_output if needed, + + Improve intelligence about when to emit inlines. + * cp-tree.h (lang_decl_flags): New field saved_inline. + * cp-tree.h (DECL_SAVED_INLINE): New macro. + * class.c (add_virtual_function): Don't set TREE_ADDRESSABLE. + * decl.h, decl.c (pending_addressable_inlines): Removed. + * decl2.c (pending_addressable_inlines): Renamed to saved_inlines. + * decl2.c (mark_inline_for_output): Do nothing if + DECL_SAVED_INLINE; otherwise set it (and add to saved_inlines list). + * decl2.c (finish_vtable_vardecl): SET_CLASSTYPE_INTERFACE_KNOWN + and set CLASSTYPE_INTERFACE_ONLY if there is a non-inline virtual. + * decl2.c (finish_file): Writing out inlines later, so we can + also handle the ones needed for vtbales. + * decl2.c (write_vtable_entries, finish_vtable_typedecl): Removed. + + * cp-tree.h, class.c, decl2.c, search.c: Remove -fvtable-hack + and flag_vtable_hack. Use -fvtable-thunks and flag_vtable_thunks + instead. (The rationale is that these optimizations both break binary + compatibility, but should become the default in a future release.) + +Wed Apr 6 10:53:56 1994 Mike Stump <mrs@cygnus.com> + + * class.c (modify_vtable_entries): Never reset the DECL_CONTEXT + of a fndecl, as we might not be from that vfield. + +Tue Apr 5 17:43:35 1994 Kung Hsu <kung@mexican.cygnus.com> + + * class.c (add_virtual_function): fix bug for pure virtual, so + that DECL_VINDEX of the dummy decl copied won't be error. + (see also Apr 4 change) + +Tue Apr 5 17:23:45 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * typeck.c (c_expand_return): Before checking that we're not + returning the address of a local, make sure it's a VAR_DECL. + (And don't worry about it being a TREE_LIST.) + +Tue Apr 5 13:26:42 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (YYDEBUG): Always define. + * lex.c (YYDEBUG): Likewise. + +Mon Apr 4 11:28:17 1994 Kung Hsu <kung@mexican.cygnus.com> + + * class.c (finish_struct): backup out the change below, put the + new change for the same purpose. The change below breaks code. + + * class.c (finish_struct): if pure virtual, copy node and make + RTL point to abort, then put in virtual table. + * decl2.c (grok_function_iit): reinstate Mar 31 change. + +Sat Apr 2 03:12:58 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (build_new): pedwarn about newing const and volatile + types. + + * tree.c (get_identifier_list): Only do the special handling + thing if we're dealing with the main variant of the record type. + + * cvt.c (convert_to_reference): When converting between + compatible reference types, use the pointer conversion machinery. + Don't just blindly overwrite the old type. + +Fri Apr 1 17:14:42 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): When looking at global functions, + be sure to use instance_ptr for the first argument, not some version + of it that has been cast to a base class. Also do this before + comparing candidates. + +Thu Mar 31 19:50:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Constructors can be called for + const objects. + +Thu Mar 31 16:20:16 1994 Kung Hsu <kung@mexican.cygnus.com> + + * decl2.c (grok_func_init): do not abort as rtl for pur virtual + fucntions. They can be defined somewhere else. + +Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) + + * decl.c (init_decl_processing): Declare __builtin_return_address + and __builtin_frame_address for C++ as well. + +Thu Mar 31 12:35:49 1994 Mike Stump <mrs@cygnus.com> + + * typeck2.c (store_init_value): Integral constant variables are + always constant, even when doing -fpic. + +Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) + + * decl.c (redeclaration_error_message): Pass the types to + comptypes. + +Wed Mar 30 21:29:25 1994 Mike Stump <mrs@cygnus.com> + + Cures incorrect errors about pure virtuals in a class, when they + have been overridden in a derived class. + + * search.c (get_abstract_virtuals): Reimplement. + * search.c (get_abstract_virtuals_1): New routine. + +Wed Mar 30 14:10:04 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (push_template_decls): Make the pushed level pseudo + global. + + * parse.y (extdefs): Don't pop everything if the current binding + level is pseudo_global. + + * decl.c (pop_everything): Stop on reaching a pseudo-global + binding level. + + * cp-tree.h (DECL_FUNCTION_MEMBER_P): Change to more reliable test. + + * decl.c (duplicate_decls): Only copy DECL_SOURCE_{FILE_LINE} if + the old decl actually had an initializer. + + * {various}: Clean up gcc -W complaints. + + * cp-tree.h (DECL_FUNCTION_MEMBER_P): Currently defined to be + (DECL_CONTEXT (NODE) != NULL_TREE). + + * parse.y (lang_extdef): Call pop_everything if necessary. + + * decl.c (pop_everything): New function for popping binding + levels left over after a syntax error. + (pushdecl): Use DECL_FUNCTION_MEMBER_P to decide whether or not + a function is a member. + +Wed Mar 30 14:20:50 1994 Mike Stump <mrs@cygnus.com> + + Cures calling a more base base class function, when a more derived + base class member should be called in some MI situations. + + * search.c (make_binfo): Use more the more specialized base + binfos from the binfo given as the second argument to make_binfo, + instead of the unspecialized ones from the TYPE_BINFO. + * class.c (finish_base_struct): Likewise, update callers. + * search.c (dfs_get_vbase_types): Likewise. + * tree.c (propagate_binfo_offsets, layout_vbasetypes): Likewise. + * decl.c (xref_tag): Use NULL_TREE instead of 0. + * lex.c (make_lang_type): Likewise. + +Wed Mar 30 14:10:04 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (pushdecl): If pushing a C-linkage function, only do a + push_overloaded_decl. + (duplicate_decls): Standard overloading does not shadow built-ins. + +Tue Mar 29 00:54:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (end_template_decl): Don't call push_overloaded_decl. + + * init.c (do_friend): Don't call push_overloaded_decl. + + * decl.c (pushdecl): Call push_overloaded_decl for functions and + function templates. + (duplicate_decls): functions and function templates are not + duplicates, but don't complain about calling this function to + compare them. + (push_overloaded_decl): Don't deal with linkage. Call + duplicate_decls. + (redeclaration_error_message): Deal with linkage. + + * decl.c (start_function): If push_overloaded_decl returns an + older version of the function, deal with it. + + * decl.c (start_function): Be sure only to push_overloaded_decl + for non-members. + + * decl.c (grokfndecl): Put back clearing of DECL_CHAIN for + methods. + (start_function): Lose broken and redundant code for checking old + decl. + + * init.c (add_friend): Give line numbers of both friend decls + when warning about re-friending. + + * pt.c (tsubst): Use comptypes rather than == to compare the + types of the method as declared and as defined, since default + parameters may be different. + + * call.c (build_method_call): Use brendan's candidate printing + routine. + + * decl.c (start_method): Methods defined in the class body are + inline whether or not it's a template class. + +Mon Mar 28 16:39:26 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (initdcl0): Add "extern" to current_declspecs if + have_extern_spec && ! used_extern_spcec. + + * tree.c (really_overloaded_fn): A fn with more than one + overload. + + * pt.c (end_template_decl): Use really_overloaded_fn. + + * decl.c (duplicate_decls): When smashing a decl into a previous + definition, keep the old file and line. + Don't deal with overloaded functions. + Lose old code for checking arg types of functions. + Check for overloaded C functions. + (pushdecl): Deal with overloaded functions. + (start_decl): Expect pushdecl to return an appropriate function decl. + (start_function): Likewise. + (push_overloaded_decl): Don't check for overloaded C functions. + + * *.c: Stop using DECL_OVERLOADED, it being archaic. + TREE_OVERLOADED should probably go, too. + +Mon Mar 28 14:00:45 1994 Ron Guilmette <rfg@netcom.com> + + * typeck.c (comp_target_types): Call comp_target_parms with + strict == 1. + +Sun Mar 27 00:07:45 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (empty_parms): Don't parse () as (...) in extern "C" + sections if we're compiling with -ansi or -pedantic. + + * decl.c (decls_match): Don't treat (int) and (int&) as matching. + + * decl2.c (grokfield): Don't pedwarn twice about initializing + field. + + * decl.c (push_overloaded_decl): Warn about shadowing + constructor. + (redeclaration_error_message): Don't allow 'int a; int a;' + + * cvt.c (build_up_reference): Only check for valid upcast if + LOOKUP_PROTECT is set, not just any flag. + +Fri Mar 25 01:22:31 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (check_newline): When we see a #pragma implementation, + also set it for the main input file. + + * init.c (build_new): Convert array size argument to size_t. + + * parse.y (primary): If we're doing a parenthesized type-id, call + groktypename before passing it to build_new. + + * call.c (build_method_call): Deal properly with const and + volatile for instances of reference type. + + * decl.c (store_return_init): Change 'if (pedantic) error' to 'if + (pedantic) pedwarn'. + + * decl.c (grokdeclarator): Don't complain about putting `static' + and `inline' on template function decls. + +Thu Mar 24 23:18:19 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Preserve const & volatile on + `this'. + +Thu Mar 24 16:21:52 1994 Mike Stump <mrs@cygnus.com> + + * init.c (build_new, build_vec_delete): Use global new and delete + for arrays. + * decl2.c (delete_sanity): Likewise. + +Thu Mar 24 02:10:46 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): If i is an lvalue, + (int &)i -> *(int*)&i, as per 5.2.8p9 of the latest WP. + (convert_force): Call convert_to_reference with LOOKUP_COMPLAIN. + +Wed Mar 23 17:45:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (duplicate_decls): Also propagate DECL_TEMPLATE_MEMBERS + and DECL_TEMPLATE_INSTANTIATIONS. + + * init.c (build_new): Handle array typedefs properly. + +Wed Mar 23 18:23:33 1994 Mike Stump <mrs@cygnus.com> + + 30th Cygnus<->FSF merge. + +Wed Mar 23 00:46:24 1994 Mike Stump <mrs@cygnus.com> + + * class.c (modify_vtable_entries): Avoid running off the end of the + virtuals list when processing a virtual destructor. + * class.c (get_vtable_entry): Likewise. + +Wed Mar 23 00:23:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (duplicate_decls): If two template decls don't match, + just return 0. + +Tue Mar 22 23:49:41 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (convert_for_assignment): Don't pedwarn about + converting function pointer to void *. + +Tue Mar 22 22:23:19 1994 Mike Stump <mrs@cygnus.com> + + Major revamp of pointer to member functions. Cures major + nonfunctionality when used in casts, and MI situations. + + * cvt.c (convert_force): Update call site of build_ptrmemfunc. + * typeck.c (convert_for_assignment): Likewise. + * typeck2.c (digest_init): Likewise. + * typeck2.c (process_init_constructor): Simplify by moving code into + digest_init. + * typeck2.c (digest_init): Do default_conversions on init value, if + we are processing pointer to member functions. + * class.c (get_vfield_offset): Now non-static. Convert bit offset + into byte offset. + * cp-tree.h (get_vfield_offset): Likewise. + * typeck.c (get_member_function_from_ptrfunc): Convert down to right + instance, before fetching vtable pointer. + * typeck.c (get_delta_difference): New routine. + * typeck.c (build_ptrmemfunc): Revamp to handle casting better, also + get vtable pointer out of right subobject. + +Tue Mar 22 17:56:48 1994 Mike Stump <mrs@cygnus.com> + + * search.c (get_binfo): Return NULL instead of aborting, when + passed a UNION_TYPE. + +Tue Mar 22 12:44:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + These patches implement handling of redefinition/redeclaration of + templates. + + * typeck.c (comptypes): Simplify. All TEMPLATE_TYPE_PARMs are + considered compatible. + + * parse.y (template_def): Pass defn argument to end_template_decl. + + * pt.c (end_template_decl): Add defn argument. Check for + redefinition. Simplify. + + * error.c (OB_UNPUT): New macro, to remove mistakes. + (aggr_variety): Subroutine of dump_aggr_type. + + * decl.c (decls_match): Support templates. + (duplicate_decls): No longer static. Don't try to lay out template + decls. + (pushdecl): Simplify. + + * cp-tree.h (DECL_TEMPLATE_MEMBERS): Use DECL_SIZE instead of + DECL_INITIAL. + +Mon Mar 21 11:46:55 1994 Jason Merrill <jason@deneb.cygnus.com> + + * error.c (dump_decl): Support class template decls. + (dump_type): Don't adorn template type parms. + + * decl.c (duplicate_decls): Save DECL_TEMPLATE_INFO from old decl + if it was a definition. + (redeclaration_error_message): Do the cp_error thang, and reject + redefinition of templates. + +Mon Mar 21 19:36:06 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (grokdeclarator): Set TREE_PUBLIC for METHOD_TYPE + in FIELD context, when appropriate. Also, + CLASSTYPE_INTERFACE_ONLY is irrelevant to setting TREE_PUBLIC. + Also, simplify check for bogus return specifiers. + +Mon Mar 21 11:46:55 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (after_type_declarator1): Expand type_quals. + (notype_declarator1): Likewise. + (absdcl1): Likewise. + +Sat Mar 19 01:05:17 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Treat class-local typedefs like static + members; i.e. 'typedef int f();' means that f is a function type, + not a method type. + + * parse.y (decl): Change direct_* back to *. + (type_id): Change direct_abstract_declarator to absdcl. + (direct_declarator, direct_initdecls, direct_initdcl0): Remove again. + +Fri Mar 18 12:47:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + These two patches fix crashes on instantiating a template inside a + function with C linkage or containing labels. + + * class.c (current_lang_stacksize): No longer static. + + * decl.c (struct saved_scope): Add lang_base, lang_stack, + lang_name, lang_stacksize, and named_labels. + (push_to_top_level): Save them. + (pop_from_top_level): Restore them. + + * gxxint.texi (Parser): Update. + + These two patches finish moving the task of expr/declarator + ambiguity resolution from the lexer to the parser, and add one more + r/r conflict. START_DECLARATOR can now be nuked. + + * parse.y (decl): Add "direct_" in typespec X rules. + (direct_declarator): New nonterminal for + direct_after_type_declarator and direct_notype_declarator. + (direct_initdecls): Like initdecls, but uses direct_initdcl0. + (direct_initdcl0): Like initdcl0, but uses direct_declarator. + (named_parm): Add typespec direct_declarator rule. + + * spew.c (yylex): #if 0 out START_DECLARATOR insertion. + + These two patches disable some excessive cleverness on the part of + g++; a non-class declaration always hides a class declaration in the + same scope, and g++ was trying to unhide it depending on the + enclosing expression. + + * spew.c (arbitrate_lookup): #if 0 out. + + * decl.c (lookup_name): Never call arbitrate_lookup. + + * parse.y (complex_notype_declarator1): Add '*' + complex_notype_declarator1 and '&' complex_notype_declarator1 rules. + + * parse.y (complex_direct_notype_declarator): Restore id_scope + see_typename TYPENAME rule, remove all other rules beginning with + those tokens. + (notype_unqualified_id): Add '~' see_typename IDENTIFIER rule. + +Thu Mar 17 17:30:01 1994 Jason Merrill <jason@deneb.cygnus.com> + + These changes fix the compiler's handling of the functional cast/ + object declaration ambiguities in section 6.8 of the ARM. They also + add 11 reduce/reduce conflicts. Sigh. + + * parse.y: Add precedence decls for OPERATOR and '~'. + (notype_unqualified_id): New nonterminal, encompasses all of the + ANSI unqualified-id nonterminal except TYPENAMEs. + (expr_or_declarator): New nonterminal to delay parsing of code like + `int (*a)'. + (primary): Use notype_unqualified_id. + (decl): Add typespec initdecls ';' and typespec declarator ';' + rules. + (initdcl0): Deal with the above. + (complex_notype_declarator1): A notype_declarator that is not also + an expr_or_declarator. + (complex_direct_notype_declarator): A direct_notype_declarator that + doesn't conflict with expr_or_declarator. Use + notype_unqualified_id. Remove id_scope see_typename TYPENAME rule. + (functional_cast): New nonterminal, for the three functional cast + rules. So that they can be moved after + complex_direct_notype_declarator. + (see_typename): Don't accept type_quals any more. + + * decl2.c (reparse_decl_as_expr): New function to deal with parse + nodes for code like `int (*a)++;'. + (reparse_decl_as_expr1): Recursive subroutine of the above. + (finish_decl_parsing): New function to deal with parse nodes for + code like `int (*a);'. See the difference? + +Thu Mar 17 12:16:10 1994 Mike Stump <mrs@cygnus.com> + + These changes break binary compatibility in code with classes + that use virtual bases. + + * search.c (dfs_get_vbase_types): Simplify and correct to make + sure virtual bases are initialized in dfs ordering. + * search.c (get_vbase_types): Simplify and make readable. + +Thu Mar 17 12:01:10 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y: s/ typename / type_id /g + +Wed Mar 16 17:42:52 1994 Kung Hsu <kung@mexican.cygnus.com> + + * parse.y (typespec): add SCOPE TYPENAME for global scoped + type. e.g. ::B x. + + * decl.c (complete_array_type): fix a bug that in -pendantic + mode even there's no initializer, it will continue to build + default index. + +Wed Mar 16 17:43:07 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (direct_notype_declarator): Add PTYPENAME rule, remove + all of the scoped PTYPENAME rules. + +Wed Mar 16 16:39:02 1994 Mike Stump <mrs@cygnus.com> + + * init.c (build_offset_ref): The value of A::typedef_name is + always the TYPE_DECL, and never an error. + +Tue Mar 15 20:02:35 1994 Jason Merrill <jason@deneb.cygnus.com> + + * search.c (get_base_distance_recursive): Two binfos can only + represent the same object if they are both via_virtual. + + * class.c (finish_base_struct): Check vbases for ambiguity, too. + + * search.c (get_vbase_types): Accept binfo argument, too. + +Tue Mar 15 19:22:05 1994 Kung Hsu <kung@mexican.cygnus.com> + + * decl.c (complete_array_type): complete TYPE_DOMAIN of the + initializer also, because back-end requires it. + +Tue Mar 15 15:33:31 1994 Jason Merrill <jason@deneb.cygnus.com> + + * error.c (dump_expr): Support member functions (which show up as + OFFSET_REFs). + +Mon Mar 14 16:24:36 1994 Mike Stump <mrs@cygnus.com> + + * init.c (build_new): Set the return type of multidimensional + news correctly. + +Fri Mar 11 15:35:39 1994 Kung Hsu <kung@mexican.cygnus.com> + + * call.c (build_method_call): if basetype not equal to type + of the instance, use the type of the instance in building + destructor. + +Thu Mar 10 17:07:10 1994 Kung Hsu <kung@mexican.cygnus.com> + + * parse.y (direct_notype_declarator): add push_nested_type for + 'template_type SCOPED_NAME' rule. + +Tue Mar 8 00:19:58 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (parm): Add typed_declspec1 {absdcl, epsilon} rules. + +Sat Mar 5 04:47:48 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (regcast_or_absdcl): New nonterminal to implement late + reduction of constructs like `int ((int)(int)(int))'. + (cast_expr): Use it. + (sub_cast_expr): Everything that can come after a cast. + (typed_declspecs1): typed_declspecs that are not typed_typespecs. + (direct_after_type_declarator): Lose PAREN_STAR_PAREN rule. + (direct_abstract_declarator): Replace '(' parmlist ')' rule with + '(' complex_parmlist ')' and regcast_or_absdcl. + (parmlist): Split + (complex_parmlist): Parmlists that are not also typenames. + (parms_comma): Enabler. + (named_parm): A parm that is not also a typename. Use declarator + rather than dont_see_typename abs_or_notype_decl. Expand + typed_declspecs inline. + (abs_or_notype_decl): Lose. + (dont_see_typename): Comment out. + (bad_parm): Break out abs_or_notype_decl into two rules. + +Fri Mar 4 18:22:39 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl2.c (reparse_decl_as_casts): New function to change parse + nodes for `(int)(int)(int)' from "function taking int and returning + function taking int and returning function taking int" to "... cast + to int, cast to int, cast to int". + + * decl2.c (reparse_decl_as_expr): Recursive function to change + parse nodes for `A()()' from "function returning function returning + A" to "A().operator()". + + * parse.y (primary): Replace `typespec LEFT_RIGHT' rule with + `typespec fcast_or_absdcl' rule. + (fcast_or_absdcl): New nonterminal to implement late reduction of + constructs like `A()()()()'. + (typename): Replace `typespec absdcl1' rule with + `typespec direct_abstract_declarator' rule. + (direct_abstract_declarator): Replace `LEFT_RIGHT type_quals' rule + with `fcast_or_absdcl type_quals' rule. + +Fri Mar 4 16:18:03 1994 Mike Stump <mrs@cygnus.com> + + * tree.c (lvalue_p): Improve OFFSET_REF handling, so that it + matches Section 5.5. + +Fri Mar 4 14:01:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * error.c (dump_type_prefix): Don't print basetype twice for + pmfs. + +Fri Mar 4 13:24:33 1994 Mike Stump <mrs@cygnus.com> + + * typeck.c (convert_arguments): Handle setHandler(A::handlerFn) + so that it is like setHandler(&A::handlerFn). Cures an `invalid + lvalue in unary `&''. + +Fri Mar 4 11:15:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * gxxint.texi (Copying Objects): New section discussing default + op= problems with virtual inheritance. + + * decl2.c (grokoptypename): Just does grokdeclarator and + build_typename_overload, since the parser can't call grokdeclarator + directly. + + * method.c (build_typename_overload): Set IDENTIFIER_GLOBAL_VALUE + and TREE_TYPE on generated identifiers. + + * decl.c (grokdeclarator): Don't deal with TYPE_EXPRs anymore. + + * parse.y (parm): Convert `const char *' to `__opPCc' here. + + * error.c (dump_decl): Say sorry rather than my_friendly_aborting + if we can't figure out what to do. + (dump_type*): Likewise. + + * typeck2.c (build_m_component_ref): 'component' is an expr, not + a decl. Also move the IS_AGGR_TYPE check after the stripping of + REFERENCE_TYPE. + +Fri Mar 4 04:46:05 1994 Mike Stump <mrs@cygnus.com> + + * call.c (build_method_call): Handle b->setHandler(A::handlerFn) + so that it is like b->setHandler(&A::handlerFn). Cures an `invalid + lvalue in unary `&''. + +Thu Mar 3 12:38:15 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y: Add precedence specification for START_DECLARATOR. + (type_quals): Move before primary. + (typename): Move before typed_declspecs, add 'typespec absdcl1' rule. + + * decl2.c (grokoptypename): Lose. + + * decl.c (grokdeclarator): Parse TYPE_EXPRs in the initial scan, + rather than waiting until later. + +Wed Mar 2 14:12:23 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (unary_expr): Use 'typename' in 'new' rules, rather + than expanding it inline. + (typename): Expand empty option of (former) absdcl inline. + (abs_or_notype_decl): Likewise. + (absdcl): Lose empty rule. + (conversion_declarator): New nonterminal for 'typename' of 'operator + typename'. + (operator_name): Use it instead of absdcl. + + * parse.y: Add precedence declarations for SCOPED_TYPENAME, + TYPEOF, and SIGOF. + (typed_declspecs): Accept typed_typespecs, rather than typespec + directly. Add rules with reserved_typespecquals. + (reserved_declspecs): Don't accept typespecqual_reserved at the + beginning of the list. The typed_declspecs rule will deal with this + omission. + (declmods): Accept nonempty_type_quals, rather than TYPE_QUAL + directly. + + * parse.y (direct_notype_declarator, + direct_after_type_declarator, direct_abstract_declarator): Split up + the declarator1 nonterminals to match the draft standard and avoid + ambiguities. + (new_type_id, new_declarator, direct_new_declarator, + new_member_declarator): New nonterminals to implement the subset of + 'typename' allowed in new expressions. + (unary_expr): Use new_type_id instead of typename. + (after_type_declarator1, absdcl1): Fix semantics of member pointers. + (abs_member_declarator, after_type_member_declarator): Lose. + + * parse.y (absdcl1): Don't require parens around + abs_member_declarator. + (abs_member_declarator): Lose see_typename from rules. + (after_type_member_declarator): Likewise. + + * tree.c (get_identifier_list): New function, containing code + previously duplicated in get_decl_list and list_hash_lookup_or_cons. + (get_decl_list): Use it. + (list_hash_lookup_or_cons): Likewise. + + * parse.y (typed_declspecs, declmods): It's not necessary to hash + the declspecs on class_obstack, so don't. This way typed_typespecs + can reduce to typed_declspecs. + +Wed Mar 2 14:29:18 1994 Jason Merrill <jason@cygnus.com> + + * cvt.c (build_up_reference): If we aren't checking visibility, + also allow base->derived conversions. + +Mon Feb 28 15:14:29 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * typeck.c (build_c_cast): Remove bogus hack when converting + to a reference type. + + * cp-tree.h (lang_decl::vbase_init_list, DECL_VBASE_INIT_LIST): + Removed, not used. + (lang_stype::methods, lang_decl::next_method): New fields. + (CLASSTYPE_METHODS, DECL_NEXT_METHOD): New macros. + * decl.c (duplicate_decls): Preserve DECL_NEXT_METHOD. + + * cp-tree.h, decl2.c (flag_vtable_hack): New flag. + * decl2.c (finish_vtable_vardecl): If flag_vtable_hack, + and !CLASSTYPE_INTERFACE_KNOWN, try to use the presence of + a non-inline virtual function to control emitting of vtables. + * class.c (finish_struct): Build CLASSTYPE_METHODS list. + * search.c (build_vbase_vtables_init): Don't assemble_external + (yet) if flag_vtable_hack. + * class.c (build_vfn_ref): Likewise. + +Mon Feb 28 14:54:13 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (component_decl): Don't include "typed_declspecs + declarator ';'" speedup, since it breaks enums. + +Fri Feb 25 15:43:44 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * class.c (finish_struct): Minor optimization for building + fn_fields list. + +Fri Feb 25 15:23:42 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (start_function): Fix detection of function overloading. + +Thu Feb 24 22:26:19 1994 Mike Stump <mrs@cygnus.com> + + * lex.c (check_newline): #pragma interface can take a string + argument, just like #pragma implementation. #pragma implementation + checks for garbage on the line, line #pragma interface does. Main + input files do not auto implement like named files, #pragma + implementation must be used explicitly. + +Thu Feb 24 17:09:01 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y (components): Handle list of one again. + (notype_components): Likewise. + (after_type_declarator1): Take maybe_raises out again. + + * gxxint.texi (Parser): Document additional r/r conflict. + +Wed Feb 23 14:42:55 1994 Jason Merrill <jason@deneb.cygnus.com> + + * gxxint.texi (Parser): Add node. + + * Makefile.in (stamp-parse): Update expected conflict count. + + * parse.y (various): Replace "declmods declarator" with "declmods + notype_declarator". The comment saying that "declmods declarator ';'" + corresponds to "int i;" was wrong; it corresponds to "const i;". + (component_decl): Add "typed_declspecs declarator ';'" rule; this + *does* correspond to "int i;". Change "declmods components" to + "declmods notype_components". + (components): Don't deal with a list of one anymore. + (notype_components): New nonterminal, corresponds to notype_declarator. + ({after_,no}type_component_decl{,0}): More new nonterminals. + ({after_,no}type_declarator): Fold in START_DECLARATOR token. + Eliminates four reduce/reduce conflicts. + + (expr): Depend on nontrivial_exprlist instead of nonnull_exprlist. + (nontrivial_exprlist): New nonterminal: A list of at least two + expr_no_commas's. + (nonnull_exprlist): Depend on nontrival_exprlist. + Eliminates four reduce/reduce conflicts. + + (named_class_head): Move intermediate code block into separate + nonterminal so that we can stick %prec EMPTY on it. + + Add more %prec EMPTY's to eliminate remaining shift/reduce + conflicts. + + (after_type_declarator): Add maybe_raises to fndecl rules. + (after_type_declarator_no_typename): Remove. + For correctness. + + Document remaining reduce/reduce conflicts. + +Tue Feb 22 12:10:32 1994 Jason Merrill <jason@deneb.cygnus.com> + + * search.c (get_base_distance): Only bash BINFO_INHERITANCE_CHAIN + (TYPE_BINFO (type)) if we care about the path. + + * tree.c (lvalue_p): A COND_EXPR is an lvalue if both of the + options are. + +Mon Feb 21 19:59:40 1994 Mike Stump <mrs@cygnus.com> + + * Makefile.in (mostlyclean): lex.c is a source file, don't + remove. + +Sat Feb 19 01:27:14 1994 Jason Merrill <jason@deneb.cygnus.com> + + * parse.y: Eliminate 20 shift/reduce conflicts. + +Fri Feb 18 11:49:42 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (type_unification): Add subr argument; if set, it means + that we are calling ourselves recursively, so a partial match is OK. + (unify): Support pointers to methods and functions. + (tsubst): Support method pointers. + * decl.c (build_ptrmemfunc_type): No longer static, so that + tsubst can get at it. + + * init.c (is_aggr_typedef): Pretend template type parms are + aggregates. + * decl2.c (build_push_scope): If cname refers to a template type + parm, just grin and nod. + + * call.c (build_overload_call_real): Pass subr argument to + type_unification. + * pt.c (do_function_instantiation): Likewise. + * class.c (instantiate_type): Likewise. + + * search.c (get_base_distance): If BINFO is a binfo, use it and + don't mess with its BINFO_INHERITANCE_CHAIN. + + * cvt.c (convert_to_reference): Fix temporary generation. + If ambiguous, return error_mark_node. + + * init.c (build_new): Put back some necessary code. + +Thu Feb 17 15:39:47 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (build_new): Deal with array types properly. + + * search.c (get_binfo): Become a shell for get_base_distance. + (get_binfo_recursive): Lose. + (get_base_distance_recursive): Find the path to the via_virtual base + that provides the most access. + (get_base_distance): Likewise. + + * parse.y (explicit_instantiation): Syntax is 'template class + A<int>', not 'template A<int>'. + + * typeck.c (convert_for_initialization): Remove bogus warning. + + * parse.y (datadef): Revert patch of Oct 27. + +Thu Feb 17 15:12:29 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * class.c (build_vfn_ref): Cast delta field to ptrdiff_type_node, + rather than integer_type_node. Does wonders for the Alpha. + +Thu Feb 17 13:36:21 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (build_ptrmemfunc_type): Make sure that the pmf type + goes onto the same obstack as its target type. + +Wed Feb 16 00:34:46 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cvt.c (convert_to_reference): If converting via constructor + on local level, go back to build_cplus_new approach. + + * tree.c (build_cplus_new): If with_cleanup_p, set cleanup slot + to error_mark_node to prevent expand_expr from building a cleanup + for this variable. + + * lex.c (default_assign_ref_body): Return *this from the memcpy + version, too. + + * decl.c (grok_reference_init): Just return if called with + error_mark_node, don't worry about initializing non-const reference + with temporary. + + * cvt.c (convert_to_reference): Do the right thing for + non-aggregate reference conversions, pedwarn when generating a + non-const reference to a temporary. + + * class.c (finish_struct): TYPE_HAS_COMPLEX_{INIT,ASSIGN}_REF and + TYPE_NEEDS_CONSTRUCTING all depend on TYPE_USES_VIRTUAL_BASECLASSES + again. + +Tue Feb 15 19:47:19 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grok_reference_init): Pawn off a lot of the work on + convert_to_reference. Generally do the right thing. + + * cvt.c (convert_to_reference): Conform to the initial comment; + i.e. don't create temps if decl != error_mark_node. Handle + cleanups better for temps that do get created. Don't pretend + that we can use an 'A' to initialize a 'const double &' just by + tacking on a NOP_EXPR. Support LOOKUP_SPECULATIVELY. + + * call.c (build_method_call): Set TREE_HAS_CONSTRUCTOR on + constructor calls. + +Mon Feb 14 14:50:17 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grok_reference_init): Make a temporary for initializing + const reference from constant expression. + +Mon Feb 14 11:31:31 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * cp-tree.h, decl.c (set_identifier_local_value): Deleted function. + * decl.c (pushdecl): Define decl in correct binding_level + (which isn't always the inner_binding_level). + + * cvt.c (build_up_reference): Don't ever call expand_aggr_init. + It's ugly, and I don't think it's the right thing to do. + + * cp-tree.h, class.c, decl.c, decl2.c, sp/search.c: + Remove NEW_CLASS_SCOPING, assuming it is always 1. + * decl.c (pop_decl_level): Removed; manually inlined. + +Sun Feb 13 19:04:56 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.h (candidate): Add basetypes field. + + * call.c (build_method_call): Do access checking after choosing a + function, not before. + + * Makefile.in (cvt.o, call.o, method.o): Depend on class.h. + (mostlyclean): Remove ../cc1plus. + +Fri Feb 11 11:52:26 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Don't allow adjusting access to a field + of a base class if a local field has the same name. + + * error.c (dump_type_prefix): Output basetype for METHOD_TYPEs. + +hu Jan 13 17:55:51 EST 1994 Gnanasekaran Swaminathan <gs4t@virginia.edu> + + * cp-tree.h (DESTRUCTOR_NAME_P): do not confuse AUTO_TEMP names + with destructor names when either NO_DOLLAR_IN_LABEL or + NO_DOT_IN_LABEL are not defined. + + Now `template <class T, T f(T&), const T*> class A {...}' works. + + * pt.c (grok_template_type): substitute template parm types + with actual types in complex type as well. + (coerce_template_parms): update the grok_template_type () + function call. + + * pt.c (tsubst): Traverse method list using DECL_CHAIN. + + * decl.c (grok_op_properties): Allow operator++/-- to have + default arguments. + + * typeck2.c (store_init_value): Don't abort when called to + initialize a type that needs constructing with a CONSTRUCTOR. + + * init.c (expand_aggr_init_1, CONSTRUCTOR case): If + store_init_value fails, build and expand an INIT_EXPR. If + store_init_value succeeds, call expand_decl_init. + +Fri Feb 11 02:49:23 1994 Mike Stump <mrs@cygnus.com> + + * class.c (build_vbase_path): Use complete_type_p instead of + resolves_to_fixed_type_p to determine if the virtual bases are in + their right place for the type of expr. Cures problem of thinking a + virtual base class is one place, when it is in fact someplace else. + +Fri Feb 11 00:26:46 1994 Mike Stump <mrs@cygnus.com> + + * init.c (resolve_offset_ref): Make sure we first convert to + intermediate type, if given, when dealing with members off `this'. + Solves an incorrrect `type `foo' is not a base type for type + `multiple'' when it is infact, a base type. + +Thu Feb 10 21:49:35 1994 Mike Stump <mrs@cygnus.com> + + * class.c (modify_other_vtable_entries): Use get_binfo, instead + of binfo_value. Solves problem with compiler giving a `base class + `B' ambiguous in binfo_value (compiler error)' on complex MI + herarchies, when a virtual function is first defied in a virtual + base class. + +Thu Feb 10 17:19:32 1994 Mike Stump <mrs@cygnus.com> + + * class.c (build_vbase_path): Don't complain about ambiguous + intermediate conversion when converting down to a virtual base + class, even if they might seem to be ambiguous. + +Thu Feb 10 12:18:26 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck2.c (build_functional_cast): #if 0 out constructor + inheritance code, improve error messages. + + * class.c (finish_base_struct): Complain about base with only + non-default constructors in derived class with no constructors. + + * decl.c (grokdeclarator): Fix detection of virtual new/delete. + +Wed Feb 9 22:02:32 1994 Mike Stump <mrs@cygnus.com> + + * search.c (build_mi_virtuals, add_mi_virtuals, + report_ambiguous_mi_virtuals): Removed unneeded code. + * class.c (finish_struct_bits): Likewise. + +Wed Feb 9 11:27:17 1994 Jason Merrill <jason@deneb.cygnus.com> + + * pt.c (end_template_instantiation): Push decl before + pop_from_top_level. + + * typeck2.c (build_m_component_ref): Make sure datum is of + aggregate type. + + * init.c (get_type_value): New function, returns + IDENTIFIER_TYPE_VALUE or IDENTIFIER_CLASS_TYPE_VALUE or NULL_TREE. + + * call.c (build_method_call): Don't die on call to destructor for + non-type. + + * decl.c (grokdeclarator): Complain about virtual op new and op + delete, make static virtuals unvirtual instead of unstatic. + + * typeck.c (build_c_cast): Also call default_conversion on + methods. + + * decl.c (grokdeclarator): Don't complain about anonymous + bitfields. + + * parse.y (simple_stmt, for loops): Move the continue point after + the cleanups. + + * class.c (finish_struct): Fix setting of + TYPE_HAS_COMPLEX_INIT_REF. + +Tue Feb 8 13:21:40 1994 Jason Merrill <jason@deneb.cygnus.com> + + * init.c (build_new): Deal with `new double (1)'. + + * class.c (finish_struct): TYPE_HAS_COMPLEX_*_REF are supersets of + TYPE_HAS_REAL_*_REF, but TYPE_HAS_COMPLEX_INIT_REF is independent of + TYPE_NEEDS_CONSTRUCTING. + + * decl.c (duplicate_decls): Propagate access decls. + + * typeck2.c (process_init_constructor): Accept empty_init_node + for initializing unions. + + * class.c, lex.c, cp-tree.h: Use + TYPE_HAS_COMPLEX_ASSIGN_REF where TYPE_HAS_REAL_ASSIGN_REF was used + before, use TYPE_HAS_COMPLEX_INIT_REF for TYPE_NEEDS_CONSTRUCTING in + some places. + + * decl.c (finish_decl): Don't complain about uninitialized const + if it was initialized before. + +Mon Feb 7 18:12:34 1994 Jason Merrill <jason@deneb.cygnus.com> + + * lex.c (default_assign_ref_body): Don't deal with vbases for + now. + + * decl.c (finish_decl): Fix reversed logic for objects and other + things that need to be constructed but have no initializer. + + * class.c (finish_struct): Don't set TYPE_HAS_* flags that are + set by grok_op_properties or finish_decl. + + * decl.c: Don't warn about extern redeclared inline unless + -Wextern-inline is given. + * decl2.c (lang_decode_option): Likewise. + * cp-tree.h: Likewise. + +Mon Feb 7 17:29:24 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (pushdecl_with_scope): Fix thinko. Add forward + declaration. + + * decl.c (pushdecl_with_scope): New function. + * decl.c (pushdecl_top_level): Use new function. + * decl.c (pushtag): Initialize newdecl. + * decl.c (pushtag): Push new type decl into correct scope. + +Mon Feb 7 14:42:03 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c, cvt.c, init.c, search.c, cp-tree.h: + Eradicate LOOKUP_PROTECTED_OK. + +Mon Feb 7 13:57:19 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * decl.c (pushtag, xref_tag), cp-tree.h: Add extra parameter + 'globalize' to signify implicit declarations. + * decl.c (globalize_nested_type, maybe_globalize_type): Removed. + * decl.c (set_identifier_type_value_with_scope): New function. + * decl.c (set_identifier_local_value): Simplify. + * spew.c (yylex, do_addr): Modify to return a _DEFN if a + forward declaration (followed by ';' and not preceded by 'friend'). + * class.c, decl.c, except.c, init.c, parse.y, + pt.c, search.c: Add new argument to calls to xref_tag and + pushtag. + +Mon Feb 7 00:22:59 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.h (ACCESSIBLY_UNIQUELY_DERIVED_P): New macro, means what + ACCESSIBLY_DERIVED_FROM_P meant before. + (ACCESSIBLY_DERIVED_FROM_P): Now disregards ambiguity. + + * cvt.c (build_up_reference): Call get_binfo with PROTECT == 1. + + * search.c (get_base_distance_recursive): Members and friends of + a class X can implicitly convert an X* to a pointer to a private or + protected immediate base class of X. + (get_binfo_recursive): Likewise. + (get_base_distance): Ignore ambiguity if PROTECT < 0. + (get_binfo): Lose multiple values of PROTECT. + (compute_access): Protected is OK if the start of the + search is an accessible base class of current_class_type. + + * method.c (build_opfncall): Do check access on operator new here. + + * decl.c (finish_function): Don't check access on operator new + here. + +Sun Feb 6 14:06:58 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (xref_tag): The base of a derived struct is NOT always + public. Duh. + + * pt.c (do_explicit_instantiation): New function, called from + parser to do explicit function instantiation. + (type_unification): Allow the args list to be terminated with + void_list_node. + (do_pending_expansions): Look at i->interface for non-member + templates. + + * parse.y (datadef): Move explicit_instantiation here. + (structsp): From here. + (datadef): Complain about `int;'. + +Sun Feb 6 12:33:18 1994 Per Bothner <bothner@kalessin.cygnus.com> + + * pt.c (end_template_instantiation), cp-tree.h: Remove unused + second parameter, and simplify first from a TREE_LIST where + we only care about its TREE_VALUE to just the value (an IDENTIFIER). + * pt.c (instantiate_member_templates): Simplify argument list + from a TREE_LIST to just an IDENTIFIER. + * lex.c (yyprint): PRE_PARSED_CLASS_DECL is now just an IDENTIFIER. + * parse.y (template_instantiate_once): Simplify accordingly. + * decl.c (inner_binding_level): New. Use various places to + simplify. + +Sun Feb 6 02:49:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck2.c (build_functional_cast): int() -> int(0). + +Sat Feb 5 00:53:21 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Don't do a bitwise copy for op= if the + class has a virtual function table. + + * typeck.c (convert_for_initialization): Restore warnings about + not using defined op=. Should really be my_friendly_aborts, I + s'pose. + +Fri Feb 4 14:21:00 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Tidy up conditions for doing bitwise + copies of objects. + + * decl.c (build_default_constructor): #if 0 out. + + * *: Eradicate TYPE_GETS_{ASSIGNMENT,ASSIGN_REF,CONST_ASSIGN_REF, + CONST_INIT_REF}, TYPE_HAS_REAL_CONSTRUCTOR. + + * decl.c (grokdeclarator): Don't return void_type_node for + friends being defined here. + + * init.c (perform_member_init): Only do the init if it's useful. + + * lex.c (default_copy_constructor_body): If we don't need to do + memberwise init, just call __builtin_memcpy. + (default_assign_ref_body): Likewise. + + * decl.c (grokdeclarator): If friendp && virtualp, friendp = 0. + +Fri Feb 4 13:02:56 1994 Mike Stump <mrs@cygnus.com> + + * lex.c (reinit_parse_for_method, cons_up_default_function): + Don't give warn_if_unknown_interface warning when it came from a + system header file. + * pt.c (end_template_decl, instantiate_template): Likewise. + * decl.c (start_decl): Likewise. + +Fri Feb 4 00:41:21 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Don't try to set TYPE_WAS_ANONYMOUS on + enums. + + * decl2.c (constructor_name_full): Use IS_AGGR_TYPE_CODE instead of + IS_AGGR_TYPE, since we don't know it's a type. + +Thu Feb 3 11:36:46 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokdeclarator): Don't complain about anonymous unions. + + * cp-tree.h (TYPE_WAS_ANONYMOUS): This struct was originally + anonymous, but had a name given to it by a typedef. + + * decl.c (grokdeclarator): When renaming an anonymous struct, set + TYPE_WAS_ANONYMOUS. + + * decl2.c (constructor_name_full): Use TYPE_WAS_ANONYMOUS. + + * cp-tree.h (DECL_UNDEFINED_FRIENDS): #if 0 out. + + * init.c (xref_friend): Don't set up DECL_UNDEFINED_FRIENDS. + (embrace_waiting_friends): Don't use DECL_UNDEFINED_FRIENDS. + + * decl.c (grokdeclarator): Set TYPE_NESTED_NAME properly on nested + anonymous structs that get typedef'd. + + * decl.c (grokdeclarator): Always return void_type_node for + friends. + + * error.c (dump_function_decl): Don't use DECL_CLASS_CONTEXT for + friends. + (dump_function_decl): Don't print out default args for + a function used in an expression. + + * decl.c (grokdeclarator): Give error on abstract declarator used + in an invalid context (i.e. `void (*)();'). + + * error.c (cp_line_of): Support _TYPE nodes. + (cp_file_of): Likewise. + + * cvt.c (build_up_reference): Don't abort if passed a SAVE_EXPR; + it can happen for the RHS of an assignment stmt where the LHS is + a COND_EXPR. + + * init.c (expand_aggr_init_1): Deal with bracketed initializer + lists properly. + + * class.c (finish_struct): Deal with enumerators and typedefs + again. + +Wed Feb 2 11:30:22 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Tidy up loop over fields. + + * errfn.c (cp_thing): Don't advance twice after a format. + + * class.c (finish_struct): Complain about needing a constructor + if a member has only non-default constructors, and don't try to + generate a default constructor. + + * decl.c (finish_decl): Also do the constructor thing if + TYPE_NEEDS_CONSTRUCTING is set (for arrays). + + * search.c (unuse_fields): New function: mark all fields in this + type unused. + (dfs_unuse_fields): Helper function. + + * class.c (pushclass): If the new class is the same as the old + class, still unuse the fields. + (unuse_fields): Move to search.c. + + * decl.c (grok_op_properties): Add friendp argument. + (grokfndecl): Pass it. + (start_method): Likewise. + + * decl2.c (delete_sanity): Add use_global_delete parameter to catch + ::delete calls. + + * parse.y (unary_expr): Pass new parameter to delete_sanity. + + * lex.c (default_copy_constructor_body): Don't choke if the union + has no fields. + (default_assign_ref_body): Likewise. + + * call.c (compute_conversion_costs_ansi): Do the right thing for + ellipsis matches. + + * decl.c (push_to_top_level): Optimize. + + * decl.c (start_function): Look for the lexical scope of a friend + in DECL_CLASS_CONTEXT. + + * init.c (do_friend): Set DECL_CLASS_CONTEXT on global friends. + +Tue Feb 1 15:59:24 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.h (TREE_GETS_PLACED_NEW): New macro. + + * init.c (init_init_processing): Don't assign BIN/BID to the + IDENTIFIER_GLOBAL_VALUEs of their respective operators. + (build_new): Check TREE_GETS_PLACED_NEW. + + * decl.c (grok_op_properties): Don't set TREE_GETS_NEW for a decl of + op new with placement, set TREE_GETS_PLACED_NEW. + + * cp-tree.h (ANON_UNION_P): New macro. Applies to decls. + + * class.c (finish_struct): Don't treat anonymous unions like + other aggregate members. Do synthesize methods for unions without + a name, since they may or may not be "anonymous unions". + + * decl2.c (grok_x_components): Wipe out memory of synthesized methods + in anonymous unions. + + * lex.c (default_copy_constructor_body): Support unions. + (default_assign_ref_body): Likewise. + +Mon Jan 31 12:07:30 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.h: Fix documentation of LOOKUP_GLOBAL, add prototypes. + + * error.c (args_as_string): New function (%A), like type_as_string + except NULL_TREE -> "..." + + * call.c (build_overload_call_real): Fix for new overloading. + + * decl.c (grok_op_properties): Set all of the TYPE_OVERLOADS_* flags + here. + + * parse.y (operator_name): Instead of here. + + * typeck2.c (build_functional_cast): Treat a TREE_LIST as a list + of functions. + + * call.c (build_overload_call_real): Support LOOKUP_SPECULATIVELY. + + * method.c (build_opfncall): Don't need to massage return value + any more, call build_overload_call with all flags. + + * typeck.c (build_x_binary_op): Put back speculative call to + build_opfncall. + (build_x_unary_op): Likewise. + (build_x_conditional_expr): Likewise. + +Mon Jan 31 10:00:30 1994 Mike Stump <mrs@cygnus.com> + + * cvt.c (build_type_conversion_1): Change call to pedwarn into + warning, and conditionalize upon warn_cast_qual. + +Fri Jan 28 11:48:15 1994 Jason Merrill <jason@deneb.cygnus.com> + + * search.c (lookup_field): If xbasetype is a binfo, copy it to + avoid clobbering its inheritance info. + + * call.c (build_method_call): Don't overwrite basetype_path with + TYPE_BINFO (inst_ptr_basetype) if they have the same type. + + * search.c (compute_access): Fix handling of protected inheritance + and friendship with the enclosing class. + + * typeck2.c (store_init_value): Allow passing of TREE_CHAIN for + initialization of arbitrary variable. + + * typeck2.c (build_functional_cast): Only try calling a method if + one exists. + + * decl.c (grokdeclarator): Move handling of constructor syntax + initialization into first loop for generality. + (parmlist_is_random): Lose. + + * lex.c (cons_up_default_function): Set TREE_PARMLIST on arguments + to default function. + +Thu Jan 27 19:26:51 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (grokparms): Abort if we get called with something we don't + expect. + +Thu Jan 27 17:37:25 1994 Mike Stump <mrs@cygnus.com> + + * call.c (build_overload_call_real): Change argument complain to + flags to match style of rest of code. Pass it down to + build_function_call_real as necessary. + * call.c (build_overload_call, build_overload_call_maybe): Change + argument complain to flags to match style of rest of code. + * cp-tree.h (build_function_call_real): Added fourth flags + argument. + * cvt.c (convert_to_reference): Only give warning messages, if + LOOKUP_COMPLAIN is set. + * typeck.c (build_x_function_call): Change simple complain + argument to build_overload_call_maybe and build_overload_call, to + LOOKUP_COMPLAIN to match style of rest of code. + * typeck2.c (build_functional_cast): Likewise. + * typeck.c (build_function_call_real): Add flags, so that we can + not complain, if we don't want to complain. Complain about + arguments, if we are complaining, otherwise don't. + * typeck.c (build_function_call, build_function_call_maybe): + Stick in flags argument. + * typeck.c (build_x_binary_op, build_x_unary_op, + build_x_conditional_expr, build_x_compound_expr): Follow style of + build_x_indirect_ref, as it is more correct and more common. + +Thu Jan 27 14:36:20 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (build_method_call): Don't check for being called with + a pointer. + + * decl2.c (finish_file): Don't play with DECL_CLASS_CONTEXT for the + static initializer function. + + * init.c (build_member_call): Use convert_force here, too. + + * search.c (compute_access): Only treat static members specially + if they are referenced directly. + +Wed Jan 26 18:28:14 1994 Jason Merrill <jason@deneb.cygnus.com> + + * gxxint.texi (Access Control): New node. + + * search.c (current_scope): New function; returns whichever of + current_class_type and current_function_decl is the most nested. + (compute_access): Total overhaul to make it clearer and more + correct. Don't use the cache for now; in the only situation where + it was used before, it gained nothing. This frees up three of the + DECL_LANG_FLAGs for possible other use! + + * cp-tree.h: #if 0 out DECL_PUBLIC & friends. + + * typeck.c (build_component_ref_1): Don't check DECL_PUBLIC. + + * call.c (build_method_call): Use convert_force to cast `this' -- + rely on the access checking for the method itself. + + * init.c (is_friend): Do the nesting thing, handle types. I am + my own friend. + (is_friend_type): Become a shell for is_friend. + (add_friend): Never stick in ctype. + Why are the friendship functions in init.c, anyway? + +Wed Jan 26 17:50:00 1994 Mike Stump <mrs@cygnus.com> + + * cvt.c (build_type_conversion_1): Don't conditionalize call to + pedwarn upon pedantic. + +Wed Jan 26 17:20:46 1994 Mike Stump <mrs@cygnus.com> + + * cvt.c (convert_to_reference): Add 8.4.3 checking so that one + gets a warning if one tries to initialize a non-const & from a + non-lvalue. + * cvt.c (convert_to_reference): Use %P format for argument + numbers in warnings. + +Wed Jan 26 14:35:06 1994 Mike Stump <mrs@cygnus.com> + + * init.c (build_delete): Follow style in call.c to construct the + virtual call to the desctructor, as that code is right. Fixes a + problem of the compiler saying a pointer conversion is ambiguous. + +Wed Jan 26 11:28:14 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.h (VTABLE_NAME_P): Change other occurrence of + VTABLE_NAME_FORMAT to VTABLE_NAME. + + * *: s/visibility/access/g + +Tue Jan 25 18:39:12 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_modify_expr): Don't smash references if INIT_EXPR. + +Tue Jan 25 13:54:29 1994 Mike Stump <mrs@cygnus.com> + + * init.c (build_delete): Back out Jan 17th & 18th pacthes, as + they break libg++. + +Tue Jan 25 13:11:45 1994 Jason Merrill <jason@deneb.cygnus.com> + + * decl.c (duplicate_decls): Fix pointer arithmetic. + +Mon Jan 24 15:50:06 1994 Chip Salzenberg <chip@fin.uucp> + + [ cp-* changes propagated from c-* changes in 940114 snapshot ] + * cp-parse.y (maybe_attribute): Allow multiple __attribute__ + clauses on a declaration. + +Mon Jan 24 17:06:23 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Do synthesize methods for anon + structs, just not unions. + +Mon Jan 24 13:50:13 1994 Kung Hsu <kung@mexican.cygnus.com> + + * decl.c (xref_tag): handle anonymous nested type. + * decl.c (globalize_nested_type): add no globalize bit check. + * spew.c (hack_more_ids) : templated nested decl not push top + level. + + * parse.y : get rid of 'goto do_components'. It is much better + for debugging. + + * decl.c (is_anon_name): get rid of the function and use the + macro ANON_AGGRNAME_P. + * pt.c : ditto. + +Fri Jan 21 14:06:02 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct): Don't synthesize any methods for + anonymous structs/unions. + + * typeck.c (build_modify_expr): Don't treat pmf's as class objects. + +Thu Jan 20 18:56:46 1994 Jason Merrill <jason@deneb.cygnus.com> + + * method.c (build_opfncall): Call build_indirect_ref on + synthesized instance for operator delete. + + * pt.c (type_unification): Don't abort if called with a list of + types in ARGS. + + * class.c (instantiate_type): Deal with function templates. + +Thu Jan 20 16:55:35 1994 Jim Wilson <wilson@sphagnum.cygnus.com> + + * Makefile.in (CC): Default to cc not gcc. + +Thu Jan 20 13:47:54 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_modify_expr): Call constructor if appropriate. + + * decl.c (push_to_top_level): Clear out class-level bindings cache. + +Wed Jan 19 13:51:22 1994 Jason Merrill <jason@deneb.cygnus.com> + + * call.c (resolve_scope_to_name): Work recursively (previously only + looked down one level). + + * lex.c (do_pending_inlines): If we're still dealing with the last + batch of inlines, don't start working on a new one. + + * Makefile.in (stamp-parse): Update conflict count. + (TAGS): Fix. + + * parse.y (explicit_instantiation): New rule; implements + 'template A<int>' syntax (though not 'template foo(int)' yet). + (structsp): Add explicit_instantiation. + +Tue Jan 18 13:53:05 1994 Jason Merrill <jason@deneb.cygnus.com> + + * class.c (finish_struct, etc.): Simplify decision to synthesize + a destructor. + + * call.c, class.c, cp-tree.h, decl.c, init.c, + ptree.c, search.c, typeck.c, typeck2.c: Nuke + TYPE_NEEDS_CONSTRUCTOR (change all calls to TYPE_NEEDS_CONSTRUCTING). + * init.c (expand_aggr_init_1): Don't try non-constructor methods + of initializing objects. + (build_new): Don't try other methods if the constructor lookup fails. + + * class.c (finish_base_struct): Set cant_have_default_ctor and + cant_synth_copy_ctor properly. + (finish_struct): Likewise. + +Mon Jan 17 13:58:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * typeck.c (build_modify_expr_1): #if 0 out again. + (build_modify_expr): #if 0 out memberwise init code again. + + * lex.c (default_copy_constructor_body): Be const-correct. + (default_assign_ref_body): Likewise. + + * init.c (perform_member_init): Use TYPE_HAS_CONSTRUCTOR to decide + whether or not to use it, rather than TYPE_NEEDS_CONSTRUCTING. + (expand_aggr_init): Disable silent conversion from initializer list + to list of args for a constructor. + + * class.c (base_info): Lose needs_default_ctor. + (finish_base_struct): Likewise. + (finish_struct): Likewise. + + * decl.c (init_decl_processing): Don't turn off flag_default_inline + just because flag_no_inline is on. + (finish_decl): Use TYPE_HAS_CONSTRUCTOR to decide to use + constructor. + + * class.c (finish_struct): Synthesize default ctor whenever + allowed. + + * Makefile.in (TAGS): Don't try to run etags on cp-parse.y. + +Sat Jan 15 18:34:33 1994 Mike Stump <mrs@cygnus.com> + + * Makefile.in, configure: Handle the C++ front-end in a + subdirectory. + * cp-*: Move C++ front-end to cp/*. + +Fri Jan 14 14:09:37 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-typeck.c (build_function_call_real): Modify to match other + instances of taking the address of the function. + + * cp-class.c (finish_struct): Set TYPE_HAS_REAL_CONSTRUCTOR to 1 if + there are non-synthesized constructors. + Only set TYPE_NEEDS_CONSTRUCTOR if TYPE_HAS_REAL_CONSTRUCTOR. + Always generate copy constructor if possible. + + * cp-tree.h (lang_type): Add has_real_constructor bitfield. + (TYPE_HAS_REAL_CONSTRUCTOR): Define. + + * cp-lex.c (default_copy_constructor_body): Use init syntax + for all bases. + + * cp-type2.c (store_init_value): Only give error for initializer list + if TYPE_HAS_REAL_CONSTRUCTOR. + +Thu Jan 13 15:38:29 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.h (DECL_SYNTHESIZED): Add defn. + (lang_decl): Add synthesized bitfield to decl_flags. + + * cp-lex.c (cons_up_default_function): Use DECL_SYNTHESIZED to mark + artificial methods, rather than a line # of 0. + +Fri Jan 14 18:25:29 1994 Kung Hsu <kung@mexican.cygnus.com> + + * cp-decl (xref_tag): fix a bug in conflict type. + * cp-parse.y : add SCOPED_NAME for uninstantiated template nested + type reference. + * cp-spew.c (yylex) : generated SCOPED_NAME token. + * cp-lex.c (yyprint): handle SCOPED_NAME. + +Fri Jan 14 17:00:29 1994 Mike Stump <mrs@cygnus.com> + + * cp-decl.c (pushdecl): Revert patch from Jan 11 19:33:03, as it is + not right. + +Thu Jan 13 14:00:35 1994 Kung Hsu <kung@mexican.cygnus.com> + + * cp-decl2.c (grok_x_components): fix a bug that enum type does not + have type_flags. + +Thu Jan 13 11:39:34 1994 Mike Stump <mrs@cygnus.com> + + Ensure that all vtable pointers are initialized with all the right + values. + + * cp-class.c (is_normal): Changed to reflect new meaning of + CLASSTYPE_VFIELD_PARENT. + * cp-class.c (maybe_fixup_vptrs): Use of + CLASSTYPE_NEEDS_VIRTUAL_REINIT here is misguided. Use + BINFO_MODIFIED instead. + * cp-class.c (finish_struct): Changed to reflect new meaning of + CLASSTYPE_VFIELD_PARENT. + * cp-decl.c (get_binfo_from_vfield): Removed, unneeded now. + * cp-decl.c (finish_function): Use init_vtbl_ptrs, instead of open + coding it here. + * cp-init.c (init_vfields): Changed name to init_vtbl_ptrs, and + re-implement. + * cp-init.c (emit_base_init): Use new name init_vtbl_ptrs. + * cp-tree.h (vfield_parent): Changed to integer. + * cp-tree.h (CLASSTYPE_VFIELD_PARENT): Changed docs to reflect new + meaning. + * cp-tree.h (init_vtbl_ptrs): Added init_vtbl_ptrs. + +Wed Jan 12 18:24:16 1994 Kung Hsu <kung@mexican.cygnus.com> + + * cp-decl.c (xref_tag): re-implement globalize nested type. + * cp-decl2.c (grok_x_components): ditto. + * cp-parse.y: ditto. + * cp-tree.h (lang_type): add no_globalize bit in type_flags. + +Wed Jan 12 14:08:09 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c (grokdeclarator): Don't set TREE_PUBLIC on friend + decls with a definition attached. + + * cp-typeck.c (build_modify_expr): Undo previous change in the case + of INIT_EXPRs. + +Tue Jan 11 19:33:03 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-typeck.c (build_modify_expr): Replace code for generating + assignment semantics for classes with an error. + (build_modify_expr_1): #if 0 out. + + * cp-decl.c (pushdecl): Patch bogus design of pushdecl + behavior for overloaded functions (it doesn't push anything). + + * cp-class.c (finish_struct): When generating default op=, + set TYPE_HAS_ASSIGNMENT. + +Mon Jan 10 18:48:06 1994 Mike Stump <mrs@cygnus.com> + + * cp-cvt.c (convert): Make {double, clashing enum} -> enum + invalid. + * cp-typeck.c (convert_for_assignment): Simplify. + * cp-decl2.c (warn_enum_clash): Removed. + * invoke.texi (-Wenum-clash): Removed. + * toplev.c (-Wenum-clash): Removed. + +Mon Jan 10 17:48:37 1994 Kung Hsu <kung@mexican.cygnus.com> + + * cp-decl.c (finish_decl): fix incorrect popclass call. + + * cp-decl.c (is_anon_name): new function, check whether the name + is anonymous name generated by compiler. + * cp-decl.c (grokdeclarator): allow nested SCOPE_REF + * cp-spew.c (hack_more_ids): handle nested type in template. + * cp-parse.y : handle nested type reference in uninstantiated + template. + * cp-call.c (build_method_call): handle uninstantiated template + case. + * cp-pt.c (search_nested_type_in_tmpl): new function, search nested + type in template. + * cp-pt.c (lookup_nested_type_by_name): new function, lookup nested + type by name. + * cp-pt.c (tsubst): handle nested type search by name. + +Mon Jan 10 14:32:18 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-init.c (build_member_call): Propagate qualifiers to new type. + + * cp-call.c (build_method_call): Count functions the new way. + +Fri Jan 7 19:03:26 1994 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c (pushtag): Set DECL_ASSEMBLER_NAME for nested classes, + too. + +Tue Jan 4 16:45:51 1994 Kung Hsu <kung@cirdan.cygnus.com> + + * cp-parse.y: change to handle whether to globalize nested class. + * cp-decl.c(xref_tag, maybe_globalize_type): Likewise. + +Mon Jan 3 22:22:32 1994 Gerald Baumgartner <gb@cygnus.com> + + * Makefile.in cp-call.c cp-class.c cp-cvt.c cp-decl.c cp-decl2.c + cp-error.c cp-init.c cp-lex.c cp-lex.h cp-method.c cp-parse.y + cp-spew.c cp-tree.c cp-tree.h cp-type2.c cp-typeck.c cp-xref.c + gplus.gperf toplev.c: Incorporated C++ signature extension. + * cp-sig.c: New file, contains most of signature processing. + * cp-hash.h: Regenerated from gplus.gperf. + + * gcc.1 g++.1: Added explanation for the `-fhandle-signatures' + and `-fno-handle-signatures' command line flags. + + * gcc.texi: Changed the last-modification date. + * invoke.texi: Added `-fhandle-signatures' in the list of + C++ language options. Added explanation for this option. + +Tue Dec 28 21:10:03 1993 Mike Stump <mrs@cygnus.com> + + * cp-init.c (expand_vec_init): Remove comptypes test, as it is too + harsh here. + +Tue Dec 28 13:42:22 1993 Mike Stump <mrs@cygnus.com> + + * cp-pt.c (do_pending_expansions): Decide to expand a template + member function, based upon it's class type, not the class type of + the first place it was declared. + +Tue Dec 28 05:42:31 1993 Mike Stump <mrs@cygnus.com> + + * cp-class.c (is_normal): New routine, use to determine when the + given binfo is the normal one. (The one that should have the simple + vtable name.) + * cp-class.c (modify_other_vtable_entries): Use DECL_ASSEMBLER_NAME + to check if two fndecls are `the same'. Sometimes this routine can + modify the main vtable, and normal should be 1, in that case, so use + is_normal() to determine if this is the main vtable for the class. + Don't recurse down virtual bases, as they are shared, and we take + care of them elsewhere. + * cp-class.c (modify_vtable_entries): If we have already updated the + vtable with the new virtual, don't do it again. + * cp-class.c (finish_struct): Set CLASSTYPE_VFIELD_PARENT as + appropriate. Do virtual function overriding in virtual bases, after + normal overriding, so that the base function list in DECL_VINDEX is + not overridden, before we have a chance to run through the list. + Use DECL_ASSEMBLER_NAME to check if two fndecls are `the same'. + Make sure we pass the right address into modify_vtable_entries. + * cp-tree.h (CLASSTYPE_VFIELD_PARENT): New field to indicate which + binfo is the one that has the vtable that we based our vtable on. + +Fri Dec 24 09:40:52 1993 Michael Tiemann <tiemann@blues.cygnus.com> + + * cp-typeck.c (c_expand_start_case): Use default_conversion to + convert expression from reference type if necessary. + +Wed Dec 22 17:58:43 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-typeck.c (build_unary_op): Make sure that it's a TREE_LIST before + trying to read its TREE_VALUE. + + * cp-class.c (finish_struct_methods): Clear DECL_IN_AGGR_P here. + (finish_struct): Instead of here. + +Tue Dec 21 14:34:25 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-tree.c (list_hash_lookup_or_cons): Make sure the type doesn't + have TYPE_PTRMEMFUNC_P set before we try to build its + CLASSTYPE_ID_AS_LIST. + (get_decl_list): Likewise, when trying to read it. + + * cp-tree.h (VTABLE_NAME): No def with NO_{DOLLAR,DOT} defined. + (VTABLE_NAME_P): Use it instead of VTABLE_NAME_FORMAT. + +Mon Dec 20 13:35:03 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-typeck.c (rationalize_conditional_expr): New function. + (unary_complex_lvalue): Use it. + (build_modify_expr): Use it, since trying to do an ADDR_EXPR of it + with build_unary_op won't cut it. Don't wrap the COND_EXPR with a + SAVE_EXPR either. + + * cp-decl2.c (explicit_warn_return_type): Deleted variable. + (lang_decode_option): Set warn_return_type, not explicit_*, for + -Wreturn-type and -Wall. This is what rest_of_compilation uses to + decide if it should go into jump_optimize or not. + * cp-tree.h (explicit_warn_return_type): Deleted. + * cp-decl.c (grokdeclarator): Use warn_return_type, not explicit_*. + (finish_function): Also complain about no return in a non-void fn if + we're being pedantic (don't rely on use of -Wreturn-type). + +Fri Dec 17 15:45:46 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-decl.c (grokdeclarator): Forbid declaration of a function as + static if it's being done inside another function. + + * cp-search.c (compute_visibility): Check for friendship both ways. + +Fri Dec 17 14:28:25 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-cvt.c (build_default_binary_type_conversion): Make error + messages more helpful. + + * cp-error.c (op_as_string): New function, returns "operator ==" + given EQ_EXPR or suchlike. + +Fri Dec 17 13:28:11 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-call.c (print_n_candidates): New function. + (build_overload_call_real): Use it when we complain about a call + being ambiguous. + +Fri Dec 17 12:41:17 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-call.c (build_method_call): Fix checking for static call + context. + + * cp-method.c (build_opfncall): Call build_indirect_ref on argument + to operator new. + + * cp-init.c (build_new): Don't mess with rval when building + indirect ref. + +Thu Dec 16 16:48:05 1993 Kung Hsu <kung@cirdan.cygnus.com> + + * cp-lex.c (default_assign_ref_body): add check when TYPE_NESTED_ + NAME(type) may not be exist. It's not a problem for old compiler. + +Thu Dec 16 14:46:06 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-tree.h (CLASSTYPE_ALTERS_VISIBILITIES_P): Delete macro, it's + never used for anything. + (struct lang_type, member type_flags): Delete field + `alters_visibility', and up `dummy' by 1. + * cp-class.c (finish_base_struct): Delete code that copies the + setting of CLASSTYPE_ALTERS_VISIBILITIES_P. + (finish_struct): Delete code that sets it. + +Thu Dec 16 14:44:39 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c, cp-init.c, cp-typeck.c: Fix arguments to + build_method_call that I messed up before. + + * cp-search.c (get_base_distance): If protect > 1, allow immediate + private base. + + * cp-class.c (finish_base_struct): Set cant_synth_* correctly. + (finish_struct): Likewise. Well, nigh-correctly; it won't deal + properly with the case where a class contains an object of an + ambiguous base class which has a protected op=. Should be fixed + when the access control code gets overhauled. + (finish_struct_methods): Set TYPE_HAS_NONPUBLIC_* correctly. + +Thu Dec 16 12:17:06 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-lex.c (real_yylex): Turn the code back on that deals with + __FUNCTION__ and __PRETTY_FUNCTION__. Don't use lookup_name, to + avoid the ambiguity problems that led to it being turned off in the + first place. + + * cp-method.c (hack_identifier): Also check for a TYPE_PTRMEMFUNC_P + to see if something is a method. + +Wed Dec 15 18:35:58 1993 Mike Stump <mrs@cygnus.com> + + * cp-typeck.c (build_modify_expr): Avoid error messages on small + enum bit fields. + * cp-typeck.c (convert_for_assignment): Add missing argument to + cp_warning and cp_pedwarn calls. + +Wed Dec 15 18:25:32 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-parse.y (member_init): ANSI C++ doesn't forbid old-style base + initializers; it's just anachronistic. + + * cp-decl.c (finish_decl): Don't require external-linkage arrays + to have a complete type at declaration time when pedantic. + +Tue Dec 14 11:37:23 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c (pushdecl): Don't set DECL_CONTEXT if it's already set. + + * cp-call.c (build_method_call): Don't dereference pointer given + as instance. + + * cp-decl.c (finish_function): Don't pass pointer to + build_method_call. + (finish_function): Likewise. + + * cp-typeck.c (build_x_function_call): Likewise. + + * cp-method.c (build_component_type_expr): Likewise. + + * cp-init.c (build_member_call): Likewise. + (build_new): Likewise. + +Mon Dec 13 18:04:33 1993 Kung Hsu <kung@cirdan.cygnus.com> + + * cp-decl.c (xref_tag): fix regression created by changes made + in Dec. 7 1993. + * cp-decl.c (xref_defn_tag): fix parallel nested class problem. + +Fri Dec 10 12:40:25 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-call.c (compute_conversion_costs_ansi) [DEBUG_MATCHING]: Print + out the final evaluation of the function, so we can see if ELLIPSIS, + USER, and EVIL were set at the end. + + * cp-call.c (convert_harshness_ansi): When the parm isn't an lvalue, + only go for setting TRIVIAL_CODE if we are dealing with types that + are compatible. + +Thu Dec 9 18:27:22 1993 Mike Stump <mrs@cygnus.com> + + * cp-decl.c (flag_huge_objects): New flag to allow large objects. + * toplev.c (lang_options): Likewise. + * cp-decl2.c (flag_huge_objects, lang_f_options): Likewise. + * cp-decl.c (delta_type_node): New type for delta entries. + * cp-tree.h (delta_type_node): Likewise. + * cp-decl.c (init_decl_processing): Setup delta_type_node. + * cp-decl.c (init_decl_processing, build_ptrmemfunc_type): Use + delta_type_node instead of short_integer_type_node. + * cp-class.c (build_vtable_entry): Likewise. + +Thu Dec 9 16:19:05 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-tree.h (OPERATOR_TYPENAME_P): Define outside of + NO_{DOLLAR,DOT} macro checks, so it always gets defined. + (VTABLE_NAME_P): Define for NO_DOT && NO_DOLLAR_IN_LABEL. + +Wed Dec 8 17:38:06 1993 Mike Stump <mrs@cygnus.com> + + * cp-decl.c (finish_decl): Make sure things that can go into + "common", do go into common, if -fcommon is given. + +Wed Dec 8 13:01:54 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-call.c (print_harshness) [DEBUG_MATCHING]: New function. + (compute_conversion_costs_ansi) [DEBUG_MATCHING]: Print out + argument matching diagnostics to make instantly clear what the + compiler is doing. + + * cp-call.c (convert_harshness_ansi): If the parm isn't an lvalue, + then check to see if the penalty was increased due to + signed/unsigned mismatch, and use a TRIVIAL_CODE if it wasn't. + +Tue Dec 7 18:29:14 1993 Kung Hsu <kung@cirdan.cygnus.com> + + * cp-decl.c (xref_tag, pushtag): Fix nested class search/resolution + problem. + +Tue Dec 7 16:09:34 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-class.c (finish_struct): Before synthesizing methods, if no + methods have yet been declared then set nonprivate_method. Don't + set non_private method after synthesizing a method. + + * cp-lex.c (extract_interface_info): If flag_alt_external_templates + is set, tie emitted code to the location of template instantiation, + rather than definition. + + * cp-tree.h: Declare flag_alt_external_templates. + + * cp-decl2.c (lang_decode_option): Support -falt-external-templates. + + * toplev.c (lang_options): Likewise. + +Mon Oct 4 12:50:02 1993 Chip Salzenberg <chip@fin.uucp> + + [changes propagated from 930810 snapshot] + * cp-decl.c (init_decl_processing): Make long long available for use + as SIZE_TYPE and PTRDIFF_TYPE. + (finish_decl): Allow file-scope static incomplete array. + (grokdeclarator): Don't pass on const and volatile fron function + value type to function type. + Warn here for volatile fn returning non-void type. + * cp-parse.y (attrib): Accept attributes `volatile' with alias + `noreturn', and `const'. + * cp-typeck.c (default_conversion): Don't lose const and volatile. + (build_binary_op_nodefault): Generate pedantic warning for comparison + of complete pointer type with incomplete pointer type. + (build_c_cast): Be careful that null pointer constant be INTEGER_CST. + +Tue Dec 7 10:46:48 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-init.c (expand_vec_init): When creating a temporary for copying + arrays, use the type of the source, not the target. + + * cp-cvt.c (convert): Pass an argument for errtype to + convert_to_reference. + + * cp-error.c (dump_expr, COMPONENT_REF & CALL_EXPR): Deal with + methods, -> and `this'. + +Mon Dec 6 17:12:33 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-error.c (parm_as_string): New function; returns `this' or arg + number. Corresponds to %P. + (dump_expr): Deal with method calls. + + * cp-cvt.c (convert_to_reference): Stop using warn_for_assignment. + * cp-typeck.c (convert_for_assignment): Likewise. + (warn_for_assignment): Lose. + +Mon Dec 6 11:33:35 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-call.c (ideal_candidate_ansi): Delete code that was never + doing anything useful. Instead, sort once, and DO NOT wipe + out any codes with EVIL_CODE, since that's what we use as a + marker for the end of the list of candidates. + + * cp-cvt.c (convert_to_aggr): Make sure to always set H_LEN. + +Mon Dec 6 12:49:17 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-init.c (get_aggr_from_typedef): New function, like + is_aggr_typedef but returns the _TYPE. + + * cp-call.c, cp-init.c, cp-method.c: Eradicate err_name. + +Sun Dec 5 18:12:48 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-lex.c (readescape): Pedwarn when a hex escape is out of range. + +Thu Nov 25 23:50:19 1993 Chip Salzenberg <chip@fin.uucp> + + Delay language context change until beginning of next decl. + + * cp-lex.h (c_header_level): Removed. + (pending_lang_change): Declared. + * cp-lex.c (c_header_level): Renamed from in_c_header, made static. + (pending_lang_change): Defined. + (check_newline): Rework code that recognizes line number and + filename changes. Instead of pushing and popping lang context, + increment and decrement pending_lang_change. + (do_pending_lang_change): Push and pop lang context according + to value of pending_lang_change. + * cp-parse.y (extdefs): Use lang_extdef instead of extdef. + (extdef): Same as extdef, but call do_pending_lang_change() first. + +Mon Nov 15 15:39:15 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-typeck.c (build_binary_op_nodefault): Warn for ordered + compare of ptr with 0 only if pedantic in both cases. + +Thu Nov 25 13:31:37 1993 Chip Salzenberg <chip@fin.uucp> + + Reinstate the below patch, which got lost in the Cygnus merge: + Tue Nov 23 13:59:24 1993 Hallvard B Furuseth (hbf@durin.uio.no) + * cp-parse.y (maybe_type_qual): Don't fail to set $$. + +Wed Nov 17 19:03:30 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-parse.y (attrib): Allow "ident(ident)" like the C front end. + +Fri Oct 22 20:43:37 1993 Paul Eggert <eggert@twinsun.com> + + * cp-lex.c (real_yylex): Diagnose floating point constants + that are too large. + +Wed Nov 17 19:10:37 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-type2.c (build_functional_cast): ARM page 16: When a class + and an object, function or enumerator are declared in the same + scope with the same name, the class name is hidden. + +Wed Nov 17 19:07:18 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-call.c (convert_harshness_ansi): Distinguish float, double, + and long double from each other when overloading. + (compute_conversion_costs_{ansi,old}, build_method_call, + build_overlay_call_real, convert_to_aggr): Always set and + always use H_LEN member of candidate structure. + +Mon Oct 11 23:10:53 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-decl.c (duplicate_decls): Note redeclarations of library + functions, and generate distinct warnings for them. + +Mon Oct 4 12:26:49 1993 Chip Salzenberg <chip@fin.uucp> + + Support format warnings in G++. + + * cp-tree.h: Protect against multiple inclusion. + Declare all public functions in c-common.c (copy from c-tree.h). + (STDIO_PROTO): Define. + (warn_format): Declare. + (record_format_info): Remove declaration. + * cp-decl.c (init_decl_processing): Call init_function_format_info. + * cp-decl2.c (lang_decode_option): Make "-Wall" include warn_format. + * cp-typeck.c (build_function_call_real): Call check_function_format. + (record_format_info): Remove -- obsolete stub. + +Sat Jul 24 12:04:29 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-decl.c (duplicate_decls): Don't warn for non-extern var decl + following an extern one (for -Wredundant-decls). + * cp-parse.y (primary): In statement expression case, if compstmt + returns something other than a BLOCK, return it unchanged. + +Thu Dec 2 20:44:58 1993 Chip Salzenberg <chip@fin.uucp> + + * cp-decl.c (warn_extern_redeclared_static): New function made + from code extracted from pushdecl. + (duplicate_decls, pushdecl): Call new function. + (lookup_name_current_level): Allow for IDENTIFIER_GLOBAL_VALUE + to be a TREE_LIST when function is declared in 'extern "C" {}'. + +Fri Dec 3 16:01:10 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-class.c (duplicate_tag_error): Use cp_error. + (finish_base_struct): Check for ambiguity with direct base, and don't + generate op= or copy ctor if it exists. + +Fri Dec 3 15:32:34 1993 Kung Hsu <kung@cirdan.cygnus.com> + + * cp-init.c (expand_member_init): when initializer name is null, + don't try to build it now because emit_base_init will handle it. + +Fri Dec 3 12:28:59 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-lex.c (init_lex): Initialize input_filename to "<internal>" for + code such as ExceptionHandler::operator=. + +Fri Dec 3 10:32:08 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c (grokdeclarator): Don't try to print out dname when + complaining about arrays of references if decl_context==TYPENAME, + since it will be null. + + * cp-decl2.c: Default to flag_ansi_overloading. + +Thu Dec 2 18:05:56 1993 Kung Hsu <kung@cirdan.cygnus.com> + + * cp-call.c (build_method_call): use binfo from instance if it's + different from binfo (basetype_path) passed from above. + +Wed Nov 17 19:14:29 1993 Chip Salzenberg <chip@fin.uucp> + + cp-error.c (dump_expr): Use unsigned chars to output a + TREE_REAL_CST in hex. + +Thu Dec 2 11:05:48 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-class.c (finish_struct): Fix typo in setting + cant_synth_asn_ref. + + * cp-tree.h (TYPE_NESTED_NAME): New macro, does + DECL_NESTED_TYPENAME (TYPE_NAME (NODE)). + + * cp-lex.c (default_copy_constructor_body): Change + DECL_NAME (TYPE_NAME (btype)) to TYPE_NESTED_NAME (btype). + (default_assign_ref_body): Likewise. + (default_copy_constructor_body): Call operator= explicitly for + base classes that have no constructor. + +Thu Dec 2 10:47:15 1993 Michael Tiemann <tiemann@blues.cygnus.com> + + * cp-call.c (build_method_call): If the instance variable is + converted to error_mark_node when we're trying to convert it to the + base type of a method we're looking up, return error_mark_node. + +Thu Dec 2 10:41:16 1993 Torbjorn Granlund <tege@cygnus.com> + + * cp-typeck.c (build_binary_op_nodefault): In *_DIV_EXPR *_MOD_EXPR + cases, tests for unsigned operands by peeking inside a NOP_EXPR. + +Wed Dec 1 13:33:34 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-call.c (compute_conversion_costs_ansi): Use the size of struct + harshness_code, not the size of short, for clearing out the + ansi_harshness. + + * cp-call.c (print_candidates): New function. + (build_method_call): When we had some candidates, but didn't get a + usable match, don't report that we got an error with the first + candidate. Instead, say there were no matches, and list the + candidates with print_candidates. In the second pass, make sure we + clear out ever_seen, so we can accurately count the number of + functions that qualified. + +Wed Dec 1 09:53:59 1993 Torbjorn Granlund <tege@cygnus.com> + + * cp-typeck.c (build_binary_op_nodefault): Shorten for *_MOD_EXPR + only if op1 is known to be != -1. + (build_binary_op_nodefault): Handle *_DIV_EXPR likewise. + +Tue Nov 30 14:07:26 1993 Brendan Kehoe <brendan@lisa.cygnus.com> + + * cp-method.c (hack_identifier): If the field itself is private, and + not from a private base class, say so. + +Mon Nov 29 03:00:56 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c (grokdeclarator): Always warn on initialization of + const member. + +Wed Nov 24 00:49:35 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-class.c (finish_struct): Set TYPE_GETS_CONST_* properly. + (finish_base_struct): Set cant_synth_asn_ref properly. + + * cp-lex.c (cons_up_default_function): Add section for operator=. + (default_assign_ref_body): New function, mostly cribbed from + default_copy_constructor_body. + + * cp-class.c (base_info): Add members cant_synth_copy_ctor, + cant_synth_asn_ref, no_const_asn_ref. + (finish_base_struct): Update no_const_asn_ref, note that you should + update cant_synth_*, propagate TYPE_GETS_ASSIGN_REF. + (finish_struct): Add decls for cant_synth_*, no_const_asn_ref, and + initialize them properly. Set no_const_asn_ref properly. Set + cant_synth_* in some of the situations where they should be set. + Propagate TYPE_GETS_ASSIGN_REF. Use cant_synth_copy_ctor. Add call + to cons_up_default_function for operator=. + +Tue Nov 23 20:24:58 1993 Mike Stump <mrs@cygnus.com> + + * cp-cvt.c (convert_force): Add code to perform casting of pointer + to member function types. + * cp-typeck.c (build_ptrmemfunc): Add FORCE parameter to indicate + when the conversion should be done, regardless. + * cp-tree.h (build_ptrmemfunc): Likewise. + * cp-type2.c (digest_init): Likewise. + * cp-typeck.c (convert_for_assignment): Likewise. + +Tue Nov 23 18:06:58 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-error.c (dump_expr): Do the right thing for variables of + reference type. + + * cp-decl.c (grok_op_properties): Set TYPE_HAS_ASSIGN_REF + and its kin properly. + (xref_tag): Propagate TYPE_GETS_ASSIGN_REF. + +Tue Nov 23 12:26:13 1993 Mike Stump <mrs@cygnus.com> + + * cp-method.c (build_opfncall): Don't count pointer to member + functions as aggregates here, as we don't want to look up methods in + them. The compiler would core dump if we did, as they don't have + normal names. + * cp-typeck.c (build_indirect_ref): Improve wording on error + message. + +Mon Nov 22 14:22:23 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c (grok_op_properties): Allow operator?: with pedwarn + (since it's supported in other compiler bits). + + * cp-method.c (report_type_mismatch): Use cp_error; ignore err_name + argument. + + * cp-error.c (dump_function_decl): Don't print return type for + constructors and destructors. + + * cp-cvt.c (cp_convert_to_pointer): Import code from + convert_to_pointer so we can return error_mark_node in the case of an + error, and to allow more meaningful error messages. + (build_type_conversion): Don't go through void* when trying + to convert to a pointer type. + + * cp-decl.c (grokfndecl): Move call to grok_op_properties back + after grokclassfn so that it's dealing with the right decl. + (grok_op_properties): Don't assert !methodp for op new and op delete. + + * cp-init.c (build_delete): Don't use TYPE_BUILT_IN (there are now + no uses of it in the compiler). + + * cp-call.c (build_scoped_method_call): Fix for destructors of simple + types. + (build_method_call): Likewise. + +Fri Nov 19 12:59:38 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.c (count_functions): Abstraction function. + + * cp-call.c (build_overload_call_real): Deal with new overloading + properly, remove dead code. + + * gcc.c (default_compilers): Generate and use .ii files in the + intermediate stage of compiling C++ source. + +Fri Nov 19 11:26:09 1993 Jim Wilson <wilson@sphagnum.cygnus.com> + + * cp-expr.c (cplus_expand_expr): Make call_target a valid memory + address before using it, so it can be later safely compared. + +Fri Nov 12 15:30:27 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-pt.c (tsubst): Deal with new overloading. + + * cp-typeck.c (fntype_p): is the arg function type? + (comp_target_parms): pedwarn on conversion from (anything) to (...). + (build_x_function_call): Deal with new overloading. + + * cp-tree.c (decl_list_length): Deal with new overloading. + (decl_value_member): Like value_member, but for DECL_CHAINs. + + * cp-decl.c (duplicate_decls): Deal with new overloading. + (start_decl): Likewise. + + * cp-class.c (instantiate_type): Deal with new overloading. + + * cp-call.c (convert_harshness_ansi): Deal with new overloading. + (convert_harshness_old): Deal with new overloading. + (build_overload_call_real): Likewise. + +Mon Nov 8 13:50:49 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-tree.c (get_unique_fn): New function; returns FUNCTION_DECL + if unambiguous, NULL_TREE otherwise. + (get_first_fn): Returns the first appropriate FUNCTION_DECL. + (is_overloaded_fn): Returns whether or not the passed tree is + a function or list of functions. + + * cp-init.c (init_init_processing): use `get_first_fn' to find + the FUNCTION_DEFN for new and delete. + + * cp-decl.c (push_overloaded_decl): Use new overloading strategy, cut + code size in half (I spit on special cases). + +Tue Sep 7 20:03:33 1993 Jason Merrill <jason@deneb.cygnus.com> + + * cp-decl.c: Allow references and template type parameters as well diff --git a/gnu/usr.bin/gcc/cp/NEWS b/gnu/usr.bin/gcc/cp/NEWS new file mode 100644 index 00000000000..ff2d5124f52 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/NEWS @@ -0,0 +1,180 @@ +*** Changes since G++ version 2.7.2: + +* A public review copy of the December 1996 Draft of the ANSI/ISO C++ + proto-standard is now available. See + + http://www.cygnus.com/misc/wp/ + + for more information. + +* g++ now uses a new implementation of templates. The basic idea is that + now templates are minimally parsed when seen and then expanded later. + This allows conformant early name binding and instantiation controls, + since instantiations no longer have to go through the parser. + + What you get: + + + Inlining of template functions works without any extra effort or + modifications. + + Instantiations of class templates and methods defined in the class + body are deferred until they are actually needed (unless + -fexternal-templates is specified). + + Nested types in class templates work. + + Static data member templates work. + + Member function templates are now supported. + + Partial specialization of class templates is now supported. + + Explicit specification of template parameters to function templates + is now supported. + + Things you may need to fix in your code: + + + Syntax errors in templates that are never instantiated will now be + diagnosed. + + Types and class templates used in templates must be declared + first, or the compiler will assume they are not types, and fail. + + Similarly, nested types of template type parameters must be tagged + with the 'typename' keyword, except in base lists. In many cases, + but not all, the compiler will tell you where you need to add + 'typename'. For more information, see + + http://www.cygnus.com/misc/wp/dec96pub/template.html#temp.res + + + Guiding declarations are no longer supported. Function declarations, + including friend declarations, do not refer to template instantiations. + You can restore the old behavior with -fguiding-decls until you fix + your code. + + Other features: + + + Default function arguments in templates will not be evaluated (or + checked for semantic validity) unless they are needed. Default + arguments in class bodies will not be parsed until the class + definition is complete. + + The -ftemplate-depth-NN flag can be used to increase the maximum + recursive template instantiation depth, which defaults to 17. If you + need to use this flag, the compiler will tell you. + + Explicit instantiation of template constructors and destructors is + now supported. For instance: + + template A<int>::A(const A&); + + Still not supported: + + + Member class templates. + + Template template parameters. + + Template friends. + +* Exception handling support has been significantly improved and is on by + default. This can result in significant runtime overhead. You can turn + it off with -fno-exceptions. + +* RTTI support has been rewritten to work properly and is now on by default. + This means code that uses virtual functions will have a modest space + overhead. You can use the -fno-rtti flag to disable RTTI support. + +* On ELF systems, duplicate copies of symbols with 'initialized common' + linkage (such as template instantiations, vtables, and extern inlines) + will now be discarded by the GNU linker, so you don't need to use -frepo. + This support requires GNU ld from binutils 2.8 or later. + +* The overload resolution code has been rewritten to conform to the latest + C++ Working Paper. Built-in operators are now considered as candidates + in operator overload resolution. Function template overloading chooses + the more specialized template, and handles base classes in type deduction + and guiding declarations properly. In this release the old code can + still be selected with -fno-ansi-overloading, although this is not + supported and will be removed in a future release. + +* Standard usage syntax for the std namespace is supported; std is treated + as an alias for global scope. General namespaces are still not supported. + +* New flags: + + + New flags -Wsign-promo (warn about potentially confusing promotions + in overload resolution), -Wno-pmf-conversion (don't warn about + converting from a bound member function pointer to function pointer). + + + A flag -Weffc++ has been added for violations of some of the style + guidelines in Scott Meyers' _Effective C++_ books. + + + -Woverloaded-virtual now warns if a virtual function in a base + class is hidden in a derived class, rather than warning about + virtual functions being overloaded (even if all of the inherited + signatures are overridden) as it did before. + + + -Wall no longer implies -W. The new warning flag, -Wsign-compare, + included in -Wall, warns about dangerous comparisons of signed and + unsigned values. Only the flag is new; it was previously part of + -W. + + + The new flag, -fno-weak, disables the use of weak symbols. + +* Synthesized methods are now emitted in any translation units that need + an out-of-line copy. They are no longer affected by #pragma interface + or #pragma implementation. + +* __FUNCTION__ and __PRETTY_FUNCTION__ are now treated as variables by the + parser; previously they were treated as string constants. So code like + `printf (__FUNCTION__ ": foo")' must be rewritten to + `printf ("%s: foo", __FUNCTION__)'. This is necessary for templates. + +* local static variables in extern inline functions will be shared between + translation units. + +* -fvtable-thunks is supported for all targets, and is the default for + Linux with glibc 2.x (also called libc 6.x). + +* bool is now always the same size as another built-in type. Previously, + a 64-bit RISC target using a 32-bit ABI would have 32-bit pointers and a + 64-bit bool. This should only affect Irix 6, which was not supported in + 2.7.2. + +* new (nothrow) is now supported. + +* Synthesized destructors are no longer made virtual just because the class + already has virtual functions, only if they override a virtual destructor + in a base class. The compiler will warn if this affects your code. + +* The g++ driver now only links against libstdc++, not libg++; it is + functionally identical to the c++ driver. + +* (void *)0 is no longer considered a null pointer constant; NULL in + <stddef.h> is now defined as __null, a magic constant of type (void *) + normally, or (size_t) with -ansi. + +* The name of a class is now implicitly declared in its own scope; A::A + refers to A. + +* Local classes are now supported. + +* __attribute__ can now be attached to types as well as declarations. + +* The compiler no longer emits a warning if an ellipsis is used as a + function's argument list. + +* Definition of nested types outside of their containing class is now + supported. For instance: + + struct A { + struct B; + B* bp; + }; + + struct A::B { + int member; + }; + +* On the HPPA, some classes that do not define a copy constructor + will be passed and returned in memory again so that functions + returning those types can be inlined. + +*** The g++ team thanks everyone that contributed to this release, + but especially: + +* Joe Buck <jbuck@synopsys.com>, the maintainer of the g++ FAQ. +* Brendan Kehoe <brendan@cygnus.com>, who coordinates testing of g++. +* Jason Merrill <jason@cygnus.com>, the g++ maintainer. +* Mark Mitchell <mmitchell@usa.net>, who implemented member function + templates and explicit qualification of function templates. +* Mike Stump <mrs@wrs.com>, the previous g++ maintainer, who did most of + the exception handling work. diff --git a/gnu/usr.bin/gcc/cp/cp-tree.def b/gnu/usr.bin/gcc/cp/cp-tree.def new file mode 100644 index 00000000000..65d20a71e5e --- /dev/null +++ b/gnu/usr.bin/gcc/cp/cp-tree.def @@ -0,0 +1,169 @@ +/* This file contains the definitions and documentation for the + additional tree codes used in the GNU C++ compiler (see tree.def + for the standard codes). + Copyright (C) 1987, 1988, 1990, 1993 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@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. */ + + +/* Reference to the contents of an offset + (a value whose type is an OFFSET_TYPE). + Operand 0 is the object within which the offset is taken. + Operand 1 is the offset. The language independent OFFSET_REF + just won't work for us. */ +DEFTREECODE (OFFSET_REF, "offset_ref", "r", 2) + +/* For DELETE_EXPR, operand 0 is the store to be destroyed. + Operand 1 is the value to pass to the destroying function + saying whether the store should be deallocated as well. */ +DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2) +DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2) + +/* Value is reference to particular overloaded class method. + Operand 0 is the class name (an IDENTIFIER_NODE); + operand 1 is the field (also an IDENTIFIER_NODE). + The COMPLEXITY field holds the class level (usually 0). */ +DEFTREECODE (SCOPE_REF, "scope_ref", "r", 2) + +/* When composing an object with a member, this is the result. + Operand 0 is the object. Operand 1 is the member (usually + a dereferenced pointer to member). */ +DEFTREECODE (MEMBER_REF, "member_ref", "r", 2) + +/* Type conversion operator in C++. TREE_TYPE is type that this + operator converts to. Operand is expression to be converted. */ +DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1) + +/* For NEW_EXPR, operand 0 is function which performs initialization, + operand 1 is argument list to initialization function, + and operand 2 is the slot which was allocated for this expression. */ +DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3) +DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3) + +/* A throw expression. operand 0 is the expression, if there was one, + else it is NULL_TREE. */ +DEFTREECODE (THROW_EXPR, "throw_expr", "e", 1) + +/* Initialization of a vector, used in build_new. Operand 0 is the target + of the initialization, operand 1 is the initializer, and operand 2 is + the number of elements. */ +DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", "e", 3) + +/* Template definition. The following fields have the specified uses, + although there are other macros in cp-tree.h that should be used for + accessing this data. + DECL_ARGUMENTS template parm vector + DECL_TEMPLATE_INFO template text &c + DECL_VINDEX list of instantiations already produced; + only done for functions so far + For class template: + DECL_INITIAL associated templates (methods &c) + DECL_RESULT null + For non-class templates: + TREE_TYPE type of object to be constructed + DECL_RESULT decl for object to be created + (e.g., FUNCTION_DECL with tmpl parms used) + */ +DEFTREECODE (TEMPLATE_DECL, "template_decl", "d", 0) + +/* Index into a template parameter list. This parameter must be a type. + Use TYPE_FIELDS to find parmlist and index. */ +DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", "t", 0) + +/* A type designated by 'typename T::t'. */ +DEFTREECODE (TYPENAME_TYPE, "typename_type", "t", 0) + +/* Index into a template parameter list. This parameter must not be a + type. */ +DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 3) + +/* A thunk is a stub function. + + Thunks are used to implement multiple inheritance: + At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree) + from the this pointer, and then jumps to DECL_INITIAL + (which is an ADDR_EXPR whose operand is a FUNCTION_DECL). + + Other kinds of thunks may be defined later. */ +DEFTREECODE (THUNK_DECL, "thunk_decl", "d", 0) + +/* A namespace declaration. */ +DEFTREECODE (NAMESPACE_DECL, "namespace_decl", "d", 0) + +/* A using declaration. DECL_INITIAL contains the specified scope. + This is not an alias, but is later expanded into multiple aliases. */ +DEFTREECODE (USING_DECL, "using_decl", "d", 0) + +/* An un-parsed default argument. Looks like an IDENTIFIER_NODE. */ +DEFTREECODE (DEFAULT_ARG, "default_arg", "c", 2) + +/* A template-id, like foo<int>. The first operand is the template. + The second is the list of explicitly specified arguments. The + template will be a FUNCTION_DECL, TEMPLATE_DECL, or a list of + overloaded functions and templates if the template-id refers to + a global template. If the template-id refers to a member template, + the template will will be an IDENTIFIER_NODE. */ +DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", "e", 2) + +/* A whole bunch of tree codes for the initial, superficial parsing of + templates. */ +DEFTREECODE (LOOKUP_EXPR, "lookup_expr", "e", 2) +DEFTREECODE (MODOP_EXPR, "modop_expr", "e", 3) +DEFTREECODE (CAST_EXPR, "cast_expr", "1", 1) +DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", "1", 1) +DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", "1", 1) +DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", "1", 1) +DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", "1", 1) +DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", "1", 1) +DEFTREECODE (ARROW_EXPR, "arrow_expr", "e", 1) +DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", "e", 2) +DEFTREECODE (TYPEID_EXPR, "typeid_expr", "e", 1) + +DEFTREECODE (EXPR_STMT, "expr_stmt", "e", 1) +DEFTREECODE (COMPOUND_STMT, "compound_stmt", "e", 1) +DEFTREECODE (DECL_STMT, "decl_stmt", "e", 3) +DEFTREECODE (IF_STMT, "if_stmt", "e", 3) +DEFTREECODE (FOR_STMT, "for_stmt", "e", 4) +DEFTREECODE (WHILE_STMT, "while_stmt", "e", 2) +DEFTREECODE (DO_STMT, "do_stmt", "e", 2) +DEFTREECODE (RETURN_STMT, "return_stmt", "e", 1) +DEFTREECODE (BREAK_STMT, "break_stmt", "e", 0) +DEFTREECODE (CONTINUE_STMT, "continue_stmt", "e", 0) +DEFTREECODE (SWITCH_STMT, "switch_stmt", "e", 2) +DEFTREECODE (GOTO_STMT, "goto_stmt", "e", 1) + +DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", "e", 2) +DEFTREECODE (CASE_LABEL, "case_label", "e", 2) +DEFTREECODE (RETURN_INIT, "return_init", "e", 2) +DEFTREECODE (TRY_BLOCK, "try_stmt", "e", 2) +DEFTREECODE (HANDLER, "catch_stmt", "e", 2) + +DEFTREECODE (IDENTITY_CONV, "identity_conv", "e", 1) +DEFTREECODE (LVALUE_CONV, "lvalue_conv", "e", 1) +DEFTREECODE (QUAL_CONV, "qual_conv", "e", 1) +DEFTREECODE (STD_CONV, "std_conv", "e", 1) +DEFTREECODE (PTR_CONV, "ptr_conv", "e", 1) +DEFTREECODE (PMEM_CONV, "pmem_conv", "e", 1) +DEFTREECODE (BASE_CONV, "base_conv", "e", 1) +DEFTREECODE (REF_BIND, "ref_bind", "e", 1) +DEFTREECODE (USER_CONV, "user_conv", "e", 4) +DEFTREECODE (AMBIG_CONV, "ambig_conv", "e", 1) +DEFTREECODE (RVALUE_CONV, "rvalue_conv", "e", 1) + +DEFTREECODE (TAG_DEFN, "tag_defn", "e", 0) diff --git a/gnu/usr.bin/gcc/cp/exception.cc b/gnu/usr.bin/gcc/cp/exception.cc new file mode 100644 index 00000000000..caaf5892282 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/exception.cc @@ -0,0 +1,195 @@ +// Functions for Exception Support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996 Free Software Foundation + +// 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 other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself 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. + +#pragma implementation "exception" + +#include "typeinfo" +#include "exception" + +/* Define terminate, unexpected, set_terminate, set_unexpected as + well as the default terminate func and default unexpected func. */ + +extern terminate_handler __terminate_func __attribute__((__noreturn__)); + +void +terminate () +{ + __terminate_func (); +} + +void +__default_unexpected () +{ + terminate (); +} + +static unexpected_handler __unexpected_func = __default_unexpected; + +terminate_handler +set_terminate (terminate_handler func) +{ + terminate_handler old = __terminate_func; + + __terminate_func = func; + return old; +} + +unexpected_handler +set_unexpected (unexpected_handler func) +{ + unexpected_handler old = __unexpected_func; + + __unexpected_func = func; + return old; +} + +void +unexpected () +{ + __unexpected_func (); +} + +/* C++-specific state about the current exception. + This must match init_exception_processing(). + + Note that handlers and caught are not redundant; when rethrown, an + exception can have multiple active handlers and still be considered + uncaught. */ + +struct cp_eh_info +{ + void *value; + void *type; + void (*cleanup)(void *, int); + bool caught; + cp_eh_info *next; + long handlers; +}; + +/* Language-specific EH info pointer, defined in libgcc2. */ + +extern cp_eh_info *__eh_info; // actually void* + +/* Is P the type_info node for a pointer of some kind? */ + +extern bool __is_pointer (void *); + +/* Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). */ + +extern "C" cp_eh_info * +__cp_exception_info (void) +{ + return __eh_info; +} + +/* Compiler hook to push a new exception onto the stack. + Used by expand_throw(). */ + +extern "C" void +__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int)) +{ + cp_eh_info *p = new cp_eh_info; + p->value = value; + p->type = type; + p->cleanup = cleanup; + p->handlers = 0; + p->caught = false; + p->next = __eh_info; + __eh_info = p; +} + +/* Compiler hook to pop an exception that has been finalized. Used by + push_eh_cleanup(). P is the info for the exception caught by the + current catch block, and HANDLER determines if we've been called from + an exception handler; if so, we avoid destroying the object on rethrow. */ + +extern "C" void +__cp_pop_exception (cp_eh_info *p, bool handler) +{ + cp_eh_info **q = &__eh_info; + + --p->handlers; + + if (p->handlers > 0 || (handler && p == *q)) + return; + + for (; *q; q = &((*q)->next)) + if (*q == p) + break; + + if (! *q) + terminate (); + + *q = p->next; + + if (p->cleanup) + /* 3 is a magic value for destructors; see build_delete(). */ + p->cleanup (p->value, 3); + else if (__is_pointer (p->type)) + /* do nothing; pointers are passed directly in p->value. */; + else + delete p->value; + + delete p; +} + +extern "C" void +__uncatch_exception (void) +{ + cp_eh_info *p = __cp_exception_info (); + if (p) + p->caught = false; + /* otherwise __throw will call terminate(); don't crash here. */ +} + +extern "C" void +__throw_bad_cast (void) +{ + throw bad_cast (); +} + +extern "C" void +__throw_bad_typeid (void) +{ + throw bad_typeid (); +} + +/* Has the current exception been caught? */ + +bool +uncaught_exception () +{ + cp_eh_info *p = __cp_exception_info (); + return p && ! p->caught; +} + +const char * exception:: +what () const +{ + return typeid (*this).name (); +} diff --git a/gnu/usr.bin/gcc/cp/friend.c b/gnu/usr.bin/gcc/cp/friend.c new file mode 100644 index 00000000000..28c0bb44a68 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/friend.c @@ -0,0 +1,440 @@ +/* Help friends in C++. + Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include <stdio.h> +#include "tree.h" +#include "rtl.h" +#include "cp-tree.h" +#include "flags.h" +#include "output.h" + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +static void add_friend PROTO((tree, tree)); +static void add_friends PROTO((tree, tree, tree)); + +/* Friend data structures: + + Lists of friend functions come from TYPE_DECL nodes. Since all + aggregate types are automatically typedef'd, these nodes are guaranteed + to exist. + + The TREE_PURPOSE of a friend list is the name of the friend, + and its TREE_VALUE is another list. + + For each element of that list, either the TREE_VALUE or the TREE_PURPOSE + will be filled in, but not both. The TREE_VALUE of that list is an + individual function which is a friend. The TREE_PURPOSE of that list + indicates a type in which all functions by that name are friends. + + Lists of friend classes come from _TYPE nodes. Love that consistency + thang. */ + +int +is_friend (type, supplicant) + tree type, supplicant; +{ + int declp; + register tree list; + + if (supplicant == NULL_TREE || type == NULL_TREE) + return 0; + + declp = (TREE_CODE_CLASS (TREE_CODE (supplicant)) == 'd'); + + if (declp) + /* It's a function decl. */ + { + tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); + tree name = DECL_NAME (supplicant); + tree ctype; + + if (DECL_FUNCTION_MEMBER_P (supplicant)) + ctype = DECL_CLASS_CONTEXT (supplicant); + else + ctype = NULL_TREE; + + for (; list ; list = TREE_CHAIN (list)) + { + if (name == TREE_PURPOSE (list)) + { + tree friends = TREE_VALUE (list); + for (; friends ; friends = TREE_CHAIN (friends)) + { + if (ctype == TREE_PURPOSE (friends)) + return 1; + if (comptypes (TREE_TYPE (supplicant), + TREE_TYPE (TREE_VALUE (friends)), 1)) + return 1; + } + break; + } + } + } + else + /* It's a type. */ + { + if (type == supplicant) + return 1; + + list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type))); + for (; list ; list = TREE_CHAIN (list)) + if (supplicant == TREE_VALUE (list)) + return 1; + } + + { + tree context; + + if (! declp) + { + /* Are we a nested or local class? If so, we aren't friends + with the CONTEXT. */ + if (IS_AGGR_TYPE (supplicant)) + context = NULL_TREE; + else + context = DECL_CONTEXT (TYPE_MAIN_DECL (supplicant)); + } + else if (DECL_FUNCTION_MEMBER_P (supplicant)) + context = DECL_CLASS_CONTEXT (supplicant); + else + context = NULL_TREE; + + if (context) + return is_friend (type, context); + } + + return 0; +} + +/* Add a new friend to the friends of the aggregate type TYPE. + DECL is the FUNCTION_DECL of the friend being added. */ + +static void +add_friend (type, decl) + tree type, decl; +{ + tree typedecl = TYPE_MAIN_DECL (type); + tree list = DECL_FRIENDLIST (typedecl); + tree name = DECL_NAME (decl); + + while (list) + { + if (name == TREE_PURPOSE (list)) + { + tree friends = TREE_VALUE (list); + for (; friends ; friends = TREE_CHAIN (friends)) + { + if (decl == TREE_VALUE (friends)) + { + cp_warning ("`%D' is already a friend of class `%T'", + decl, type); + cp_warning_at ("previous friend declaration of `%D'", + TREE_VALUE (friends)); + return; + } + } + TREE_VALUE (list) = tree_cons (error_mark_node, decl, + TREE_VALUE (list)); + return; + } + list = TREE_CHAIN (list); + } + DECL_FRIENDLIST (typedecl) + = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), + DECL_FRIENDLIST (typedecl)); + if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR]) + { + tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); + TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1; + if (parmtypes && TREE_CHAIN (parmtypes)) + { + tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes)); + if (TREE_CODE (parmtype) == REFERENCE_TYPE + && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl)) + TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1; + } + } +} + +/* Declare that every member function NAME in FRIEND_TYPE + (which may be NULL_TREE) is a friend of type TYPE. */ + +static void +add_friends (type, name, friend_type) + tree type, name, friend_type; +{ + tree typedecl = TYPE_MAIN_DECL (type); + tree list = DECL_FRIENDLIST (typedecl); + + while (list) + { + if (name == TREE_PURPOSE (list)) + { + tree friends = TREE_VALUE (list); + while (friends && TREE_PURPOSE (friends) != friend_type) + friends = TREE_CHAIN (friends); + if (friends) + if (friend_type) + warning ("method `%s::%s' is already a friend of class", + TYPE_NAME_STRING (friend_type), + IDENTIFIER_POINTER (name)); + else + warning ("function `%s' is already a friend of class `%s'", + IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (DECL_NAME (typedecl))); + else + TREE_VALUE (list) = tree_cons (friend_type, NULL_TREE, + TREE_VALUE (list)); + return; + } + list = TREE_CHAIN (list); + } + DECL_FRIENDLIST (typedecl) + = tree_cons (name, + build_tree_list (friend_type, NULL_TREE), + DECL_FRIENDLIST (typedecl)); + if (! strncmp (IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]), + strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR])))) + { + TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1; + sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists"); + } +} + +/* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already + been defined, we make all of its member functions friends of + TYPE. If not, we make it a pending friend, which can later be added + when its definition is seen. If a type is defined, then its TYPE_DECL's + DECL_UNDEFINED_FRIENDS contains a (possibly empty) list of friend + classes that are not defined. If a type has not yet been defined, + then the DECL_WAITING_FRIENDS contains a list of types + waiting to make it their friend. Note that these two can both + be in use at the same time! */ + +void +make_friend_class (type, friend_type) + tree type, friend_type; +{ + tree classes; + + if (IS_SIGNATURE (type)) + { + error ("`friend' declaration in signature definition"); + return; + } + if (IS_SIGNATURE (friend_type)) + { + error ("signature type `%s' declared `friend'", + IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type))); + return; + } + if (type == friend_type) + { + pedwarn ("class `%s' is implicitly friends with itself", + TYPE_NAME_STRING (type)); + return; + } + + GNU_xref_hier (TYPE_NAME_STRING (type), + TYPE_NAME_STRING (friend_type), 0, 0, 1); + + classes = CLASSTYPE_FRIEND_CLASSES (type); + while (classes && TREE_VALUE (classes) != friend_type) + classes = TREE_CHAIN (classes); + if (classes) + warning ("class `%s' is already friends with class `%s'", + TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type)); + else + { + CLASSTYPE_FRIEND_CLASSES (type) + = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); + } +} + +/* Main friend processor. This is large, and for modularity purposes, + has been removed from grokdeclarator. It returns `void_type_node' + to indicate that something happened, though a FIELD_DECL is + not returned. + + CTYPE is the class this friend belongs to. + + DECLARATOR is the name of the friend. + + DECL is the FUNCTION_DECL that the friend is. + + In case we are parsing a friend which is part of an inline + definition, we will need to store PARM_DECL chain that comes + with it into the DECL_ARGUMENTS slot of the FUNCTION_DECL. + + FLAGS is just used for `grokclassfn'. + + QUALS say what special qualifies should apply to the object + pointed to by `this'. */ + +tree +do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) + tree ctype, declarator, decl, parmdecls; + enum overload_flags flags; + tree quals; + int funcdef_flag; +{ + /* Every decl that gets here is a friend of something. */ + DECL_FRIEND_P (decl) = 1; + + if (ctype) + { + tree cname = TYPE_NAME (ctype); + if (TREE_CODE (cname) == TYPE_DECL) + cname = DECL_NAME (cname); + + /* A method friend. */ + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (flags == NO_SPECIAL && ctype && declarator == cname) + DECL_CONSTRUCTOR_P (decl) = 1; + + /* This will set up DECL_ARGUMENTS for us. */ + grokclassfn (ctype, cname, decl, flags, quals); + if (TYPE_SIZE (ctype) != 0) + decl = check_classfn (ctype, decl); + + if (TREE_TYPE (decl) != error_mark_node) + { + if (TYPE_SIZE (ctype)) + add_friend (current_class_type, decl); + else + { + cp_error ("member `%D' declared as friend before type `%T' defined", + decl, ctype); + } + } + } + else + { + /* Possibly a bunch of method friends. */ + + /* Get the class they belong to. */ + tree ctype = IDENTIFIER_TYPE_VALUE (cname); + tree fields = lookup_fnfields (TYPE_BINFO (ctype), declarator, 0); + + if (fields) + add_friends (current_class_type, declarator, ctype); + else + error ("method `%s' is not a member of class `%s'", + IDENTIFIER_POINTER (declarator), + IDENTIFIER_POINTER (cname)); + decl = void_type_node; + } + } + else if (TREE_CODE (decl) == FUNCTION_DECL + && ((IDENTIFIER_LENGTH (declarator) == 4 + && IDENTIFIER_POINTER (declarator)[0] == 'm' + && ! strcmp (IDENTIFIER_POINTER (declarator), "main")) + || (IDENTIFIER_LENGTH (declarator) > 10 + && IDENTIFIER_POINTER (declarator)[0] == '_' + && IDENTIFIER_POINTER (declarator)[1] == '_' + && strncmp (IDENTIFIER_POINTER (declarator)+2, + "builtin_", 8) == 0))) + { + /* raw "main", and builtin functions never gets overloaded, + but they can become friends. */ + add_friend (current_class_type, decl); + DECL_FRIEND_P (decl) = 1; + decl = void_type_node; + } + /* A global friend. + @@ or possibly a friend from a base class ?!? */ + else if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* Friends must all go through the overload machinery, + even though they may not technically be overloaded. + + Note that because classes all wind up being top-level + in their scope, their friend wind up in top-level scope as well. */ + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)), + TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); + DECL_ARGUMENTS (decl) = parmdecls; + if (funcdef_flag) + DECL_CLASS_CONTEXT (decl) = current_class_type; + + if (! DECL_USE_TEMPLATE (decl)) + { + /* We can call pushdecl here, because the TREE_CHAIN of this + FUNCTION_DECL is not needed for other purposes. Don't do this + for a template instantiation. */ + decl = pushdecl (decl); + + if (! funcdef_flag && ! flag_guiding_decls + && current_template_parms && uses_template_parms (decl)) + { + static int explained; + cp_warning ("friend declaration `%#D'", decl); + warning (" will not be treated as a template instantiation"); + if (! explained) + { + warning (" unless you compile with -fguiding-decls"); + warning (" or add <> after the function name"); + explained = 1; + } + } + } + + make_decl_rtl (decl, NULL_PTR, 1); + add_friend (current_class_type, decl); + + DECL_FRIEND_P (decl) = 1; + } + else + { + /* @@ Should be able to ingest later definitions of this function + before use. */ + tree decl = lookup_name_nonclass (declarator); + if (decl == NULL_TREE) + { + warning ("implicitly declaring `%s' as struct", + IDENTIFIER_POINTER (declarator)); + decl = xref_tag (record_type_node, declarator, NULL_TREE, 1); + decl = TYPE_MAIN_DECL (decl); + } + + /* Allow abbreviated declarations of overloaded functions, + but not if those functions are really class names. */ + if (TREE_CODE (decl) == TREE_LIST && TREE_TYPE (TREE_PURPOSE (decl))) + { + warning ("`friend %s' archaic, use `friend class %s' instead", + IDENTIFIER_POINTER (declarator), + IDENTIFIER_POINTER (declarator)); + decl = TREE_TYPE (TREE_PURPOSE (decl)); + } + + if (TREE_CODE (decl) == TREE_LIST) + add_friends (current_class_type, TREE_PURPOSE (decl), NULL_TREE); + else + make_friend_class (current_class_type, TREE_TYPE (decl)); + decl = void_type_node; + } + return decl; +} diff --git a/gnu/usr.bin/gcc/cp/g++FAQ.texi b/gnu/usr.bin/gcc/cp/g++FAQ.texi new file mode 100644 index 00000000000..f0064f346b1 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/g++FAQ.texi @@ -0,0 +1,2158 @@ +\input texinfo.tex @c -*-texinfo-*- +@c %**start of header +@setfilename g++FAQ.info +@settitle Frequently asked questions about the GNU C++ compiler +@setchapternewpage off +@c version: @(#)g++FAQ.texi 1.56 09/15/97 +@c %**end of header + +@iftex +@finalout +@end iftex +@titlepage +@title G++ FAQ +@subtitle Frequently asked questions about the GNU C++ compiler +@subtitle September 14, 1997 +@sp 1 +@author Joe Buck +@page +@end titlepage + +@ifinfo +@node Top, basics, (dir), (dir) +@top +@unnumbered FAQ for g++ and libg++, by Joe Buck (jbuck@@synopsys.com) +@end ifinfo + +@cindex FAQ for g++, latest version +@cindex Archive site for FAQ lists +@cindex rtfm.mit.edu +@cindex Joe Buck <jbuck@@synopsys.com> +@cindex FAQ for C++ + +This is a list of frequently asked questions (FAQ) for g++ users; thanks to +all those who sent suggestions for improvements. Thanks to Marcus Speh +for doing the index. A hypertext version is available on the World Wide +Web at @file{http://www.cygnus.com/misc/g++FAQ_toc.html}. + +This document has just been reorganized a bit. There is some new +information about upcoming g++ releases and egcs; more needs to be done +but that will need to wait for next time. A diff would look misleadingly +large, since I blew away and rebuilt the texinfo menus. + +Please send updates and corrections to the FAQ to +@code{jbuck@@synopsys.com}. Please do @emph{not} use me as a resource +to get your questions answered; that's what @file{gnu.g++.help} is for and I +don't have the time to support the net's use of g++. + +Many FAQs, including this one, are available on the archive site +``rtfm.mit.edu''; see @* +@file{ftp://rtfm.mit.edu/pub/usenet/news.answers}. +This FAQ may be found in the subdirectory g++-FAQ. + +@cindex Marshall Cline +@cindex comp.lang.c++ +@cindex C++ FAQ +This FAQ is intended to supplement, not replace, Marshall Cline's +excellent FAQ for the C++ language and for the newsgroup +@file{comp.lang.c++}. Especially if g++ is the first C++ +compiler you've ever used, the question ``How do I do <X> with g++?'' +is probably really ``How do I do <X> in C++?''. +You can find this FAQ at +@file{ftp://rtfm.mit.edu/pub/usenet/comp.lang.c++}, +or in HTML form at @file{http://www.cerfnet.com/~mpcline/On-Line-C++-FAQs/}. + +@menu +* basics:: What is g++? How do I get it? +* installation:: How to install, installation problems +* evolution:: The Evolution of g++ +* User Problems:: Commonly reported problems and bugs +* legalities:: Lawyer stuff, GPL, LGPL, etc. +* index:: Index of terms + + --- The Detailed Node Listing --- + +The basics: what is g++? + +* latest versions:: +* g++ for Unix:: +* g++ for HP:: +* g++ for Solaris 2.x:: +* g++ for other platforms:: +* 1.x vs 2.x versions:: + +Installation Issues and Problems + +* gcc-2 + g++-1:: +* what else do I need?:: +* use GNU linker?:: +* Use GNU assembler?:: +* shared libraries:: +* repository:: +* repo bugs:: +* Use GNU C library?:: +* Global constructor problems:: +* Strange assembler errors:: +* Other problems building libg++:: +* More size_t problems:: +* Rebuild libg++?:: +* co-existing versions:: +* Installing on Linux:: +* Linux Slackware 3.0:: + +The Evolution of g++ + +* version 2.7.x:: +* libstdc++:: +* new work:: +* egcs:: +* When?:: + +User Problems + +* missing virtual table:: +* for scope:: +* const constructor:: +* unused parameter warnings:: +* jump crosses initialization:: +* Demangler:: +* static data members:: +* internal compiler error:: +* bug reports:: +* porting to g++:: +* name mangling:: +* problems linking with other libraries:: +* documentation:: +* templates:: +* undefined templates:: +* redundant templates:: +* Standard Template Library:: +* STL and string:: +* exceptions:: +* namespaces:: +* agreement with standards:: +* compiling standard libraries:: +* debugging on SVR4 systems:: +* debugging problems on Solaris:: +* X11 conflicts with libg++:: +* assignment to streams:: +@end menu + +@node basics, installation, Top, Top +@chapter The basics: what is g++? + +@cindex Free Software Foundation +@cindex GNU Public License +@cindex GPL + +g++ is the traditional nickname of GNU C++, a freely redistributable +C++ compiler produced by the Free Software Foundation plus dozens of +skilled volunteers. I say ``traditional nickname'' because the GNU +compiler suite, gcc, bundles together compilers for C, Objective-C, +and C++ in one package. + +While the source code to gcc/g++ can be downloaded for free, +it is not public domain, but is protected by the GNU Public License, +or GPL (@pxref{legalities}). + +@menu +* latest versions:: +* g++ for Unix:: +* g++ for HP:: +* g++ for Solaris 2.x:: +* g++ for other platforms:: +* 1.x vs 2.x versions:: +@end menu + +@node latest versions, g++ for Unix, basics, basics +@section What is the latest version of gcc, g++, and libg++? + +@cindex gcc/g++, version date +The current version of gcc/g++ is 2.7.2.3, released August 20, 1997. +Although that looks very recent, the only change is a minor patch to +resolve a problem with Linux and the GNU C library; users not interested +in that functionality have no reason to upgrade. + +The current version of libg++ is 2.7.2, released July 4, 1996. +The last release of gcc/g++ with improvements to the C++ front end was +2.7.2, released Nov. 25, 1995, nearly two years ago. + +I would strongly recommend that anyone using a g++ version earlier +than 2.7.2 should upgrade if at all possible (@pxref{version 2.7.x}). + +For some non-Unix platforms, the latest port of gcc may be an earlier +version (2.6.3, say). You'll need to use a version of libg++ that +has the same first two digits as the compiler version, e.g. use libg++ +2.6.x (for the latest x you can find) with gcc version 2.6.3. + +The latest "1.x" version of gcc is 1.42, and the latest "1.x" version of +g++ is 1.42.0. +While gcc 1.42 is quite usable for C programs, +I recommend against using g++ 1.x except in special circumstances +(and I can't think of any such circumstances). + +@node g++ for Unix, g++ for HP, latest versions, basics +@section How do I get a copy of g++ for Unix? + +First, you may already have it if you have gcc for your platform; +g++ and gcc are combined now (as of gcc version 2.0). +@cindex GNU gcc, version +@cindex GNU g++ and gcc + +You can get g++ from a friend who has a copy, by anonymous FTP or +UUCP, or by ordering a tape or CD-ROM from the Free Software +Foundation. +@cindex g++, ordering +@cindex g++, getting a copy + +The Free Software Foundation is a nonprofit organization that +distributes software and manuals to raise funds for more GNU +development. Getting your copy from the FSF contributes directly to +paying staff to develop GNU software. CD-ROMs cost $400 if an +organization is buying, or $100 if an individual is buying. Tapes +cost around $200 depending on media type. I recommend asking for +version 2, not version 1, of g++. +@cindex FSF [Free Software Foundation] +@cindex GNU [GNU's not unix] + +For more information about ordering from the FSF, contact +gnu@@prep.ai.mit.edu, phone (617) 542-5942 or anonymous ftp file +@file{ftp://prep.ai.mit.edu/pub/gnu/GNUinfo/ORDERS} (you can +also use one of the sites listed below if you can't get into ``prep''). + +@cindex FSF, contact <gnu@@prep.ai.mit.edu> + +Here is a list of anonymous FTP archive sites for GNU software. +If no directory is given, look in @file{/pub/gnu}. + +@cindex GNUware, anonymous FTP sites + +@example +ASIA: ftp.cs.titech.ac.jp, tron.um.u-tokyo.ac.jp:/pub/GNU/prep +cair-archive.kaist.ac.kr, ftp.nectec.or.th:/pub/mirrors/gnu + +AUSTRALIA: archie.au:/gnu (archie.oz or archie.oz.au for ACSnet) + +AFRICA: ftp.sun.ac.za + +MIDDLE-EAST: ftp.technion.ac.il:/pub/unsupported/gnu + +EUROPE: irisa.irisa.fr, ftp.univ-lyon1.fr, +ftp.mcc.ac.uk, unix.hensa.ac.uk:/mirrors/uunet/systems/gnu, +src.doc.ic.ac.uk:/gnu, ftp.ieunet.ie, ftp.eunet.ch, +nic.switch.ch:/mirror/gnu, ftp.informatik.rwth-aachen.de, +ftp.informatik.tu-muenchen.de, ftp.win.tue.nl, ftp.nl.net, +ftp.etsimo.uniovi.es, ftp.funet.fi, ftp.denet.dk, +ftp.stacken.kth.se, isy.liu.se, ftp.luth.se:/pub/unix/gnu, +ftp.sunet.se, archive.eu.net + +SOUTH AMERICA: ftp.inf.utfsm.cl, ftp.unicamp.br + +WESTERN CANADA: ftp.cs.ubc.ca:/mirror2/gnu + +USA: wuarchive.wustl.edu:/systems/gnu, labrea.stanford.edu, +ftp.digex.net, ftp.kpc.com:/pub/mirror/gnu, f.ms.uky.edu:/pub3/gnu, +jaguar.utah.edu:/gnustuff, ftp.hawaii.edu:/mirrors/gnu, +uiarchive.cso.uiuc.edu, ftp.cs.columbia.edu:/archives/gnu/prep, +gatekeeper.dec.com:/pub/GNU, ftp.uu.net:/systems/gnu +@end example + +The ``official site'' is prep.ai.mit.edu, but your transfer will probably +go faster if you use one of the above machines. + +@cindex gzip +Most GNU utilities are compressed with ``gzip'', the GNU compression +utility. All GNU archive sites should have a copy of this program, +which you will need to uncompress the distributions. + +@cindex libg++ +Don't forget to retrieve libg++ as well! + +@node g++ for HP, g++ for Solaris 2.x, g++ for Unix, basics +@section Getting gcc/g++ for the HP Precision Architecture + +@cindex HP Precision Architecture +@cindex Hewlett-Packard +@cindex GNU GAS +@cindex GNU gdb + +If you use the HP Precision Architecture (HP-9000/7xx and HP-9000/8xx) +and you want to use debugging, you'll need to use the GNU assembler, GAS +(version 2.3 or later). If you build from source, you must tell the +configure program that you are using GAS or you won't get debugging +support. A non-standard debug format is used, since until recently HP +considered their debug format a trade secret. Thanks to the work of +lots of good folks both inside and outside HP, the company has seen the +error of its ways and has now released the required information. The +team at the University of Utah that did the gcc port now has code that +understands the native HP format. + +There are binaries for GNU tools in +@file{ftp://jaguar.cs.utah.edu/dist/}, +but these are older versions. + +Jeff Law has left the University of Utah, so the Utah prebuilt +binaries may be discontinued. + +@node g++ for Solaris 2.x, g++ for other platforms, g++ for HP, basics +@section Getting gcc/g++ binaries for Solaris 2.x + +``Sun took the C compiler out of Solaris 2.x. Am I stuck?'' + +@cindex Solaris +@cindex gcc/g++ binaries for Solaris + +You'll need to get prebuilt binaries from someone. + +It used to be that you could get GCC binaries from prep.ai.mit.edu; +these are no longer there. + +@cindex Solaris pkgadd utility +The WWW site @file{http://smc.vnet.net/solaris_2.5.html} +contains various +GNU and freeware programs for Solaris2.5 running on the sparc. These are +packaged to enable easy installation using the Solaris ``pkgadd'' utility. +These include GNU emacs, gcc, gdb, perl, and others. These versions +are more recent than the binaries at ``prep'' (gcc 2.7.2 and libg++ +2.7.1 are there). + +@node g++ for other platforms, 1.x vs 2.x versions, g++ for Solaris 2.x, basics +@section How do I get a copy of g++ for (some other platform)? + +@cindex Windows NT support +As of gcc-2.7.x, there is Windows NT support in gcc. Some special +utilities are required. See the INSTALL file from the distribution. +If you're interested in GNU tools on Windows NT, see +@file{http://www.cygnus.com/misc/gnu-win32/} on the WWW, or the +anonymous FTP directory +@file{ftp://ftp.cygnus.com/pub/gnu-win32/}. + +@cindex VMS support +@cindex VAX +@cindex VMS, g++/libg++ precompiled + +The standard gcc/g++ distribution includes VMS support for the Vax. +Since the FSF people don't use VMS, it's likely to be somewhat less +solid than the Unix version. Precompiled copies of g++ and libg++ in +VMS-installable form for the Vax are available by FTP from +@file{ftp://mango.rsmas.miami.edu/pub/VMS-gcc/}. + +@cindex OpenVMS/Alpha +Klaus Kaempf (kkaempf@@progis.de) +has done a port to OpenVMS for the Alpha; this is not yet a +part of the official gcc/g++. +The port includes g++ and all libraries from the libg++ distribution. See +@file{http://www.progis.de} for more details. + +@cindex MS-DOS support +@cindex Delorie's gcc/g++ +@cindex DJGPP +@cindex EMX +There are two different versions of gcc/g++ for MS-DOS: EMX and DJGPP. +EMX also works for OS/2 and is described later. +DJGPP is DJ Delorie's port. It can be found on many FTP archive +sites; try +@file{ftp://ftp.coast.net/SimTel/vendors/djgpp/} +or, for a complete list, see +@file{http://www.delorie.com/djgpp/getting.html}. + + +The latest version of DJGPP is 2.00. See +@file{http://www.delorie.com/djgpp/v2/} for information on this version. + +FSF sells floppies with DJGPP on them; see above for ordering software +from the FSF. + +DJGPP has its own newsgroup: @file{comp.os.msdos.djgpp}. + +@cindex Amiga support +Development and porting efforts for GNU tools, including gcc/g++, for +the Amiga are maintained by an initiative named ADE (Amiga Developers +Environment. More information about ADE is available at +@file{http://www.ninemoons.com/}. + +For more information on Amiga ports of gcc/g++, retrieve the file +@file{ftp://prep.ai.mit.edu/pub/gnu/MicrosPorts/Amiga}. + +@cindex Atari ST support +A port of gcc to the Atari ST can be found at @* +@file{ftp://atari.archive.umich.edu/atari/Gnustuff/Tos} +along with many +other GNU programs. This version is usually the same as the latest FSF +release. See the ``Software FAQ'' for the Usenet group +@file{comp.sys.atari.st} for more information. + +@cindex EMX port +@cindex OS/2 support + +EMX is a port of gcc to OS/2; it can also be used on MS-DOS. In addition to +the compiler port, the EMX port's C library attempts to provide a +Unix-like environment. For more information ask around on +@file{comp.os.os2.programmer.porting}. Version 0.9c, based on gcc-2.7.2.1, +was released in +November 1996. It is available by FTP and the WWW from, among other +places + +@example +@file{http://www.os2ss.com/unix/emx09c/} +@file{ftp://ftp.cdrom.com/pub/os2/emx09c/} (US) +@file{ftp://ftp.leo.org/pub/comp/os/os2/leo/devtools/emx+gcc/} (Germany) +@end example + +Eberhard Mattes did the EMX port. His address is +mattes@@azu.informatik.uni-stuttgart.de. +Read the FAQ file included with the distribution before harassing the author. + +@cindex Apple support +@cindex Macintosh support + +I'm looking for more information on gcc/g++ support on the Apple +Macintosh. Until recently, this FAQ did not provide such information, +but FSF is no longer boycotting Apple as the League for Programming +Freedom boycott has been dropped. + +Versions 1.37.1 and 2.3.3 of gcc were ported by Stan Shebs and are available +at @* +@file{ftp://ftp.cygnus.com/pub/mac} + +They are both interfaced to MPW. +Stan is working on a version using the current (post-2.7) sources, contact +him directly (shebs@@cygnus.com) for more information. + +@node 1.x vs 2.x versions, , g++ for other platforms, basics +@section But I can only find g++-1.42! + +``I keep hearing people talking about g++ 2.7.2 (or some other number +starting with 2), but the latest version I can find is g++ 1.42. +Where is it?'' + +@cindex Objective-C +@cindex g++, version number +As of gcc 2.0, C, C++, and Objective-C as well are all combined into a +single distribution called gcc. If you get gcc you already have g++. The +standard installation procedure for any gcc version 2 compiler will +install the C++ compiler as well. + +One could argue that we shouldn't even refer to "g++-2.x.y" but it's a +convention. It means ``the C++ compiler included with gcc-2.x.y.'' + +@node installation, evolution, basics, Top +@chapter Installation Issues and Problems + +@menu +* gcc-2 + g++-1:: +* what else do I need?:: +* use GNU linker?:: +* Use GNU assembler?:: +* shared libraries:: +* repository:: +* repo bugs:: +* Use GNU C library?:: +* Global constructor problems:: +* Strange assembler errors:: +* Other problems building libg++:: +* More size_t problems:: +* Rebuild libg++?:: +* co-existing versions:: +* Installing on Linux:: +* Linux Slackware 3.0:: +@end menu + +@node gcc-2 + g++-1, what else do I need?, installation, installation +@section I can't build g++ 1.x.y with gcc-2.x.y! + +``I obtained gcc-2.x.y and g++ 1.x.y and I'm trying to build it, but +I'm having major problems. What's going on?'' + +@cindex g++, building +If you wish to build g++-1.42, you must obtain gcc-1.42 first. The +installation instructions for g++ version 1 leave a lot to be desired, +unfortunately, and I would recommend that, unless you have a special +reason for needing the 1.x compiler, that C++ users use the latest +g++-2.x version, as it +is the version that is being actively maintained. + +@cindex g++, template support +@cindex Templates +@cindex ANSI draft standard +There is no template support in g++-1.x, and it is generally much further +away from the ANSI draft standard than g++-2.x is. + +@node what else do I need?, use GNU linker?, gcc-2 + g++-1, installation +@section OK, I've obtained gcc; what else do I need? + +@cindex libg++ +First off, you'll want libg++ as you can do almost nothing without it +(unless you replace it with some other class library). + +@cindex GNU GAS +@cindex GNU GAS [assembler] +Second, depending on your platform, you may need "GAS", the GNU assembler, +or the GNU linker (see next question). + +@cindex GNU gdb +Finally, while it is not required, you'll almost certainly want the GNU +debugger, gdb. The latest version is +4.16, released April 22, 1996. +Other debuggers (like dbx, for example) will normally not be able to +understand at least some of the debug information produced by g++. + +@node use GNU linker?, Use GNU assembler?, what else do I need?, installation +@section Should I use the GNU linker, or should I use "collect"? + +@cindex Linker +@cindex System VR3, linker +@cindex System VR4, linker +First off, for novices: special measures must be taken with C++ to arrange +for the calling of constructors for global or static objects before the +execution of your program, and for the calling of destructors at the end. +(Exception: System VR3 and System VR4 linkers, Linux/ELF, and some other +systems support user-defined +segments; g++ on these systems requires neither the GNU linker nor +collect. So if you have such a system, the answer is that you don't +need either one, though using GNU ld does have some advantages over +the native linker in some cases). + +@cindex AT&T cfront +@cindex Cfront-end +@cindex collect program +@cindex GNU linker +@cindex GNU binutils +If you have experience with AT&T's "cfront", this function is performed +there by programs named "patch" or "munch". With GNU C++, it is performed +either by the GNU linker or by a program known as "collect". The collect +program is part of the gcc-2.x distribution; you can obtain the GNU linker +separately as part of the "binutils" package. The latest version of +binutils is 2.7, released July 10, 1996; 2.6 is in common use and works +well. + +(To be technical, it's "collect2"; there were originally several +alternative versions of collect, and this is the one that survived). + +There are advantages and disadvantages to either choice. + +Advantages of the GNU linker: +@cindex GNU linker, advantages +@cindex GNU ld +@cindex ld [GNU linker] + +It's faster than using collect -- collect basically runs the standard Unix +linker on your program twice, inserting some extra code after the first +pass to call the constructors. This is a sizable time penalty for large +programs. The GNU linker does not require this extra pass. + +GNU ld reports undefined symbols using their true names, not the mangled +names (but as of 2.7.0 so does collect). + +If there are undefined symbols, GNU ld reports which object file(s) refer to +the undefined symbol(s). On some OSes (e.g. SunOS, Solaris) the native +linker does not do this, so you have to track down who's referring to +the missing symbols yourself. + +As of binutils version 2.2, on systems that use the so-called "a.out" +debug format (e.g. Suns running SunOS 4.x), the GNU linker compresses +the debug symbol table considerably. The 2.7 version adds some symbol +table compression for ELF and Solaris targets. + +@cindex collect linker, advantages +Advantages of collect: + +@cindex Shared libraries +If your native linker supports shared libraries, you can use shared +libraries with collect. This used to be a strong reason @emph{not} +to use the GNU linker, but recent versions of GNU ld support linking +with shared libraries on many platforms, and creating shared libraries +on a few (such as Intel x86 systems that use ELF object format as well +as SunOS and Solaris). + +@xref{shared libraries} + +@cindex GNU linker, porting +The GNU linker has not been ported to as many platforms as g++ has, so you +may be forced to use collect. + +If you use collect, you don't need to get something extra and figure out +how to install it; the standard gcc installation procedure will do it for you. + +I used to say at this point that I don't see a clear win for either +linking alternative, but with all the improvements in the GNU linker +I think that it is now the better choice. Take your pick. + +If you run Linux, the only available linker is the GNU linker. + +@node Use GNU assembler?, shared libraries, use GNU linker?, installation +@section Should I use the GNU assembler, or my vendor's assembler? + +@cindex Assembler +@cindex GNU GAS +This depends on your platform and your decision about the GNU linker. For +most platforms, you'll need to use GAS if you use the GNU linker. For +some platforms, you have no choice; check the gcc installation notes to +see whether you must use GAS. But you can usually use the vendor's +assembler if you don't use the GNU linker. + +The GNU assembler assembles faster than many native assemblers; however, +on many platforms it cannot support the local debugging format. + +It used to be that the GNU assembler couldn't handle +position-independent code on SunOS. This is no longer true if you +have version 2.6 or newer. + +On HPUX or IRIX, you must use GAS (and configure gcc with the +@code{--with-gnu-as} option) to debug your programs. GAS is +strongly recommended particularly on the HP platform because of +limitations in the HP assembler. + +The GNU assembler has been merged with the binutils +distribution, so the GNU assembler and linker are now together in +this package (as of binutils version 2.5.1). + +On Linux the assembler is the GNU assembler. + +@node shared libraries, repository, Use GNU assembler?, installation +@section How do I build shared libraries with g++? + +For gcc-2.7.0 and later, building C++ shared libraries should work fine +on supported platforms (HPUX 9+, IRIX 5+, DEC UNIX (formerly OSF/1), +SGI/IRIX, AIX, SunOS 4, Linux/ELF and all targets using SVR4-style ELF shared +libraries). There are two separate issues: building libg++ as a shared +library, and making your own shared libraries. For libg++ it is simply +a matter of giving the @code{--enable-shared} option to the configure +program. When compiling your own code for shared libraries you +generally +must use the @code{-fPIC} flag to get position-independent code. + +@cindex -shared flag of gcc + +If your shared library contains global or static objects with +constructors, then make sure to use @code{gcc -shared}, not +@code{ld}, to create the shared library. This will make sure +that any processor-specific magic needed to execute the constructors +is included. + +In theory, constructors for objects in your shared library should be +called when the library is opened (by dlopen or equivalent). This +does not work on some platforms (e.g. SunOS4; it does work on Solaris +and ELF systems such as Linux): on the broken platforms, the +constructors are not called correctly. + +David Nilsen has suggested the following workaround: + +The thing to realize is that if you link your dynamic module with the +@code{-shared} flag, the collect program nicely groups all the static +ctors/dtors for you into a list and sets up a function that will call +them (Note: this means that this trick won't work if you use the GNU +linker without collect (@pxref{use GNU linker?}). + +The magic is knowing these function names. Currently, they're called: + +@example +_GLOBAL__DI <-- calls all module constructors +_GLOBAL__DD <-- calls all module destructors +@end example + +[ possibly the leading underscore will differ between platforms: jbuck ] + +Therefore, if you make a wrapper around dlopen that looks up the +symbol @code{_GLOBAL__DI} (or @code{__GLOBAL__DI} on SunOS4 machines), and +calls it, you'll simulate getting the constructors called. + +You also need to set up the destructors to be called as well, so you +need to put a wrapper around dlclose, which will call the +@code{_GLOBAL__DD} function in the module when/if it's unloaded. + +Lastly, to get things 100% correct, you need to set up the destructors +to also be called if the module is not unloaded, but the main program +exits. I do this by registering a single function with @code{atexit()} that +calls all the destructors left in dynamically loaded modules. + +@cindex Shared version of libg++ +Check the file @file{README.SHLIB} from the libg++ distribution for more +about making and using shared libraries. + +@cindex Shared libraries with HP + +A patch is needed to build shared versions of version 2.7.2 of libg++ +and libstdc++ on the HP-PA architecture. You can find the patch at +@file{ftp://ftp.cygnus.com/pub/g++/libg++-2.7.2-hppa-gcc-fix}. + +@node repository, repo bugs, shared libraries, installation +@section How do I use the new repository code? + +@cindex repo patch +Because there is some disagreement about the details of the template +repository mechanism, you'll need to obtain a patch from Cygnus Support +to enable the 2.7.2 repository code. You can obtain the patch by +anonymous FTP: @file{ftp://ftp.cygnus.com/pub/g++/gcc-2.7.2-repo.gz}. + +There are patches for 2.7.0 and 2.7.1 in the same directory, though +if you're going to rebuild the compiler you should use the latest one. + +@cindex repo patch for BSD +If you're running NetBSD or BSDI, the Cygnus repo patch is not quite +correct. Tim Liddelow has made an alternate version available at +@file{ftp://ftp.cst.com.au/pub/gcc-2.7.2-repo-bsd.gz}. + +After you've applied the patch, the @code{-frepo} flag will enable the +repository mechanism. The flag works much like the existing +@code{-fno-implicit-templates} flag, except that auxiliary files, with +an @file{.rpo} extension, are built that specify what template +expansions are needed. At link time, the (patched) collect program +detects missing templates and recompiles some of the object files +so that the required templates are expanded. + +Note that the mechanism differs from that of cfront in that template +definitions still must be visible at the point where they are to be +expanded. No assumption is made that @file{foo.C} contains template +definitions corresponding to template declarations in @file{foo.h}. + +@cindex closure with repo +@cindex template closure +Jason Merrill writes: ``To perform closure on a set of objects, just try +to link them together. It will fail, but as a side effect all needed +instances will be generated in the objects.'' + +@node repo bugs, Use GNU C library?, repository, installation +@section Known bugs and problems with the repo patch + +``The @code{-frepo} won't expand templated friend functions!'' + +This is a known bug; currently you'll have to explicitly instantiate +friend functions when using @code{-frepo} due to this bug (in 2.7.0 +through 2.7.2 at least). + +With earlier versions of the repo patch, there was a bug that happens +when you have given a quoted command line switch, something like + +@example +-D'MESSAGE="hello there"' +@end example + +The repo code tries to recompile files using the same flags you +originally specified, but doesn't quote arguments that need quoting, +resulting in failures in some cases. This is no longer a problem +with the 2.7.2 patch. + +@node Use GNU C library?, Global constructor problems, repo bugs, installation +@section Should I use the GNU C library? + +@cindex GNU C library +@cindex libg++ +At this point in time, no (unless you are running Linux or the GNU Hurd +system). The GNU C library is still very young, and +libg++ still conflicts with it in some places. Use your native C library +unless you know a lot about the gory details of libg++ and gnu-libc. This +will probably change in the future. + +@node Global constructor problems, Strange assembler errors, Use GNU C library?, installation +@section Global constructors aren't being called + +@cindex global constructors +``I've installed gcc and it almost works, but constructors and +destructors for global objects and objects at file scope aren't being +called. What did I do wrong?'' + +@cindex collect program +It appears that you are running on a platform that requires you to +install either "collect2" or the GNU linker, and you have done neither. +For more information, see the section discussing the GNU linker +(@pxref{use GNU linker?}). + +@cindex constructor problems on Solaris +@cindex Solaris, constructor problems +On Solaris 2.x, you shouldn't need a collect program and GNU ld doesn't run. +If your global constructors aren't being called, you may need to install +a patch, available from Sun, to fix your linker. The number of the +``jumbo patch'' that applies is 101409-03. Thanks to Russell Street +(r.street@@auckland.ac.nz) for this info. + +@cindex IRIX, installing collect +It appears that on IRIX, the collect2 program is not being installed +by default during the installation process, though it is required; +you can install it manually by executing + +@example +make install-collect2 +@end example + +from the gcc source directory after installing the compiler. (I'm +not certain for which versions of gcc this problem occurs, and whether +it is still present). + +@node Strange assembler errors, Other problems building libg++, Global constructor problems, installation +@section Strange assembler errors when linking C++ programs + +``I've installed gcc and it seemed to go OK, but when I attempt to link +any C++ program, I'm getting strange errors from the assembler! How +can that be?'' + +The messages in question might look something like + +@example +as: "/usr/tmp/cca14605.s", line 8: error: statement syntax +as: "/usr/tmp/cca14605.s", line 14: error: statement syntax +@end example + +(on a Sun, different on other platforms). The important thing is that +the errors come out at the link step, @emph{not} when a C++ file is +being compiled. + +@cindex nm program +@cindex GNU nm program +Here's what's going on: the collect2 program uses the Unix ``nm'' +program to obtain a list of symbols for the global constructors and +destructors, and it builds a little assembly language module that +will permit them all to be called. If you're seeing this symptom, +you have an old version of GNU nm somewhere on your path. This old +version prints out symbol names in a format that the collect2 program +does not expect, so bad assembly code is generated. + +The solution is either to remove the old version of GNU nm from your +path (and that of everyone else who uses g++), or to install a newer +version (it is part of the GNU "binutils" package). Recent versions +of GNU nm do not have this problem. + +@node Other problems building libg++, More size_t problems, Strange assembler errors, installation +@section Other problems building libg++ +@cindex libg++ on Ultrix +@cindex libg++ on SunOS + +``I am having trouble building libg++. Help!'' + +On some platforms (for example, Ultrix), you may see errors complaining +about being unable to open dummy.o. On other platforms (for example, +SunOS), you may see problems having to do with the type of size_t. +The fix for these problems is to make libg++ by saying "make CC=gcc". +According to Per Bothner, it should no longer be necessary to specify +"CC=gcc" for libg++-2.3.1 or later. + +``I built and installed libg++, but g++ can't find it. Help!'' + +The string given to @file{configure} that identifies your system must +be the same when you install libg++ as it was when you installed gcc. +Also, if you used the @code{--prefix} option to install gcc somewhere +other than @file{/usr/local}, you must use the same value for +@code{--prefix} when installing libg++, or else g++ will not be able +to find libg++. + +@cindex patch for libg++-2.6.2 + +The toplevel Makefile in the libg++ 2.6.2 distribution is broken, which +along with a bug in g++ 2.6.3 causes problems linking programs that use the +libstdc++ complex classes. A patch for this is available from +@file{ftp://ftp.cygnus.com//pub/g++/libg++-2.6.2-fix.gz}. + +@node More size_t problems, Rebuild libg++?, Other problems building libg++, installation +@section But I'm @emph{still} having problems with @code{size_t}! + +@cindex Type of size_t +``I did all that, and I'm @emph{still} having problems with disagreeing +definitions of size_t, SIZE_TYPE, and the type of functions like +@code{strlen}.'' + +@cindex _G_config.h +The problem may be that you have an old version of @file{_G_config.h} +lying around. As of libg++ version 2.4, @file{_G_config.h}, since it is +platform-specific, is inserted into a different directory; most include +files are in @file{$prefix/lib/g++-include}, but this file now lives in +@file{$prefix/$arch/include}. If, after upgrading your libg++, you find that +there is an old copy of @file{_G_config.h} left around, remove it, +otherwise g++ will find the old one first. + +@node Rebuild libg++?, co-existing versions, More size_t problems, installation +@section Do I need to rebuild libg++ to go with my new g++? + +``After I upgraded g++ to the latest version, I'm seeing undefined +symbols.'' + +or + +``If I upgrade to a new version of g++, do I need to reinstall libg++?'' + +@cindex Incompatibilities between g++ versions + +As a rule, the first two digits of your g++ and libg++ should be the +same. Normally when you do an upgrade in the ``minor version number'' +(2.5.7 to 2.5.8, say) there isn't a need to rebuild libg++, but there +have been a couple of exceptions in the past. + +@node co-existing versions, Installing on Linux, Rebuild libg++?, installation +@section I want several versions of g++ and libg++ to co-exist. + +I recommend against using the @code{-V} flag to make multiple versions +of gcc/g++ co-exist, unless they are different minor releases that can use +the same compiled version of libg++. The reason is that all these +versions will try to use the same libg++ version, which usually will +not work. + +Instead, use the @code{--prefix} flag when configuring gcc. Use a +different value of @code{--prefix} for each gcc version. Use the +same value of @code{--prefix} when configuring libg++. You can then +have any number of co-existing gcc/libg++ pairs. Symbolic links can +be used so that users don't need to put all these different directories +on their paths. + +One possible system to use is to set @code{--prefix} to +@file{/usr/local/gcc-2.x.y} for version 2.x.y of gcc, and to link +whichever version of gcc you wish to be the default into +@file{/usr/local/bin/gcc} and @file{/usr/local/bin/g++}. + +@node Installing on Linux, Linux Slackware 3.0, co-existing versions, installation +@section Trouble installing g++ and libg++ on Linux + +``I've downloaded the latest g++ and libg++ and I'm trying to install +them on Linux, and I'm having lots of problems.'' + +@cindex Linux +FSF releases of libg++ won't install on Linux unchanged, since Linux +uses are part of the libio library from libg++ for its standard C +library, only this is changed in a way that it clashes with libg++. +This means that you'll need a patched version of libg++ for it to +work. + +If you want to upgrade to a new gcc/libg++ combination, the easiest +thing to do is to grab the prebuilt versions of gcc and libg++ for Linux +from @file{ftp://tsx-11.mit.edu/pub/linux/packages/GCC}. Follow the +directions carefully. If you want to build from source, you'll need +a patch for libg++; the Linux developers have named the patched libg++ +version libg++-2.7.1.3 and there is a patch file in the above-named +directory. + +See @file{http://sunsite.unc.edu/LDP/HOWTO/GCC-HOWTO.html}, +the Linux GCC HOWTO, for more on gcc/g++ and Linux. + +Linux is in the process of switching over to the GNU C library, version +2, which will become Linux libc version 6. Once this process is +complete, there's a good chance that the installation process on Linux +will be smoother, but only experts should try making this new library +work at this point. + +@node Linux Slackware 3.0, , Installing on Linux, installation +@section Problems with g++ on Linux Slackware 3.0 + +@cindex Slackware +@cindex Linux Slackware +``When I try to compile the traditional Hello, world program on Linux, +the compiler can't find @file{iostream.h}. What's the deal?'' + +You probably have the Slackware 3.0 release. There's an error in the +setup. It's easy to fix, though; log in as root, and make a symbolic +link: + +@example +ln -s /usr/lib/g++-include /usr/include/g++ +@end example + +@node evolution, User Problems, installation, Top +@chapter The Evolution of g++ + +This chapter discusses the evolution of g++ and describes what can be expected +in the future. + +@menu +* version 2.7.x:: What's changed in 2.7.x from earlier versions +* libstdc++:: The GNU C++ standard library +* new work:: What's been done since 2.7.x +* egcs:: The Experimental GNU Compiler System +* When?:: When can I get all this new stuff? +@end menu + +@node version 2.7.x, libstdc++, evolution, evolution +@section What's new in version 2.7.x of gcc/g++ + +The current version of gcc/g++ is 2.7.2.2, released February 10, 1997. +The only change between 2.7.2.1 and 2.7.2.2 is that support was added +for using the GNU C library, version 2, on Linux; users not interested +in that functionality have no reason to upgrade. +The previous version of gcc/g++ is 2.7.2.1, released August 14, 1996. +The current version of libg++ is 2.7.2, released July 4, 1996. + +Note that gcc 2.7.2.1 just consists of several small patches to +gcc-2.7.2. The release is mainly +intended to fix platform-specific bugs and does not affect the C++ +``front end'' of the compiler (the part that parses your C++ code). + +The 2.7.x releases represent a great deal of work on the part of the g++ +maintainers to fix outstanding bugs and move the compiler closer to the +current ANSI/ISO standards committee's working paper, including +supporting many of the new features that have been added to the +language. I recommend that everyone read the NEWS file contained in the +distribution (and that system administrators make the file available to +their users). I've borrowed liberally from this file here. + +@cindex C++ working paper +If any features seem unfamiliar, you will probably want to +look at the recently-released public review copy of the C++ Working +Paper. A new draft, dated 2 December 1996, has been released for +public comment. You can find it on the web at +@file{http://www.cygnus.com/misc/wp/} or +@file{http://www.maths.warwick.ac.uk/c++/pub/wp/html/cd2/}. +See +@file{http://www.setech.com/x3.html} +or +@file{http://www.maths.warwick.ac.uk/c++/pub/} to download the +document in PostScript, PDF (Adobe Acrobat), HTML, or ASCII +form. + +Here are the main points: + +@itemize @bullet +@item +@cindex for scope +As described above, the scope of variables declared in the +initialization part of a for statement has been changed; such variables +are now visible only in the loop body. Use @code{-fno-for-scope} to get +the old behavior. You'll need this flag to build groff version 1.09, +Ptolemy, and many other free software packages. + +@item +@cindex vtable duplication +Code that does not use #pragma interface/implementation will most +likely shrink dramatically, as g++ now only emits the vtable for a +class in the translation unit where its first non-inline, non-abstract +virtual function is defined. + +@item +@cindex automatic template instantiation +Support for automatic template instantiation has @emph{not} been enabled +in the official distribution, due to a disagreement over design philosophies. +But you can get a patch from Cygnus to turn it on; retrieve the patch +from @file{ftp://ftp.cygnus.com/pub/g++/gcc-2.7.2-repo.gz} to patch +gcc-2.7.2 (there are also patches for earlier gcc versions). + +@item +@cindex exception handling, 2.7.0 + +@xref{exceptions} + +@item +@cindex run-time type identification +Support for Run-Time Type Identification has been added with @code{-frtti}. +This support is still in alpha; one major restriction is that any file +compiled with @code{-frtti} must include @code{<typeinfo>} (@emph{not} +@code{typeinfo.h} as the NEWS file says). +Also, all C++ code you link with (including libg++) has to be built with +@code{-frtti}, so it's still tricky to use. + +@item +@cindex compiler-generated operators +Synthesis of compiler-generated constructors, destructors and +assignment operators is now deferred until the functions are used. + +@item +@cindex assignment in conditional expressions +The parsing of expressions such as @code{a ? b : c = 1} +has changed from +@code{(a ? b : c) = 1} to @code{a ? b : (c = 1)}. This is a new C/C++ +incompatibility brought to you by the ANSI/ISO standards committee. + +@item +@cindex new operator keywords +The operator keywords and, and_eq, bitand, bitor, compl, not, not_eq, +or, or_eq, xor and xor_eq are now supported. Use @code{-ansi} or +@code{-foperator-names} to enable them. + +@item +@cindex explicit keyword +The @code{explicit} keyword is now supported. @code{explicit} is used to mark +constructors and type conversion operators that should not be used +implicitly. + +@item +@cindex user-defined type conversion +Handling of user-defined type conversion has been improved. + +@item +@cindex explicit template instantiation +Explicit instantiation of template methods is now supported. Also, +@code{inline template class foo<int>;} +can be used to emit only the vtable +for a template class. + +@item +@cindex -fcheck-new +With -fcheck-new, g++ will check the return value of all calls to +operator new, and not attempt to modify a returned null pointer. + +@item +collect2 now demangles linker output, and c++filt has become part of +the gcc distribution. + +@item +Improvements to template instantiation: only members actually used +are instantiated. (Actually this is not quite true: some inline +templates that are not successfully inlined may be expanded even +though they are not needed). + +@end itemize + +@node libstdc++, new work, version 2.7.x, evolution +@section The GNU Standard C++ Library + +The GNU Standard C++ Library (also called the ``GNU ANSI C++ Library'' +in places in the code) is not libg++, though it is included in the +libg++ distribution. Rather, it contains classes and functions +required by the ANSI/ISO standard. The copyright conditions are the +same as those for for the iostreams classes; the LGPL is not used +(@pxref{legalities}). + +This library, libstdc++, is in the libg++ distribution in versions 2.6.2 +and later. It requires at least gcc 2.6.3 to build the libg++-2.6.2 +version; use at least gcc 2.7.0 to build the libg++ 2.7.0 version. It +contains a hacked-up version of HP's implementation of the Standard +Template Library (@pxref{Standard Template Library}). I've +successfully used this Standard Template Library version to build +a number of the demos you'll see on various web pages. + +As of version 2.7.0, the streams classes are now in libstdc++ instead of +libg++, and libiostream is being phased out (don't use it). The g++ +program searches this library. + +The maintainers of libg++ have de-emphasized work on the older libg++ classes +in favor of enhancing libstdc++ to cover the full language, so while libg++ +will always be available, enhancements to it should not be expected. + +@node new work, egcs, libstdc++, evolution +@section What can we expect in future gcc releases? + +A great deal of work has gone into enhancements to the C++ front end, as well +as to other aspects of the compiler. + +The next major release(s) of gcc/g++ can be expected to have the following +features: + +@itemize @bullet +@cindex new template implementation +@item +A completely new template implementation, much closer to the draft +standard. Limitations in 2.7.2.x concerning inlining template functions +will be eliminated. Static template data members, template class member +functions, partial specification, and default template arguments will be +supported. An instantiation method resembling that used in Borland C++ +(instantiating functions possibly in multiple .o files and using weak +symbols to link correctly) will be provided, in addition to other +options. The SGI version of STL will be shipped with libstdc++ and will +compile unchanged. + +@item +@cindex new exception implementation +Exception handling has been re-worked; exceptions will work together +with optimization. +Actually, there are two separate implementations: one based on setjmp/longjmp +and designed to be highly portable, and one designed to be more efficient but +requiring more processor-specific support (getting exceptions right has proven +to be extremely difficult and has been the chief obstacle to getting a new +release out). + +@item +@cindex RTTI +RTTI has been re-done to work correctly and is on by default. + +@item +@cindex overloading +Overloading has been re-worked to conform to the latest draft of the +standard. +@end itemize + +Features that are still missing include namespaces and templates as +template arguments. + +@node egcs, When?, new work, evolution +@section What's this I hear about egcs? + +The egcs effort is a new effort to merge several threads of gcc +development and to provide a faster development process. +For more information see @file{http://www.cygnus.com/egcs/}. + +@node When?, , egcs, evolution +@section OK, when can I get this stuff? + +The FSF has a policy of never announcing release dates in advance. +I'm sure this is frustrating to a lot of people, since it's taken +so long, and this frustration was one of the reasons the egcs effort +was created. An egcs release should be expected to occur in the +very near future. [ More on this next time ]. + +@node User Problems, legalities, evolution, Top +@chapter User Problems + +@menu +* missing virtual table:: +* for scope:: +* const constructor:: +* unused parameter warnings:: +* jump crosses initialization:: +* Demangler:: +* static data members:: +* internal compiler error:: +* bug reports:: +* porting to g++:: +* name mangling:: +* problems linking with other libraries:: +* documentation:: +* templates:: +* undefined templates:: +* redundant templates:: +* Standard Template Library:: +* STL and string:: +* exceptions:: +* namespaces:: +* agreement with standards:: +* compiling standard libraries:: +* debugging on SVR4 systems:: +* debugging problems on Solaris:: +* X11 conflicts with libg++:: +* assignment to streams:: +@end menu + +@node missing virtual table, for scope, User Problems, User Problems +@section Linker complains about missing virtual table + +``I'm getting a message complaining about an undefined virtual table. Is +this a compiler bug?'' + +(On platforms that run neither collect nor the GNU linker, like Solaris, +you may see an odd undefined symbol like "_vt.3foo", where foo is a +class name). + +This is probably because you are missing a definition for the first +(non-inline) virtual function of the class. Since gcc-2.7.0, g++ uses +a trick borrowed from cfront: the .o file containing the definition for +the first non-inline virtual function for the class will also contain +the virtual function table. + +@node for scope, const constructor, missing virtual table, User Problems +@section gcc-2.7.0 breaks declarations in "for" statements! + +@cindex declarations in for statements +@cindex for statements: declarations + +gcc-2.7.0 implements the new ANSI/ISO rule on the scope of variables +declared in for loops. + +@example +for (int i = 1; i <= 10; i++) @{ + // do something here +@} +foo(i); +@end example + +In the above example, most existing C++ compilers would pass the +value 11 to the function @code{foo}. In gcc 2.7 and in the ANSI/ISO +working paper, the scope of @code{i} is only the for loop body, so +this is an error. So that old code can be compiled, the new gcc has +a flag @code{-fno-for-scope} that causes the old rule to be used. +@cindex -fno-for-scope + +As of 2.7.1, the compiler attempts to issue warnings about code that +has different meanings under the two sets of rules, but the code is +not perfect: the intent was that code that has valid, but different, +meanings under the ARM rules and the working paper rules would give +warnings but have the new behavior, and this doesn't seem to happen. + +The @code{-ffor-scope} flag under 2.7.1 and 2.7.2 gives the 2.7.0 behavior. + +@node const constructor, unused parameter warnings, for scope, User Problems +@section g++ seems to want a const constructor. What's that? + +gcc-2.7.1 introduced a bug that causes the compiler to ask for a +const constructor (there's no such thing in C++) in certain situations +where a const object appears in a template class. Most cases have been +fixed in gcc-2.7.2, but unfortunately not all. Still, if you're running +gcc-2.7.1 and have this problem, upgrade to 2.7.2; it is a vast improvement. + +@cindex ObjectSpace<STL> + +The default constructor for the template @code{pair} in ObjectSpace's +implementation of STL triggers the bug in one place, for gcc 2.7.2. If +you're using ObjectSpace<STL> and having this problem, simply +change the default constructor from + +@example +os_pair () : first (T1 ()), second (T2 ()) @{@} +@end example + +to just + +@example +os_pair () @{@} +@end example + +Once this is done, ObjectSpace<STL> works fairly well. + +@node unused parameter warnings, jump crosses initialization, const constructor, User Problems +@section How to silence ``unused parameter'' warnings + +@cindex -Wall +@cindex -Wunused + +``When I use @code{-Wall} (or @code{-Wunused}), g++ warns about +unused parameters. But the parameters have to be there, for use +in derived class functions. How do I get g++ to stop complaining?'' + +The answer is to simply omit the names of the unused parameters when +defining the function. This makes clear, both to g++ and to readers +of your code, that the parameter is unused. For example: + +@example +int Foo::bar(int arg) @{ return 0; @} +@end example + +will give a warning for the unused parameter @code{arg}. To suppress +the warning write + +@example +int Foo::bar(int) @{ return 0; @} +@end example + +@node jump crosses initialization, Demangler, unused parameter warnings, User Problems +@section g++ objects to a declaration in a case statement + +``The compiler objects to my declaring a variable in one of the branches +of a case statement. Earlier versions used to accept this code. Why?'' + +The draft standard does not allow a goto or a jump to a case label to +skip over an initialization of a variable or a class object. For +example: + +@example +switch ( i ) @{ + case 1: + Object obj(0); + ... + break; + case 2: + ... + break; +@} +@end example + +The reason is that @code{obj} is also in scope in the rest of the switch +statement. + +As of version 2.7.0, the compiler will object that the jump to the +second case level crosses the initialization of @code{obj}. Older +compiler versions would object only if class Object has a destructor. +In either case, the solution is to add a set of curly braces around +the case branch: + +@example + case 1: + @{ + Object obj(0); + ... + break; + @} +@end example + +@node Demangler, static data members, jump crosses initialization, User Problems +@section Where can I find a demangler? + +@cindex demangler program +A g++-compatible demangler named @code{c++filt} can be found in the +@file{binutils} distribution. This distribution (which also contains +the GNU linker) can be found at any GNU archive site. + +As of version 2.7.0, @code{c++filt} is included with gcc and is +installed automatically. Even better, it is used by the @code{collect} +linker, so you don't see mangled symbols anymore (except on platforms +that use neither collect nor the GNU linker, like Solaris). + +@node static data members, internal compiler error, Demangler, User Problems +@section Linker reports undefined symbols for static data members + +@cindex Static data members +``g++ reports undefined symbols for all my static data members when I link, +even though the program works correctly for compiler XYZ. What's going on?'' + +The problem is almost certainly that you don't give definitions for +your static data members. If you have + +@example +class Foo @{ + ... + void method(); + static int bar; +@}; +@end example + +you have only declared that there is an int named Foo::bar and a member +function named Foo::method that is defined somewhere. You still need to +define @emph{both} method() and bar in some source file. According to +the draft ANSI standard, you must supply an initializer, such as + +@example +int Foo::bar = 0; +@end example + +@noindent +in one (and only one) source file. + +@node internal compiler error, bug reports, static data members, User Problems +@section What does ``Internal compiler error'' mean? + +It means that the compiler has detected a bug in itself. Unfortunately, +g++ still has many bugs, though it is a lot better than it used to be. +If you see this message, please send in a complete bug report (see next +section). + +@node bug reports, porting to g++, internal compiler error, User Problems +@section I think I have found a bug in g++. + +@cindex Bug in g++, newly found +``I think I have found a bug in g++, but I'm not sure. How do I know, +and who should I tell?'' + +@cindex Manual, for gcc +First, see the excellent section on bugs and bug reports in the gcc manual +(which is included in the gcc distribution). As a short summary of that +section: if the compiler gets a fatal signal, for any input, it's a bug +(newer versions of g++ will ask you to send in a bug report when they +detect an error in themselves). Same thing for producing invalid +assembly code. + +When you report a bug, make sure to describe your platform (the type of +computer, and the version of the operating system it is running) and the +version of the compiler that you are running. See the output of the +command @code{g++ -v} if you aren't sure. Also provide enough code +so that the g++ maintainers can duplicate your bug. Remember that the +maintainers won't have your header files; one possibility is to send +the output of the preprocessor (use @code{g++ -E} to get this). This +is what a ``complete bug report'' means. + +I will add some extra notes that are C++-specific, since the notes from +the gcc documentation are generally C-specific. + +@cindex g++ bug report +First, mail your bug report to "bug-g++@@prep.ai.mit.edu". You may also +post to @file{gnu.g++.bug}, but it's better to use mail, particularly if you +have any doubt as to whether your news software generates correct reply +addresses. Don't mail C++ bugs to bug-gcc@@prep.ai.mit.edu. + +@strong{News:} as I write this (late February 1996) the gateway +connecting the bug-g++ mailing list and the @file{gnu.g++.bug} newsgroup +is (temporarily?) broken. Please mail, do not post bug reports. + +@cindex libg++ bug report +If your bug involves libg++ rather than the compiler, mail to +bug-lib-g++@@prep.ai.mit.edu. If you're not sure, choose one, and if you +guessed wrong, the maintainers will forward it to the other list. + +@cindex C++, reference books +@cindex ARM [Annotated C++ Ref Manual] +Second, if your program does one thing, and you think it should do +something else, it is best to consult a good reference if in doubt. +The standard reference is the draft working paper from the ANSI/ISO +C++ standardization committee, which you can get on the net. +For PostScript and PDF (Adobe Acrobat) versions, see the +archive at @file{ftp://research.att.com/dist/stdc++/WP}. For HTML and ASCII +versions, see @file{ftp://ftp.cygnus.com/pub/g++}. On the World Wide Web, see +@file{http://www.cygnus.com/misc/wp/}. + +An older +standard reference is "The Annotated C++ Reference Manual", by Ellis and +Stroustrup (copyright 1990, ISBN #0-201-51459-1). This is what they're +talking about on the net when they refer to ``the ARM''. But you should +know that changes have been made to the language since then. + +The ANSI/ISO C++ standards committee have adopted some changes to the +C++ language since the publication of the original ARM, and newer +versions of g++ (2.5.x and later) support some of these changes, notably +the mutable keyword (added in 2.5.0), the bool type (added in 2.6.0), +and changes in the scope of variables defined in for statements (added +in 2.7.0). +You can obtain an addendum to the ARM explaining many of these changes by FTP +from @file{ftp://ftp.std.com/AW/stroustrup2e/new_iso.ps}. + +@cindex AT&T cfront +Note that the behavior of (any version of) AT&T's "cfront" compiler is +NOT the standard for the language. + +@node porting to g++, name mangling, bug reports, User Problems +@section Porting programs from other compilers to g++ + +``I have a program that runs on <some other C++ compiler>, and I want +to get it running under g++. Is there anything I should watch out +for?'' + +@cindex Porting to g++ + +Note that g++ supports many of the newer keywords that have recently +been added to the language. Your other C++ compiler may not support +them, so you may need to rename variables and members that conflict +with these keywords. + +There are two other reasons why a program that worked under one compiler +might fail under another: your program may depend on the order of +evaluation of side effects in an expression, or it may depend on the +lifetime of a temporary (you may be assuming that a temporary object +"lives" longer than the standard guarantees). As an example of the +first: + +@example +void func(int,int); + +int i = 3; +func(i++,i++); +@end example + +@cindex Order of evaluation, problems in porting +Novice programmers think that the increments will be evaluated in strict +left-to-right order. Neither C nor C++ guarantees this; the second +increment might happen first, for example. func might get 3,4, or it +might get 4,3. + +@cindex Classes, problems in porting +@cindex Problems in porting, class +The second problem often happens with classes like the libg++ String +class. Let's say I have + +@example +String func1(); +void func2(const char*); +@end example + +and I say + +@example +func2(func1()); +@end example + +because I know that class String has an "operator const char*". So what +really happens is + +@example +func2(func1().convert()); +@end example + +@cindex temporaries +where I'm pretending I have a convert() method that is the same as the +cast. This is unsafe in g++ versions before 2.6.0, because the +temporary String object may be deleted after its last use (the call to +the conversion function), leaving the pointer pointing to garbage, so by +the time func2 is called, it gets an invalid argument. + +@cindex ANSI draft standard +Both the cfront and the old g++ behaviors are legal according to the ARM, +but the powers that be have decided that compiler writers were given +too much freedom here. + +The ANSI C++ committee has now come to a resolution of the lifetime of +temporaries problem: they specify that temporaries should be deleted at +end-of-statement (and at a couple of other points). This means that g++ +versions before 2.6.0 now delete temporaries too early, and cfront +deletes temporaries too late. As of version 2.6.0, g++ does things +according to the new standard. + +@cindex Scope, problems in porting +@cindex Problems in porting, scope +For now, the safe way to write such code is to give the temporary a name, +which forces it to live until the end of the scope of the name. For +example: + +@example +String& tmp = func1(); +func2(tmp); +@end example + +Finally, like all compilers (but especially C++ compilers, it seems), +g++ has bugs, and you may have tweaked one. If so, please file a bug +report (after checking the above issues). + +@node name mangling, problems linking with other libraries, porting to g++, User Problems +@section Why does g++ mangle names differently from other C++ compilers? + +See the answer to the next question. +@cindex Mangling names + +@node problems linking with other libraries, documentation, name mangling, User Problems +@section Why can't g++ code link with code from other C++ compilers? + +``Why can't I link g++-compiled programs against libraries compiled by +some other C++ compiler?'' + +@cindex Mangling names +@cindex Cygnus Support +Some people think that, +if only the FSF and Cygnus Support folks would stop being +stubborn and mangle names the same way that, say, cfront does, then any +g++-compiled program would link successfully against any cfront-compiled +library and vice versa. Name mangling is the least of the problems. +Compilers differ as to how objects are laid out, how multiple inheritance +is implemented, how virtual function calls are handled, and so on, so if +the name mangling were made the same, your programs would link against +libraries provided from other compilers but then crash when run. For this +reason, the ARM @emph{encourages} compiler writers to make their name mangling +different from that of other compilers for the same platform. +Incompatible libraries are then detected at link time, rather than at run +time. +@cindex ARM [Annotated C++ Ref Manual] +@cindex Compiler differences + +@node documentation, templates, problems linking with other libraries, User Problems +@section What documentation exists for g++ 2.x? + +@cindex g++, documentation +Relatively little. +While the gcc manual that comes with the distribution has some coverage +of the C++ part of the compiler, it focuses mainly on the C compiler +(though the information on the ``back end'' pertains to C++ as well). +Still, there is useful information on the command line options and the +#pragma interface and #pragma implementation directives in the manual, +and there is a useful section on template instantiation in the 2.6 version. +There is a Unix-style manual entry, "g++.1", in the gcc-2.x +distribution; the information here is a subset of what is in the manual. + +You can buy a nicely printed and bound copy of this manual from the FSF; +see above for ordering information. + +A draft of a document describing the g++ internals appears in the gcc +distribution (called g++int.texi); it is incomplete but gives lots of +information. + +For class libraries, there are several resources available: + +@itemize @bullet +@item +The libg++ distribution has a manual +@file{libg++/libg++.texi} describing the old libg++ classes, and +another manual @file{libio/iostream.texi} describing the iostreams +implementation. +@item +While there is no libg++-specific document describing the STL +implementation, SGI's web site, at @file{http://www.sgi.com/Technology/STL/}, +is an excellent resource. +@end itemize + +@node templates, undefined templates, documentation, User Problems +@section Problems with the template implementation + +@cindex g++, template support +@cindex Templates + +g++ does not implement a separate pass to instantiate template functions +and classes at this point; for this reason, it will not work, for the most +part, to declare your template functions in one file and define them in +another. The compiler will need to see the entire definition of the +function, and will generate a static copy of the function in each file +in which it is used. + +(The experimental template repository code (@pxref{repository}) that +can be added to 2.7.0 or later does implement a separate pass, but there +is still no searching of files that the compiler never saw). + +@cindex -fno-implicit-templates +For version 2.6.0, however, a new switch @code{-fno-implicit-templates} +was added; with this switch, templates are expanded only under user +control. I recommend that all g++ users that use templates read the +section ``Template Instantiation'' in the gcc manual (version 2.6.x +and newer). g++ now supports explicit template expansion using the +syntax from the latest C++ working paper: + +@example +template class A<int>; +template ostream& operator << (ostream&, const A<int>&); +@end example + +@cindex template limitations +As of version 2.6.3, there are still a few limitations in the template +implementation besides the above (thanks to Jason Merrill for this info): +These are still present in version 2.7.2, but a new implementation of +templates planned for version 2.8 will eliminate them. + +@enumerate 1 +@item +Static data member templates are not supported. You can work around +this by explicitly declaring the static variable for each template +specialization: + +@example +template <class T> struct A @{ + static T t; +@}; + +template <class T> T A<T>::t = 0; // gets bogus error +int A<int>::t = 0; // OK (workaround) +@end example + +(still a limitation in 2.7.2) + +@item +Template member names are not available when defining member function +templates. + +@example +template <class T> struct A @{ + typedef T foo; + void f (foo); + void g (foo arg) @{ ... @}; // this works +@}; + +template <class T> void A<T>::f (foo) @{ @} // gets bogus error +@end example + +@item +Templates are instantiated using the parser. This results in two +problems: + +a) Class templates are instantiated in some situations where such +instantiation should not occur. + +@example +template <class T> class A @{ @}; +A<int> *aip = 0; // should not instantiate A<int> (but does) +@end example + +b) Function templates cannot be inlined at the site of their +instantiation. + +@example +template <class T> inline T min (T a, T b) @{ return a < b ? a : b; @} + +void f () @{ + int i = min (1, 0); // not inlined +@} + +void g () @{ + int j = min (1, 0); // inlined +@} +@end example + +A workaround that works in version 2.6.1 and later is to specify + +@example +extern template int min (int, int); +@end example + +before @code{f()}; this will force it to be instantiated (though not +emitted). + +@item +Member function templates are always instantiated when their containing +class is. This is wrong. +@end enumerate + +@node undefined templates, redundant templates, templates, User Problems +@section I get undefined symbols when using templates + +(Thanks to Jason Merrill for this section). + +@cindex template instantiation +g++ does not automatically instantiate templates defined in other files. +Because of this, code written for cfront will often produce undefined +symbol errors when compiled with g++. You need to tell g++ which template +instances you want, by explicitly instantiating them in the file where they +are defined. For instance, given the files + +@file{templates.h}: +@example +template <class T> +class A @{ +public: + void f (); + T t; +@}; + +template <class T> void g (T a); +@end example + +@file{templates.cc}: +@example +#include "templates.h" + +template <class T> +void A<T>::f () @{ @} + +template <class T> +void g (T a) @{ @} +@end example + + +main.cc: +@example +#include "templates.h" + +main () +@{ + A<int> a; + a.f (); + g (a); +@} +@end example + +compiling everything with @code{g++ main.cc templates.cc} will result in +undefined symbol errors for @samp{A<int>::f ()} and @samp{g (A<int>)}. To +fix these errors, add the lines + +@example +template class A<int>; +template void g (A<int>); +@end example + +to the bottom of @samp{templates.cc} and recompile. + +@node redundant templates, Standard Template Library, undefined templates, User Problems +@section I get multiply defined symbols using templates + +You may be running into a bug that was introduced in version 2.6.1 +(and is still present in 2.6.3) that generated external linkage +for templates even when neither @code{-fexternal-templates} nor +@code{-fno-implicit-templates} is specified. There is a patch for +this problem at @* +@file{ftp://ftp.cygnus.com/pub/g++/gcc-2.6.3-template-fix}. + +I recommend either applying the patch or +using @code{-fno-implicit-templates} +together with explicit template instantiation as described in previous +sections. + +This bug is fixed in 2.7.0. + +@node Standard Template Library, STL and string, redundant templates, User Problems +@section Does g++ support the Standard Template Library? + +@cindex STL +@cindex Standard Template Library +The Standard Template Library (STL) uses many of the extensions that the +ANSI/ISO committee has made to templates, and g++ doesn't support +some of these yet. So if you grab HP's free implementation of STL it +isn't going to work. However, starting with libg++-2.6.2 libg++ contains a +hacked version of STL, based on work by Carsten Bormann, which permits +g++ to compile at least the containers (thanks to Per Bothner for this +text). + +Actually, as of libg++ version 2.7.2 most of this works quite well, most +of the time; +I've succeeded +in making significant use of it. +Almost all of the ObjectSpace examples (a set of +over 200 simple examples of STL usage) now work. + +When version 2.8.0 is out (with its complete redesign of the template +implementation) a much more complete implementation of the +STL (based on a newer free implementation from SGI) will be included. +In the meantime, a group at the Moscow Center for Sparc Technology has +a port of the SGI STL implementation that mostly works with gcc-2.7.2. +See +@file{http://www.ipmce.su/people/fbp/stl/stlport.html}. + +In addition, there are several commercial suppliers of STL implementations; +ObjectSpace's version supports gcc-2.7.x. + +Mumit Khan has produced an ``STL newbie guide'' with lots of information +on using STL with gcc. See + +@file{http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html} + +@node STL and string, exceptions, Standard Template Library, User Problems +@section I'm having problems mixing STL and the standard string class + +This is due to a bug in g++ version 2.7.2 and 2.7.2.1; the compiler +is confused by the operator declarations. There is an easy workaround, +however; just make sure that the @code{<string>} header is included +before any STL headers. That is, just say + +@example +#include <string> +@end example + +before any other @code{#include} directives. + +Unfortunately, this doesn't solve all problems; you may still have +difficulty with the relational operators !=, <=, >, and >=, thanks +to a conflict with the very general definition of these operators +in function.h. One trick that sometimes works is to try to use == +and < in your code instead of the other operators. Another is to +use a derived class of <string>. The only completely satisfactory +solution, I'm afraid, is to wait for the new release. + +@node exceptions, namespaces, STL and string, User Problems +@section Problems and limitations with exceptions + +Recent g++ versions provide limited support for exceptions. You must +provide the @code{-fhandle-exceptions} flag to enable exception +handling. As of version 2.7.2, exceptions may not work properly +(and you may get odd error messages when compiling) if you turn +on optimization (the @code{-O} flag). + +You must give the @code{-frtti} switch to enable catching +of derived exception objects with handlers for the base exception class; +if @code{-frtti} is not given, only exact type matching works. + +For exception handling to work with 2.7.0 your CPU must be a SPARC, +RS6000/PowerPC, 386/486/Pentium, or ARM. Release 2.7.1 added support +for the Alpha, and ``m68k is rumored to work on some platforms'' +and ``VAX may also work'' (according to Mike Stump). +@emph{It still doesn't work on HP-PA or MIPS platforms.} + +@node namespaces, agreement with standards, exceptions, User Problems +@section Does g++ support namespaces? + +As of version 2.7.2, g++ recognizes the keywords @code{namespace} and +@code{using}, and there is some rudimentary code present, but almost +nothing connected with namespaces works yet. It appears that this will +still be true when 2.8.0 is released. + +@node agreement with standards, compiling standard libraries, namespaces, User Problems +@section What are the differences between g++ and the ARM specification of C++? + +@cindex ARM [Annotated C++ Ref Manual] +@cindex exceptions +As of version 2.7.0, g++ has exception support on most but not all +platforms +(no support on MIPS-based platforms yet), but +it doesn't work right if optimization is enabled, which means the +exception +implementation is still +not really ready for production use. + + +@cindex mutable +Some features that the ANSI/ISO standardization committee has voted in +that don't appear in the ARM are supported, notably the @code{mutable} +keyword, in version 2.5.x. 2.6.x adds support for the built-in boolean +type @code{bool}, with constants @code{true} and @code{false}. The +beginnings of run-time type identification are present, so there are +more reserved words: @code{typeid}, @code{static_cast}, +@code{reinterpret_cast}, @code{const_cast}, and @code{dynamic_cast}. + +@cindex g++ bugs +As with any beta-test compiler, there are bugs. You can help improve +the compiler by submitting detailed bug reports. + +One of the weakest areas of g++ other than templates is the resolution +of overloaded functions and operators in complex cases. The usual +symptom is that in a case where the ARM says that it is ambiguous which +function should be chosen, g++ chooses one (often the first one +declared). This is usually not a problem when porting C++ code from +other compilers to g++, but shows up as errors when code developed under +g++ is ported to other compilers. (I believe this is no longer a +significant problem in 2.7.0). + +[A full bug list would be very long indeed, so I won't put one here. +I may add a list of frequently-reported bugs and "non-bugs" like the +static class members issue mentioned above]. + +@node compiling standard libraries, debugging on SVR4 systems, agreement with standards, User Problems +@section Will g++ compile InterViews? The NIH class library? Rogue Wave? + +@cindex NIH class library +@cindex NIHCL with g++ +The NIH class library uses a non-portable, compiler-dependent hack +to initialize itself, which makes life difficult for g++ users. +It will not work without modification, and I don't know what modifications +are required or whether anyone has done them successfully. + +In short, it's not going to happen any time soon (previous FAQs referred +to patches that a new NIHCL release would hopefully contain, but this +hasn't happened). + +@strong{Note:} I thought I saw an item indicating that someone +@emph{had} patched NIHCL to work with g++. Any pointers? + +@cindex InterViews +I think that as of version 2.5.6, the standard g++ will compile the +standard 3.1 InterViews completely successfully. +Note that you'll need the @code{-fno-for-scope} flag +if you use gcc-2.7.0; with 2.7.2 you may be able to omit this flag +but you'll get warnings. + +@cindex Rogue Wave +According to Jason Merrill, gcc-2.7.0 and newer works with Rogue +Wave's @code{tools.h++} class library, but you may want to grab +@file{ftp://ftp.cygnus.com/pub/g++/Tools.h++-6.1-patch}. Again, +you'll need the @code{-fno-for-scope} flag since Rogue Wave hasn't +fixed their code to comply with the new standard yet. + +@node debugging on SVR4 systems, debugging problems on Solaris, compiling standard libraries, User Problems +@section Debugging on SVR4 systems +@cindex System VR4, debugging + +``How do I get debugging to work on my System V Release 4 system?'' + +@cindex DWARF debug format + +Most systems based on System V Release 4 (except Solaris) encode symbolic +debugging information in a format known as `DWARF'. + +Although the GNU C compiler already knows how to write out symbolic debugging +information in the DWARF format, the GNU C++ compiler does not yet have this +feature yet. However, work is in progress for DWARF 2 debug support for +gcc and g++ and will be available in a future release (probably 2.8.0). + +@cindex stabs +@cindex --with-stabs + +In the meantime, you @emph{can} get g++ debugging under SVR4 systems by +configuring gcc with the @code{--with-stabs} option. This causes gcc to +use an alternate debugging format, one more like that used under SunOS4. +You won't need to do anything special to GDB; it will always understand +the ``stabs'' format. + +@node debugging problems on Solaris, X11 conflicts with libg++, debugging on SVR4 systems, User Problems +@section debugging problems on Solaris + +``I'm on Solaris, and gdb says it doesn't know about some of my local +symbols. Help!'' + +This problem was introduced in gcc 2.7.2; debug symbols for +locals that aren't declared at the beginning of a block come out in the +wrong order, and gdb can't find such symbols. + +This problem is fixed in gcc-2.7.2.1. + +@node X11 conflicts with libg++, assignment to streams, debugging problems on Solaris, User Problems +@section X11 conflicts with libg++ in definition of String +@cindex String, conflicts in definition + +``X11 and Motif define String, and this conflicts with the String class +in libg++. How can I use both together?'' + +One possible method is the following: + +@example +#define String XString +#include <X11/Intrinsic.h> +/* include other X11 and Motif headers */ +#undef String +@end example + +and remember to use the correct @code{String} or @code{XString} when +you declare things later. + +@node assignment to streams, , X11 conflicts with libg++, User Problems +@section Why can't I assign one stream to another? + +[ Thanks to Per Bothner and Jerry Schwarz for this section. ] + +Assigning one stream to another seems like a reasonable thing to do, but +it's a bad idea. Usually, this comes up because people want to assign +to @code{cout}. This is poor style, especially for libraries, and is +contrary to good object-oriented design. (Libraries that write directly +to @code{cout} are less flexible, modular, and object-oriented). + +The iostream classes do not allow assigning to arbitrary streams, because +this can violate typing: + +@example +ifstream foo ("foo"); +istrstream str(...); +foo = str; +foo->close (); /* Oops! Not defined for istrstream! */ +@end example + +@cindex assignment to cout + +The original cfront implementation of iostreams by Jerry Schwarz allows +you to assign to @code{cin}, @code{cout}, @code{cerr}, and @code{clog}, +but this is not part of the draft standard for iostreams and generally +isn't considered a good idea, so standard-conforming code shouldn't use +this technique. + +The GNU implementation of iostream did not support assigning to +@code{cin}, @code{cout}, @code{cerr}, and @code{clog} +for quite a while, but it now does, for backward +compatibility with cfront iostream (versions 2.6.1 and later of libg++). + +The ANSI/ISO C++ Working Paper does provide ways of changing the +streambuf associated with a stream. Assignment isn't allowed; +there is an explicit named member that must be used. + +However, it is not wise to do this, and the results are confusing. For +example: @code{fstream::rdbuf} is supposed to return the @emph{original} +filebuf, not the one you assigned. (This is not yet implemented in GNU +iostream.) This must be so because @code{fstream::rdbuf} is defined to +return a @code{filebuf *}. + +@node legalities, index, User Problems, Top +@chapter What are the rules for shipping code built with g++ and libg++? +@cindex Shipping rules +@cindex GPL [GNU Public License] + +``Is it is possible to distribute programs for profit that are created +with g++ and use the g++ libraries?'' + +I am not a lawyer, and this is not legal advice. In any case, I have +little interest in telling people how to violate the spirit of the +GNU licenses without violating the letter. This section tells you +how to comply with the intention of the GNU licenses as best I understand +them. + +@cindex FSF [Free Software Foundation] +The FSF has no objection to your making money. Its only interest is that +source code to their programs, and libraries, and to modified versions of +their programs and libraries, is always available. + +The short answer is that you do not need to release the source to +your program, but you can't just ship a stripped executable either, +unless you use only the subset of libg++ that includes the iostreams +classes (see discussion below) or the new libstdc++ library (available +in libg++ 2.6.2 and later). + +Compiling your code with a GNU compiler does not affect its copyright; +it is still yours. However, in order to ship code that links in a GNU +library such as libg++ there are certain rules you must follow. The +rules are described in the file COPYING.LIB that accompanies gcc +distributions; it is also included in the libg++ distribution. +See that file for the exact rules. The agreement is called the +Library GNU Public License or LGPL. It is much "looser" than the +GNU Public License, or GPL, that covers must GNU programs. + +@cindex libg++, shipping code +Here's the deal: let's say that you use some version of libg++, +completely unchanged, in your software, and you want to ship only +a binary form of your code. You can do this, but there are several +special requirements. If you want to use libg++ but ship only object +code for your code, you have to ship source for libg++ (or ensure +somehow that your customer already has the source for the exact +version you are using), and ship your application in linkable form. +You cannot forbid your customer from reverse-engineering or extending +your program by exploiting its linkable form. + +@cindex libg++, modifying +Furthermore, if you modify libg++ itself, you must provide source +for your modifications (making a derived class does not count as +modifying the library -- that is "a work that uses the library"). + +@cindex special copying conditions for iostreams +For certain portions of libg++ that implement required parts of the C++ +language (such as iostreams and other standard classes), the FSF has +loosened the copyright requirement still more by adding the ``special +exception'' clause, which reads as follows: + +@quotation +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. +@end quotation + +If your only use of libg++ uses code with this exception, you may ship +stripped executables or license your executables under different +conditions without fear of violating an FSF copyright. It is the intent +of FSF and Cygnus that, as the other classes required by the ANSI/ISO +draft standard are developed, these will also be placed under this +``special exception'' license. +The code in the new libstdc++ library, intended to implement standard +classes as defined by ANSI/ISO, is also licensed this way. + +To avoid coming under the influence of the LGPL, you can link with +@file{-liostream} rather than @file{-lg++} (for version 2.6.x and +earlier), or @file{-lstdc++} now that it is available. In version 2.7.0 +all the standard classes are in @file{-lstdc++}; you can do the link +step with @code{c++} instead of @code{g++} to search only the +@file{-lstdc++} library and avoid the LGPL'ed code in @file{-lg++}. + +If you wish to discuss legal issues connected with GNU software on the +net, please use @file{gnu.misc.discuss}, not the technical newsgroups. + +@node index, , legalities, Top +@comment node-name, next, previous, up +@appendix Concept Index + +@printindex cp + +@page +@contents +@bye diff --git a/gnu/usr.bin/gcc/cp/g++spec.c b/gnu/usr.bin/gcc/cp/g++spec.c new file mode 100644 index 00000000000..66b27565766 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/g++spec.c @@ -0,0 +1,255 @@ +/* Specific flags and argument handling of the C++ front-end. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" + +#include <sys/types.h> +#include <stdio.h> + +#include "gansidecl.h" + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#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) +/* This bit is set if they did `-lc'. */ +#define WITHLIBC (1<<3) + +#ifndef MATH_LIBRARY +#define MATH_LIBRARY "-lm" +#endif + +extern char *xmalloc PROTO((size_t)); + +void +lang_specific_driver (fn, in_argc, in_argv) + void (*fn)(); + int *in_argc; + char ***in_argv; +{ + int i, j; + + /* If non-zero, the user gave us the `-v' flag. */ + int saw_verbose_flag = 0; + + /* This will be 0 if we encounter a situation where we should not + link in libstdc++. */ + int library = 1; + + /* 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 = 2; + + /* 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; + + /* 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; + + /* "-lm" or "-lmath" if it appears on the command line. */ + char *saw_math = 0; + + /* "-lc" if it appears on the command line. */ + char *saw_libc = 0; + + /* An array used to flag each argument that needs a bit set for + LANGSPEC, MATHLIB, or WITHLIBC. */ + int *args; + + /* By default, we throw on the math library. */ + int need_math = 1; + + /* The total number of arguments with the new stuff. */ + int argc; + + /* The argument list. */ + char **argv; + + /* The total number of arguments with the new stuff. */ + int num_args = 1; + + argc = *in_argc; + argv = *in_argv; + + + args = (int *) xmalloc (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; + } + + /* We don't do this anymore, since we don't get them with minus + signs on them. */ + if (argv[i][0] == '\0' || argv[i][1] == '\0') + continue; + + if (argv[i][0] == '-') + { + if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0 + || strcmp (argv[i], "-nodefaultlibs") == 0)) + { + library = 0; + } + else if (strcmp (argv[i], "-lm") == 0 + || strcmp (argv[i], "-lmath") == 0 +#ifdef ALT_LIBM + || strcmp (argv[i], ALT_LIBM) == 0 +#endif + ) + { + args[i] |= MATHLIB; + need_math = 0; + } + else if (strcmp (argv[i], "-lc") == 0) + args[i] |= WITHLIBC; + else if (strcmp (argv[i], "-v") == 0) + { + saw_verbose_flag = 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; + added -= 2; + } + 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) + (*fn) ("argument to `%s' missing\n", quote); + + /* If we know we don't have to do anything, bail now. */ + if (! added && ! library) + { + free (args); + return; + } + + num_args = argc + added + need_math; + arglist = (char **) xmalloc (num_args * sizeof (char *)); + + /* NOTE: We start at 1 now, not 0. */ + for (i = 0, j = 0; i < argc; i++, j++) + { + arglist[j] = argv[i]; + + /* Make sure -lstdc++ is before the math library, since libstdc++ + itself uses those math routines. */ + if (!saw_math && (args[i] & MATHLIB) && library) + { + --j; + saw_math = argv[i]; + } + + if (!saw_libc && (args[i] & WITHLIBC) && library) + { + --j; + saw_libc = 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 `-lstdc++' if we haven't already done so. */ + if (library) + arglist[j++] = "-lstdc++"; + if (saw_math) + arglist[j++] = saw_math; + else if (library) + arglist[j++] = MATH_LIBRARY; + if (saw_libc) + arglist[j++] = saw_libc; + + arglist[j] = NULL; + + *in_argc = j; + *in_argv = arglist; +} diff --git a/gnu/usr.bin/gcc/cp/inc/exception b/gnu/usr.bin/gcc/cp/inc/exception new file mode 100644 index 00000000000..d38806b81c4 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/inc/exception @@ -0,0 +1,42 @@ +// Exception Handling support header for -*- C++ -*- +// Copyright (C) 1995, 1996 Free Software Foundation + +#ifndef __EXCEPTION__ +#define __EXCEPTION__ + +#pragma interface "exception" + +extern "C++" { + +#if 0 +namespace std { +#endif + +class exception { +public: + exception () { } + virtual ~exception () { } + virtual const char* what () const; +}; + +class bad_exception : public exception { +public: + bad_exception () { } + virtual ~bad_exception () { } +}; + +typedef void (*terminate_handler) (); +typedef void (*unexpected_handler) (); + +terminate_handler set_terminate (terminate_handler); +void terminate (void); +unexpected_handler set_unexpected (unexpected_handler); +void unexpected (void); +bool uncaught_exception (); +} // extern "C++" + +#if 0 +} // namespace std +#endif + +#endif diff --git a/gnu/usr.bin/gcc/cp/inc/new b/gnu/usr.bin/gcc/cp/inc/new new file mode 100644 index 00000000000..f4b0b975cdb --- /dev/null +++ b/gnu/usr.bin/gcc/cp/inc/new @@ -0,0 +1,48 @@ +// The -*- C++ -*- dynamic memory management header. +// Copyright (C) 1994, 1996 Free Software Foundation + +#ifndef __NEW__ +#define __NEW__ + +#pragma interface "new" +#include <stddef.h> +#include <exception> + +extern "C++" { + +#if 0 +namespace std { +#endif + + class bad_alloc : public exception { + public: + virtual const char* what() const throw() { return "bad_alloc"; } + }; + + struct nothrow_t {}; + extern const nothrow_t nothrow; + typedef void (*new_handler)(); + extern "C" new_handler set_new_handler (new_handler); + +#if 0 +} // namespace std +#endif + +// G++ implementation internals +extern new_handler __new_handler; +extern "C" void __default_new_handler (void); + +// replaceable signatures +void *operator new (size_t); +void *operator new (size_t, const nothrow_t&) throw(); +void *operator new[] (size_t); +void *operator new[] (size_t, const nothrow_t&) throw(); +void operator delete (void *) throw(); +void operator delete[] (void *) throw(); + +// default placement versions of operator new +inline void *operator new(size_t, void *place) throw() { return place; } +inline void *operator new[](size_t, void *place) throw() { return place; } +} // extern "C++" + +#endif diff --git a/gnu/usr.bin/gcc/cp/inc/new.h b/gnu/usr.bin/gcc/cp/inc/new.h new file mode 100644 index 00000000000..eed0910b668 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/inc/new.h @@ -0,0 +1,13 @@ +// -*- C++ -*- forwarding header. + +#ifndef __NEW_H__ +#define __NEW_H__ + +#include <new> + +#if 0 +using std::new_handler; +using std::set_new_handler; +#endif + +#endif // __NEW_H__ diff --git a/gnu/usr.bin/gcc/cp/inc/typeinfo b/gnu/usr.bin/gcc/cp/inc/typeinfo new file mode 100644 index 00000000000..26526594db5 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/inc/typeinfo @@ -0,0 +1,71 @@ +// RTTI support for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996 Free Software Foundation + +#ifndef __TYPEINFO__ +#define __TYPEINFO__ + +#include <exception> + +extern "C++" { + +#if 0 +namespace std { +#endif + +class type_info { +private: + // assigning type_info is not supported. made private. + type_info& operator= (const type_info&); + type_info (const type_info&); + +protected: + type_info (const char *n): _name (n) { } + + const char *_name; + +public: + // destructor + virtual ~type_info (); + + bool before (const type_info& arg) const; + const char* name () const + { return _name; } + bool operator== (const type_info& arg) const; + bool operator!= (const type_info& arg) const; +}; + +// We can't rely on common symbols being shared between translation units +// under Windows. Sigh. + +#ifndef _WIN32 +inline bool type_info:: +operator== (const type_info& arg) const +{ + return &arg == this; +} + +inline bool type_info:: +operator!= (const type_info& arg) const +{ + return &arg != this; +} +#endif + +class bad_cast : public exception { +public: + bad_cast() { } + virtual ~bad_cast() { } +}; + +class bad_typeid : public exception { + public: + bad_typeid () { } + virtual ~bad_typeid () { } +}; + +#if 0 +} // namespace std +#endif + +} // extern "C++" +#endif diff --git a/gnu/usr.bin/gcc/cp/mpw-config.in b/gnu/usr.bin/gcc/cp/mpw-config.in new file mode 100644 index 00000000000..88dd85f72e9 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/mpw-config.in @@ -0,0 +1,11 @@ +# Configuration fragment for G++. +# Most of the real configuration work happens in the main GCC configure. + +# We need to join some lines in the Makefile.in before the sed +# process will work properly. The funky little sed script works by +# recognizing lines with a trailing '$@ \', adding the next line to +# its "pattern space", editing out the backslash and line, then +# putting the result out. + +sed -e '/$@ \\/{N;s/$@ \\./$@ /;P;D;}' \Option-d + "{srcdir}"Makefile.in >"{o}"hacked_Makefile.in diff --git a/gnu/usr.bin/gcc/cp/mpw-make.sed b/gnu/usr.bin/gcc/cp/mpw-make.sed new file mode 100644 index 00000000000..120b5a1fa3a --- /dev/null +++ b/gnu/usr.bin/gcc/cp/mpw-make.sed @@ -0,0 +1,112 @@ +# Sed commands to finish translating the G++ Unix makefile into MPW syntax. + +# Remove control-Ls, they upset MPW make. +s///g + +# Remove references to always-empty variables used to mark things. +/CYGNUS-LOCAL-/s/{CYGNUS-LOCAL-[a-z0-9]*}//g + +# Add a bunch of definitions, mostly empty. +/^# Variables that exist for you to override.$/a\ +\ +xmake_file = \ +tmake_file = \ +build_xm_file = \ +MALLOC = \ +MD_DEPS = \ +REAL_H = \ +HOST_CC_LD = {CC_LD}\ +ALL_CCLDFLAGS = \ +HOST_CCLDFLAGS = \ +CONFIG_H = \ +LIBDEPS = \ + +# The "target" variable is special to MPW make, avoid it. +/{target}/s/{target}/{target_canonical}/g + +# Suppress the suppression of smart makes. +/^\.y\.c/d + +# Whack out "..." assignments. +/\.\.\./s/^\([a-z_]*= \.\.\.\)/#\1/ + +# Previous edits go a little overboard, undo. +/^objext = /s/"{o}"// + +# Always link in low-level MPW functions. +/^LIBDEPS=/s/$/ ::strerror.c.o ::mpwlib.c.o/ +/{CLIB}/s/{CLIB}/ ::strerror.c.o ::mpwlib.c.o {CLIB}/ + +# Don't get tricky about finding various .o file, point at dir above. +/^SUBDIR_OBSTACK/s/`.*`/::obstack.c.o/ +/^SUBDIR_USE_ALLOCA/s/`.*`/::alloca.c.o/ +/^SUBDIR_MALLOC/s/`.*`// + +# Point includes at parent directly correctly. +/^INCLUDES = /s/:\./::/g +/^INCLUDES = /s/"{srcdir}"\.\./"{topsrcdir}"gcc:/g +/^INCLUDES = /s,"{srcdir}"/\.\.,"{topsrcdir}"gcc:,g +/^INCLUDES = /s,"{srcdir}":config,"{topsrcdir}"gcc:config:,g + +# Add the special MPW include dirs. +/^INCLUDES = /s/$/ -i "{topsrcdir}"include:mpw: -i :::extra-include:/ + +# A nasty hack to reduce confusion. +/true/s/ ; @true$// + +# (should be in common translation?) +/{CC_LD} /s/$/ {EXTRALIBS}/ + +# Don't use general compiler flags (which may include definitions +# and other compiler-only bits) with linking commands. +/{CC_LD} /s/ALL_CFLAGS/ALL_CCLDFLAGS/ + +# Whack out build rules that are not useful. +/^Makefile \\Option-f /,/^$/d +/^config.status \\Option-f /,/^$/d +# (Note that MPW make is not case sensitive, and so this name +# is considered the same as "md_file".) +/^{MD_FILE} \\Option-f/,/^$/d + +# Depending on config.status is not useful for us. +/config.status/s/ config.status// + +# Repeat of stuff from generic edit. +/{s}/s/"{s}""{s}"/"{s}"/g +/{s}/s/"{s}""{srcdir}"/"{s}"/g +/{s}/s/"{srcdir}""{s}"/"{s}"/g + +# Fix references to C frontend files in main dir. +/::c-/s/"{o}"::c-/"{o}":c-/g + +# Fix pathnames to generated files in the objdir. +/parse/s/"{s}"parse\.\([chy]\)/"{o}"parse.\1/g +/parse/s/^parse\.\([chy]\)/"{o}"parse.\1/ +/y.tab.c/s/"{s}"y\.tab\.c/"{o}"y.tab.c/g +/y.tab.c/s/^y\.tab\.c/"{o}"y.tab.c/ +/y.tab.h/s/"{s}"y\.tab\.h/"{o}"y.tab.h/g +/y.tab.h/s/^y\.tab\.h/"{o}"y.tab.h/ + +# Put in the definition of YYEMPTY directly. +/grep/s/grep .* >>/Echo '#define YYEMPTY -1' >>/ + +# If the dates are wrong, then this tries to run gperf, which we don't +# really want. +/^"{srcdir}"hash.h/,/hash.h$/d + +# Sed the object file list instead of using cat (meow). +/cat/s/`cat /`sed -e 's,:,::,g' -e 's,{objext},.o,g' / + +# Simplify dependencies of generated parser files. +/^{PARSE_C}/s/^/#/ +/^stamp-parse/s/^stamp-parse/{PARSE_C}/ + +# Fix the compile line for the generated parser. +/{CC} -c/,/echo {PARSE_C}/c\ + {CC} @DASH_C_FLAG@ {ALL_CFLAGS} {ALL_CPPFLAGS} {INCLUDES} {BIG_SWITCHFLAG} "{o}"parse.c -o "{o}"parse.c.o\ + +# Change all Rez commands to use mac-gcc.r. +/{REZ}/s/"{s}"[-a-zA-Z{}]*\.r/"{topsrcdir}"gcc:mac-gcc.r/ + +# Remove pathname junk from the container name. +/{REZ}/s/'"'::cc1plus'"'/'"'cc1plus'"'/ diff --git a/gnu/usr.bin/gcc/cp/new.cc b/gnu/usr.bin/gcc/cp/new.cc new file mode 100644 index 00000000000..0db3497f1fa --- /dev/null +++ b/gnu/usr.bin/gcc/cp/new.cc @@ -0,0 +1,31 @@ +// Implementation file for the -*- C++ -*- dynamic memory management header. +// Copyright (C) 1996 Free Software Foundation + +// 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 other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself 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. + +#pragma implementation "new" +#include "new" + +const nothrow_t nothrow = { }; diff --git a/gnu/usr.bin/gcc/cp/new1.cc b/gnu/usr.bin/gcc/cp/new1.cc new file mode 100644 index 00000000000..0ee111d2939 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/new1.cc @@ -0,0 +1,54 @@ +// Support routine for the -*- C++ -*- dynamic memory management. +// Copyright (C) 1997 Free Software Foundation + +// 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 other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself 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. + +#include "new" + +extern "C" void *malloc (size_t); + +typedef void (*vfp)(void); +extern vfp __new_handler; +extern void __default_new_handler (void); + +void *operator new (size_t sz, const nothrow_t&) throw() +{ + void *p; + vfp handler = __new_handler; + + /* malloc (0) is unpredictable; avoid it. */ + if (sz == 0) + sz = 1; + p = (void *) malloc (sz); + while (p == 0) + { + if (! handler) + return 0; + (*handler) (); + p = (void *) malloc (sz); + } + + return p; +} diff --git a/gnu/usr.bin/gcc/cp/new2.cc b/gnu/usr.bin/gcc/cp/new2.cc new file mode 100644 index 00000000000..5aca49d21d1 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/new2.cc @@ -0,0 +1,33 @@ +// Support routine for the -*- C++ -*- dynamic memory management. +// Copyright (C) 1997 Free Software Foundation + +// 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 other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself 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. + +#include "new" + +void *operator new[] (size_t sz, const nothrow_t& nothrow) throw() +{ + return ::operator new(sz, nothrow); +} diff --git a/gnu/usr.bin/gcc/cp/rtti.c b/gnu/usr.bin/gcc/cp/rtti.c new file mode 100644 index 00000000000..e7b83d37726 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/rtti.c @@ -0,0 +1,1394 @@ +/* RunTime Type Identification + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Mostly written by Jason Merrill (jason@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. */ + + +#include "config.h" +#include <stdio.h> +#include "tree.h" +#include "cp-tree.h" +#include "flags.h" +#include "output.h" +#include "assert.h" + +#ifndef INT_TYPE_SIZE +#define INT_TYPE_SIZE BITS_PER_WORD +#endif + +extern struct obstack permanent_obstack; + +static tree call_void_fn PROTO((char *)); +static tree build_headof_sub PROTO((tree)); +static tree build_headof PROTO((tree)); +static tree get_tinfo_var PROTO((tree)); +static tree get_typeid_1 PROTO((tree)); +static tree ifnonnull PROTO((tree, tree)); +static tree build_dynamic_cast_1 PROTO((tree, tree)); +static void expand_si_desc PROTO((tree, tree)); +static void expand_class_desc PROTO((tree, tree)); +static void expand_attr_desc PROTO((tree, tree)); +static void expand_ptr_desc PROTO((tree, tree)); +static void expand_generic_desc PROTO((tree, tree, char *)); +static tree throw_bad_cast PROTO((void)); +static tree throw_bad_typeid PROTO((void)); + +tree type_info_type_node; +tree tinfo_fn_id; +tree tinfo_fn_type; + +void +init_rtti_processing () +{ + type_info_type_node = xref_tag + (class_type_node, get_identifier ("type_info"), NULL_TREE, 1); + tinfo_fn_id = get_identifier ("__tf"); + tinfo_fn_type = build_function_type + (build_reference_type (build_type_variant (type_info_type_node, 1, 0)), + void_list_node); +} + +/* Given a pointer to an object with at least one virtual table + pointer somewhere, return a pointer to a possible sub-object that + has a virtual table pointer in it that is the vtable parent for + that sub-object. */ + +static tree +build_headof_sub (exp) + tree exp; +{ + tree type = TREE_TYPE (TREE_TYPE (exp)); + tree basetype = CLASSTYPE_RTTI (type); + tree binfo = get_binfo (basetype, type, 0); + + exp = convert_pointer_to_real (binfo, exp); + return exp; +} + +/* Given the expression EXP of type `class *', return the head of the + object pointed to by EXP with type cv void*, if the class has any + virtual functions (TYPE_VIRTUAL_P), else just return the + expression. */ + +static tree +build_headof (exp) + tree exp; +{ + tree type = TREE_TYPE (exp); + tree aref; + tree offset; + + if (TREE_CODE (type) != POINTER_TYPE) + { + error ("`headof' applied to non-pointer type"); + return error_mark_node; + } + type = TREE_TYPE (type); + + if (!TYPE_VIRTUAL_P (type)) + return exp; + + /* If we don't have rtti stuff, get to a sub-object that does. */ + if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp)))) + exp = build_headof_sub (exp); + + /* We use this a couple of times below, protect it. */ + exp = save_expr (exp); + + aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node); + + if (flag_vtable_thunks) + offset = aref; + else + offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0); + + type = build_type_variant (ptr_type_node, TREE_READONLY (exp), + TREE_THIS_VOLATILE (exp)); + return build (PLUS_EXPR, type, exp, + cp_convert (ptrdiff_type_node, offset)); +} + +/* Build a call to a generic entry point taking and returning void. */ + +static tree +call_void_fn (name) + char *name; +{ + tree d = get_identifier (name); + tree type; + + if (IDENTIFIER_GLOBAL_VALUE (d)) + d = IDENTIFIER_GLOBAL_VALUE (d); + else + { + push_obstacks (&permanent_obstack, &permanent_obstack); + + type = build_function_type (void_type_node, void_list_node); + d = build_lang_decl (FUNCTION_DECL, d, type); + DECL_EXTERNAL (d) = 1; + TREE_PUBLIC (d) = 1; + DECL_ARTIFICIAL (d) = 1; + pushdecl_top_level (d); + make_function_rtl (d); + assemble_external (d); + + pop_obstacks (); + } + + return build_call (d, void_type_node, NULL_TREE); +} + +/* Get a bad_cast node for the program to throw... + + See libstdc++/exception.cc for __throw_bad_cast */ + +static tree +throw_bad_cast () +{ + return call_void_fn ("__throw_bad_cast"); +} + +static tree +throw_bad_typeid () +{ + return call_void_fn ("__throw_bad_typeid"); +} + +/* Return the type_info function associated with the expression EXP. If + EXP is a reference to a polymorphic class, return the dynamic type; + otherwise return the static type of the expression. */ + +tree +get_tinfo_fn_dynamic (exp) + tree exp; +{ + tree type; + + if (exp == error_mark_node) + return error_mark_node; + + if (type_unknown_p (exp)) + { + error ("typeid of overloaded function"); + return error_mark_node; + } + + type = TREE_TYPE (exp); + + /* peel back references, so they match. */ + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + + /* Peel off cv qualifiers. */ + type = TYPE_MAIN_VARIANT (type); + + /* If exp is a reference to polymorphic type, get the real type_info. */ + if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0)) + { + /* build reference to type_info from vtable. */ + tree t; + + if (! flag_rtti) + warning ("taking dynamic typeid of object without -frtti"); + + /* If we don't have rtti stuff, get to a sub-object that does. */ + if (! CLASSTYPE_VFIELDS (type)) + { + exp = build_unary_op (ADDR_EXPR, exp, 0); + exp = build_headof_sub (exp); + exp = build_indirect_ref (exp, NULL_PTR); + } + + if (flag_vtable_thunks) + t = build_vfn_ref ((tree *) 0, exp, integer_one_node); + else + t = build_vfn_ref ((tree *) 0, exp, integer_zero_node); + TREE_TYPE (t) = build_pointer_type (tinfo_fn_type); + return t; + } + + /* otherwise return the type_info for the static type of the expr. */ + return get_tinfo_fn (TYPE_MAIN_VARIANT (type)); +} + +tree +build_typeid (exp) + tree exp; +{ + exp = get_tinfo_fn_dynamic (exp); + exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE); + return convert_from_reference (exp); +} + +tree +build_x_typeid (exp) + tree exp; +{ + tree cond = NULL_TREE; + tree type = TREE_TYPE (tinfo_fn_type); + int nonnull; + + if (processing_template_decl) + return build_min_nt (TYPEID_EXPR, exp); + + if (TREE_CODE (exp) == INDIRECT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE + && TYPE_VIRTUAL_P (TREE_TYPE (exp)) + && ! resolves_to_fixed_type_p (exp, &nonnull) + && ! nonnull) + { + exp = stabilize_reference (exp); + cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); + } + + exp = get_tinfo_fn_dynamic (exp); + + if (exp == error_mark_node) + return error_mark_node; + + exp = build_call (exp, type, NULL_TREE); + + if (cond) + { + tree bad = throw_bad_typeid (); + + bad = build_compound_expr + (expr_tree_cons (NULL_TREE, bad, build_expr_list + (NULL_TREE, cp_convert (type, integer_zero_node)))); + exp = build (COND_EXPR, type, cond, exp, bad); + } + + return convert_from_reference (exp); +} + +static tree +get_tinfo_var (type) + tree type; +{ + tree tname = build_overload_with_type (get_identifier ("__ti"), type); + tree tdecl, arrtype; + int size; + + if (IDENTIFIER_GLOBAL_VALUE (tname)) + return IDENTIFIER_GLOBAL_VALUE (tname); + + /* Figure out how much space we need to allocate for the type_info object. + If our struct layout or the type_info classes are changed, this will + need to be modified. */ + if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) + size = 3 * POINTER_SIZE + INT_TYPE_SIZE; + else if (TREE_CODE (type) == POINTER_TYPE + && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE + || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)) + size = 3 * POINTER_SIZE; + else if (IS_AGGR_TYPE (type)) + { + if (CLASSTYPE_N_BASECLASSES (type) == 0) + size = 2 * POINTER_SIZE; + else if (! TYPE_USES_COMPLEX_INHERITANCE (type) + && (TREE_VIA_PUBLIC + (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)))) + size = 3 * POINTER_SIZE; + else + size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype); + } + else + size = 2 * POINTER_SIZE; + + push_obstacks (&permanent_obstack, &permanent_obstack); + + /* The type for a character array of the appropriate size. */ + arrtype = build_cplus_array_type + (unsigned_char_type_node, + build_index_type (size_int (size / BITS_PER_UNIT - 1))); + + tdecl = build_decl (VAR_DECL, tname, arrtype); + TREE_PUBLIC (tdecl) = 1; + DECL_EXTERNAL (tdecl) = 1; + DECL_ARTIFICIAL (tdecl) = 1; + pushdecl_top_level (tdecl); + cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); + + pop_obstacks (); + + return tdecl; +} + +tree +get_tinfo_fn (type) + tree type; +{ + tree name; + tree d; + + if (TREE_CODE (type) == OFFSET_TYPE) + type = TREE_TYPE (type); + if (TREE_CODE (type) == METHOD_TYPE) + type = build_function_type (TREE_TYPE (type), + TREE_CHAIN (TYPE_ARG_TYPES (type))); + + name = build_overload_with_type (tinfo_fn_id, type); + + if (IDENTIFIER_GLOBAL_VALUE (name)) + return IDENTIFIER_GLOBAL_VALUE (name); + + push_obstacks (&permanent_obstack, &permanent_obstack); + + d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type); + DECL_EXTERNAL (d) = 1; + TREE_PUBLIC (d) = 1; + DECL_ARTIFICIAL (d) = 1; + DECL_NOT_REALLY_EXTERN (d) = 1; + DECL_MUTABLE_P (d) = 1; + TREE_TYPE (name) = copy_to_permanent (type); + pushdecl_top_level (d); + make_function_rtl (d); + assemble_external (d); + mark_inline_for_output (d); + if (at_eof) + import_export_decl (d); + + pop_obstacks (); + + return d; +} + +static tree +get_typeid_1 (type) + tree type; +{ + tree t = build_call + (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE); + return convert_from_reference (t); +} + +/* Return the type_info object for TYPE, creating it if necessary. */ + +tree +get_typeid (type) + tree type; +{ + if (type == error_mark_node) + return error_mark_node; + + if (processing_template_decl) + return build_min_nt (TYPEID_EXPR, type); + + /* If the type of the type-id is a reference type, the result of the + typeid expression refers to a type_info object representing the + referenced type. */ + if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); + + /* The top-level cv-qualifiers of the lvalue expression or the type-id + that is the operand of typeid are always ignored. */ + type = TYPE_MAIN_VARIANT (type); + + return get_typeid_1 (type); +} + +/* Check whether TEST is null before returning RESULT. If TEST is used in + RESULT, it must have previously had a save_expr applied to it. */ + +static tree +ifnonnull (test, result) + tree test, result; +{ + return build (COND_EXPR, TREE_TYPE (result), + build (EQ_EXPR, boolean_type_node, test, integer_zero_node), + cp_convert (TREE_TYPE (result), integer_zero_node), + result); +} + +/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working + paper. */ + +static tree +build_dynamic_cast_1 (type, expr) + tree type, expr; +{ + enum tree_code tc = TREE_CODE (type); + tree exprtype = TREE_TYPE (expr); + enum tree_code ec; + tree dcast_fn; + + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; + + if (processing_template_decl) + { + tree t = build_min (DYNAMIC_CAST_EXPR, type, expr); + return t; + } + + assert (exprtype != NULL_TREE); + ec = TREE_CODE (exprtype); + + switch (tc) + { + case POINTER_TYPE: + if (ec == REFERENCE_TYPE) + { + expr = convert_from_reference (expr); + exprtype = TREE_TYPE (expr); + ec = TREE_CODE (exprtype); + } + if (ec != POINTER_TYPE) + goto fail; + if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) + goto fail; + if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE) + goto fail; + if (TREE_READONLY (TREE_TYPE (exprtype)) + && ! TYPE_READONLY (TREE_TYPE (type))) + goto fail; + if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) + break; + /* else fall through */ + case REFERENCE_TYPE: + if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE) + goto fail; + if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE) + goto fail; + break; + /* else fall through */ + default: + goto fail; + } + + /* Apply trivial conversion T -> T& for dereferenced ptrs. */ + if (ec == RECORD_TYPE) + { + exprtype = build_type_variant (exprtype, TREE_READONLY (expr), + TREE_THIS_VOLATILE (expr)); + exprtype = build_reference_type (exprtype); + expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, + LOOKUP_NORMAL, NULL_TREE); + ec = REFERENCE_TYPE; + } + + if (tc == REFERENCE_TYPE) + { + if (ec != REFERENCE_TYPE) + goto fail; + if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE) + goto fail; + if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE) + goto fail; + if (TREE_READONLY (TREE_TYPE (exprtype)) + && ! TYPE_READONLY (TREE_TYPE (type))) + goto fail; + } + + /* If *type is an unambiguous accessible base class of *exprtype, + convert statically. */ + { + int distance; + tree path; + + distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1, + &path); + if (distance >= 0) + return build_vbase_path (PLUS_EXPR, type, expr, path, 0); + } + + /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */ + if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype))) + { + tree expr1; + /* if TYPE is `void *', return pointer to complete object. */ + if (tc == POINTER_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) + { + /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b. */ + if (TREE_CODE (expr) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL + && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE) + return build1 (NOP_EXPR, type, expr); + + /* Since expr is used twice below, save it. */ + expr = save_expr (expr); + + expr1 = build_headof (expr); + if (TREE_TYPE (expr1) != type) + expr1 = build1 (NOP_EXPR, type, expr1); + return ifnonnull (expr, expr1); + } + else + { + tree retval; + tree result, td1, td2, td3, elems, expr2; + + /* If we got here, we can't convert statically. Therefore, + dynamic_cast<D&>(b) (b an object) cannot succeed. */ + if (ec == REFERENCE_TYPE) + { + if (TREE_CODE (expr) == VAR_DECL + && TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE) + { + cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", + expr, type); + return throw_bad_cast (); + } + } + /* Ditto for dynamic_cast<D*>(&b). */ + else if (TREE_CODE (expr) == ADDR_EXPR) + { + tree op = TREE_OPERAND (expr, 0); + if (TREE_CODE (op) == VAR_DECL + && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) + { + cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed", + expr, type); + retval = build_int_2 (0, 0); + TREE_TYPE (retval) = type; + return retval; + } + } + + /* Since expr is used twice below, save it. */ + expr = save_expr (expr); + + expr1 = expr; + if (tc == REFERENCE_TYPE) + expr1 = build_unary_op (ADDR_EXPR, expr1, 0); + + /* Build run-time conversion. */ + expr2 = build_headof (expr1); + + if (ec == POINTER_TYPE) + td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR)); + else + td1 = get_tinfo_fn_dynamic (expr); + td1 = decay_conversion (td1); + + td2 = decay_conversion + (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type)))); + td3 = decay_conversion + (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)))); + + elems = tree_cons + (NULL_TREE, td1, tree_cons + (NULL_TREE, td2, tree_cons + (NULL_TREE, build_int_2 (1, 0), tree_cons + (NULL_TREE, expr2, tree_cons + (NULL_TREE, td3, tree_cons + (NULL_TREE, expr1, NULL_TREE)))))); + + dcast_fn = get_identifier ("__dynamic_cast"); + if (IDENTIFIER_GLOBAL_VALUE (dcast_fn)) + dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn); + else + { + tree tmp; + + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, TREE_TYPE (td1), tree_cons + (NULL_TREE, TREE_TYPE (td1), tree_cons + (NULL_TREE, integer_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, TREE_TYPE (td1), tree_cons + (NULL_TREE, ptr_type_node, void_list_node)))))); + tmp = build_function_type (ptr_type_node, tmp); + dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp); + DECL_EXTERNAL (dcast_fn) = 1; + TREE_PUBLIC (dcast_fn) = 1; + DECL_ARTIFICIAL (dcast_fn) = 1; + pushdecl_top_level (dcast_fn); + make_function_rtl (dcast_fn); + assemble_external (dcast_fn); + pop_obstacks (); + } + + result = build_call + (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems); + + if (tc == REFERENCE_TYPE) + { + expr1 = throw_bad_cast (); + expr1 = build_compound_expr + (expr_tree_cons (NULL_TREE, expr1, + build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node)))); + TREE_TYPE (expr1) = type; + result = save_expr (result); + return build (COND_EXPR, type, result, result, expr1); + } + + /* Now back to the type we want from a void*. */ + result = cp_convert (type, result); + return ifnonnull (expr, result); + } + } + + fail: + cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'", + expr, exprtype, type); + return error_mark_node; +} + +tree +build_dynamic_cast (type, expr) + tree type, expr; +{ + return convert_from_reference (build_dynamic_cast_1 (type, expr)); +} + +/* Build and initialize various sorts of descriptors. Every descriptor + node has a name associated with it (the name created by mangling). + For this reason, we use the identifier as our access to the __*_desc + nodes, instead of sticking them directly in the types. Otherwise we + would burden all built-in types (and pointer types) with slots that + we don't necessarily want to use. + + For each descriptor we build, we build a variable that contains + the descriptor's information. When we need this info at runtime, + all we need is access to these variables. + + Note: these constructors always return the address of the descriptor + info, since that is simplest for their mutual interaction. */ + +extern tree const_string_type_node; + +/* Build an initializer for a __si_type_info node. */ + +static void +expand_si_desc (tdecl, type) + tree tdecl; + tree type; +{ + tree t, elems, fn; + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name)+1, name)); + + type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)); + expand_expr_stmt (get_typeid_1 (type)); + t = decay_conversion (get_tinfo_var (type)); + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, t, NULL_TREE))); + + fn = get_identifier ("__rtti_si"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, build_pointer_type (type_info_type_node), + void_list_node))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); + expand_expr_stmt (fn); +} + +/* Build an initializer for a __class_type_info node. */ + +static void +expand_class_desc (tdecl, type) + tree tdecl; + tree type; +{ + tree name_string; + tree fn, tmp; + char *name; + + int i = CLASSTYPE_N_BASECLASSES (type); + int base_cnt = 0; + tree binfos = TYPE_BINFO_BASETYPES (type); +#if 0 + /* See code below that used these. */ + tree vb = CLASSTYPE_VBASECLASSES (type); + int n_base = i; +#endif + tree base, elems, access, offset, isvir; + tree elt, elts = NULL_TREE; + static tree base_info_type_node; + + if (base_info_type_node == NULL_TREE) + { + tree fields [4]; + + /* A reasonably close approximation of __class_type_info::base_info */ + + push_obstacks (&permanent_obstack, &permanent_obstack); + base_info_type_node = make_lang_type (RECORD_TYPE); + + /* Actually const __user_type_info * */ + fields [0] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, + build_pointer_type (build_type_variant (type_info_type_node, 1, 0))); + fields [1] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node); + DECL_BIT_FIELD (fields[1]) = 1; + DECL_FIELD_SIZE (fields[1]) = 29; + + fields [2] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, boolean_type_node); + DECL_BIT_FIELD (fields[2]) = 1; + DECL_FIELD_SIZE (fields[2]) = 1; + + /* Actually enum access */ + fields [3] = build_lang_field_decl + (FIELD_DECL, NULL_TREE, integer_type_node); + DECL_BIT_FIELD (fields[3]) = 1; + DECL_FIELD_SIZE (fields[3]) = 2; + + finish_builtin_type (base_info_type_node, "__base_info", fields, + 3, ptr_type_node); + pop_obstacks (); + } + + while (--i >= 0) + { + tree binfo = TREE_VEC_ELT (binfos, i); + + expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo))); + base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo))); + + if (TREE_VIA_VIRTUAL (binfo)) + { + tree t = BINFO_TYPE (binfo); + char *name; + tree field; + + name = (char *) alloca (TYPE_NAME_LENGTH (t)+sizeof (VBASE_NAME)+1); + sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (t)); + field = lookup_field (type, get_identifier (name), 0, 0); + offset = size_binop (FLOOR_DIV_EXPR, + DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT)); + } + else + offset = BINFO_OFFSET (binfo); + + if (TREE_VIA_PUBLIC (binfo)) + access = access_public_node; + else if (TREE_VIA_PROTECTED (binfo)) + access = access_protected_node; + else + access = access_private_node; + if (TREE_VIA_VIRTUAL (binfo)) + isvir = boolean_true_node; + else + isvir = boolean_false_node; + + elt = build + (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons + (NULL_TREE, base, tree_cons + (NULL_TREE, offset, tree_cons + (NULL_TREE, isvir, tree_cons + (NULL_TREE, access, NULL_TREE))))); + TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1; + elts = expr_tree_cons (NULL_TREE, elt, elts); + base_cnt++; + } +#if 0 + i = n_base; + while (vb) + { + tree b; + access = access_public_node; + while (--i >= 0) + { + b = TREE_VEC_ELT (binfos, i); + if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b)) + { + if (TREE_VIA_PUBLIC (b)) + access = access_public_node; + else if (TREE_VIA_PROTECTED (b)) + access = access_protected_node; + else + access = access_private_node; + break; + } + } + base = build_t_desc (BINFO_TYPE (vb), 1); + offset = BINFO_OFFSET (vb); + isvir = build_int_2 (1, 0); + + base_list = expr_tree_cons (NULL_TREE, base, base_list); + isvir_list = expr_tree_cons (NULL_TREE, isvir, isvir_list); + acc_list = expr_tree_cons (NULL_TREE, access, acc_list); + off_list = expr_tree_cons (NULL_TREE, offset, off_list); + + base_cnt++; + vb = TREE_CHAIN (vb); + } +#endif + + name = build_overload_name (type, 1, 1); + name_string = combine_strings (build_string (strlen (name)+1, name)); + + { + tree arrtype = build_array_type (base_info_type_node, NULL_TREE); + elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts); + TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts) + = TREE_STATIC (elts) = 1; + complete_array_type (arrtype, elts, 1); + } + + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, decay_conversion (elts), tree_cons + (NULL_TREE, cp_convert (sizetype, build_int_2 (base_cnt, 0)), + NULL_TREE)))); + + fn = get_identifier ("__rtti_class"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons + (NULL_TREE, sizetype, void_list_node)))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); + expand_expr_stmt (fn); +} + +/* Build an initializer for a __pointer_type_info node. */ + +static void +expand_ptr_desc (tdecl, type) + tree tdecl; + tree type; +{ + tree t, elems, fn; + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name)+1, name)); + + type = TREE_TYPE (type); + expand_expr_stmt (get_typeid_1 (type)); + t = decay_conversion (get_tinfo_var (type)); + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, t, NULL_TREE))); + + fn = get_identifier ("__rtti_ptr"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, build_pointer_type (type_info_type_node), + void_list_node))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); + expand_expr_stmt (fn); +} + +/* Build an initializer for a __attr_type_info node. */ + +static void +expand_attr_desc (tdecl, type) + tree tdecl; + tree type; +{ + tree elems, t, fn; + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name)+1, name)); + tree attrval = build_int_2 + (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0); + + expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type))); + t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type))); + elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), tree_cons + (NULL_TREE, attrval, expr_tree_cons (NULL_TREE, t, NULL_TREE)))); + + fn = get_identifier ("__rtti_attr"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, tree_cons + (NULL_TREE, integer_type_node, tree_cons + (NULL_TREE, build_pointer_type (type_info_type_node), + void_list_node)))); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); + expand_expr_stmt (fn); +} + +/* Build an initializer for a type_info node that just has a name. */ + +static void +expand_generic_desc (tdecl, type, fnname) + tree tdecl; + tree type; + char *fnname; +{ + char *name = build_overload_name (type, 1, 1); + tree name_string = combine_strings (build_string (strlen (name)+1, name)); + tree elems = tree_cons + (NULL_TREE, decay_conversion (tdecl), tree_cons + (NULL_TREE, decay_conversion (name_string), NULL_TREE)); + + tree fn = get_identifier (fnname); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree tmp; + push_obstacks (&permanent_obstack, &permanent_obstack); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, const_string_type_node, void_list_node)); + tmp = build_function_type (void_type_node, tmp); + + fn = build_lang_decl (FUNCTION_DECL, fn, tmp); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems); + expand_expr_stmt (fn); +} + +/* Generate the code for a type_info initialization function. + Note that we take advantage of the passage + + 5.2.7 Type identification [expr.typeid] + + Whether or not the destructor is called for the type_info object at the + end of the program is unspecified. + + and don't bother to arrange for these objects to be destroyed. It + doesn't matter, anyway, since the destructors don't do anything. + + This must only be called from toplevel (i.e. from finish_file)! */ + +void +synthesize_tinfo_fn (fndecl) + tree fndecl; +{ + tree type = TREE_TYPE (DECL_NAME (fndecl)); + tree tmp, addr; + + tree tdecl = get_tinfo_var (type); + DECL_EXTERNAL (tdecl) = 0; + TREE_STATIC (tdecl) = 1; + DECL_COMMON (tdecl) = 1; + TREE_USED (tdecl) = 1; + DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node); + cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); + + start_function (NULL_TREE, fndecl, NULL_TREE, 1); + store_parm_decls (); + clear_last_expr (); + push_momentary (); + + /* If the first word of the array (the vtable) is non-zero, we've already + initialized the object, so don't do it again. */ + addr = decay_conversion (tdecl); + tmp = cp_convert (build_pointer_type (ptr_type_node), addr); + tmp = build_indirect_ref (tmp, 0); + tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1); + expand_start_cond (tmp, 0); + + if (TREE_CODE (type) == FUNCTION_TYPE) + expand_generic_desc (tdecl, type, "__rtti_func"); + else if (TREE_CODE (type) == ARRAY_TYPE) + expand_generic_desc (tdecl, type, "__rtti_array"); + else if (TYPE_VOLATILE (type) || TYPE_READONLY (type)) + expand_attr_desc (tdecl, type); + else if (TREE_CODE (type) == POINTER_TYPE) + { + if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) + expand_generic_desc (tdecl, type, "__rtti_ptmd"); + else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE) + expand_generic_desc (tdecl, type, "__rtti_ptmf"); + else + expand_ptr_desc (tdecl, type); + } + else if (TYPE_PTRMEMFUNC_P (type)) + expand_generic_desc (tdecl, type, "__rtti_ptmf"); + else if (IS_AGGR_TYPE (type)) + { + if (CLASSTYPE_N_BASECLASSES (type) == 0) + expand_generic_desc (tdecl, type, "__rtti_user"); + else if (! TYPE_USES_COMPLEX_INHERITANCE (type) + && (TREE_VIA_PUBLIC + (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0)))) + expand_si_desc (tdecl, type); + else + expand_class_desc (tdecl, type); + } + else if (TREE_CODE (type) == ENUMERAL_TYPE) + expand_generic_desc (tdecl, type, "__rtti_user"); + else + my_friendly_abort (252); + + expand_end_cond (); + + /* OK, now return the type_info object. */ + tmp = cp_convert (build_pointer_type (type_info_type_node), addr); + tmp = build_indirect_ref (tmp, 0); + c_expand_return (tmp); + finish_function (lineno, 0, 0); +} + +#if 0 +/* This is the old dossier type descriptor generation code, it's much + more extended than rtti. It's reserved for later use. */ +/* Build an initializer for a __t_desc node. So that we can take advantage + of recursion, we accept NULL for TYPE. + DEFINITION is greater than zero iff we must define the type descriptor + (as opposed to merely referencing it). 1 means treat according to + #pragma interface/#pragma implementation rules. 2 means define as + global and public, no matter what. */ + +tree +build_t_desc (type, definition) + tree type; + int definition; +{ + tree tdecl; + tree tname, name_string; + tree elems, fields; + tree parents, vbases, offsets, ivars, methods, target_type; + int method_count = 0, field_count = 0; + + if (type == NULL_TREE) + return NULL_TREE; + + tname = build_t_desc_overload (type); + if (IDENTIFIER_AS_DESC (tname) + && (!definition || TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname)))) + return IDENTIFIER_AS_DESC (tname); + + tdecl = lookup_name (tname, 0); + if (tdecl == NULL_TREE) + { + tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); + DECL_EXTERNAL (tdecl) = 1; + TREE_PUBLIC (tdecl) = 1; + tdecl = pushdecl_top_level (tdecl); + } + /* If we previously defined it, return the defined result. */ + else if (definition && DECL_INITIAL (tdecl)) + return IDENTIFIER_AS_DESC (tname); + + if (definition) + { + tree taggr = type; + /* Let T* and T& be written only when T is written (if T is an aggr). + We do this for const, but not for volatile, since volatile + is rare and const is not. */ + if (!TYPE_VOLATILE (taggr) + && (TREE_CODE (taggr) == POINTER_TYPE + || TREE_CODE (taggr) == REFERENCE_TYPE) + && IS_AGGR_TYPE (TREE_TYPE (taggr))) + taggr = TREE_TYPE (taggr); + + /* If we know that we don't need to write out this type's + vtable, then don't write out it's dossier. Somebody + else will take care of that. */ + if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr)) + { + if (CLASSTYPE_VTABLE_NEEDS_WRITING (taggr)) + { + TREE_PUBLIC (tdecl) = ! CLASSTYPE_INTERFACE_ONLY (taggr) + && CLASSTYPE_INTERFACE_KNOWN (taggr); + DECL_EXTERNAL (tdecl) = 0; + } + else + { + if (write_virtuals != 0) + TREE_PUBLIC (tdecl) = 1; + } + } + else + { + DECL_EXTERNAL (tdecl) = 0; + TREE_PUBLIC (tdecl) = (definition > 1); + } + } + SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); + + if (!definition || DECL_EXTERNAL (tdecl)) + { + /* That's it! */ + cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0); + return IDENTIFIER_AS_DESC (tname); + } + + /* Show that we are defining the t_desc for this type. */ + DECL_INITIAL (tdecl) = error_mark_node; + + parents = build_expr_list (NULL_TREE, integer_zero_node); + vbases = build_expr_list (NULL_TREE, integer_zero_node); + offsets = build_expr_list (NULL_TREE, integer_zero_node); + methods = NULL_TREE; + ivars = NULL_TREE; + + if (TYPE_LANG_SPECIFIC (type)) + { + int i = CLASSTYPE_N_BASECLASSES (type); + tree method_vec = CLASSTYPE_METHOD_VEC (type); + tree *meth, *end; + tree binfos = TYPE_BINFO_BASETYPES (type); + tree vb = CLASSTYPE_VBASECLASSES (type); + + while (--i >= 0) + parents = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0), parents); + + while (vb) + { + vbases = tree_cons (NULL_TREE, build_t_desc (BINFO_TYPE (vb), 0), vbases); + offsets = tree_cons (NULL_TREE, BINFO_OFFSET (vb), offsets); + vb = TREE_CHAIN (vb); + } + + if (method_vec) + for (meth = TREE_VEC_END (method_vec), + end = &TREE_VEC_ELT (method_vec, 0); meth-- != end; ) + if (*meth) + { + methods = tree_cons (NULL_TREE, build_m_desc (*meth), methods); + method_count++; + } + } + + if (IS_AGGR_TYPE (type)) + { + for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) + if (TREE_CODE (fields) == FIELD_DECL + || TREE_CODE (fields) == VAR_DECL) + { + ivars = tree_cons (NULL_TREE, build_i_desc (fields), ivars); + field_count++; + } + ivars = nreverse (ivars); + } + + parents = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), parents, 0); + vbases = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), vbases, 0); + offsets = finish_table (NULL_TREE, integer_type_node, offsets, 0); + if (methods == NULL_TREE) + methods = null_pointer_node; + else + methods = build_unary_op (ADDR_EXPR, + finish_table (NULL_TREE, __m_desc_type_node, methods, 0), + 0); + if (ivars == NULL_TREE) + ivars = null_pointer_node; + else + ivars = build_unary_op (ADDR_EXPR, + finish_table (NULL_TREE, __i_desc_type_node, ivars, 0), + 0); + if (TREE_TYPE (type)) + target_type = build_t_desc (TREE_TYPE (type), definition); + else + target_type = integer_zero_node; + + name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname))); + + elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), + tree_cons (NULL_TREE, + TYPE_SIZE(type)? size_in_bytes(type) : integer_zero_node, + /* really should use bitfield initialization here. */ + tree_cons (NULL_TREE, integer_zero_node, + tree_cons (NULL_TREE, target_type, + tree_cons (NULL_TREE, build_int_2 (field_count, 2), + tree_cons (NULL_TREE, build_int_2 (method_count, 2), + tree_cons (NULL_TREE, ivars, + tree_cons (NULL_TREE, methods, + tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, parents, 0), + tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, vbases, 0), + build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, offsets, 0)))))))))))); + return build_generic_desc (tdecl, elems); +} + +/* Build an initializer for a __i_desc node. */ + +tree +build_i_desc (decl) + tree decl; +{ + tree elems, name_string; + tree taggr; + + name_string = DECL_NAME (decl); + name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); + + /* Now decide whether this ivar should cause it's type to get + def'd or ref'd in this file. If the type we are looking at + has a proxy definition, we look at the proxy (i.e., a + `foo *' is equivalent to a `foo'). */ + taggr = TREE_TYPE (decl); + + if ((TREE_CODE (taggr) == POINTER_TYPE + || TREE_CODE (taggr) == REFERENCE_TYPE) + && TYPE_VOLATILE (taggr) == 0) + taggr = TREE_TYPE (taggr); + + elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), + tree_cons (NULL_TREE, DECL_FIELD_BITPOS (decl), + build_tree_list (NULL_TREE, build_t_desc (TREE_TYPE (decl), + ! IS_AGGR_TYPE (taggr))))); + taggr = build (CONSTRUCTOR, __i_desc_type_node, NULL_TREE, elems); + TREE_CONSTANT (taggr) = 1; + TREE_STATIC (taggr) = 1; + TREE_READONLY (taggr) = 1; + return taggr; +} + +/* Build an initializer for a __m_desc node. */ + +tree +build_m_desc (decl) + tree decl; +{ + tree taggr, elems, name_string; + tree parm_count, req_count, vindex, vcontext; + tree parms; + int p_count, r_count; + tree parm_types = NULL_TREE; + + for (parms = TYPE_ARG_TYPES (TREE_TYPE (decl)), p_count = 0, r_count = 0; + parms != NULL_TREE; parms = TREE_CHAIN (parms), p_count++) + { + taggr = TREE_VALUE (parms); + if ((TREE_CODE (taggr) == POINTER_TYPE + || TREE_CODE (taggr) == REFERENCE_TYPE) + && TYPE_VOLATILE (taggr) == 0) + taggr = TREE_TYPE (taggr); + + parm_types = tree_cons (NULL_TREE, build_t_desc (TREE_VALUE (parms), + ! IS_AGGR_TYPE (taggr)), + parm_types); + if (TREE_PURPOSE (parms) == NULL_TREE) + r_count++; + } + + parm_types = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), + nreverse (parm_types), 0); + parm_count = build_int_2 (p_count, 0); + req_count = build_int_2 (r_count, 0); + + if (DECL_VINDEX (decl)) + vindex = DECL_VINDEX (decl); + else + vindex = integer_zero_node; + if (DECL_CONTEXT (decl) + && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') + vcontext = build_t_desc (DECL_CONTEXT (decl), 0); + else + vcontext = integer_zero_node; + name_string = DECL_NAME (decl); + if (name_string == NULL) + name_string = DECL_ASSEMBLER_NAME (decl); + name_string = combine_strings (build_string (IDENTIFIER_LENGTH (name_string)+1, IDENTIFIER_POINTER (name_string))); + + /* Now decide whether the return type of this mvar + should cause it's type to get def'd or ref'd in this file. + If the type we are looking at has a proxy definition, + we look at the proxy (i.e., a `foo *' is equivalent to a `foo'). */ + taggr = TREE_TYPE (TREE_TYPE (decl)); + + if ((TREE_CODE (taggr) == POINTER_TYPE + || TREE_CODE (taggr) == REFERENCE_TYPE) + && TYPE_VOLATILE (taggr) == 0) + taggr = TREE_TYPE (taggr); + + elems = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, name_string, 0), + tree_cons (NULL_TREE, vindex, + tree_cons (NULL_TREE, vcontext, + tree_cons (NULL_TREE, build_t_desc (TREE_TYPE (TREE_TYPE (decl)), + ! IS_AGGR_TYPE (taggr)), + tree_cons (NULL_TREE, build_c_cast (build_pointer_type (default_function_type), build_unary_op (ADDR_EXPR, decl, 0)), + tree_cons (NULL_TREE, parm_count, + tree_cons (NULL_TREE, req_count, + build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, parm_types, 0))))))))); + + taggr = build (CONSTRUCTOR, __m_desc_type_node, NULL_TREE, elems); + TREE_CONSTANT (taggr) = 1; + TREE_STATIC (taggr) = 1; + TREE_READONLY (taggr) = 1; + return taggr; +} +#endif /* dossier */ diff --git a/gnu/usr.bin/gcc/cp/tinfo.cc b/gnu/usr.bin/gcc/cp/tinfo.cc new file mode 100644 index 00000000000..d82aaaf0431 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/tinfo.cc @@ -0,0 +1,125 @@ +// Methods for type_info for -*- C++ -*- Run Time Type Identification. +// Copyright (C) 1994, 1996 Free Software Foundation + +// 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 other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself 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. + +#include <stddef.h> +#include "tinfo.h" +#include "new" // for placement new + +// This file contains the minimal working set necessary to link with code +// that uses virtual functions and -frtti but does not actually use RTTI +// functionality. + +type_info:: +~type_info () +{ } + +extern "C" void +__rtti_class (void *addr, const char *name, + const __class_type_info::base_info *bl, size_t bn) +{ new (addr) __class_type_info (name, bl, bn); } + +extern "C" void +__rtti_si (void *addr, const char *n, const type_info *ti) +{ + new (addr) __si_type_info + (n, static_cast <const __user_type_info &> (*ti)); +} + +extern "C" void +__rtti_user (void *addr, const char *name) +{ new (addr) __user_type_info (name); } + +// dynamic_cast helper methods. +// Returns a pointer to the desired sub-object or 0. + +void * __user_type_info:: +dcast (const type_info& to, int, void *addr, const type_info *, void *) const +{ return (*this == to) ? addr : 0; } + +void * __si_type_info:: +dcast (const type_info& to, int require_public, void *addr, + const type_info *sub, void *subptr) const +{ + if (*this == to) + return addr; + return base.dcast (to, require_public, addr, sub, subptr); +} + +void* __class_type_info:: +dcast (const type_info& desired, int is_public, void *objptr, + const type_info *sub, void *subptr) const +{ + if (*this == desired) + return objptr; + + void *match_found = 0; + for (int i = 0; i < n_bases; i++) + { + if (is_public && base_list[i].access != PUBLIC) + continue; + + void *p = (char *)objptr + base_list[i].offset; + if (base_list[i].is_virtual) + p = *(void **)p; + p = base_list[i].base->dcast (desired, is_public, p, sub, subptr); + if (p) + { + if (match_found == 0) + match_found = p; + else if (match_found != p) + { + if (sub) + { + // Perhaps we're downcasting from *sub to desired; see if + // subptr is a subobject of exactly one of {match_found,p}. + + const __user_type_info &d = + static_cast <const __user_type_info &> (desired); + + void *os = d.dcast (*sub, 1, match_found); + void *ns = d.dcast (*sub, 1, p); + + if (os == ns) + /* ambiguous -- subptr is a virtual base */; + else if (os == subptr) + continue; + else if (ns == subptr) + { + match_found = p; + continue; + } + } + + // base found at two different pointers, + // conversion is not unique + return 0; + } + } + } + + return match_found; +} diff --git a/gnu/usr.bin/gcc/cp/tinfo.h b/gnu/usr.bin/gcc/cp/tinfo.h new file mode 100644 index 00000000000..3df55a5c709 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/tinfo.h @@ -0,0 +1,55 @@ +// RTTI support internals for -*- C++ -*- +// Copyright (C) 1994, 1995, 1996 Free Software Foundation + +#include "typeinfo" + +// Class declarations shared between the typeinfo implementation files. + +// type_info for a class with no base classes (or an enum). + +struct __user_type_info : public type_info { + __user_type_info (const char *n) : type_info (n) {} + + // If our type can be converted to the desired type, + // return the pointer, adjusted accordingly; else return 0. + virtual void* dcast (const type_info &, int, void *, + const type_info * = 0, void * = 0) const; +}; + +// type_info for a class with one public, nonvirtual base class. + +class __si_type_info : public __user_type_info { + const __user_type_info &base; + +public: + __si_type_info (const char *n, const __user_type_info &b) + : __user_type_info (n), base (b) { } + + virtual void *dcast (const type_info &, int, void *, + const type_info * = 0, void * = 0) const; +}; + +// type_info for a general class. + +typedef unsigned int USItype __attribute__ ((mode (SI))); + +struct __class_type_info : public __user_type_info { + enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 }; + + struct base_info { + const __user_type_info *base; + USItype offset: 29; + bool is_virtual: 1; + access access: 2; + }; + + const base_info *base_list; + size_t n_bases; + + __class_type_info (const char *name, const base_info *bl, size_t bn) + : __user_type_info (name), base_list (bl), n_bases (bn) {} + + // This is a little complex. + virtual void* dcast (const type_info &, int, void *, + const type_info * = 0, void * = 0) const; +}; diff --git a/gnu/usr.bin/gcc/cp/tinfo2.cc b/gnu/usr.bin/gcc/cp/tinfo2.cc new file mode 100644 index 00000000000..128661c1cd2 --- /dev/null +++ b/gnu/usr.bin/gcc/cp/tinfo2.cc @@ -0,0 +1,323 @@ +// Methods for type_info for -*- C++ -*- Run Time Type Identification. +// Copyright (C) 1994, 1996 Free Software Foundation + +// 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 other files, +// some of which are compiled with GCC, to produce an executable, +// this library does not by itself 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. + +#include <stddef.h> +#include "tinfo.h" +#include "new" // for placement new + +// service function for comparing types by name. + +static inline int +fast_compare (const char *n1, const char *n2) { + int c; + if (n1 == n2) return 0; + if (n1 == 0) return *n2; + else if (n2 == 0) return *n1; + + c = (int)*n1++ - (int)*n2++; + return c == 0 ? strcmp (n1, n2) : c; +}; + +bool +type_info::before (const type_info &arg) const +{ + return fast_compare (name (), arg.name ()) < 0; +} + +#ifdef _WIN32 +bool type_info:: +operator== (const type_info& arg) const +{ + return fast_compare (name (), arg.name ()) == 0; +} + +bool type_info:: +operator!= (const type_info& arg) const +{ + return fast_compare (name (), arg.name ()) != 0; +} +#endif + +// type info for pointer type. + +struct __pointer_type_info : public type_info { + const type_info& type; + + __pointer_type_info (const char *n, const type_info& ti) + : type_info (n), type (ti) {} +}; + +// type info for attributes + +struct __attr_type_info : public type_info { + enum cv { NONE = 0, CONST = 1, VOLATILE = 2, CONSTVOL = 1 | 2 }; + + const type_info& type; + cv attr; + + __attr_type_info (const char *n, cv a, const type_info& t) + : type_info (n), type (t), attr (a) {} +}; + +// type_info for builtin type + +struct __builtin_type_info : public type_info { + __builtin_type_info (const char *n): type_info (n) {} +}; + +// type info for function. + +struct __func_type_info : public type_info { + __func_type_info (const char *n) : type_info (n) {} +}; + +// type info for pointer to member function. + +struct __ptmf_type_info : public type_info { + __ptmf_type_info (const char *n) : type_info (n) {} +}; + +// type info for pointer to data member. + +struct __ptmd_type_info : public type_info { + __ptmd_type_info (const char *n): type_info (n) {} +}; + +// type info for array. + +struct __array_type_info : public type_info { + __array_type_info (const char *n): type_info (n) {} +}; + +// Entry points for the compiler. + +/* Low level match routine used by compiler to match types of catch + variables and thrown objects. */ + +extern "C" void* +__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr) +{ + const type_info &catch_type = *(const type_info *)catch_type_r; + const type_info &throw_type = *(const type_info *)throw_type_r; + + if (catch_type == throw_type) + return objptr; + +#if 0 + printf ("We want to match a %s against a %s!\n", + throw_type.name (), catch_type.name ()); +#endif + + void *new_objptr = 0; + + if (const __user_type_info *p + = dynamic_cast <const __user_type_info *> (&throw_type)) + { + /* The 1 skips conversions to private bases. */ + new_objptr = p->dcast (catch_type, 1, objptr); + } + else if (const __pointer_type_info *fr = + dynamic_cast <const __pointer_type_info *> (&throw_type)) + { + const __pointer_type_info *to = + dynamic_cast <const __pointer_type_info *> (&catch_type); + + if (! to) + goto fail; + + const type_info *subfr = &fr->type, *subto = &to->type; + __attr_type_info::cv cvfrom, cvto; + + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subfr)) + { + cvfrom = at->attr; + subfr = &at->type; + } + else + cvfrom = __attr_type_info::NONE; + + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subto)) + { + cvto = at->attr; + subto = &at->type; + } + else + cvto = __attr_type_info::NONE; + + if (((cvfrom & __attr_type_info::CONST) + > (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + > (cvto & __attr_type_info::VOLATILE))) + goto fail; + + if (*subto == *subfr) + new_objptr = objptr; + else if (*subto == typeid (void) + && dynamic_cast <const __func_type_info *> (subfr) == 0) + new_objptr = objptr; + else if (const __user_type_info *p + = dynamic_cast <const __user_type_info *> (subfr)) + { + /* The 1 skips conversions to private bases. */ + new_objptr = p->dcast (*subto, 1, objptr); + } + else if (const __pointer_type_info *pfr + = dynamic_cast <const __pointer_type_info *> (subfr)) + { + // Multi-level pointer conversion. + + const __pointer_type_info *pto + = dynamic_cast <const __pointer_type_info *> (subto); + + if (! pto) + goto fail; + + bool constp = (cvto & __attr_type_info::CONST); + for (subto = &pto->type, subfr = &pfr->type; ; + subto = &pto->type, subfr = &pfr->type) + { + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subfr)) + { + cvfrom = at->attr; + subfr = &at->type; + } + else + cvfrom = __attr_type_info::NONE; + + if (const __attr_type_info *at + = dynamic_cast <const __attr_type_info *> (subto)) + { + cvto = at->attr; + subto = &at->type; + } + else + cvto = __attr_type_info::NONE; + + if (((cvfrom & __attr_type_info::CONST) + > (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + > (cvto & __attr_type_info::VOLATILE))) + goto fail; + + if (! constp + && (((cvfrom & __attr_type_info::CONST) + < (cvto & __attr_type_info::CONST)) + || ((cvfrom & __attr_type_info::VOLATILE) + < (cvto & __attr_type_info::VOLATILE)))) + goto fail; + + if (*subto == *subfr) + { + new_objptr = objptr; + break; + } + + pto = dynamic_cast <const __pointer_type_info *> (subto); + pfr = dynamic_cast <const __pointer_type_info *> (subfr); + if (! pto || ! pfr) + goto fail; + + if (! (cvto & __attr_type_info::CONST)) + constp = false; + } + } + } + fail: + +#if 0 + if (new_objptr) + printf ("It converts, delta is %d\n", new_objptr-objptr); +#endif + return new_objptr; +} + +/* Called from __cp_pop_exception. Is P the type_info node for a pointer + of some kind? */ + +bool +__is_pointer (void *p) +{ + const type_info *t = reinterpret_cast <const type_info *>(p); + const __pointer_type_info *pt = + dynamic_cast <const __pointer_type_info *> (t); + return pt != 0; +} + +extern "C" void +__rtti_ptr (void *addr, const char *n, const type_info *ti) +{ new (addr) __pointer_type_info (n, *ti); } + +extern "C" void +__rtti_attr (void *addr, const char *n, int attrval, const type_info *ti) +{ + new (addr) __attr_type_info + (n, static_cast <__attr_type_info::cv> (attrval), *ti); +} + +extern "C" void +__rtti_func (void *addr, const char *name) +{ new (addr) __func_type_info (name); } + +extern "C" void +__rtti_ptmf (void *addr, const char *name) +{ new (addr) __ptmf_type_info (name); } + +extern "C" void +__rtti_ptmd (void *addr, const char *name) +{ new (addr) __ptmd_type_info (name); } + +extern "C" void +__rtti_array (void *addr, const char *name) +{ new (addr) __array_type_info (name); } + +extern "C" void * +__dynamic_cast (const type_info& (*from)(void), const type_info& (*to)(void), + int require_public, void *address, + const type_info & (*sub)(void), void *subptr) +{ + return static_cast <const __user_type_info &> (from ()).dcast + (to (), require_public, address, &(sub ()), subptr); +} + +// type_info nodes and functions for the builtin types. The mangling here +// must match the mangling in gcc/cp/rtti.c. + +#define BUILTIN(mangled) \ +unsigned char __ti##mangled [sizeof (__builtin_type_info)] \ + __attribute__ ((aligned (__alignof__ (void *)))); \ +extern "C" const type_info &__tf##mangled (void) { \ + if ((*(void **) __ti##mangled) == 0) \ + new (__ti##mangled) __builtin_type_info (#mangled); \ + return *(type_info *)__ti##mangled; \ +} + +BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b); +BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f); +BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc); diff --git a/gnu/usr.bin/gcc/ginclude/ppc-asm.h b/gnu/usr.bin/gcc/ginclude/ppc-asm.h new file mode 100644 index 00000000000..4512d94352a --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/ppc-asm.h @@ -0,0 +1,170 @@ +/* PowerPC asm definitions for GNU C. */ +/* Under winnt, 1) gas supports the following as names and 2) in particular + defining "toc" breaks the FUNC_START macro as ".toc" becomes ".2" */ + +#if !defined(__WINNT__) +#define r0 0 +#define sp 1 +#define toc 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + +#define f0 0 +#define f1 1 +#define f2 2 +#define f3 3 +#define f4 4 +#define f5 5 +#define f6 6 +#define f7 7 +#define f8 8 +#define f9 9 +#define f10 10 +#define f11 11 +#define f12 12 +#define f13 13 +#define f14 14 +#define f15 15 +#define f16 16 +#define f17 17 +#define f18 18 +#define f19 19 +#define f20 20 +#define f21 21 +#define f22 22 +#define f23 23 +#define f24 24 +#define f25 25 +#define f26 26 +#define f27 27 +#define f28 28 +#define f29 29 +#define f30 30 +#define f31 31 +#endif + +/* + * Macros to glue together two tokens. + */ + +#ifdef __STDC__ +#define XGLUE(a,b) a##b +#else +#define XGLUE(a,b) a/**/b +#endif + +#define GLUE(a,b) XGLUE(a,b) + +/* + * Macros to begin and end a function written in assembler. If -mcall-aixdesc + * or -mcall-nt, create a function descriptor with the given name, and create + * the real function with one or two leading periods respectively. + */ + +#ifdef _RELOCATABLE +#define DESC_SECTION ".got2" +#else +#define DESC_SECTION ".got1" +#endif + +#if defined(_CALL_AIXDESC) +#define FUNC_NAME(name) GLUE(.,name) +#define FUNC_START(name) \ + .section DESC_SECTION,"aw"; \ +name: \ + .long GLUE(.,name); \ + .long _GLOBAL_OFFSET_TABLE_; \ + .long 0; \ + .previous; \ + .type GLUE(.,name),@function; \ + .globl name; \ + .globl GLUE(.,name); \ +GLUE(.,name): + +#define FUNC_END(name) \ +GLUE(.L,name): \ + .size GLUE(.,name),GLUE(.L,name)-GLUE(.,name) + +#elif defined(__WINNT__) +#define FUNC_NAME(name) GLUE(..,name) +#define FUNC_START(name) \ + .pdata; \ + .align 2; \ + .ualong GLUE(..,name),GLUE(name,.e),0,0,GLUE(..,name); \ + .reldata; \ +name: \ + .ualong GLUE(..,name),.toc; \ + .section .text; \ + .globl name; \ + .globl GLUE(..,name); \ +GLUE(..,name): + +#define FUNC_END(name) \ +GLUE(name,.e): ; \ +GLUE(FE_MOT_RESVD..,name): + +#elif defined(_CALL_NT) +#define FUNC_NAME(name) GLUE(..,name) +#define FUNC_START(name) \ + .section DESC_SECTION,"aw"; \ +name: \ + .long GLUE(..,name); \ + .long _GLOBAL_OFFSET_TABLE_; \ + .previous; \ + .type GLUE(..,name),@function; \ + .globl name; \ + .globl GLUE(..,name); \ +GLUE(..,name): + +#define FUNC_END(name) \ +GLUE(.L,name): \ + .size GLUE(..,name),GLUE(.L,name)-GLUE(..,name) + +#else +#define FUNC_NAME(name) name +#define FUNC_START(name) \ + .type name,@function; \ + .globl name; \ +name: + +#define FUNC_END(name) \ +GLUE(.L,name): \ + .size name,GLUE(.L,name)-name +#endif + diff --git a/gnu/usr.bin/gcc/ginclude/va-arc.h b/gnu/usr.bin/gcc/ginclude/va-arc.h new file mode 100644 index 00000000000..a718ad6245d --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/va-arc.h @@ -0,0 +1,111 @@ +/* stdarg/varargs support for the ARC */ + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef void * __gnuc_va_list; +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) + +/* In GCC version 2, we want an ellipsis at the end of the declaration + of the argument list. GCC version 1 can't parse it. */ + +#if __GNUC__ > 1 +#define __va_ellipsis ... +#else +#define __va_ellipsis +#endif + +/* See arc_setup_incoming_varargs for reasons for the oddity in va_start. */ +#ifdef _STDARG_H +#define va_start(AP, LASTARG) \ +(AP = (__gnuc_va_list) ((int *) __builtin_next_arg (LASTARG) \ + + (__builtin_args_info (0) < 8 \ + ? (__builtin_args_info (0) & 1) \ + : 0))) +#else +#define va_alist __builtin_va_alist +#define va_dcl int __builtin_va_alist; __va_ellipsis +#define va_start(AP) \ +(AP = (__gnuc_va_list) ((int *) &__builtin_va_alist \ + + (__builtin_args_info (0) < 8 \ + ? (__builtin_args_info (0) & 1) \ + : 0))) +#endif + +#ifndef va_end +void va_end (__gnuc_va_list); /* Defined in libgcc.a */ + +/* Values returned by __builtin_classify_type. */ + +enum __va_type_classes { + __no_type_class = -1, + __void_type_class, + __integer_type_class, + __char_type_class, + __enumeral_type_class, + __boolean_type_class, + __pointer_type_class, + __reference_type_class, + __offset_type_class, + __real_type_class, + __complex_type_class, + __function_type_class, + __method_type_class, + __record_type_class, + __union_type_class, + __array_type_class, + __string_type_class, + __set_type_class, + __file_type_class, + __lang_type_class +}; + +#endif +#define va_end(AP) ((void)0) + +/* Avoid errors if compiling GCC v2 with GCC v1. */ +#if __GNUC__ == 1 +#define __extension__ +#endif + +/* All aggregates are passed by reference. All scalar types larger than 8 + bytes are passed by reference. */ +/* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. + The casts to char * avoid warnings about invalid pointer arithmetic. */ + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +#ifdef __big_endian__ +#define va_arg(AP,TYPE) \ +__extension__ \ +(*({((__builtin_classify_type (*(TYPE*) 0) >= __record_type_class \ + || __va_rounded_size (TYPE) > 8) \ + ? ((AP) = (char *)(AP) + __va_rounded_size (TYPE *), \ + *(TYPE **) (void *) ((char *)(AP) - __va_rounded_size (TYPE *))) \ + : ((TYPE *) (void *) \ + (AP = (void *) ((__alignof__ (TYPE) > 4 \ + ? ((int) AP + 8 - 1) & -8 \ + : (int) AP) \ + + __va_rounded_size (TYPE))) - 1));})) +#else +#define va_arg(AP,TYPE) \ +__extension__ \ +(*({((__builtin_classify_type (*(TYPE*) 0) >= __record_type_class \ + || __va_rounded_size (TYPE) > 8) \ + ? ((AP) = (char *)(AP) + __va_rounded_size (TYPE *), \ + *(TYPE **) (void *) ((char *)(AP) - __va_rounded_size (TYPE *))) \ + : ((AP = (void *) ((__alignof__ (TYPE) > 4 \ + ? ((int) AP + 8 - 1) & -8 \ + : (int) AP) \ + + __va_rounded_size (TYPE))), \ + (TYPE *) (void *) (AP - __va_rounded_size (TYPE))));})) +#endif + +#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff --git a/gnu/usr.bin/gcc/ginclude/va-m32r.h b/gnu/usr.bin/gcc/ginclude/va-m32r.h new file mode 100644 index 00000000000..4ef0ad8267a --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/va-m32r.h @@ -0,0 +1,86 @@ +/* GNU C stdarg/varargs support for the M32R */ + +/* Define __gnuc_va_list. */ +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef void *__gnuc_va_list; +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) + +/* Common code for va_start for both varargs and stdarg. */ + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +#ifdef _STDARG_H /* stdarg.h support */ + +/* Calling __builtin_next_arg gives the proper error message if LASTARG is + not indeed the last argument. */ +#define va_start(AP, LASTARG) \ + (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG))) + +#else /* varargs.h support */ + +#define va_alist __builtin_va_alist +/* The ... causes current_function_varargs to be set in cc1. */ +#define va_dcl int __builtin_va_alist; ... +#define va_start(AP) AP=(char *) &__builtin_va_alist + +#endif /* _STDARG_H */ + +/* Nothing needs to be done to end varargs/stdarg processing */ +#define va_end(AP) ((void) 0) + +/* Values returned by __builtin_classify_type. */ +enum __type_class +{ + __no_type_class = -1, + __void_type_class, + __integer_type_class, + __char_type_class, + __enumeral_type_class, + __boolean_type_class, + __pointer_type_class, + __reference_type_class, + __offset_type_class, + __real_type_class, + __complex_type_class, + __function_type_class, + __method_type_class, + __record_type_class, + __union_type_class, + __array_type_class, + __string_type_class, + __set_type_class, + __file_type_class, + __lang_type_class +}; + +/* Return whether a type is passed by reference. */ +#define __va_by_reference_p(TYPE) (sizeof (TYPE) > 8) + +#define va_arg(AP,TYPE) \ +__extension__ (*({ \ + register TYPE *__ptr; \ + \ + if (__va_by_reference_p (TYPE)) \ + { \ + __ptr = *(TYPE **)(void *) (AP); \ + (AP) = (__gnuc_va_list) ((char *) (AP) + sizeof (void *)); \ + } \ + else \ + { \ + __ptr = (TYPE *)(void *) \ + ((char *) (AP) + (sizeof (TYPE) < __va_rounded_size (char) \ + ? __va_rounded_size (TYPE) - sizeof (TYPE) \ + : 0)); \ + (AP) = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)); \ + } \ + \ + __ptr; \ +})) + +#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff --git a/gnu/usr.bin/gcc/ginclude/va-mn10200.h b/gnu/usr.bin/gcc/ginclude/va-mn10200.h new file mode 100644 index 00000000000..b458b56e0be --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/va-mn10200.h @@ -0,0 +1,37 @@ +/* CYGNUS LOCAL entire file/law */ +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef void *__gnuc_va_list; +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) +#define __gnuc_va_start(AP) (AP = (__gnuc_va_list)__builtin_saveregs()) +#define __va_ellipsis ... + +#ifdef _STDARG_H +#define va_start(AP, LASTARG) \ + (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG))) +#else +#define va_alist __builtin_va_alist +#define va_dcl int __builtin_va_alist; __va_ellipsis +#define va_start(AP) AP=(char *) &__builtin_va_alist +#endif + +/* Now stuff common to both varargs & stdarg implementations. */ +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#undef va_end +void va_end (__gnuc_va_list); +#define va_end(AP) ((void)0) +#define va_arg(AP, TYPE) \ + (sizeof (TYPE) > 8 \ + ? (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (char *)),\ + **((TYPE **) (void *) ((char *) (AP) - __va_rounded_size (char *))))\ + : (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))) +#endif +/* END CYGNUS LOCAL */ diff --git a/gnu/usr.bin/gcc/ginclude/va-mn10300.h b/gnu/usr.bin/gcc/ginclude/va-mn10300.h new file mode 100644 index 00000000000..e156ccf5939 --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/va-mn10300.h @@ -0,0 +1,35 @@ +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef void *__gnuc_va_list; +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) +#define __gnuc_va_start(AP) (AP = (__gnuc_va_list)__builtin_saveregs()) +#define __va_ellipsis ... + +#ifdef _STDARG_H +#define va_start(AP, LASTARG) \ + (__builtin_next_arg (LASTARG), __gnuc_va_start (AP)) +#else +#define va_alist __builtin_va_alist +#define va_dcl int __builtin_va_alist; __va_ellipsis +#define va_start(AP) AP=(char *) &__builtin_va_alist +#endif + +/* Now stuff common to both varargs & stdarg implementations. */ +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#undef va_end +void va_end (__gnuc_va_list); +#define va_end(AP) ((void)0) +#define va_arg(AP, TYPE) \ + (sizeof (TYPE) > 8 \ + ? (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (char *)),\ + **((TYPE **) (void *) ((char *) (AP) - __va_rounded_size (char *))))\ + : (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))) +#endif diff --git a/gnu/usr.bin/gcc/ginclude/va-sh.h b/gnu/usr.bin/gcc/ginclude/va-sh.h new file mode 100644 index 00000000000..f1671c7b0b6 --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/va-sh.h @@ -0,0 +1,199 @@ +/* This is just like the default gvarargs.h + except for differences described below. */ + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST + +#ifdef __SH3E__ + +typedef long __va_greg; +typedef double __va_freg; + +typedef struct { + __va_greg * __va_next_o; /* next available register */ + __va_greg * __va_next_o_limit; /* past last available register */ + __va_freg * __va_next_fp; /* next available fp register */ + __va_freg * __va_next_fp_limit; /* last available fp register */ + __va_greg * __va_next_stack; /* next extended word on stack */ +} __gnuc_va_list; + +#else /* ! SH3E */ + +typedef void *__gnuc_va_list; + +#endif /* ! SH3E */ + +#endif /* __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) + +#ifdef _STDARG_H + +#ifdef __SH3E__ + +#define va_start(AP, LASTARG) \ +__extension__ \ + ({ \ + AP.__va_next_fp = (__va_freg *) __builtin_saveregs (); \ + AP.__va_next_fp_limit = (AP.__va_next_fp + \ + (__builtin_args_info (1) < 8 ? 8 - __builtin_args_info (1) : 0)); \ + AP.__va_next_o = (__va_greg *) AP.__va_next_fp_limit; \ + AP.__va_next_o_limit = (AP.__va_next_o + \ + (__builtin_args_info (0) < 4 ? 4 - __builtin_args_info (0) : 0)); \ + AP.__va_next_stack = (__va_greg *) __builtin_next_arg (LASTARG); \ + }) + +#else /* ! SH3E */ + +#define va_start(AP, LASTARG) \ + (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG))) + +#endif /* ! SH3E */ + +#else /* _VARARGS_H */ + +#define va_alist __builtin_va_alist +#define va_dcl int __builtin_va_alist;... + +#ifdef __SH3E__ + +#define va_start(AP) \ +__extension__ \ + ({ \ + AP.__va_next_fp = (__va_freg *) __builtin_saveregs (); \ + AP.__va_next_fp_limit = (AP.__va_next_fp + \ + (__builtin_args_info (1) < 8 ? 8 - __builtin_args_info (1) : 0)); \ + AP.__va_next_o = (__va_greg *) AP.__va_next_fp_limit; \ + AP.__va_next_o_limit = (AP.__va_next_o + \ + (__builtin_args_info (0) < 4 ? 4 - __builtin_args_info (0) : 0)); \ + AP.__va_next_stack = (__va_greg *) __builtin_next_arg (__builtin_va_alist) \ + - (__builtin_args_info (0) >= 4 || __builtin_args_info (1) >= 8 ? 1 : 0); \ + }) + +#else /* ! SH3E */ + +#define va_start(AP) AP=(char *) &__builtin_va_alist + +#endif /* ! SH3E */ + +#endif /* _STDARG */ + +#ifndef va_end +void va_end (__gnuc_va_list); /* Defined in libgcc.a */ + +/* Values returned by __builtin_classify_type. */ + +enum __va_type_classes { + __no_type_class = -1, + __void_type_class, + __integer_type_class, + __char_type_class, + __enumeral_type_class, + __boolean_type_class, + __pointer_type_class, + __reference_type_class, + __offset_type_class, + __real_type_class, + __complex_type_class, + __function_type_class, + __method_type_class, + __record_type_class, + __union_type_class, + __array_type_class, + __string_type_class, + __set_type_class, + __file_type_class, + __lang_type_class +}; + +#endif +#define va_end(pvar) ((void)0) + +#ifdef __LITTLE_ENDIAN__ +#define __LITTLE_ENDIAN_P 1 +#else +#define __LITTLE_ENDIAN_P 0 +#endif + +#define __SCALAR_TYPE(TYPE) \ + ((TYPE) == __integer_type_class \ + || (TYPE) == __char_type_class \ + || (TYPE) == __enumeral_type_class) + +/* RECORD_TYPE args passed using the C calling convention are + passed by invisible reference. ??? RECORD_TYPE args passed + in the stack are made to be word-aligned; for an aggregate that is + not word-aligned, we advance the pointer to the first non-reg slot. */ + + /* When this is a smaller-than-int integer, using + auto-increment in the promoted (SImode) is fastest; + however, there is no way to express that is C. Therefore, + we use an asm. + We want the MEM_IN_STRUCT_P bit set in the emitted RTL, therefore we + use unions even when it would otherwise be unnecessary. */ + +#define __va_arg_sh1(AP, TYPE) __extension__ \ +__extension__ \ +({(sizeof (TYPE) == 1 \ + ? ({union {TYPE t; char c;} __t; \ + asm("" \ + : "=r" (__t.c) \ + : "0" ((((union { int i, j; } *) (AP))++)->i)); \ + __t.t;}) \ + : sizeof (TYPE) == 2 \ + ? ({union {TYPE t; short s;} __t; \ + asm("" \ + : "=r" (__t.s) \ + : "0" ((((union { int i, j; } *) (AP))++)->i)); \ + __t.t;}) \ + : sizeof (TYPE) >= 4 || __LITTLE_ENDIAN_P \ + ? (((union { TYPE t; int i;} *) (AP))++)->t \ + : ((union {TYPE t;TYPE u;}*) ((char *)++(int *)(AP) - sizeof (TYPE)))->t);}) + +#ifdef __SH3E__ + +#define __PASS_AS_FLOAT(TYPE_CLASS,SIZE) \ + (TYPE_CLASS == __real_type_class && SIZE == 4) + +#define va_arg(pvar,TYPE) \ +__extension__ \ +({int __type = __builtin_classify_type (* (TYPE *) 0); \ + void * __result_p; \ + if (__PASS_AS_FLOAT (__type, sizeof(TYPE))) \ + { \ + if (pvar.__va_next_fp < pvar.__va_next_fp_limit) \ + { \ + __result_p = &pvar.__va_next_fp; \ + } \ + else \ + __result_p = &pvar.__va_next_stack; \ + } \ + else \ + { \ + if (pvar.__va_next_o + ((sizeof (TYPE) + 3) / 4) \ + <= pvar.__va_next_o_limit) \ + __result_p = &pvar.__va_next_o; \ + else \ + { \ + if (sizeof (TYPE) > 4) \ + pvar.__va_next_o = pvar.__va_next_o_limit; \ + \ + __result_p = &pvar.__va_next_stack; \ + } \ + } \ + __va_arg_sh1(*(void **)__result_p, TYPE);}) + +#else /* ! SH3E */ + +#define va_arg(AP, TYPE) __va_arg_sh1((AP), TYPE) + +#endif /* SH3E */ + +/* Copy __gnuc_va_list into another variable of this type. */ +#define __va_copy(dest, src) (dest) = (src) + +#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff --git a/gnu/usr.bin/gcc/ginclude/va-v850.h b/gnu/usr.bin/gcc/ginclude/va-v850.h new file mode 100644 index 00000000000..96da6d5a3de --- /dev/null +++ b/gnu/usr.bin/gcc/ginclude/va-v850.h @@ -0,0 +1,34 @@ +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +typedef void *__gnuc_va_list; +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) + +#ifdef _STDARG_H +#define va_start(AP, LASTARG) \ + (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG))) +#else +#define __va_ellipsis ... +#define va_alist __builtin_va_alist +#define va_dcl int __builtin_va_alist; __va_ellipsis +#define va_start(AP) AP=(char *) &__builtin_va_alist +#endif + +/* Now stuff common to both varargs & stdarg implementations. */ +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#undef va_end +void va_end (__gnuc_va_list); +#define va_end(AP) ((void)0) +#define va_arg(AP, TYPE) \ + (sizeof (TYPE) > 8 \ + ? (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (char *)),\ + **((TYPE **) (void *) ((char *) (AP) - __va_rounded_size (char *))))\ + : (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))) +#endif diff --git a/gnu/usr.bin/gcc/objc/Make-lang.in b/gnu/usr.bin/gcc/objc/Make-lang.in new file mode 100644 index 00000000000..1170d5a1439 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/Make-lang.in @@ -0,0 +1,308 @@ +# Top level makefile fragment for GNU Objective-C +# Copyright (C) 1997 Free Software Foundation, Inc. + +#This file is part of GNU CC. + +#GNU CC is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 2, or (at your option) +#any later version. + +#GNU CC is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with GNU CC; see the file COPYING. If not, write to +#the Free Software Foundation, 59 Temple Place - Suite 330, +#Boston, MA 02111-1307, USA. + +# This file provides the language dependent support in the main Makefile. +# Each language makefile fragment must provide the following targets: +# +# foo.all.build, foo.all.cross, foo.start.encap, foo.rest.encap, +# foo.info, foo.dvi, +# foo.install-normal, foo.install-common, foo.install-info, foo.install-man, +# foo.uninstall, foo.distdir, +# foo.mostlyclean, foo.clean, foo.distclean, foo.extraclean, +# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4 +# +# where `foo' is the name of the language. +# +# It should also provide rules for: +# +# - making any compiler driver (eg: g++) +# - the compiler proper (eg: cc1plus) +# - define the names for selecting the language in LANGUAGES. +# +# Extra flags to pass to recursive makes. +OBJC_FLAGS_TO_PASS = \ + "OBJC_FOR_BUILD=$(OBJC_FOR_BUILD)" \ + "OBJCFLAGS=$(OBJCFLAGS)" \ + "OBJC_FOR_TARGET=$(OBJC_FOR_TARGET)" \ + +# Actual names to use when installing a native compiler. +#OBJC_INSTALL_NAME = `t='$(program_transform_name)'; echo c++ | sed $$t` + +# Actual names to use when installing a cross-compiler. +#OBJC_CROSS_NAME = `t='$(program_transform_cross_name)'; echo c++ | sed $$t` + +# +# Define the names for selecting Objective-C in LANGUAGES. +OBJC objc: cc1obj objc-runtime +OBJECTIVE-C objective-c: cc1obj objc-runtime + +# Tell GNU make to ignore these if they exist. +.PHONY: objective-c objc ObjC + +# The Objective C thread file +OBJC_THREAD_FILE=thr-$(GCC_THREAD_FILE) + +# Language-specific object files for Objective C. +OBJC_OBJS = objc-parse.o objc-act.o $(C_AND_OBJC_OBJS) + +cc1obj: $(P) $(OBJC_OBJS) $(OBJS) $(BC_OBJS) $(LIBDEPS) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(OBJC_OBJS) $(OBJS) \ + $(BC_OBJS) $(LIBS) + +# Objective C language specific files. + +objc-parse.o : $(srcdir)/objc/objc-parse.c \ + $(CONFIG_H) $(TREE_H) \ + $(srcdir)/c-lex.h $(srcdir)/c-tree.h $(srcdir)/input.h \ + $(srcdir)/flags.h $(srcdir)/output.h $(srcdir)/objc/objc-act.h + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -I$(srcdir)/objc \ + -c $(srcdir)/objc/objc-parse.c + +$(srcdir)/objc/objc-parse.c : $(srcdir)/objc/objc-parse.y + cd $(srcdir)/objc; \ + $(BISON) $(BISONFLAGS) objc-parse.y -o objc-parse.c + +$(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in + echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y + sed -e "/^ifc$$/,/^end ifc$$/d" \ + -e "/^ifobjc$$/d" -e "/^end ifobjc$$/d" \ + $(srcdir)/c-parse.in >>tmp-objc-prs.y + $(srcdir)/move-if-change tmp-objc-prs.y $(srcdir)/objc/objc-parse.y + +objc-act.o : $(srcdir)/objc/objc-act.c \ + $(CONFIG_H) $(TREE_H) $(RTL_H) \ + $(srcdir)/c-tree.h $(srcdir)/c-lex.h \ + $(srcdir)/flags.h $(srcdir)/objc/objc-act.h $(srcdir)/input.h \ + $(srcdir)/function.h $(srcdir)/output.h $(srcdir)/c-parse.h + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -I$(srcdir)/objc \ + -c $(srcdir)/objc/objc-act.c + +objc-runtime: objc-headers libobjc.a + +# copy objc header files into build directory +objc-headers: stmp-fixinc + if [ -d include ]; then true; else mkdir include; fi + cd objc; \ + if [ -f Makefile ]; then \ + $(MAKE) copy-headers \ + tooldir=$(tooldir) \ + AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" \ + GCC_FOR_TARGET="../xgcc -B../" \ + GCC_CFLAGS="$(GCC_CFLAGS)" incinstalldir=../include; \ + fi + touch objc-headers + +# Objective C runtime library specific files. + +OBJC_O = objc/hash.o objc/sarray.o \ + objc/class.o objc/sendmsg.o \ + objc/init.o objc/archive.o \ + objc/encoding.o objc/selector.o \ + objc/objects.o objc/misc.o \ + objc/NXConstStr.o objc/Object.o \ + objc/Protocol.o objc/nil_method.o \ + objc/thr.o objc/linking.o \ + objc/$(OBJC_THREAD_FILE).o + +objc/hash.o: $(srcdir)/objc/hash.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/hash.c -o $@ +objc/sarray.o: $(srcdir)/objc/sarray.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/sarray.c -o $@ +objc/class.o: $(srcdir)/objc/class.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/class.c -o $@ +objc/sendmsg.o: $(srcdir)/objc/sendmsg.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -Iobjc \ + -c $(srcdir)/objc/sendmsg.c -o $@ +objc/init.o: $(srcdir)/objc/init.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/init.c -o $@ +objc/archive.o: $(srcdir)/objc/archive.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/archive.c -o $@ +objc/encoding.o: $(srcdir)/objc/encoding.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/encoding.c -o $@ +objc/selector.o: $(srcdir)/objc/selector.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/selector.c -o $@ +objc/objects.o: $(srcdir)/objc/objects.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/objects.c -o $@ +objc/misc.o: $(srcdir)/objc/misc.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/misc.c -o $@ +objc/NXConstStr.o: $(srcdir)/objc/NXConstStr.m $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -fgnu-runtime -c $(srcdir)/objc/NXConstStr.m -o $@ +objc/Object.o: $(srcdir)/objc/Object.m $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -fgnu-runtime -c $(srcdir)/objc/Object.m -o $@ +objc/Protocol.o: $(srcdir)/objc/Protocol.m $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -fgnu-runtime -c $(srcdir)/objc/Protocol.m -o $@ +objc/thr.o: $(srcdir)/objc/thr.h $(srcdir)/objc/thr.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/thr.c -o $@ +objc/$(OBJC_THREAD_FILE).o: $(srcdir)/objc/$(OBJC_THREAD_FILE).c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/$(OBJC_THREAD_FILE).c -o $@ +objc/nil_method.o: $(srcdir)/objc/nil_method.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/nil_method.c -o $@ +objc/linking.o: $(srcdir)/objc/linking.m $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -fgnu-runtime -c $(srcdir)/objc/linking.m -o $@ + +objc/libobjc_entry.o: $(srcdir)/objc/libobjc_entry.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/objc/libobjc_entry.c -o $@ + +# Build the Objective C runtime library. +libobjc.a: cc1obj specs stmp-int-hdrs libgcc2.ready \ + $(USE_COLLECT2) $(EXTRA_PARTS) objc/runtime-info.h $(OBJC_O) + -rm -f libobjc.a + $(AR) $(AR_FLAGS) libobjc.a $(OBJC_O) + -if $(RANLIB_TEST) ; then $(RANLIB) libobjc.a; else true; fi + +libobjc_s.a: libobjc.a + mv libobjc.a libobjc_s.a + +# Create a relocatable DLL +libobjc.dll: libobjc_s.a objc/libobjc_entry.o + $(GCC_FOR_TARGET) -mdll -Wl,--base-file -Wl,libobjc.base \ + -o libobjc.dll libobjc_s.a \ + objc/libobjc_entry.o -lkernel32 + $(DLLTOOL) --dllname libobjc.dll --def $(srcdir)/objc/libobjc.def \ + --base-file libobjc.base --output-exp libobjc.exp + $(GCC_FOR_TARGET) -mdll -Wl,--base-file libobjc.base libobjc.exp \ + -o libobjc.dll libobjc_s.a \ + objc/libobjc_entry.o -lkernel32 + $(DLLTOOL) --dllname libobjc.dll --def $(srcdir)/objc/libobjc.def \ + --base-file libobjc.base --output-exp libobjc.exp + $(GCC_FOR_TARGET) libobjc.exp -mdll \ + -o libobjc.dll libobjc_s.a \ + objc/libobjc_entry.o -lkernel32 + $(DLLTOOL) --dllname libobjc.dll --def $(srcdir)/objc/libobjc.def \ + --output-lib libobjc.a + +# Platform generated information needed by ObjC runtime +objc/runtime-info.h: cc1obj + echo "" > emptyfile + echo "/* This file is automatically generated */" >$@ + ./cc1obj -print-objc-runtime-info emptyfile >>$@ + +# +# Build hooks: + +objc.all.build: +objc.all.cross: +objc.start.encap: +objc.rest.encap: + +objc.info: +objc.dvi: + +# +# Install hooks: +# cc1obj is installed elsewhere as part of $(COMPILERS). + +objc.install-normal: installdirs + -if [ -f libobjc.a ] ; then \ + rm -f $(libsubdir)/libobjc.a; \ + $(INSTALL_DATA) libobjc.a $(libsubdir)/libobjc.a; \ + if $(RANLIB_TEST) ; then \ + (cd $(libsubdir); $(RANLIB) libobjc.a); else true; fi; \ + chmod a-x $(libsubdir)/libobjc.a; \ + else true; fi + -if [ -f libobjc_s.a ] ; then \ + rm -f $(libsubdir)/libobjc_s.a; \ + $(INSTALL_DATA) libobjc_s.a $(libsubdir)/libobjc_s.a; \ + if $(RANLIB_TEST) ; then \ + (cd $(libsubdir); $(RANLIB) libobjc_s.a); else true; fi; \ + chmod a-x $(libsubdir)/libobjc_s.a; \ + else true; fi + -if [ -f libobjc.dll ] ; then \ + rm -f $(bindir)/libobjc.dll; \ + $(INSTALL_DATA) libobjc.dll $(bindir)/libobjc.dll; \ + else true; fi + +objc.install-common: + +objc.install-info: + +objc.install-man: + +objc.uninstall: +# +# Clean hooks: +# A lot of the ancillary files are deleted by the main makefile. +# We just have to delete files specific to us. +objc.mostlyclean: + -rm -f tmp-objc-prs.y + -rm -f objc/*$(objext) objc/xforward objc/fflags + -rm -f objc/runtime-info.h + -rm -f libobjc.a libobjc_s.a libobjc.dll + -rm -f libobjc.base libobjc.exp +objc.clean: objc.mostlyclean + -rm -rf objc-headers +objc.distclean: + -rm -f objc/Makefile objc/Make-host objc/Make-target + -rm -f objc/config.status objc/config.cache + -rm -f objc-parse.output +objc.extraclean: +objc.maintainer-clean: + -rm -f objc/objc-parse.y + -rm -f objc/objc-parse.c objc/objc-parse.output + +# +# Stage hooks: + +objc.stage1: + -mv objc/*$(objext) stage1/objc + -mv cc1obj$(exeext) stage1 + -mv libobjc.a stage1 +objc.stage2: + -mv objc/*$(objext) stage2/objc + -mv cc1obj$(exeext) stage2 + -mv libobjc.a stage2 +objc.stage3: + -mv objc/*$(objext) stage3/objc + -mv cc1obj$(exeext) stage3 + -mv libobjc.a stage3 +objc.stage4: + -mv objc/*$(objext) stage4/objc + -mv cc1obj$(exeext) stage4 + -mv libobjc.a stage4 + +# +# Maintenance hooks: + +# This target creates the files that can be rebuilt, but go in the +# distribution anyway. It then copies the files to the distdir directory. +objc.distdir: + mkdir tmp/objc + cd objc ; $(MAKE) $(FLAGS_TO_PASS) objc-parse.c + cd objc; \ + for file in *[0-9a-zA-Z+]; do \ + ln $$file ../tmp/objc >/dev/null 2>&1 || cp $$file ../tmp/objc; \ + done diff --git a/gnu/usr.bin/gcc/objc/Makefile.in b/gnu/usr.bin/gcc/objc/Makefile.in new file mode 100644 index 00000000000..9d521f54cdc --- /dev/null +++ b/gnu/usr.bin/gcc/objc/Makefile.in @@ -0,0 +1,91 @@ +# GNU Objective C Runtime Makefile +# Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. +# +# This file is part of GNU CC. +# +# GNU CC is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2, or (at your option) any later version. +# +# GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# GNU CC; see the file COPYING. If not, write to the Free Software +# Foundation, 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# This makefile is run by the parent dir's makefile. +# thisdir1=`pwd`; \ +# srcdir1=`cd $(srcdir); pwd`; \ +# cd objc; \ +# $(MAKE) $(MAKEFLAGS) -f $$srcdir1/objc/Makefile libobjc.a \ +# srcdir=$$srcdir1 tooldir=$(tooldir) AR="$(AR)" AR_FLAGS="$(AR_FLAGS)" \ +# GCC_FOR_TARGET="$$thisdir1/xgcc -B$$thisdir1/" \ +# GCC_CFLAGS="$(GCC_CFLAGS)" incinstalldir=$$thisdir1/include +# OBJC_THREAD_FILE="$(OBJC_THREAD_FILE)" +# Two targets are used by ../Makefile: `all' and `mostlyclean'. + +SHELL=/bin/sh + +.SUFFIXES: .m + +OPTIMIZE= -O + +srcdir = . +VPATH = $(srcdir) + +AR = ar +AR_FLAGS = rc + +# Define this as & to perform parallel make on a Sequent. +# Note that this has some bugs, and it seems currently necessary +# to compile all the gen* files first by hand to avoid erroneous results. +P = + +# Definition of `all' is here so that new rules inserted by sed +# do not specify the default target. +all: all.indirect + +# sed inserts variable overrides after the following line. +####target overrides +####host overrides +####cross overrides +####build overrides +# + +OBJC_H = hash.h objc-list.h sarray.h objc.h objc-api.h \ + NXConstStr.h Object.h Protocol.h encoding.h typedstream.h thr.h + +# Now figure out from those variables how to compile and link. +all.indirect: Makefile compiler objc-runtime + +compiler: + cd ..; $(MAKE) cc1obj + +objc-runtime: + cd ..; $(MAKE) libobjc.a + +# copy objc headers to installation include directory +copy-headers: + -rm -fr $(incinstalldir)/objc + -mkdir $(incinstalldir)/objc + for file in $(OBJC_H); do \ + realfile=$(srcdir)/$${file}; \ + cp $${realfile} $(incinstalldir)/objc; \ + chmod a+r $(incinstalldir)/objc/$${file}; \ + done + +Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure + cd ..; $(SHELL) config.status + +mostlyclean: + -rm -f *.o libobjc.a xforward fflags +clean: mostlyclean +distclean: mostlyclean +extraclean: mostlyclean + +# For Sun VPATH. + diff --git a/gnu/usr.bin/gcc/objc/README.threads b/gnu/usr.bin/gcc/objc/README.threads new file mode 100644 index 00000000000..2cafb4ea7cf --- /dev/null +++ b/gnu/usr.bin/gcc/objc/README.threads @@ -0,0 +1,50 @@ +============================================================================== +README - Wed Nov 29 15:16:24 EST 1995 +------------------------------------------------------------------------------ + +Limited documentation is available in the THREADS file. + +This version has been tested on Sun Solaris, SGI Irix, and Windows NT. +It should also work on any single threaded system. + +Thanks go to the following people for help test and debug the library: + + Scott Christley, scottc@ocbi.com + Andrew McCallum, mccallum@cs.rochester.edu + +galen +gchunt@cs.rochester.edu + +Any questions, bug reports, etc should be directed to: + +Scott Christley, scottc@ocbi.com + +Please do not bug Galen with email as he no longer supports the code. + +============================================================================== +Changes from prior releases (in revered chronological order): +------------------------------------------------------------------------------ + +* Fixed bug in copy part of sarray_realloc. I had an < which should + have been <=. (Bug report from Scott). + +------------------------------------------------------------------------------ + +* Support for DEC OSF/1 is definitely broken. My programs always + seg-fault when I link with libpthreads.a. + +* Thread id's are no longer int's, but are instead of type + _objc_thread_t which is typedef'ed from a void *. An invalid thread + id is denoted by NULL and not -1 as before. + +------------------------------------------------------------------------------ + +* Renamed thread-winnt.c to thread-win32.c to better reflect support + for the API on both Windows NT and Windows 95 platforms. + (Who knows, maybe even Win32s :-). + +* Fixed bugs in Win32 support as per report from Scott Christley. + +* Fixed bug in sarray_get as per report from Scott Christley. + + diff --git a/gnu/usr.bin/gcc/objc/THREADS b/gnu/usr.bin/gcc/objc/THREADS new file mode 100644 index 00000000000..9dfbbed97af --- /dev/null +++ b/gnu/usr.bin/gcc/objc/THREADS @@ -0,0 +1,374 @@ +This file describes in little detail the modifications to the +Objective-C runtime needed to make it thread safe. + +First off, kudos to Galen Hunt who is the author of this great work. + +If you have an comments or just want to know where to +send me money to express your undying gratitude for threading the +Objective-C runtime you can reach Galen at: + + gchunt@cs.rochester.edu + +Any questions, comments, bug reports, etc. should send email either to the +GCC bug account or to: + + Scott Christley <scottc@net-community.com> + +* Sarray Threading: + +The most critical component of the Objective-C runtime is the sparse array +structure (sarray). Sarrays store object selectors and implementations. +Following in the tradition of the Objective-C runtime, my threading +support assumes that fast message dispatching is far more important +than *ANY* and *ALL* other operations. The message dispatching thus +uses *NO* locks on any kind. In fact, if you look in sarray.h, you +will notice that the message dispatching has not been modified. +Instead, I have modified the sarray management functions so that all +updates to the sarray data structure can be made in parallel will +message dispatching. + +To support concurrent message dispatching, no dynamically allocated +sarray data structures are freed while more than one thread is +operational. Sarray data structures that are no longer in use are +kept in a linked list of garbage and are released whenever the program +is operating with a single thread. The programmer can also flush the +garbage list by calling sarray_remove_garbage when the programmer can +ensure that no message dispatching is taking place concurrently. The +amount of un-reclaimed sarray garbage should normally be extremely +small in a real program as sarray structures are freed only when using +the "poseAs" functionality and early in program initialization, which +normally occurs while the program is single threaded. + +****************************************************************************** +* Static Variables: + +The following variables are either statically or globally defined. This list +does not include variables which are internal to implementation dependent +versions of thread-*.c. + +The following threading designations are used: + SAFE : Implicitly thread safe. + SINGLE : Must only be used in single thread mode. + MUTEX : Protected by single global mutex objc_runtime_mutex. + UNUSED : Not used in the runtime. + +Variable Name: Usage: Defined: Also used in: +=========================== ====== ============ ===================== +__objc_class_hash MUTEX class.c +__objc_class_links_resolved UNUSED class.c runtime.h +__objc_class_number MUTEX class.c +__objc_dangling_categories UNUSED init.c +__objc_module_list MUTEX init.c +__objc_selector_array MUTEX selector.c +__objc_selector_hash MUTEX selector.c +__objc_selector_max_index MUTEX selector.c sendmsg.c runtime.h +__objc_selector_names MUTEX selector.c +__objc_thread_exit_status SAFE thread.c +__objc_uninstalled_dtable MUTEX sendmsg.c selector.c +_objc_load_callback SAFE init.c objc-api.h +_objc_lookup_class SAFE class.c objc-api.h +_objc_object_alloc SINGLE objects.c objc-api.h +_objc_object_copy SINGLE objects.c objc-api.h +_objc_object_dispose SINGLE objects.c objc-api.h +frwd_sel SAFE2 sendmsg.c +idxsize MUTEX sarray.c sendmsg.c sarray.h +initialize_sel SAFE2 sendmsg.c +narrays MUTEX sarray.c sendmsg.c sarray.h +nbuckets MUTEX sarray.c sendmsg.c sarray.h +nindices MUTEX sarray.c sarray.h +previous_constructors SAFE1 init.c +proto_class SAFE1 init.c +unclaimed_categories MUTEX init.c +unclaimed_proto_list MUTEX init.c +uninitialized_statics MUTEX init.c + +Notes: +1) Initialized once in unithread mode. +2) Initialized value will always be same, guaranteed by lock on selector + hash table. + + +****************************************************************************** +* Frontend/Backend design: + +The design of the Objective-C runtime thread and mutex functions utilizes a +frontend/backend implementation. + +The frontend, as characterized by the files thr.h and thr.c, is a set +of platform independent structures and functions which represent the +user interface. Objective-C programs should use these structures and +functions for their thread and mutex work if they wish to maintain a +high degree of portability across platforms. + +The backend is composed of a file with the necessary code to map the ObjC +thread and mutex to a platform specific implementation. For example, the +file thr-solaris.c contains the implementation for Solaris. When you +configure GCC, it attempts to pick an appropriate backend file for the +target platform; however, you can override this choice by assign the +OBJC_THREAD_FILE make variable to the basename of the backend file. This +is especially useful on platforms which have multiple thread libraries. +For example: + + make OBJC_THREAD_FILE=thr-posix + +would indicate that the generic posix backend file, thr-posix.c, should be +compiled with the ObjC runtime library. If your platform does not support +threads then you should specify the OBJC_THREAD_FILE=thr-single backend file +to compile the ObjC runtime library without thread or mutex support; note +that programs which rely upon the ObjC thread and mutex functions will +compile and link correctly but attempting to create a thread or mutex will +result in an error. + +It is questionable whether it is really necessary to have both a +frontend and backend function for all available functionality. On the +one hand, it provides a clear, consistent differentiation between what +is public and what is private with the downside of having the overhead +of multiple functions calls. For example, the function to have a thread +yield the processor is objc_thread_yield; in the current implementation +this produces a function call set: + +objc_thread_yield() -> __objc_thread_yield() -> system yield function + +This has two extra function calls over calling the platform specific function +explicitly, but the issue is whether only the overhead of a single function +is necessary. + +objc_thread_yield() -> system yield function + +This breaks the public/private dichotomy between the frontend/backend +for the sake of efficiency. It is possible to just use a preprocessor +define so as to eliminate the extra function call: + +#define objc_thread_yield() __objc_thread_yield() + +This has the undesirable effect that if objc_thread_yield is actually +turned into a function based upon future need; then ObjC programs which +access the thread functions would need to be recompiled versus just +being relinked. + +****************************************************************************** +* Threads: + +The thread system attempts to create multiple threads using whatever +operating system or library thread support is available. It does +assume that all system functions are thread safe. Notably this means +that the system implementation of malloc and free must be thread safe. +If a system has multiple processors, the threads are configured for +full parallel processing. + +* Backend initialization functions + +__objc_init_thread_system(void), int + Initialize the thread subsystem. Called once by __objc_exec_class. + Return -1 if error otherwise return 0. + +__objc_close_thread_system(void), int + Closes the thread subsystem, not currently guaranteed to be called. + Return -1 if error otherwise return 0. + +***** +* Frontend thread functions +* User programs should use these functions. + +objc_thread_detach(SEL selector, id object, id argument), objc_thread_t + Creates and detaches a new thread. The new thread starts by + sending the given selector with a single argument to the + given object. + +objc_thread_set_priority(int priority), int + Sets a thread's relative priority within the program. Valid + options are: + + OBJC_THREAD_INTERACTIVE_PRIORITY + OBJC_THREAD_BACKGROUND_PRIORITY + OBJC_THREAD_LOW_PRIORITY + +objc_thread_get_priority(void), int + Query a thread's priority. + +objc_thread_yield(void), void + Yields processor to another thread with equal or higher + priority. It is up to the system scheduler to determine if + the processor is taken or not. + +objc_thread_exit(void), int + Terminates a thread. If this is the last thread executing + then the program will terminate. + +objc_thread_id(void), int + Returns the current thread's id. + +objc_thread_set_data(void *value), int + Set a pointer to the thread's local storage. Local storage is + thread specific. + +objc_thread_get_data(void), void * + Returns the pointer to the thread's local storage. + +***** +* Backend thread functions +* User programs should *NOT* directly call these functions. + +__objc_thread_detach(void (*func)(void *arg), void *arg), objc_thread_t + Spawns a new thread executing func, called by objc_thread_detach. + Return NULL if error otherwise return thread id. + +__objc_thread_set_priority(int priority), int + Set the thread's priority, called by objc_thread_set_priority. + Return -1 if error otherwise return 0. + +__objc_thread_get_priority(void), int + Query a thread's priority, called by objc_thread_get_priority. + Return -1 if error otherwise return the priority. + +__objc_thread_yield(void), void + Yields the processor, called by objc_thread_yield. + +__objc_thread_exit(void), int + Terminates the thread, called by objc_thread_exit. + Return -1 if error otherwise function does not return. + +__objc_thread_id(void), objc_thread_t + Returns the current thread's id, called by objc_thread_id. + Return -1 if error otherwise return thread id. + +__objc_thread_set_data(void *value), int + Set pointer for thread local storage, called by objc_thread_set_data. + Returns -1 if error otherwise return 0. + +__objc_thread_get_data(void), void * + Returns the pointer to the thread's local storage. + Returns NULL if error, called by objc_thread_get_data. + + +****************************************************************************** +* Mutexes: + +Mutexes can be locked recursively. Each locked mutex remembers +its owner (by thread id) and how many times it has been locked. The +last unlock on a mutex removes the system lock and allows other +threads to access the mutex. + +***** +* Frontend mutex functions +* User programs should use these functions. + +objc_mutex_allocate(void), objc_mutex_t + Allocates a new mutex. Mutex is initially unlocked. + Return NULL if error otherwise return mutex pointer. + +objc_mutex_deallocate(objc_mutex_t mutex), int + Free a mutex. Before freeing the mutex, makes sure that no + one else is using it. + Return -1 if error otherwise return 0. + +objc_mutex_lock(objc_mutex_t mutex), int + Locks a mutex. As mentioned earlier, the same thread may call + this routine repeatedly. + Return -1 if error otherwise return 0. + +objc_mutex_trylock(objc_mutex_t mutex), int + Attempts to lock a mutex. If lock on mutex can be acquired + then function operates exactly as objc_mutex_lock. + Return -1 if failed to acquire lock otherwise return 0. + +objc_mutex_unlock(objc_mutex_t mutex), int + Unlocks the mutex by one level. Other threads may not acquire + the mutex until this thread has released all locks on it. + Return -1 if error otherwise return 0. + +***** +* Backend mutex functions +* User programs should *NOT* directly call these functions. + +__objc_mutex_allocate(objc_mutex_t mutex), int + Allocates a new mutex, called by objc_mutex_allocate. + Return -1 if error otherwise return 0. + +__objc_mutex_deallocate(objc_mutex_t mutex), int + Free a mutex, called by objc_mutex_deallocate. + Return -1 if error otherwise return 0. + +__objc_mutex_lock(objc_mutex_t mutex), int + Locks a mutex, called by objc_mutex_lock. + Return -1 if error otherwise return 0. + +__objc_mutex_trylock(objc_mutex_t mutex), int + Attempts to lock a mutex, called by objc_mutex_trylock. + Return -1 if failed to acquire lock or error otherwise return 0. + +__objc_mutex_unlock(objc_mutex_t mutex), int + Unlocks the mutex, called by objc_mutex_unlock. + Return -1 if error otherwise return 0. + +****************************************************************************** +* Condition Mutexes: + +Mutexes can be locked recursively. Each locked mutex remembers +its owner (by thread id) and how many times it has been locked. The +last unlock on a mutex removes the system lock and allows other +threads to access the mutex. + +* +* Frontend condition mutex functions +* User programs should use these functions. +* + +objc_condition_allocate(void), objc_condition_t + Allocate a condition mutex. + Return NULL if error otherwise return condition pointer. + +objc_condition_deallocate(objc_condition_t condition), int + Deallocate a condition. Note that this includes an implicit + condition_broadcast to insure that waiting threads have the + opportunity to wake. It is legal to dealloc a condition only + if no other thread is/will be using it. Does NOT check for + other threads waiting but just wakes them up. + Return -1 if error otherwise return 0. + +objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int + Wait on the condition unlocking the mutex until objc_condition_signal() + or objc_condition_broadcast() are called for the same condition. The + given mutex *must* have the depth 1 so that it can be unlocked + here, for someone else can lock it and signal/broadcast the condition. + The mutex is used to lock access to the shared data that make up the + "condition" predicate. + Return -1 if error otherwise return 0. + +objc_condition_broadcast(objc_condition_t condition), int + Wake up all threads waiting on this condition. It is recommended that + the called would lock the same mutex as the threads in + objc_condition_wait before changing the "condition predicate" + and make this call and unlock it right away after this call. + Return -1 if error otherwise return 0. + +objc_condition_signal(objc_condition_t condition), int + Wake up one thread waiting on this condition. + Return -1 if error otherwise return 0. + +* +* Backend condition mutex functions +* User programs should *NOT* directly call these functions. +* + +__objc_condition_allocate(objc_condition_t condition), int + Allocate a condition mutex, called by objc_condition_allocate. + Return -1 if error otherwise return 0. + +__objc_condition_deallocate(objc_condition_t condition), int + Deallocate a condition, called by objc_condition_deallocate. + Return -1 if error otherwise return 0. + +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int + Wait on the condition, called by objc_condition_wait. + Return -1 if error otherwise return 0 when condition is met. + +__objc_condition_broadcast(objc_condition_t condition), int + Wake up all threads waiting on this condition. + Called by objc_condition_broadcast. + Return -1 if error otherwise return 0. + +__objc_condition_signal(objc_condition_t condition), int + Wake up one thread waiting on this condition. + Called by objc_condition_signal. + Return -1 if error otherwise return 0. diff --git a/gnu/usr.bin/gcc/objc/THREADS.MACH b/gnu/usr.bin/gcc/objc/THREADS.MACH new file mode 100644 index 00000000000..55de6637866 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/THREADS.MACH @@ -0,0 +1,23 @@ +This readme refers to the file thr-mach.c. + +Under mach, thread priorities are kinda strange-- any given thread has +a MAXIMUM priority and a BASE priority. The BASE priority is the +current priority of the thread and the MAXIMUM is the maximum possible +priority the thread can assume. The developer can lower, but never +raise the maximum priority. + +The gcc concept of thread priorities is that they run at one of three +levels; interactive, background, and low. + +Under mach, this is translated to: + +interactive -- set priority to maximum +background -- set priority to 2/3 of maximum +low -- set priority to 1/3 of maximum + +This means that it is possible for a thread with the priority of +interactive to actually run at a lower priority than another thread +with a background, or even low, priority if the developer has modified +the maximum priority. + + diff --git a/gnu/usr.bin/gcc/objc/config-lang.in b/gnu/usr.bin/gcc/objc/config-lang.in new file mode 100644 index 00000000000..736ba73b4ec --- /dev/null +++ b/gnu/usr.bin/gcc/objc/config-lang.in @@ -0,0 +1,37 @@ +# Top level configure fragment for the GNU Objective-C Runtime Library. +# Copyright (C) 1997 Free Software Foundation, Inc. + +#This file is part of GNU CC. + +#GNU CC is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 2, or (at your option) +#any later version. + +#GNU CC is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with GNU CC; see the file COPYING. If not, write to +#the Free Software Foundation, 59 Temple Place - Suite 330, +#Boston, MA 02111-1307, USA. + +# Configure looks for the existence of this file to auto-config each language. +# We define several parameters used by configure: +# +# language - name of language as it would appear in $(LANGUAGES) +# compilers - value to add to $(COMPILERS) +# stagestuff - files to add to $(STAGESTUFF) +# diff_excludes - files to ignore when building diffs between two versions. + +language="objc" + +compilers="cc1obj\$(exeext)" + +stagestuff="" + +diff_excludes="" + +echo "Using \`$srcdir/objc/thr-${thread_file}.c' as Objective-C Runtime thread file." diff --git a/gnu/usr.bin/gcc/objc/libobjc.def b/gnu/usr.bin/gcc/objc/libobjc.def new file mode 100644 index 00000000000..a4a6049e816 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/libobjc.def @@ -0,0 +1,161 @@ +; GNU Objective C Runtime DLL Export Definitions +; Copyright (C) 1997 Free Software Foundation, Inc. +; Contributed by Scott Christley <scottc@net-community.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. + +LIBRARY libobjc +EXPORTS +search_for_method_in_list +objc_get_uninstalled_dtable +hash_is_key_in_hash +objc_verror +_objc_load_callback +objc_malloc +objc_atomic_malloc +objc_valloc +objc_realloc +objc_calloc +objc_free +__objc_init_thread_system +objc_mutex_allocate +objc_mutex_deallocate +objc_mutex_lock +objc_mutex_trylock +objc_mutex_unlock +objc_thread_detach +objc_thread_exit +objc_thread_get_data +objc_thread_get_priority +objc_thread_id +objc_thread_set_data +objc_thread_set_priority +objc_thread_yield +__objc_class_name_Object +__objc_class_name_Protocol +__objc_class_name_NXConstantString +objc_error +__objc_object_alloc +__objc_object_copy +__objc_object_dispose +class_create_instance +object_copy +object_dispose +__objc_init_selector_tables +__objc_register_selectors_from_class +__sel_register_typed_name +sel_get_any_typed_uid +sel_get_any_uid +sel_get_name +sel_get_type +sel_get_typed_uid +sel_get_uid +sel_is_mapped +sel_register_name +sel_register_typed_name +sel_types_match +method_get_first_argument +method_get_next_argument +method_get_nth_argument +method_get_number_of_arguments +method_get_sizeof_arguments +objc_aligned_size +objc_alignof_type +objc_get_type_qualifiers +objc_promoted_size +objc_sizeof_type +objc_skip_argspec +objc_skip_offset +objc_skip_type_qualifiers +objc_skip_typespec +__objc_read_nbyte_uint +__objc_read_nbyte_ulong +__objc_write_class +__objc_write_object +__objc_write_selector +objc_close_typed_stream +objc_end_of_typed_stream +objc_flush_typed_stream +objc_get_stream_class_version +objc_open_typed_stream +objc_open_typed_stream_for_file +objc_read_array +objc_read_char +objc_read_int +objc_read_long +objc_read_object +objc_read_selector +objc_read_short +objc_read_string +objc_read_type +objc_read_types +objc_read_unsigned_char +objc_read_unsigned_int +objc_read_unsigned_long +objc_read_unsigned_short +objc_write_array +objc_write_char +objc_write_int +objc_write_long +objc_write_object +objc_write_object_reference +objc_write_root_object +objc_write_selector +objc_write_short +objc_write_string +objc_write_string_atomic +objc_write_type +objc_write_types +objc_write_unsigned_char +objc_write_unsigned_int +objc_write_unsigned_long +objc_write_unsigned_short +__objc_exec_class +__objc_init_dispatch_tables +__objc_install_premature_dtable +__objc_print_dtable_stats +__objc_responds_to +__objc_update_dispatch_table_for_class +class_add_method_list +class_get_class_method +class_get_instance_method +get_imp +nil_method +objc_msg_lookup +objc_msg_lookup_super +objc_msg_sendv +__objc_add_class_to_hash +__objc_init_class_tables +__objc_resolve_class_links +class_pose_as +objc_get_class +objc_get_meta_class +objc_lookup_class +objc_next_class +sarray_at_put +sarray_at_put_safe +sarray_free +sarray_lazy_copy +sarray_new +sarray_realloc +sarray_remove_garbage +hash_add +hash_delete +hash_new +hash_next +hash_remove +hash_value_for_key diff --git a/gnu/usr.bin/gcc/objc/libobjc_entry.c b/gnu/usr.bin/gcc/objc/libobjc_entry.c new file mode 100644 index 00000000000..2d584ab3c1e --- /dev/null +++ b/gnu/usr.bin/gcc/objc/libobjc_entry.c @@ -0,0 +1,55 @@ +/* GNU Objective C Runtime DLL Entry + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Scott Christley <scottc@net-community.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. */ + +/* 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. */ + +#include <windows.h> + +/* + DLL entry function for Objective-C Runtime library + This function gets called everytime a process/thread attaches to DLL + */ +WINBOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, + LPVOID lpReserved) +{ + switch(ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_PROCESS_DETACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + return TRUE; +} + +/* + This section terminates the list of imports under GCC. If you do not + include this then you will have problems when linking with DLLs. + */ +asm (".section .idata$3\n" ".long 0,0,0,0,0,0,0,0"); diff --git a/gnu/usr.bin/gcc/objc/linking.m b/gnu/usr.bin/gcc/objc/linking.m new file mode 100644 index 00000000000..8ecca028110 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/linking.m @@ -0,0 +1,40 @@ +/* Force linking of classes required by Objective C runtime. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Ovidiu Predescu (ovidiu@net-community.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. */ + +/* 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. */ + +#include <objc/Object.h> +#include <objc/NXConstStr.h> + +/* Generate references to Object and NXConstanstString classes since they are + needed by the runtime system to run correctly. */ + + +void __objc_linking (void) +{ + [Object name]; + [NXConstantString name]; +} + diff --git a/gnu/usr.bin/gcc/objc/nil_method.c b/gnu/usr.bin/gcc/objc/nil_method.c new file mode 100644 index 00000000000..1b6212826bd --- /dev/null +++ b/gnu/usr.bin/gcc/objc/nil_method.c @@ -0,0 +1,40 @@ +/* GNU Objective C Runtime nil receiver function + Copyright (C) 1993, 1995, 1996 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. */ + +/* This is the nil method, the function that is called when the receiver + of a method is nil */ + +#include "runtime.h" + +id +nil_method(id receiver, SEL op, ...) +{ + return receiver; +} + + + + diff --git a/gnu/usr.bin/gcc/objc/objc-act.c b/gnu/usr.bin/gcc/objc/objc-act.c new file mode 100644 index 00000000000..6b0de8d3556 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc-act.c @@ -0,0 +1,8410 @@ +/* Implement classes and message passing for Objective C. + Copyright (C) 1992, 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + Contributed by Steve Naroff. + +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. */ + +/* Purpose: This module implements the Objective-C 4.0 language. + + compatibility issues (with the Stepstone translator): + + - does not recognize the following 3.3 constructs. + @requires, @classes, @messages, = (...) + - methods with variable arguments must conform to ANSI standard. + - tagged structure definitions that appear in BOTH the interface + and implementation are not allowed. + - public/private: all instance variables are public within the + context of the implementation...I consider this to be a bug in + the translator. + - statically allocated objects are not supported. the user will + receive an error if this service is requested. + + code generation `options': + + - OBJC_INT_SELECTORS */ + +#include "config.h" +#include <stdio.h> +#include "tree.h" +#include "c-tree.h" +#include "c-lex.h" +#include "flags.h" +#include "objc-act.h" +#include "input.h" +#include "except.h" +#include "function.h" +#include <string.h> +#include "output.h" + +/* This is the default way of generating a method name. */ +/* I am not sure it is really correct. + Perhaps there's a danger that it will make name conflicts + if method names contain underscores. -- rms. */ +#ifndef OBJC_GEN_METHOD_LABEL +#define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME, NUM) \ + do { \ + char *temp; \ + sprintf ((BUF), "_%s_%s_%s_%s", \ + ((IS_INST) ? "i" : "c"), \ + (CLASS_NAME), \ + ((CAT_NAME)? (CAT_NAME) : ""), \ + (SEL_NAME)); \ + for (temp = (BUF); *temp; temp++) \ + if (*temp == ':') *temp = '_'; \ + } while (0) +#endif + +/* These need specifying. */ +#ifndef OBJC_FORWARDING_STACK_OFFSET +#define OBJC_FORWARDING_STACK_OFFSET 0 +#endif + +#ifndef OBJC_FORWARDING_MIN_OFFSET +#define OBJC_FORWARDING_MIN_OFFSET 0 +#endif + +/* Define the special tree codes that we use. */ + +/* Table indexed by tree code giving a string containing a character + classifying the tree code. Possibilities are + t, d, s, c, r, <, 1 and 2. See objc-tree.def for details. */ + +#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, + +char *objc_tree_code_type[] = { + "x", +#include "objc-tree.def" +}; +#undef DEFTREECODE + +/* Table indexed by tree code giving number of expression + operands beyond the fixed part of the node structure. + Not used for types or decls. */ + +#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, + +int objc_tree_code_length[] = { + 0, +#include "objc-tree.def" +}; +#undef DEFTREECODE + +/* Names of tree components. + Used for printing out the tree and error messages. */ +#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, + +char *objc_tree_code_name[] = { + "@@dummy", +#include "objc-tree.def" +}; +#undef DEFTREECODE + +/* Set up for use of obstacks. */ + +#include "obstack.h" + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +/* This obstack is used to accumulate the encoding of a data type. */ +static struct obstack util_obstack; +/* This points to the beginning of obstack contents, + so we can free the whole contents. */ +char *util_firstobj; + +/* List of classes with list of their static instances. */ +static tree objc_static_instances = NULL_TREE; + +/* The declaration of the array administrating the static instances. */ +static tree static_instances_decl = NULL_TREE; + +/* for encode_method_def */ +#include "rtl.h" +#include "c-parse.h" + +#define OBJC_VERSION (flag_next_runtime ? 5 : 8) +#define PROTOCOL_VERSION 2 + +#define OBJC_ENCODE_INLINE_DEFS 0 +#define OBJC_ENCODE_DONT_INLINE_DEFS 1 + +/*** Private Interface (procedures) ***/ + +/* Used by compile_file. */ + +static void init_objc PROTO((void)); +static void finish_objc PROTO((void)); + +/* Code generation. */ + +static void synth_module_prologue PROTO((void)); +static tree build_constructor PROTO((tree, tree)); +static char *build_module_descriptor PROTO((void)); +static tree init_module_descriptor PROTO((tree)); +static tree build_objc_method_call PROTO((int, tree, tree, + tree, tree, tree)); +static void generate_strings PROTO((void)); +static tree get_proto_encoding PROTO((tree)); +static void build_selector_translation_table PROTO((void)); +static tree build_ivar_chain PROTO((tree, int)); + +static tree objc_add_static_instance PROTO((tree, tree)); + +static tree build_ivar_template PROTO((void)); +static tree build_method_template PROTO((void)); +static tree build_private_template PROTO((tree)); +static void build_class_template PROTO((void)); +static void build_selector_template PROTO((void)); +static void build_category_template PROTO((void)); +static tree build_super_template PROTO((void)); +static tree build_category_initializer PROTO((tree, tree, tree, + tree, tree, tree)); +static tree build_protocol_initializer PROTO((tree, tree, tree, + tree, tree)); + +static void synth_forward_declarations PROTO((void)); +static void generate_ivar_lists PROTO((void)); +static void generate_dispatch_tables PROTO((void)); +static void generate_shared_structures PROTO((void)); +static tree generate_protocol_list PROTO((tree)); +static void generate_forward_declaration_to_string_table PROTO((void)); +static void build_protocol_reference PROTO((tree)); + +static tree init_selector PROTO((int)); +static tree build_keyword_selector PROTO((tree)); +static tree synth_id_with_class_suffix PROTO((char *, tree)); + +/* From expr.c */ +extern int apply_args_register_offset PROTO((int)); + +static void generate_static_references PROTO((void)); +static int check_methods_accessible PROTO((tree, tree, + int)); +static void encode_aggregate_within PROTO((tree, int, int, + char, char)); + +/* We handle printing method names ourselves for ObjC */ +extern char *(*decl_printable_name) (); + +/* Misc. bookkeeping */ + +typedef struct hashed_entry *hash; +typedef struct hashed_attribute *attr; + +struct hashed_attribute +{ + attr next; + tree value; +}; +struct hashed_entry +{ + attr list; + hash next; + tree key; +}; + +static void hash_init PROTO((void)); +static void hash_enter PROTO((hash *, tree)); +static hash hash_lookup PROTO((hash *, tree)); +static void hash_add_attr PROTO((hash, tree)); +static tree lookup_method PROTO((tree, tree)); +static tree lookup_instance_method_static PROTO((tree, tree)); +static tree lookup_class_method_static PROTO((tree, tree)); +static tree add_class PROTO((tree)); +static void add_category PROTO((tree, tree)); + +enum string_section +{ + class_names, /* class, category, protocol, module names */ + meth_var_names, /* method and variable names */ + meth_var_types /* method and variable type descriptors */ +}; + +static tree add_objc_string PROTO((tree, + enum string_section)); +static tree get_objc_string_decl PROTO((tree, + enum string_section)); +static tree build_objc_string_decl PROTO((tree, + enum string_section)); +static tree build_selector_reference_decl PROTO((tree)); + +/* Protocol additions. */ + +static tree add_protocol PROTO((tree)); +static tree lookup_protocol PROTO((tree)); +static tree lookup_and_install_protocols PROTO((tree)); + +/* Type encoding. */ + +static void encode_type_qualifiers PROTO((tree)); +static void encode_pointer PROTO((tree, int, int)); +static void encode_array PROTO((tree, int, int)); +static void encode_aggregate PROTO((tree, int, int)); +static void encode_bitfield PROTO((int, int)); +static void encode_type PROTO((tree, int, int)); +static void encode_field_decl PROTO((tree, int, int)); + +static void really_start_method PROTO((tree, tree)); +static int comp_method_with_proto PROTO((tree, tree)); +static int comp_proto_with_proto PROTO((tree, tree)); +static tree get_arg_type_list PROTO((tree, int, int)); +static tree expr_last PROTO((tree)); + +/* Utilities for debugging and error diagnostics. */ + +static void warn_with_method PROTO((char *, int, tree)); +static void error_with_ivar PROTO((char *, tree, tree)); +static char *gen_method_decl PROTO((tree, char *)); +static char *gen_declaration PROTO((tree, char *)); +static char *gen_declarator PROTO((tree, char *, char *)); +static int is_complex_decl PROTO((tree)); +static void adorn_decl PROTO((tree, char *)); +static void dump_interface PROTO((FILE *, tree)); + +/* Everything else. */ + +static void objc_fatal PROTO((void)); +static tree define_decl PROTO((tree, tree)); +static tree lookup_method_in_protocol_list PROTO((tree, tree, int)); +static tree lookup_protocol_in_reflist PROTO((tree, tree)); +static tree create_builtin_decl PROTO((enum tree_code, + tree, char *)); +static tree my_build_string PROTO((int, char *)); +static void build_objc_symtab_template PROTO((void)); +static tree init_def_list PROTO((tree)); +static tree init_objc_symtab PROTO((tree)); +static void forward_declare_categories PROTO((void)); +static void generate_objc_symtab_decl PROTO((void)); +static tree build_selector PROTO((tree)); +static tree build_msg_pool_reference PROTO((int)); +static tree build_typed_selector_reference PROTO((tree, tree)); +static tree build_selector_reference PROTO((tree)); +static tree build_class_reference_decl PROTO((tree)); +static void add_class_reference PROTO((tree)); +static tree objc_copy_list PROTO((tree, tree *)); +static tree build_protocol_template PROTO((void)); +static tree build_descriptor_table_initializer PROTO((tree, tree)); +static tree build_method_prototype_list_template PROTO((tree, int)); +static tree build_method_prototype_template PROTO((void)); +static int forwarding_offset PROTO((tree)); +static tree encode_method_prototype PROTO((tree, tree)); +static tree generate_descriptor_table PROTO((tree, char *, int, tree, tree)); +static void generate_method_descriptors PROTO((tree)); +static tree build_tmp_function_decl PROTO((void)); +static void hack_method_prototype PROTO((tree, tree)); +static void generate_protocol_references PROTO((tree)); +static void generate_protocols PROTO((void)); +static void check_ivars PROTO((tree, tree)); +static tree build_ivar_list_template PROTO((tree, int)); +static tree build_method_list_template PROTO((tree, int)); +static tree build_ivar_list_initializer PROTO((tree, tree)); +static tree generate_ivars_list PROTO((tree, char *, + int, tree)); +static tree build_dispatch_table_initializer PROTO((tree, tree)); +static tree generate_dispatch_table PROTO((tree, char *, + int, tree)); +static tree build_shared_structure_initializer PROTO((tree, tree, tree, tree, + tree, int, tree, tree, + tree)); +static void generate_category PROTO((tree)); +static int is_objc_type_qualifier PROTO((tree)); +static tree adjust_type_for_id_default PROTO((tree)); +static tree check_duplicates PROTO((hash)); +static tree receiver_is_class_object PROTO((tree)); +static int check_methods PROTO((tree, tree, int)); +static int conforms_to_protocol PROTO((tree, tree)); +static void check_protocols PROTO((tree, char *, char *)); +static tree encode_method_def PROTO((tree)); +static void gen_declspecs PROTO((tree, char *, int)); +static void generate_classref_translation_entry PROTO((tree)); +static void handle_class_ref PROTO((tree)); + +/*** Private Interface (data) ***/ + +/* Reserved tag definitions. */ + +#define TYPE_ID "id" +#define TAG_OBJECT "objc_object" +#define TAG_CLASS "objc_class" +#define TAG_SUPER "objc_super" +#define TAG_SELECTOR "objc_selector" + +#define UTAG_CLASS "_objc_class" +#define UTAG_IVAR "_objc_ivar" +#define UTAG_IVAR_LIST "_objc_ivar_list" +#define UTAG_METHOD "_objc_method" +#define UTAG_METHOD_LIST "_objc_method_list" +#define UTAG_CATEGORY "_objc_category" +#define UTAG_MODULE "_objc_module" +#define UTAG_STATICS "_objc_statics" +#define UTAG_SYMTAB "_objc_symtab" +#define UTAG_SUPER "_objc_super" +#define UTAG_SELECTOR "_objc_selector" + +#define UTAG_PROTOCOL "_objc_protocol" +#define UTAG_PROTOCOL_LIST "_objc_protocol_list" +#define UTAG_METHOD_PROTOTYPE "_objc_method_prototype" +#define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list" + +#define STRING_OBJECT_CLASS_NAME "NXConstantString" +#define PROTOCOL_OBJECT_CLASS_NAME "Protocol" + +static char *TAG_GETCLASS; +static char *TAG_GETMETACLASS; +static char *TAG_MSGSEND; +static char *TAG_MSGSENDSUPER; +static char *TAG_EXECCLASS; + +/* Set by `continue_class' and checked by `is_public'. */ + +#define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC (record_type)) +#define TYPED_OBJECT(type) \ + (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type)) + +/* Some commonly used instances of "identifier_node". */ + +static tree self_id, ucmd_id; +static tree unused_list; + +static tree self_decl, umsg_decl, umsg_super_decl; +static tree objc_get_class_decl, objc_get_meta_class_decl; + +static tree super_type, selector_type, id_type, objc_class_type; +static tree instance_type, protocol_type; + +/* Type checking macros. */ + +#define IS_ID(TYPE) \ + (TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (id_type)) +#define IS_PROTOCOL_QUALIFIED_ID(TYPE) \ + (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE)) +#define IS_SUPER(TYPE) \ + (super_type && TYPE_MAIN_VARIANT (TYPE) == TYPE_MAIN_VARIANT (super_type)) + +static tree class_chain = NULL_TREE; +static tree alias_chain = NULL_TREE; +static tree interface_chain = NULL_TREE; +static tree protocol_chain = NULL_TREE; + +/* Chains to manage selectors that are referenced and defined in the + module. */ + +static tree cls_ref_chain = NULL_TREE; /* Classes referenced. */ +static tree sel_ref_chain = NULL_TREE; /* Selectors referenced. */ + +/* Chains to manage uniquing of strings. */ + +static tree class_names_chain = NULL_TREE; +static tree meth_var_names_chain = NULL_TREE; +static tree meth_var_types_chain = NULL_TREE; + +/* Hash tables to manage the global pool of method prototypes. */ + +static hash *nst_method_hash_list = 0; +static hash *cls_method_hash_list = 0; + +/* Backend data declarations. */ + +static tree UOBJC_SYMBOLS_decl; +static tree UOBJC_INSTANCE_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl; +static tree UOBJC_INSTANCE_METHODS_decl, UOBJC_CLASS_METHODS_decl; +static tree UOBJC_CLASS_decl, UOBJC_METACLASS_decl; +static tree UOBJC_SELECTOR_TABLE_decl; +static tree UOBJC_MODULES_decl; +static tree UOBJC_STRINGS_decl; + +/* The following are used when compiling a class implementation. + implementation_template will normally be an interface, however if + none exists this will be equal to implementation_context...it is + set in start_class. */ + +static tree implementation_context = NULL_TREE; +static tree implementation_template = NULL_TREE; + +struct imp_entry +{ + struct imp_entry *next; + tree imp_context; + tree imp_template; + tree class_decl; /* _OBJC_CLASS_<my_name>; */ + tree meta_decl; /* _OBJC_METACLASS_<my_name>; */ +}; + +static void handle_impent PROTO((struct imp_entry *)); + +static struct imp_entry *imp_list = 0; +static int imp_count = 0; /* `@implementation' */ +static int cat_count = 0; /* `@category' */ + +static tree objc_class_template, objc_category_template, uprivate_record; +static tree objc_protocol_template, objc_selector_template; +static tree ucls_super_ref, uucls_super_ref; + +static tree objc_method_template, objc_ivar_template; +static tree objc_symtab_template, objc_module_template; +static tree objc_super_template, objc_object_reference; + +static tree objc_object_id, objc_class_id, objc_id_id; +static tree constant_string_id; +static tree constant_string_type; +static tree UOBJC_SUPER_decl; + +static tree method_context = NULL_TREE; +static int method_slot = 0; /* Used by start_method_def, */ + +#define BUFSIZE 1024 + +static char *errbuf; /* Buffer for error diagnostics */ + +/* Data imported from tree.c. */ + +extern enum debug_info_type write_symbols; + +/* Data imported from toplev.c. */ + +extern char *dump_base_name; + +/* Generate code for GNU or NeXT runtime environment. */ + +#ifdef NEXT_OBJC_RUNTIME +int flag_next_runtime = 1; +#else +int flag_next_runtime = 0; +#endif + +int flag_typed_selectors; + +/* Open and close the file for outputting class declarations, if requested. */ + +int flag_gen_declaration = 0; + +FILE *gen_declaration_file; + +/* Warn if multiple methods are seen for the same selector, but with + different argument types. */ + +int warn_selector = 0; + +/* Warn if methods required by a protocol are not implemented in the + class adopting it. When turned off, methods inherited to that + class are also considered implemented */ + +int flag_warn_protocol = 1; + +/* Tells "encode_pointer/encode_aggregate" whether we are generating + type descriptors for instance variables (as opposed to methods). + Type descriptors for instance variables contain more information + than methods (for static typing and embedded structures). This + was added to support features being planned for dbkit2. */ + +static int generating_instance_variables = 0; + +/* Tells the compiler that this is a special run. Do not perform + any compiling, instead we are to test some platform dependent + features and output a C header file with appropriate definitions. */ + +static int print_struct_values = 0; + +/* Some platforms pass small structures through registers versus through + an invisible pointer. Determine at what size structure is the + transition point between the two possibilities. */ + +void +generate_struct_by_value_array () +{ + tree type; + tree field_decl, field_decl_chain; + int i, j; + int aggregate_in_mem[32]; + int found = 0; + + /* Presumbaly no platform passes 32 byte structures in a register. */ + for (i = 1; i < 32; i++) + { + char buffer[5]; + + /* Create an unnamed struct that has `i' character components */ + type = start_struct (RECORD_TYPE, NULL_TREE); + + strcpy (buffer, "c1"); + field_decl = create_builtin_decl (FIELD_DECL, + char_type_node, + buffer); + field_decl_chain = field_decl; + + for (j = 1; j < i; j++) + { + sprintf (buffer, "c%d", j + 1); + field_decl = create_builtin_decl (FIELD_DECL, + char_type_node, + buffer); + chainon (field_decl_chain, field_decl); + } + finish_struct (type, field_decl_chain, NULL_TREE); + + aggregate_in_mem[i] = aggregate_value_p (type); + if (!aggregate_in_mem[i]) + found = 1; + } + + /* We found some structures that are returned in registers instead of memory + so output the necessary data. */ + if (found) + { + for (i = 31; i >= 0; i--) + if (!aggregate_in_mem[i]) + break; + printf ("#define OBJC_MAX_STRUCT_BY_VALUE %d\n\n", i); + + /* The first member of the structure is always 0 because we don't handle + structures with 0 members */ + printf ("static int struct_forward_array[] = {\n 0"); + + for (j = 1; j <= i; j++) + printf (", %d", aggregate_in_mem[j]); + printf ("\n};\n"); + } + + exit (0); +} + +void +lang_init () +{ +#if !USE_CPPLIB + /* The beginning of the file is a new line; check for #. + With luck, we discover the real source file's name from that + and put it in input_filename. */ + ungetc (check_newline (), finput); +#endif + + /* The line number can be -1 if we had -g3 and the input file + had a directive specifying line 0. But we want predefined + functions to have a line number of 0, not -1. */ + if (lineno == -1) + lineno = 0; + + /* If gen_declaration desired, open the output file. */ + if (flag_gen_declaration) + { + int dump_base_name_length = strlen (dump_base_name); + register char *dumpname = (char *) xmalloc (dump_base_name_length + 7); + strcpy (dumpname, dump_base_name); + strcat (dumpname, ".decl"); + gen_declaration_file = fopen (dumpname, "w"); + if (gen_declaration_file == 0) + pfatal_with_name (dumpname); + } + + if (flag_next_runtime) + { + TAG_GETCLASS = "objc_getClass"; + TAG_GETMETACLASS = "objc_getMetaClass"; + TAG_MSGSEND = "objc_msgSend"; + TAG_MSGSENDSUPER = "objc_msgSendSuper"; + TAG_EXECCLASS = "__objc_execClass"; + } + else + { + TAG_GETCLASS = "objc_get_class"; + TAG_GETMETACLASS = "objc_get_meta_class"; + TAG_MSGSEND = "objc_msg_lookup"; + TAG_MSGSENDSUPER = "objc_msg_lookup_super"; + TAG_EXECCLASS = "__objc_exec_class"; + flag_typed_selectors = 1; + } + + if (doing_objc_thang) + init_objc (); + + if (print_struct_values) + generate_struct_by_value_array (); +} + +static void +objc_fatal () +{ + fatal ("Objective-C text in C source file"); +} + +void +finish_file () +{ + if (doing_objc_thang) + finish_objc (); /* Objective-C finalization */ + + if (gen_declaration_file) + fclose (gen_declaration_file); +} + +void +lang_finish () +{ +} + +char * +lang_identify () +{ + return "objc"; +} + +int +lang_decode_option (p) + char *p; +{ + if (!strcmp (p, "-lang-objc")) + doing_objc_thang = 1; + else if (!strcmp (p, "-gen-decls")) + flag_gen_declaration = 1; + else if (!strcmp (p, "-Wselector")) + warn_selector = 1; + else if (!strcmp (p, "-Wno-selector")) + warn_selector = 0; + else if (!strcmp (p, "-Wprotocol")) + flag_warn_protocol = 1; + else if (!strcmp (p, "-Wno-protocol")) + flag_warn_protocol = 0; + else if (!strcmp (p, "-fgnu-runtime")) + flag_next_runtime = 0; + else if (!strcmp (p, "-fno-next-runtime")) + flag_next_runtime = 0; + else if (!strcmp (p, "-fno-gnu-runtime")) + flag_next_runtime = 1; + else if (!strcmp (p, "-fnext-runtime")) + flag_next_runtime = 1; + else if (!strcmp (p, "-print-objc-runtime-info")) + print_struct_values = 1; + else + return c_decode_option (p); + + return 1; +} + +static tree +define_decl (declarator, declspecs) + tree declarator; + tree declspecs; +{ + tree decl = start_decl (declarator, declspecs, 0, NULL_TREE, NULL_TREE); + finish_decl (decl, NULL_TREE, NULL_TREE); + return decl; +} + +/* Return 1 if LHS and RHS are compatible types for assignment or + various other operations. Return 0 if they are incompatible, and + return -1 if we choose to not decide. When the operation is + REFLEXIVE, check for compatibility in either direction. + + For statically typed objects, an assignment of the form `a' = `b' + is permitted if: + + `a' is of type "id", + `a' and `b' are the same class type, or + `a' and `b' are of class types A and B such that B is a descendant of A. */ + +int +maybe_objc_comptypes (lhs, rhs, reflexive) + tree lhs, rhs; + int reflexive; +{ + if (doing_objc_thang) + return objc_comptypes (lhs, rhs, reflexive); + return -1; +} + +static tree +lookup_method_in_protocol_list (rproto_list, sel_name, class_meth) + tree rproto_list; + tree sel_name; + int class_meth; +{ + tree rproto, p; + tree fnd = 0; + + for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) + { + p = TREE_VALUE (rproto); + + if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) + { + if ((fnd = lookup_method (class_meth + ? PROTOCOL_CLS_METHODS (p) + : PROTOCOL_NST_METHODS (p), sel_name))) + ; + else if (PROTOCOL_LIST (p)) + fnd = lookup_method_in_protocol_list (PROTOCOL_LIST (p), + sel_name, class_meth); + } + else + ; /* An identifier...if we could not find a protocol. */ + + if (fnd) + return fnd; + } + + return 0; +} + +static tree +lookup_protocol_in_reflist (rproto_list, lproto) + tree rproto_list; + tree lproto; +{ + tree rproto, p; + + /* Make sure the protocol is support by the object on the rhs. */ + if (TREE_CODE (lproto) == PROTOCOL_INTERFACE_TYPE) + { + tree fnd = 0; + for (rproto = rproto_list; rproto; rproto = TREE_CHAIN (rproto)) + { + p = TREE_VALUE (rproto); + + if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) + { + if (lproto == p) + fnd = lproto; + + else if (PROTOCOL_LIST (p)) + fnd = lookup_protocol_in_reflist (PROTOCOL_LIST (p), lproto); + } + + if (fnd) + return fnd; + } + } + else + ; /* An identifier...if we could not find a protocol. */ + + return 0; +} + +/* Return 1 if LHS and RHS are compatible types for assignment + or various other operations. Return 0 if they are incompatible, + and return -1 if we choose to not decide. When the operation + is REFLEXIVE, check for compatibility in either direction. */ + +int +objc_comptypes (lhs, rhs, reflexive) + tree lhs; + tree rhs; + int reflexive; +{ + /* New clause for protocols. */ + + if (TREE_CODE (lhs) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE + && TREE_CODE (rhs) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE) + { + int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs); + int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs); + + if (lhs_is_proto) + { + tree lproto, lproto_list = TYPE_PROTOCOL_LIST (lhs); + tree rproto, rproto_list; + tree p; + + if (rhs_is_proto) + { + rproto_list = TYPE_PROTOCOL_LIST (rhs); + + /* Make sure the protocol is supported by the object + on the rhs. */ + for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) + { + p = TREE_VALUE (lproto); + rproto = lookup_protocol_in_reflist (rproto_list, p); + + if (!rproto) + warning ("object does not conform to the `%s' protocol", + IDENTIFIER_POINTER (PROTOCOL_NAME (p))); + } + } + else if (TYPED_OBJECT (TREE_TYPE (rhs))) + { + tree rname = TYPE_NAME (TREE_TYPE (rhs)); + tree rinter; + + /* Make sure the protocol is supported by the object + on the rhs. */ + for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) + { + p = TREE_VALUE (lproto); + rproto = 0; + rinter = lookup_interface (rname); + + while (rinter && !rproto) + { + tree cat; + + rproto_list = CLASS_PROTOCOL_LIST (rinter); + rproto = lookup_protocol_in_reflist (rproto_list, p); + + /* Check for protocols adopted by categories. */ + cat = CLASS_CATEGORY_LIST (rinter); + while (cat && !rproto) + { + rproto_list = CLASS_PROTOCOL_LIST (cat); + rproto = lookup_protocol_in_reflist (rproto_list, p); + + cat = CLASS_CATEGORY_LIST (cat); + } + + rinter = lookup_interface (CLASS_SUPER_NAME (rinter)); + } + + if (!rproto) + warning ("class `%s' does not implement the `%s' protocol", + IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))), + IDENTIFIER_POINTER (PROTOCOL_NAME (p))); + } + } + + /* May change...based on whether there was any mismatch */ + return 1; + } + else if (rhs_is_proto) + /* Lhs is not a protocol...warn if it is statically typed */ + return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0); + + else + /* Defer to comptypes .*/ + return -1; + } + + else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE) + ; /* Fall thru. This is the case we have been handling all along */ + else + /* Defer to comptypes. */ + return -1; + + /* `id' = `<class> *', `<class> *' = `id' */ + + if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs)) + || (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs))) + return 1; + + /* `id' = `Class', `Class' = `id' */ + + else if ((TYPE_NAME (lhs) == objc_object_id + && TYPE_NAME (rhs) == objc_class_id) + || (TYPE_NAME (lhs) == objc_class_id + && TYPE_NAME (rhs) == objc_object_id)) + return 1; + + /* `<class> *' = `<class> *' */ + + else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs)) + { + tree lname = TYPE_NAME (lhs); + tree rname = TYPE_NAME (rhs); + tree inter; + + if (lname == rname) + return 1; + + /* If the left hand side is a super class of the right hand side, + allow it. */ + for (inter = lookup_interface (rname); inter; + inter = lookup_interface (CLASS_SUPER_NAME (inter))) + if (lname == CLASS_SUPER_NAME (inter)) + return 1; + + /* Allow the reverse when reflexive. */ + if (reflexive) + for (inter = lookup_interface (lname); inter; + inter = lookup_interface (CLASS_SUPER_NAME (inter))) + if (rname == CLASS_SUPER_NAME (inter)) + return 1; + + return 0; + } + else + /* Defer to comptypes. */ + return -1; +} + +/* Called from c-decl.c before all calls to rest_of_decl_compilation. */ + +void +objc_check_decl (decl) + tree decl; +{ + tree type = TREE_TYPE (decl); + + if (TREE_CODE (type) == RECORD_TYPE + && TREE_STATIC_TEMPLATE (type) + && type != constant_string_type) + { + error_with_decl (decl, "`%s' cannot be statically allocated"); + fatal ("statically allocated objects not supported"); + } +} + +void +maybe_objc_check_decl (decl) + tree decl; +{ + if (doing_objc_thang) + objc_check_decl (decl); +} + +/* Implement static typing. At this point, we know we have an interface. */ + +tree +get_static_reference (interface, protocols) + tree interface; + tree protocols; +{ + tree type = xref_tag (RECORD_TYPE, interface); + + if (protocols) + { + tree t, m = TYPE_MAIN_VARIANT (type); + + push_obstacks_nochange (); + end_temporary_allocation (); + t = copy_node (type); + TYPE_BINFO (t) = make_tree_vec (2); + pop_obstacks (); + + /* Add this type to the chain of variants of TYPE. */ + TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); + TYPE_NEXT_VARIANT (m) = t; + + /* Look up protocols and install in lang specific list. */ + TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols); + + /* This forces a new pointer type to be created later + (in build_pointer_type)...so that the new template + we just created will actually be used...what a hack! */ + if (TYPE_POINTER_TO (t)) + TYPE_POINTER_TO (t) = 0; + + type = t; + } + + return type; +} + +tree +get_object_reference (protocols) + tree protocols; +{ + tree type_decl = lookup_name (objc_id_id); + tree type; + + if (type_decl && TREE_CODE (type_decl) == TYPE_DECL) + { + type = TREE_TYPE (type_decl); + if (TYPE_MAIN_VARIANT (type) != id_type) + warning ("Unexpected type for `id' (%s)", + gen_declaration (type, errbuf)); + } + else + fatal ("Undefined type `id', please import <objc/objc.h>"); + + /* This clause creates a new pointer type that is qualified with + the protocol specification...this info is used later to do more + elaborate type checking. */ + + if (protocols) + { + tree t, m = TYPE_MAIN_VARIANT (type); + + push_obstacks_nochange (); + end_temporary_allocation (); + t = copy_node (type); + TYPE_BINFO (t) = make_tree_vec (2); + pop_obstacks (); + + /* Add this type to the chain of variants of TYPE. */ + TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); + TYPE_NEXT_VARIANT (m) = t; + + /* Look up protocols...and install in lang specific list */ + TYPE_PROTOCOL_LIST (t) = lookup_and_install_protocols (protocols); + + /* This forces a new pointer type to be created later + (in build_pointer_type)...so that the new template + we just created will actually be used...what a hack! */ + if (TYPE_POINTER_TO (t)) + TYPE_POINTER_TO (t) = NULL; + + type = t; + } + return type; +} + +static tree +lookup_and_install_protocols (protocols) + tree protocols; +{ + tree proto; + tree prev = NULL; + tree return_value = protocols; + + for (proto = protocols; proto; proto = TREE_CHAIN (proto)) + { + tree ident = TREE_VALUE (proto); + tree p = lookup_protocol (ident); + + if (!p) + { + error ("Cannot find protocol declaration for `%s'", + IDENTIFIER_POINTER (ident)); + if (prev) + TREE_CHAIN (prev) = TREE_CHAIN (proto); + else + return_value = TREE_CHAIN (proto); + } + else + { + /* Replace identifier with actual protocol node. */ + TREE_VALUE (proto) = p; + prev = proto; + } + } + + return return_value; +} + +/* Create and push a decl for a built-in external variable or field NAME. + CODE says which. + TYPE is its data type. */ + +static tree +create_builtin_decl (code, type, name) + enum tree_code code; + tree type; + char *name; +{ + tree decl = build_decl (code, get_identifier (name), type); + + if (code == VAR_DECL) + { + TREE_STATIC (decl) = 1; + make_decl_rtl (decl, 0, 1); + pushdecl (decl); + } + + DECL_ARTIFICIAL (decl) = 1; + return decl; +} + +/* Purpose: "play" parser, creating/installing representations + of the declarations that are required by Objective-C. + + Model: + + type_spec--------->sc_spec + (tree_list) (tree_list) + | | + | | + identifier_node identifier_node */ + +static void +synth_module_prologue () +{ + tree temp_type; + tree super_p; + + /* Defined in `objc.h' */ + objc_object_id = get_identifier (TAG_OBJECT); + + objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id); + + id_type = build_pointer_type (objc_object_reference); + + objc_id_id = get_identifier (TYPE_ID); + objc_class_id = get_identifier (TAG_CLASS); + + objc_class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id)); + protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier (PROTOCOL_OBJECT_CLASS_NAME))); + + /* Declare type of selector-objects that represent an operation name. */ + +#ifdef OBJC_INT_SELECTORS + /* `unsigned int' */ + selector_type = unsigned_type_node; +#else + /* `struct objc_selector *' */ + selector_type + = build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier (TAG_SELECTOR))); +#endif /* not OBJC_INT_SELECTORS */ + + /* Forward declare type, or else the prototype for msgSendSuper will + complain. */ + + super_p = build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier (TAG_SUPER))); + + + /* id objc_msgSend (id, SEL, ...); */ + + temp_type + = build_function_type (id_type, + tree_cons (NULL_TREE, id_type, + tree_cons (NULL_TREE, selector_type, + NULL_TREE))); + + if (! flag_next_runtime) + { + umsg_decl = build_decl (FUNCTION_DECL, + get_identifier (TAG_MSGSEND), temp_type); + DECL_EXTERNAL (umsg_decl) = 1; + TREE_PUBLIC (umsg_decl) = 1; + DECL_INLINE (umsg_decl) = 1; + DECL_ARTIFICIAL (umsg_decl) = 1; + + if (flag_traditional && TAG_MSGSEND[0] != '_') + DECL_BUILT_IN_NONANSI (umsg_decl) = 1; + + make_decl_rtl (umsg_decl, NULL_PTR, 1); + pushdecl (umsg_decl); + } + else + umsg_decl = builtin_function (TAG_MSGSEND, temp_type, NOT_BUILT_IN, 0); + + /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ + + temp_type + = build_function_type (id_type, + tree_cons (NULL_TREE, super_p, + tree_cons (NULL_TREE, selector_type, + NULL_TREE))); + + umsg_super_decl = builtin_function (TAG_MSGSENDSUPER, + temp_type, NOT_BUILT_IN, 0); + + /* id objc_getClass (const char *); */ + + temp_type = build_function_type (id_type, + tree_cons (NULL_TREE, + const_string_type_node, + tree_cons (NULL_TREE, void_type_node, + NULL_TREE))); + + objc_get_class_decl + = builtin_function (TAG_GETCLASS, temp_type, NOT_BUILT_IN, 0); + + /* id objc_getMetaClass (const char *); */ + + objc_get_meta_class_decl + = builtin_function (TAG_GETMETACLASS, temp_type, NOT_BUILT_IN, 0); + + /* static SEL _OBJC_SELECTOR_TABLE[]; */ + + if (! flag_next_runtime) + { + if (flag_typed_selectors) + { + /* Suppress outputting debug symbols, because + dbxout_init hasn'r been called yet. */ + enum debug_info_type save_write_symbols = write_symbols; + write_symbols = NO_DEBUG; + + build_selector_template (); + temp_type = build_array_type (objc_selector_template, NULL_TREE); + + write_symbols = save_write_symbols; + } + else + temp_type = build_array_type (selector_type, NULL_TREE); + + layout_type (temp_type); + UOBJC_SELECTOR_TABLE_decl + = create_builtin_decl (VAR_DECL, temp_type, + "_OBJC_SELECTOR_TABLE"); + + /* Avoid warning when not sending messages. */ + TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1; + } + + generate_forward_declaration_to_string_table (); + + /* Forward declare constant_string_id and constant_string_type. */ + constant_string_id = get_identifier (STRING_OBJECT_CLASS_NAME); + constant_string_type = xref_tag (RECORD_TYPE, constant_string_id); +} + +/* Custom build_string which sets TREE_TYPE! */ + +static tree +my_build_string (len, str) + int len; + char *str; +{ + int wide_flag = 0; + tree a_string = build_string (len, str); + + /* Some code from combine_strings, which is local to c-parse.y. */ + if (TREE_TYPE (a_string) == int_array_type_node) + wide_flag = 1; + + TREE_TYPE (a_string) + = build_array_type (wide_flag ? integer_type_node : char_type_node, + build_index_type (build_int_2 (len - 1, 0))); + + TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */ + TREE_STATIC (a_string) = 1; + + return a_string; +} + +/* Return a newly constructed OBJC_STRING_CST node whose value is + the LEN characters at STR. + The TREE_TYPE is not initialized. */ + +tree +build_objc_string (len, str) + int len; + char *str; +{ + tree s = build_string (len, str); + + TREE_SET_CODE (s, OBJC_STRING_CST); + return s; +} + +/* Given a chain of OBJC_STRING_CST's, build a static instance of + NXConstanString which points at the concatenation of those strings. + We place the string object in the __string_objects section of the + __OBJC segment. The Objective-C runtime will initialize the isa + pointers of the string objects to point at the NXConstandString class + object. */ + +tree +build_objc_string_object (strings) + tree strings; +{ + tree string, initlist, constructor; + int length; + + if (!doing_objc_thang) + objc_fatal (); + + if (lookup_interface (constant_string_id) == NULL_TREE) + { + error ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER (constant_string_id)); + return error_mark_node; + } + + add_class_reference (constant_string_id); + + /* Combine_strings will work for OBJC_STRING_CST's too. */ + string = combine_strings (strings); + TREE_SET_CODE (string, STRING_CST); + length = TREE_STRING_LENGTH (string) - 1; + + if (! flag_next_runtime) + { + push_obstacks_nochange (); + end_temporary_allocation (); + if (! TREE_PERMANENT (strings)) + string = my_build_string (length + 1, + TREE_STRING_POINTER (string)); + } + + /* & ((NXConstantString) {0, string, length}) */ + + initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); + initlist + = tree_cons (NULL_TREE, copy_node (build_unary_op (ADDR_EXPR, string, 1)), + initlist); + initlist = tree_cons (NULL_TREE, build_int_2 (length, 0), initlist); + constructor = build_constructor (constant_string_type, nreverse (initlist)); + + if (!flag_next_runtime) + { + constructor + = objc_add_static_instance (constructor, constant_string_type); + pop_obstacks (); + } + + return (build_unary_op (ADDR_EXPR, constructor, 1)); +} + +/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */ + +static tree +objc_add_static_instance (constructor, class_decl) + tree constructor, class_decl; +{ + static int num_static_inst; + tree *chain, decl, decl_spec, decl_expr; + char buf[256]; + + push_obstacks_nochange (); + end_temporary_allocation (); + + /* Find the list of static instances for the CLASS_DECL. Create one if + not found. */ + for (chain = &objc_static_instances; + *chain && TREE_VALUE (*chain) != class_decl; + chain = &TREE_CHAIN (*chain)); + if (!*chain) + { + *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE); + add_objc_string (TYPE_NAME (class_decl), class_names); + } + + sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++); + decl = build_decl (VAR_DECL, get_identifier (buf), class_decl); + DECL_COMMON (decl) = 1; + TREE_STATIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + pushdecl_top_level (decl); + rest_of_decl_compilation (decl, 0, 1, 0); + + /* Do this here so it gets output later instead of possibly + inside something else we are writing. */ + DECL_INITIAL (decl) = constructor; + + /* Add the DECL to the head of this CLASS' list. */ + TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain)); + + pop_obstacks (); + return decl; +} + +/* Build a static constant CONSTRUCTOR + with type TYPE and elements ELTS. */ + +static tree +build_constructor (type, elts) + tree type, elts; +{ + tree constructor = build (CONSTRUCTOR, type, NULL_TREE, elts); + + TREE_CONSTANT (constructor) = 1; + TREE_STATIC (constructor) = 1; + TREE_READONLY (constructor) = 1; + + return constructor; +} + +/* Take care of defining and initializing _OBJC_SYMBOLS. */ + +/* Predefine the following data type: + + struct _objc_symtab + { + long sel_ref_cnt; + SEL *refs; + short cls_def_cnt; + short cat_def_cnt; + void *defs[cls_def_cnt + cat_def_cnt]; + }; */ + +static void +build_objc_symtab_template () +{ + tree field_decl, field_decl_chain, index; + + objc_symtab_template + = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB)); + + /* long sel_ref_cnt; */ + + field_decl = create_builtin_decl (FIELD_DECL, + long_integer_type_node, + "sel_ref_cnt"); + field_decl_chain = field_decl; + + /* SEL *refs; */ + + field_decl = create_builtin_decl (FIELD_DECL, + build_pointer_type (selector_type), + "refs"); + chainon (field_decl_chain, field_decl); + + /* short cls_def_cnt; */ + + field_decl = create_builtin_decl (FIELD_DECL, + short_integer_type_node, + "cls_def_cnt"); + chainon (field_decl_chain, field_decl); + + /* short cat_def_cnt; */ + + field_decl = create_builtin_decl (FIELD_DECL, + short_integer_type_node, + "cat_def_cnt"); + chainon (field_decl_chain, field_decl); + + /* void *defs[cls_def_cnt + cat_def_cnt]; */ + + if (!flag_next_runtime) + index = build_index_type (build_int_2 (imp_count + cat_count, 0)); + else + index = build_index_type (build_int_2 (imp_count + cat_count - 1, + imp_count == 0 && cat_count == 0 + ? -1 : 0)); + field_decl = create_builtin_decl (FIELD_DECL, + build_array_type (ptr_type_node, index), + "defs"); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE); +} + +/* Create the initial value for the `defs' field of _objc_symtab. + This is a CONSTRUCTOR. */ + +static tree +init_def_list (type) + tree type; +{ + tree expr, initlist = NULL_TREE; + struct imp_entry *impent; + + if (imp_count) + for (impent = imp_list; impent; impent = impent->next) + { + if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) + { + expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + } + + if (cat_count) + for (impent = imp_list; impent; impent = impent->next) + { + if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) + { + expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + } + + if (!flag_next_runtime) + { + /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */ + tree expr; + + if (static_instances_decl) + expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0); + else + expr = build_int_2 (0, 0); + + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + return build_constructor (type, nreverse (initlist)); +} + +/* Construct the initial value for all of _objc_symtab. */ + +static tree +init_objc_symtab (type) + tree type; +{ + tree initlist; + + /* sel_ref_cnt = { ..., 5, ... } */ + + initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); + + /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ + + if (flag_next_runtime || ! sel_ref_chain) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + initlist = tree_cons (NULL_TREE, + build_unary_op (ADDR_EXPR, + UOBJC_SELECTOR_TABLE_decl, 1), + initlist); + + /* cls_def_cnt = { ..., 5, ... } */ + + initlist = tree_cons (NULL_TREE, build_int_2 (imp_count, 0), initlist); + + /* cat_def_cnt = { ..., 5, ... } */ + + initlist = tree_cons (NULL_TREE, build_int_2 (cat_count, 0), initlist); + + /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ + + if (imp_count || cat_count || static_instances_decl) + { + + tree field = TYPE_FIELDS (type); + field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field)))); + + initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)), + initlist); + } + + return build_constructor (type, nreverse (initlist)); +} + +/* Push forward-declarations of all the categories + so that init_def_list can use them in a CONSTRUCTOR. */ + +static void +forward_declare_categories () +{ + struct imp_entry *impent; + tree sav = implementation_context; + + for (impent = imp_list; impent; impent = impent->next) + { + if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) + { + /* Set an invisible arg to synth_id_with_class_suffix. */ + implementation_context = impent->imp_context; + impent->class_decl + = create_builtin_decl (VAR_DECL, objc_category_template, + IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY", implementation_context))); + } + } + implementation_context = sav; +} + +/* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab' + and initialized appropriately. */ + +static void +generate_objc_symtab_decl () +{ + tree sc_spec; + + if (!objc_category_template) + build_category_template (); + + /* forward declare categories */ + if (cat_count) + forward_declare_categories (); + + if (!objc_symtab_template) + build_objc_symtab_template (); + + sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); + + UOBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"), + tree_cons (NULL_TREE, + objc_symtab_template, sc_spec), + 1, + NULL_TREE, NULL_TREE); + + TREE_USED (UOBJC_SYMBOLS_decl) = 1; + DECL_IGNORED_P (UOBJC_SYMBOLS_decl) = 1; + DECL_ARTIFICIAL (UOBJC_SYMBOLS_decl) = 1; + finish_decl (UOBJC_SYMBOLS_decl, + init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)), + NULL_TREE); +} + +static tree +init_module_descriptor (type) + tree type; +{ + tree initlist, expr; + + /* version = { 1, ... } */ + + expr = build_int_2 (OBJC_VERSION, 0); + initlist = build_tree_list (NULL_TREE, expr); + + /* size = { ..., sizeof (struct objc_module), ... } */ + + expr = size_in_bytes (objc_module_template); + initlist = tree_cons (NULL_TREE, expr, initlist); + + /* name = { ..., "foo.m", ... } */ + + expr = add_objc_string (get_identifier (input_filename), class_names); + initlist = tree_cons (NULL_TREE, expr, initlist); + + /* symtab = { ..., _OBJC_SYMBOLS, ... } */ + + if (UOBJC_SYMBOLS_decl) + expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_decl, 0); + else + expr = build_int_2 (0, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + + return build_constructor (type, nreverse (initlist)); +} + +/* Write out the data structures to describe Objective C classes defined. + If appropriate, compile and output a setup function to initialize them. + Return a string which is the name of a function to call to initialize + the Objective C data structures for this file (and perhaps for other files + also). + + struct objc_module { ... } _OBJC_MODULE = { ... }; */ + +static char * +build_module_descriptor () +{ + tree decl_specs, field_decl, field_decl_chain; + + objc_module_template + = start_struct (RECORD_TYPE, get_identifier (UTAG_MODULE)); + + /* Long version; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); + field_decl = get_identifier ("version"); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* long size; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); + field_decl = get_identifier ("size"); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* char *name; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_symtab *symtab; */ + + decl_specs = get_identifier (UTAG_SYMTAB); + decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs)); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("symtab")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_module_template, field_decl_chain, NULL_TREE); + + /* Create an instance of "objc_module". */ + + decl_specs = tree_cons (NULL_TREE, objc_module_template, + build_tree_list (NULL_TREE, + ridpointers[(int) RID_STATIC])); + + UOBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"), + decl_specs, 1, NULL_TREE, NULL_TREE); + + DECL_ARTIFICIAL (UOBJC_MODULES_decl) = 1; + DECL_IGNORED_P (UOBJC_MODULES_decl) = 1; + finish_decl (UOBJC_MODULES_decl, + init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)), + NULL_TREE); + + /* Mark the decl to avoid "defined but not used" warning. */ + DECL_IN_SYSTEM_HEADER (UOBJC_MODULES_decl) = 1; + + /* Generate a constructor call for the module descriptor. + This code was generated by reading the grammar rules + of c-parse.in; Therefore, it may not be the most efficient + way of generating the requisite code. */ + + if (flag_next_runtime) + return 0; + + { + tree parms, function_decl, decelerator, void_list_node; + tree function_type; + extern tree get_file_function_name (); + tree init_function_name = get_file_function_name ('I'); + + /* Declare void __objc_execClass (void *); */ + + void_list_node = build_tree_list (NULL_TREE, void_type_node); + function_type + = build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)); + function_decl = build_decl (FUNCTION_DECL, + get_identifier (TAG_EXECCLASS), + function_type); + DECL_EXTERNAL (function_decl) = 1; + DECL_ARTIFICIAL (function_decl) = 1; + TREE_PUBLIC (function_decl) = 1; + + pushdecl (function_decl); + rest_of_decl_compilation (function_decl, 0, 0, 0); + + parms + = build_tree_list (NULL_TREE, + build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0)); + decelerator = build_function_call (function_decl, parms); + + /* void _GLOBAL_$I$<gnyf> () {objc_execClass (&L_OBJC_MODULES);} */ + + start_function (void_list_node, + build_parse_node (CALL_EXPR, init_function_name, + /* This has the format of the output + of get_parm_info. */ + tree_cons (NULL_TREE, NULL_TREE, + void_list_node), + NULL_TREE), + NULL_TREE, NULL_TREE, 0); +#if 0 /* This should be turned back on later + for the systems where collect is not needed. */ + /* Make these functions nonglobal + so each file can use the same name. */ + TREE_PUBLIC (current_function_decl) = 0; +#endif + TREE_USED (current_function_decl) = 1; + store_parm_decls (); + + assemble_external (function_decl); + c_expand_expr_stmt (decelerator); + + TREE_PUBLIC (current_function_decl) = 1; + + function_decl = current_function_decl; + finish_function (0); + + /* Return the name of the constructor function. */ + return XSTR (XEXP (DECL_RTL (function_decl), 0), 0); + } +} + +/* extern const char _OBJC_STRINGS[]; */ + +static void +generate_forward_declaration_to_string_table () +{ + tree sc_spec, decl_specs, expr_decl; + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); + + expr_decl + = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE); + + UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs); +} + +/* Return the DECL of the string IDENT in the SECTION. */ + +static tree +get_objc_string_decl (ident, section) + tree ident; + enum string_section section; +{ + tree chain, decl; + + if (section == class_names) + chain = class_names_chain; + else if (section == meth_var_names) + chain = meth_var_names_chain; + else if (section == meth_var_types) + chain = meth_var_types_chain; + + for (; chain != 0; chain = TREE_VALUE (chain)) + if (TREE_VALUE (chain) == ident) + return (TREE_PURPOSE (chain)); + + abort (); + return NULL_TREE; +} + +/* Output references to all statically allocated objects. Return the DECL + for the array built. */ + +static void +generate_static_references () +{ + tree decls = NULL_TREE, ident, decl_spec, expr_decl, expr = NULL_TREE; + tree class_name, class, decl, instance, idecl, initlist; + tree cl_chain, in_chain, type; + int num_inst, num_class; + char buf[256]; + + if (flag_next_runtime) + abort (); + + for (cl_chain = objc_static_instances, num_class = 0; + cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++) + { + for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain); + in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain)); + + sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class); + ident = get_identifier (buf); + + expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE); + decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), + build_tree_list (NULL_TREE, + ridpointers[(int) RID_STATIC])); + decl = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE); + DECL_CONTEXT (decl) = 0; + DECL_ARTIFICIAL (decl) = 1; + + /* Output {class_name, ...}. */ + class = TREE_VALUE (cl_chain); + class_name = get_objc_string_decl (TYPE_NAME (class), class_names); + initlist = build_tree_list (NULL_TREE, + build_unary_op (ADDR_EXPR, class_name, 1)); + + /* Output {..., instance, ...}. */ + for (in_chain = TREE_PURPOSE (cl_chain); + in_chain; in_chain = TREE_CHAIN (in_chain)) + { + expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + /* Output {..., NULL}. */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + + expr = build_constructor (TREE_TYPE (decl), nreverse (initlist)); + finish_decl (decl, expr, NULL_TREE); + TREE_USED (decl) = 1; + + type = build_array_type (build_pointer_type (void_type_node), 0); + decl = build_decl (VAR_DECL, ident, type); + make_decl_rtl (decl, 0, 1); + TREE_USED (decl) = 1; + decls + = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, decl, 1), decls); + } + + decls = tree_cons (NULL_TREE, build_int_2 (0, 0), decls); + ident = get_identifier ("_OBJC_STATIC_INSTANCES"); + expr_decl = build_nt (ARRAY_REF, ident, NULL_TREE); + decl_spec = tree_cons (NULL_TREE, build_pointer_type (void_type_node), + build_tree_list (NULL_TREE, + ridpointers[(int) RID_STATIC])); + static_instances_decl + = start_decl (expr_decl, decl_spec, 1, NULL_TREE, NULL_TREE); + TREE_USED (static_instances_decl) = 1; + DECL_CONTEXT (static_instances_decl) = 0; + DECL_ARTIFICIAL (static_instances_decl) = 1; + end_temporary_allocation (); + expr = build_constructor (TREE_TYPE (static_instances_decl), + nreverse (decls)); + finish_decl (static_instances_decl, expr, NULL_TREE); +} + +/* Output all strings. */ + +static void +generate_strings () +{ + tree sc_spec, decl_specs, expr_decl; + tree chain, string_expr; + tree string, decl; + + for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + sc_spec + = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); + expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); + decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + end_temporary_allocation (); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_decl (decl, string_expr, NULL_TREE); + } + + for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + sc_spec + = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); + expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); + decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_decl (decl, string_expr, NULL_TREE); + } + + for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain)) + { + string = TREE_VALUE (chain); + decl = TREE_PURPOSE (chain); + sc_spec + = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec); + expr_decl = build_nt (ARRAY_REF, DECL_NAME (decl), NULL_TREE); + decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1, + IDENTIFIER_POINTER (string)); + finish_decl (decl, string_expr, NULL_TREE); + } +} + +static tree +build_selector_reference_decl (name) + tree name; +{ + tree decl, ident; + char buf[256]; + static int idx = 0; + + sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx++); + + push_obstacks_nochange (); + end_temporary_allocation (); + + ident = get_identifier (buf); + + decl = build_decl (VAR_DECL, ident, selector_type); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + TREE_USED (decl) = 1; + TREE_READONLY (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_CONTEXT (decl) = 0; + + make_decl_rtl (decl, 0, 1); + pushdecl_top_level (decl); + + pop_obstacks (); + + return decl; +} + +/* Just a handy wrapper for add_objc_string. */ + +static tree +build_selector (ident) + tree ident; +{ + tree expr = add_objc_string (ident, meth_var_names); + if (flag_typed_selectors) + return expr; + else + return build_c_cast (selector_type, expr); /* cast! */ +} + +/* Synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>] + The cast stops the compiler from issuing the following message: + grok.m: warning: initialization of non-const * pointer from const * + grok.m: warning: initialization between incompatible pointer types. */ + +static tree +build_msg_pool_reference (offset) + int offset; +{ + tree expr = build_int_2 (offset, 0); + tree cast; + + expr = build_array_ref (UOBJC_STRINGS_decl, expr); + expr = build_unary_op (ADDR_EXPR, expr, 0); + + cast = build_tree_list (build_tree_list (NULL_TREE, + ridpointers[(int) RID_CHAR]), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); + TREE_TYPE (expr) = groktypename (cast); + return expr; +} + +static tree +init_selector (offset) + int offset; +{ + tree expr = build_msg_pool_reference (offset); + TREE_TYPE (expr) = selector_type; + return expr; +} + +static void +build_selector_translation_table () +{ + tree sc_spec, decl_specs; + tree chain, initlist = NULL_TREE; + int offset = 0; + tree decl, var_decl, name; + + /* The corresponding pop_obstacks is in finish_decl, + called at the end of this function. */ + if (! flag_next_runtime) + push_obstacks_nochange (); + + for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) + { + tree expr; + + expr = build_selector (TREE_VALUE (chain)); + + if (flag_next_runtime) + { + name = DECL_NAME (TREE_PURPOSE (chain)); + + sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); + + /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */ + decl_specs = tree_cons (NULL_TREE, selector_type, sc_spec); + + var_decl = name; + + /* The `decl' that is returned from start_decl is the one that we + forward declared in `build_selector_reference' */ + decl = start_decl (var_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + } + + /* add one for the '\0' character */ + offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1; + + if (flag_next_runtime) + finish_decl (decl, expr, NULL_TREE); + else + { + if (flag_typed_selectors) + { + tree eltlist = NULL_TREE; + tree encoding = get_proto_encoding (TREE_PURPOSE (chain)); + eltlist = tree_cons (NULL_TREE, expr, NULL_TREE); + eltlist = tree_cons (NULL_TREE, encoding, eltlist); + expr = build_constructor (objc_selector_template, + nreverse (eltlist)); + } + initlist = tree_cons (NULL_TREE, expr, initlist); + + } + } + + if (! flag_next_runtime) + { + /* Cause the variable and its initial value to be actually output. */ + DECL_EXTERNAL (UOBJC_SELECTOR_TABLE_decl) = 0; + TREE_STATIC (UOBJC_SELECTOR_TABLE_decl) = 1; + /* NULL terminate the list and fix the decl for output. */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + DECL_INITIAL (UOBJC_SELECTOR_TABLE_decl) = (tree) 1; + initlist = build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl), + nreverse (initlist)); + finish_decl (UOBJC_SELECTOR_TABLE_decl, initlist, NULL_TREE); + current_function_decl = NULL_TREE; + } +} + +static tree +get_proto_encoding (proto) + tree proto; +{ + tree encoding; + if (proto) + { + tree tmp_decl; + + if (! METHOD_ENCODING (proto)) + { + tmp_decl = build_tmp_function_decl (); + hack_method_prototype (proto, tmp_decl); + encoding = encode_method_prototype (proto, tmp_decl); + METHOD_ENCODING (proto) = encoding; + } + else + encoding = METHOD_ENCODING (proto); + + return add_objc_string (encoding, meth_var_types); + } + else + return build_int_2 (0, 0); +} + +/* sel_ref_chain is a list whose "value" fields will be instances of + identifier_node that represent the selector. */ + +static tree +build_typed_selector_reference (ident, proto) + tree ident, proto; +{ + tree *chain = &sel_ref_chain; + tree expr; + int index = 0; + + while (*chain) + { + if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto) + goto return_at_index; + + index++; + chain = &TREE_CHAIN (*chain); + } + + *chain = perm_tree_cons (proto, ident, NULL_TREE); + + return_at_index: + expr = build_unary_op (ADDR_EXPR, + build_array_ref (UOBJC_SELECTOR_TABLE_decl, + build_int_2 (index, 0)), + 1); + return build_c_cast (selector_type, expr); +} + +static tree +build_selector_reference (ident) + tree ident; +{ + tree *chain = &sel_ref_chain; + tree expr; + int index = 0; + + while (*chain) + { + if (TREE_VALUE (*chain) == ident) + return (flag_next_runtime + ? TREE_PURPOSE (*chain) + : build_array_ref (UOBJC_SELECTOR_TABLE_decl, + build_int_2 (index, 0))); + + index++; + chain = &TREE_CHAIN (*chain); + } + + expr = build_selector_reference_decl (ident); + + *chain = perm_tree_cons (expr, ident, NULL_TREE); + + return (flag_next_runtime + ? expr + : build_array_ref (UOBJC_SELECTOR_TABLE_decl, + build_int_2 (index, 0))); +} + +static tree +build_class_reference_decl (name) + tree name; +{ + tree decl, ident; + char buf[256]; + static int idx = 0; + + sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", idx++); + + push_obstacks_nochange (); + end_temporary_allocation (); + + ident = get_identifier (buf); + + decl = build_decl (VAR_DECL, ident, objc_class_type); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + TREE_USED (decl) = 1; + TREE_READONLY (decl) = 1; + DECL_CONTEXT (decl) = 0; + DECL_ARTIFICIAL (decl) = 1; + + make_decl_rtl (decl, 0, 1); + pushdecl_top_level (decl); + + pop_obstacks (); + + return decl; +} + +/* Create a class reference, but don't create a variable to reference + it. */ + +static void +add_class_reference (ident) + tree ident; +{ + tree chain; + + if ((chain = cls_ref_chain)) + { + tree tail; + do + { + if (ident == TREE_VALUE (chain)) + return; + + tail = chain; + chain = TREE_CHAIN (chain); + } + while (chain); + + /* Append to the end of the list */ + TREE_CHAIN (tail) = perm_tree_cons (NULL_TREE, ident, NULL_TREE); + } + else + cls_ref_chain = perm_tree_cons (NULL_TREE, ident, NULL_TREE); +} + +/* Get a class reference, creating it if necessary. Also create the + reference variable. */ + +tree +get_class_reference (ident) + tree ident; +{ + if (flag_next_runtime) + { + tree *chain; + tree decl; + + for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain)) + if (TREE_VALUE (*chain) == ident) + { + if (! TREE_PURPOSE (*chain)) + TREE_PURPOSE (*chain) = build_class_reference_decl (ident); + + return TREE_PURPOSE (*chain); + } + + decl = build_class_reference_decl (ident); + *chain = perm_tree_cons (decl, ident, NULL_TREE); + return decl; + } + else + { + tree params; + + add_class_reference (ident); + + params = build_tree_list (NULL_TREE, + my_build_string (IDENTIFIER_LENGTH (ident) + 1, + IDENTIFIER_POINTER (ident))); + + assemble_external (objc_get_class_decl); + return build_function_call (objc_get_class_decl, params); + } +} + +/* SEL_REFDEF_CHAIN is a list whose "value" fields will be instances + of identifier_node that represent the selector. It returns the + offset of the selector from the beginning of the _OBJC_STRINGS + pool. This offset is typically used by init_selector during code + generation. + + For each string section we have a chain which maps identifier nodes + to decls for the strings. */ + +static tree +add_objc_string (ident, section) + tree ident; + enum string_section section; +{ + tree *chain, decl; + + if (section == class_names) + chain = &class_names_chain; + else if (section == meth_var_names) + chain = &meth_var_names_chain; + else if (section == meth_var_types) + chain = &meth_var_types_chain; + + while (*chain) + { + if (TREE_VALUE (*chain) == ident) + return build_unary_op (ADDR_EXPR, TREE_PURPOSE (*chain), 1); + + chain = &TREE_CHAIN (*chain); + } + + decl = build_objc_string_decl (ident, section); + + *chain = perm_tree_cons (decl, ident, NULL_TREE); + + return build_unary_op (ADDR_EXPR, decl, 1); +} + +static tree +build_objc_string_decl (name, section) + tree name; + enum string_section section; +{ + tree decl, ident; + char buf[256]; + static int class_names_idx = 0; + static int meth_var_names_idx = 0; + static int meth_var_types_idx = 0; + + if (section == class_names) + sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++); + else if (section == meth_var_names) + sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++); + else if (section == meth_var_types) + sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++); + + push_obstacks_nochange (); + end_temporary_allocation (); + ident = get_identifier (buf); + + decl = build_decl (VAR_DECL, ident, build_array_type (char_type_node, 0)); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + TREE_USED (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_CONSTANT (decl) = 1; + DECL_CONTEXT (decl) = 0; + DECL_ARTIFICIAL (decl) = 1; + + make_decl_rtl (decl, 0, 1); + pushdecl_top_level (decl); + + pop_obstacks (); + + return decl; +} + + +void +objc_declare_alias (alias_ident, class_ident) + tree alias_ident; + tree class_ident; +{ + if (!doing_objc_thang) + objc_fatal (); + + if (is_class_name (class_ident) != class_ident) + warning ("Cannot find class `%s'", IDENTIFIER_POINTER (class_ident)); + else if (is_class_name (alias_ident)) + warning ("Class `%s' already exists", IDENTIFIER_POINTER (alias_ident)); + else + alias_chain = tree_cons (class_ident, alias_ident, alias_chain); +} + +void +objc_declare_class (ident_list) + tree ident_list; +{ + tree list; + + if (!doing_objc_thang) + objc_fatal (); + + for (list = ident_list; list; list = TREE_CHAIN (list)) + { + tree ident = TREE_VALUE (list); + tree decl; + + if ((decl = lookup_name (ident))) + { + error ("`%s' redeclared as different kind of symbol", + IDENTIFIER_POINTER (ident)); + error_with_decl (decl, "previous declaration of `%s'"); + } + + if (! is_class_name (ident)) + { + tree record = xref_tag (RECORD_TYPE, ident); + TREE_STATIC_TEMPLATE (record) = 1; + class_chain = tree_cons (NULL_TREE, ident, class_chain); + } + } +} + +tree +is_class_name (ident) + tree ident; +{ + tree chain; + + if (lookup_interface (ident)) + return ident; + + for (chain = class_chain; chain; chain = TREE_CHAIN (chain)) + { + if (ident == TREE_VALUE (chain)) + return ident; + } + + for (chain = alias_chain; chain; chain = TREE_CHAIN (chain)) + { + if (ident == TREE_VALUE (chain)) + return TREE_PURPOSE (chain); + } + + return 0; +} + +tree +lookup_interface (ident) + tree ident; +{ + tree chain; + + for (chain = interface_chain; chain; chain = TREE_CHAIN (chain)) + { + if (ident == CLASS_NAME (chain)) + return chain; + } + return NULL_TREE; +} + +static tree +objc_copy_list (list, head) + tree list; + tree *head; +{ + tree newlist = NULL_TREE, tail = NULL_TREE; + + while (list) + { + tail = copy_node (list); + + /* The following statement fixes a bug when inheriting instance + variables that are declared to be bitfields. finish_struct + expects to find the width of the bitfield in DECL_INITIAL, + which it nulls out after processing the decl of the super + class...rather than change the way finish_struct works (which + is risky), I create the situation it expects...s.naroff + (7/23/89). */ + + if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0) + DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0); + + newlist = chainon (newlist, tail); + list = TREE_CHAIN (list); + } + + *head = newlist; + return tail; +} + +/* Used by: build_private_template, get_class_ivars, and + continue_class. COPY is 1 when called from @defs. In this case + copy all fields. Otherwise don't copy leaf ivars since we rely on + them being side-effected exactly once by finish_struct. */ + +static tree +build_ivar_chain (interface, copy) + tree interface; + int copy; +{ + tree my_name, super_name, ivar_chain; + + my_name = CLASS_NAME (interface); + super_name = CLASS_SUPER_NAME (interface); + + /* Possibly copy leaf ivars. */ + if (copy) + objc_copy_list (CLASS_IVARS (interface), &ivar_chain); + else + ivar_chain = CLASS_IVARS (interface); + + while (super_name) + { + tree op1; + tree super_interface = lookup_interface (super_name); + + if (!super_interface) + { + /* fatal did not work with 2 args...should fix */ + error ("Cannot find interface declaration for `%s', superclass of `%s'", + IDENTIFIER_POINTER (super_name), + IDENTIFIER_POINTER (my_name)); + exit (FATAL_EXIT_CODE); + } + + if (super_interface == interface) + { + fatal ("Circular inheritance in interface declaration for `%s'", + IDENTIFIER_POINTER (super_name)); + } + + interface = super_interface; + my_name = CLASS_NAME (interface); + super_name = CLASS_SUPER_NAME (interface); + + op1 = CLASS_IVARS (interface); + if (op1) + { + tree head, tail = objc_copy_list (op1, &head); + + /* Prepend super class ivars...make a copy of the list, we + do not want to alter the original. */ + TREE_CHAIN (tail) = ivar_chain; + ivar_chain = head; + } + } + return ivar_chain; +} + +/* struct <classname> { + struct objc_class *isa; + ... + }; */ + +static tree +build_private_template (class) + tree class; +{ + tree ivar_context; + + if (CLASS_STATIC_TEMPLATE (class)) + { + uprivate_record = CLASS_STATIC_TEMPLATE (class); + ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class)); + } + else + { + uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class)); + + ivar_context = build_ivar_chain (class, 0); + + finish_struct (uprivate_record, ivar_context, NULL_TREE); + + CLASS_STATIC_TEMPLATE (class) = uprivate_record; + + /* mark this record as class template - for class type checking */ + TREE_STATIC_TEMPLATE (uprivate_record) = 1; + } + + instance_type + = groktypename (build_tree_list (build_tree_list (NULL_TREE, + uprivate_record), + build1 (INDIRECT_REF, NULL_TREE, + NULL_TREE))); + + return ivar_context; +} + +/* Begin code generation for protocols... */ + +/* struct objc_protocol { + char *protocol_name; + struct objc_protocol **protocol_list; + struct objc_method_desc *instance_methods; + struct objc_method_desc *class_methods; + }; */ + +static tree +build_protocol_template () +{ + tree decl_specs, field_decl, field_decl_chain; + tree template; + + template = start_struct (RECORD_TYPE, get_identifier (UTAG_PROTOCOL)); + + /* struct objc_class *isa; */ + + decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, + get_identifier (UTAG_CLASS))); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* char *protocol_name; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_name")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_protocol **protocol_list; */ + + decl_specs = build_tree_list (NULL_TREE, template); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list")); + field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_method_list *instance_methods; */ + + decl_specs + = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_method_list *class_methods; */ + + decl_specs + = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + return finish_struct (template, field_decl_chain, NULL_TREE); +} + +static tree +build_descriptor_table_initializer (type, entries) + tree type; + tree entries; +{ + tree initlist = NULL_TREE; + + do + { + tree eltlist = NULL_TREE; + + eltlist + = tree_cons (NULL_TREE, + build_selector (METHOD_SEL_NAME (entries)), NULL_TREE); + eltlist + = tree_cons (NULL_TREE, + add_objc_string (METHOD_ENCODING (entries), + meth_var_types), + eltlist); + + initlist + = tree_cons (NULL_TREE, + build_constructor (type, nreverse (eltlist)), initlist); + + entries = TREE_CHAIN (entries); + } + while (entries); + + return build_constructor (build_array_type (type, 0), nreverse (initlist)); +} + +/* struct objc_method_prototype_list { + int count; + struct objc_method_prototype { + SEL name; + char *types; + } list[1]; + }; */ + +static tree +build_method_prototype_list_template (list_type, size) + tree list_type; + int size; +{ + tree objc_ivar_list_record; + tree decl_specs, field_decl, field_decl_chain; + + /* Generate an unnamed struct definition. */ + + objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE); + + /* int method_count; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); + field_decl = get_identifier ("method_count"); + + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* struct objc_method method_list[]; */ + + decl_specs = build_tree_list (NULL_TREE, list_type); + field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"), + build_int_2 (size, 0)); + + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE); + + return objc_ivar_list_record; +} + +static tree +build_method_prototype_template () +{ + tree proto_record; + tree decl_specs, field_decl, field_decl_chain; + + proto_record + = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD_PROTOTYPE)); + +#ifdef OBJC_INT_SELECTORS + /* unsigned int _cmd; */ + decl_specs + = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); + field_decl = get_identifier ("_cmd"); +#else /* OBJC_INT_SELECTORS */ + /* struct objc_selector *_cmd; */ + decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE, + get_identifier (TAG_SELECTOR)), NULL_TREE); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd")); +#endif /* OBJC_INT_SELECTORS */ + + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_types")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (proto_record, field_decl_chain, NULL_TREE); + + return proto_record; +} + +/* True if last call to forwarding_offset yielded a register offset. */ +static int offset_is_register; + +static int +forwarding_offset (parm) + tree parm; +{ + int offset_in_bytes; + + if (GET_CODE (DECL_INCOMING_RTL (parm)) == MEM) + { + rtx addr = XEXP (DECL_INCOMING_RTL (parm), 0); + + /* ??? Here we assume that the parm address is indexed + off the frame pointer or arg pointer. + If that is not true, we produce meaningless results, + but do not crash. */ + if (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 1)) == CONST_INT) + offset_in_bytes = INTVAL (XEXP (addr, 1)); + else + offset_in_bytes = 0; + + offset_in_bytes += OBJC_FORWARDING_STACK_OFFSET; + offset_is_register = 0; + } + else if (GET_CODE (DECL_INCOMING_RTL (parm)) == REG) + { + int regno = REGNO (DECL_INCOMING_RTL (parm)); + offset_in_bytes = apply_args_register_offset (regno); + offset_is_register = 1; + } + else + return 0; + + /* This is the case where the parm is passed as an int or double + and it is converted to a char, short or float and stored back + in the parmlist. In this case, describe the parm + with the variable's declared type, and adjust the address + if the least significant bytes (which we are using) are not + the first ones. */ + if (BYTES_BIG_ENDIAN && TREE_TYPE (parm) != DECL_ARG_TYPE (parm)) + offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm))) + - GET_MODE_SIZE (GET_MODE (DECL_RTL (parm)))); + + return offset_in_bytes; +} + +static tree +encode_method_prototype (method_decl, func_decl) + tree method_decl; + tree func_decl; +{ + tree parms; + int stack_size, i; + tree user_args; + int max_parm_end = 0; + char buf[40]; + tree result; + + /* ONEWAY and BYCOPY, for remote object are the only method qualifiers. */ + encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (method_decl))); + + /* C type. */ + encode_type (TREE_TYPE (TREE_TYPE (func_decl)), + obstack_object_size (&util_obstack), + OBJC_ENCODE_INLINE_DEFS); + + /* Stack size. */ + for (parms = DECL_ARGUMENTS (func_decl); parms; + parms = TREE_CHAIN (parms)) + { + int parm_end = (forwarding_offset (parms) + + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms))) + / BITS_PER_UNIT)); + + if (!offset_is_register && max_parm_end < parm_end) + max_parm_end = parm_end; + } + + stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET; + + sprintf (buf, "%d", stack_size); + obstack_grow (&util_obstack, buf, strlen (buf)); + + user_args = METHOD_SEL_ARGS (method_decl); + + /* Argument types. */ + for (parms = DECL_ARGUMENTS (func_decl), i = 0; parms; + parms = TREE_CHAIN (parms), i++) + { + /* Process argument qualifiers for user supplied arguments. */ + if (i > 1) + { + encode_type_qualifiers (TREE_PURPOSE (TREE_TYPE (user_args))); + user_args = TREE_CHAIN (user_args); + } + + /* Type. */ + encode_type (TREE_TYPE (parms), + obstack_object_size (&util_obstack), + OBJC_ENCODE_INLINE_DEFS); + + /* Compute offset. */ + sprintf (buf, "%d", forwarding_offset (parms)); + + /* Indicate register. */ + if (offset_is_register) + obstack_1grow (&util_obstack, '+'); + + obstack_grow (&util_obstack, buf, strlen (buf)); + } + + obstack_1grow (&util_obstack, '\0'); + result = get_identifier (obstack_finish (&util_obstack)); + obstack_free (&util_obstack, util_firstobj); + return result; +} + +static tree +generate_descriptor_table (type, name, size, list, proto) + tree type; + char *name; + int size; + tree list; + tree proto; +{ + tree sc_spec, decl_specs, decl, initlist; + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, type, sc_spec); + + decl = start_decl (synth_id_with_class_suffix (name, proto), + decl_specs, 1, NULL_TREE, NULL_TREE); + + initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0)); + initlist = tree_cons (NULL_TREE, list, initlist); + + finish_decl (decl, build_constructor (type, nreverse (initlist)), + NULL_TREE); + + return decl; +} + +static void +generate_method_descriptors (protocol) /* generate_dispatch_tables */ + tree protocol; +{ + static tree objc_method_prototype_template; + tree initlist, chain, method_list_template; + tree cast, variable_length_type; + int size; + + if (!objc_method_prototype_template) + objc_method_prototype_template = build_method_prototype_template (); + + cast = build_tree_list (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_PROTOTYPE_LIST))), + NULL_TREE); + variable_length_type = groktypename (cast); + + chain = PROTOCOL_CLS_METHODS (protocol); + if (chain) + { + size = list_length (chain); + + method_list_template + = build_method_prototype_list_template (objc_method_prototype_template, + size); + + initlist + = build_descriptor_table_initializer (objc_method_prototype_template, + chain); + + UOBJC_CLASS_METHODS_decl + = generate_descriptor_table (method_list_template, + "_OBJC_PROTOCOL_CLASS_METHODS", + size, initlist, protocol); + TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type; + } + else + UOBJC_CLASS_METHODS_decl = 0; + + chain = PROTOCOL_NST_METHODS (protocol); + if (chain) + { + size = list_length (chain); + + method_list_template + = build_method_prototype_list_template (objc_method_prototype_template, + size); + initlist + = build_descriptor_table_initializer (objc_method_prototype_template, + chain); + + UOBJC_INSTANCE_METHODS_decl + = generate_descriptor_table (method_list_template, + "_OBJC_PROTOCOL_INSTANCE_METHODS", + size, initlist, protocol); + TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type; + } + else + UOBJC_INSTANCE_METHODS_decl = 0; +} + +static tree +build_tmp_function_decl () +{ + tree decl_specs, expr_decl, parms; + static int xxx = 0; + char buffer[80]; + + /* struct objc_object *objc_xxx (id, SEL, ...); */ + pushlevel (0); + decl_specs = build_tree_list (NULL_TREE, objc_object_reference); + push_parm_decl (build_tree_list + (build_tree_list (decl_specs, + build1 (INDIRECT_REF, NULL_TREE, + NULL_TREE)), + build_tree_list (NULL_TREE, NULL_TREE))); + + decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, + get_identifier (TAG_SELECTOR))); + expr_decl = build1 (INDIRECT_REF, NULL_TREE, NULL_TREE); + + push_parm_decl (build_tree_list (build_tree_list (decl_specs, expr_decl), + build_tree_list (NULL_TREE, NULL_TREE))); + parms = get_parm_info (0); + poplevel (0, 0, 0); + + decl_specs = build_tree_list (NULL_TREE, objc_object_reference); + sprintf (buffer, "__objc_tmp_%x", xxx++); + expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULL_TREE); + expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl); + + return define_decl (expr_decl, decl_specs); +} + +static void +hack_method_prototype (nst_methods, tmp_decl) + tree nst_methods; + tree tmp_decl; +{ + tree parms; + tree parm; + + /* Hack to avoid problem with static typing of self arg. */ + TREE_SET_CODE (nst_methods, CLASS_METHOD_DECL); + start_method_def (nst_methods); + TREE_SET_CODE (nst_methods, INSTANCE_METHOD_DECL); + + if (METHOD_ADD_ARGS (nst_methods) == (tree) 1) + parms = get_parm_info (0); /* we have a `, ...' */ + else + parms = get_parm_info (1); /* place a `void_at_end' */ + + poplevel (0, 0, 0); /* Must be called BEFORE start_function. */ + + /* Usually called from store_parm_decls -> init_function_start. */ + + DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms); + current_function_decl = tmp_decl; + + { + /* Code taken from start_function. */ + tree restype = TREE_TYPE (TREE_TYPE (tmp_decl)); + /* Promote the value to int before returning it. */ + if (TREE_CODE (restype) == INTEGER_TYPE + && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node)) + restype = integer_type_node; + DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype); + } + + for (parm = DECL_ARGUMENTS (tmp_decl); parm; parm = TREE_CHAIN (parm)) + DECL_CONTEXT (parm) = tmp_decl; + + init_function_start (tmp_decl, "objc-act", 0); + + /* Typically called from expand_function_start for function definitions. */ + assign_parms (tmp_decl, 0); + + /* install return type */ + TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods)); + +} + +static void +generate_protocol_references (plist) + tree plist; +{ + tree lproto; + + /* Forward declare protocols referenced. */ + for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) + { + tree proto = TREE_VALUE (lproto); + + if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE + && PROTOCOL_NAME (proto)) + { + if (! PROTOCOL_FORWARD_DECL (proto)) + build_protocol_reference (proto); + + if (PROTOCOL_LIST (proto)) + generate_protocol_references (PROTOCOL_LIST (proto)); + } + } +} + +static void +generate_protocols () +{ + tree p, tmp_decl, encoding; + tree sc_spec, decl_specs, decl; + tree initlist, protocol_name_expr, refs_decl, refs_expr; + tree cast_type2 = 0; + + tmp_decl = build_tmp_function_decl (); + + if (! objc_protocol_template) + objc_protocol_template = build_protocol_template (); + + /* If a protocol was directly referenced, pull in indirect references. */ + for (p = protocol_chain; p; p = TREE_CHAIN (p)) + if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p)) + generate_protocol_references (PROTOCOL_LIST (p)); + + for (p = protocol_chain; p; p = TREE_CHAIN (p)) + { + tree nst_methods = PROTOCOL_NST_METHODS (p); + tree cls_methods = PROTOCOL_CLS_METHODS (p); + + /* If protocol wasn't referenced, don't generate any code. */ + if (! PROTOCOL_FORWARD_DECL (p)) + continue; + + /* Make sure we link in the Protocol class. */ + add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME)); + + while (nst_methods) + { + if (! METHOD_ENCODING (nst_methods)) + { + hack_method_prototype (nst_methods, tmp_decl); + encoding = encode_method_prototype (nst_methods, tmp_decl); + METHOD_ENCODING (nst_methods) = encoding; + } + nst_methods = TREE_CHAIN (nst_methods); + } + + while (cls_methods) + { + if (! METHOD_ENCODING (cls_methods)) + { + hack_method_prototype (cls_methods, tmp_decl); + encoding = encode_method_prototype (cls_methods, tmp_decl); + METHOD_ENCODING (cls_methods) = encoding; + } + + cls_methods = TREE_CHAIN (cls_methods); + } + generate_method_descriptors (p); + + if (PROTOCOL_LIST (p)) + refs_decl = generate_protocol_list (p); + else + refs_decl = 0; + + /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], + NULL_TREE); + decl_specs = tree_cons (NULL_TREE, objc_protocol_template, sc_spec); + + decl = start_decl (synth_id_with_class_suffix ("_OBJC_PROTOCOL", p), + decl_specs, 1, NULL_TREE, NULL_TREE); + + protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names); + + if (refs_decl) + { + if (!cast_type2) + cast_type2 + = groktypename + (build_tree_list (build_tree_list (NULL_TREE, + objc_protocol_template), + build1 (INDIRECT_REF, NULL_TREE, + build1 (INDIRECT_REF, NULL_TREE, + NULL_TREE)))); + + refs_expr = build_unary_op (ADDR_EXPR, refs_decl, 0); + TREE_TYPE (refs_expr) = cast_type2; + } + else + refs_expr = build_int_2 (0, 0); + + /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set + by generate_method_descriptors, which is called above. */ + initlist = build_protocol_initializer (TREE_TYPE (decl), + protocol_name_expr, refs_expr, + UOBJC_INSTANCE_METHODS_decl, + UOBJC_CLASS_METHODS_decl); + finish_decl (decl, initlist, NULL_TREE); + + /* Mark the decl as used to avoid "defined but not used" warning. */ + TREE_USED (decl) = 1; + } +} + +static tree +build_protocol_initializer (type, protocol_name, protocol_list, + instance_methods, class_methods) + tree type; + tree protocol_name; + tree protocol_list; + tree instance_methods; + tree class_methods; +{ + tree initlist = NULL_TREE, expr; + static tree cast_type = 0; + + if (!cast_type) + cast_type + = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_CLASS))), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); + + /* Filling the "isa" in with one allows the runtime system to + detect that the version change...should remove before final release. */ + + expr = build_int_2 (PROTOCOL_VERSION, 0); + TREE_TYPE (expr) = cast_type; + initlist = tree_cons (NULL_TREE, expr, initlist); + initlist = tree_cons (NULL_TREE, protocol_name, initlist); + initlist = tree_cons (NULL_TREE, protocol_list, initlist); + + if (!instance_methods) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + expr = build_unary_op (ADDR_EXPR, instance_methods, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + if (!class_methods) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + expr = build_unary_op (ADDR_EXPR, class_methods, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + return build_constructor (type, nreverse (initlist)); +} + +/* struct objc_category { + char *category_name; + char *class_name; + struct objc_method_list *instance_methods; + struct objc_method_list *class_methods; + struct objc_protocol_list *protocols; + }; */ + +static void +build_category_template () +{ + tree decl_specs, field_decl, field_decl_chain; + + objc_category_template = start_struct (RECORD_TYPE, + get_identifier (UTAG_CATEGORY)); + /* char *category_name; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("category_name")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* char *class_name; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_name")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_method_list *instance_methods; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_LIST))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("instance_methods")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_method_list *class_methods; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_LIST))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class_methods")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_protocol **protocol_list; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list")); + field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_category_template, field_decl_chain, NULL_TREE); +} + +/* struct objc_selector { + void *sel_id; + char *sel_type; + }; */ + +static void +build_selector_template () +{ + + tree decl_specs, field_decl, field_decl_chain; + + objc_selector_template + = start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR)); + + /* void *sel_id; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* char *sel_type; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_type")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_selector_template, field_decl_chain, NULL_TREE); +} + +/* struct objc_class { + struct objc_class *isa; + struct objc_class *super_class; + char *name; + long version; + long info; + long instance_size; + struct objc_ivar_list *ivars; + struct objc_method_list *methods; + if (flag_next_runtime) + struct objc_cache *cache; + else { + struct sarray *dtable; + struct objc_class *subclass_list; + struct objc_class *sibling_class; + } + struct objc_protocol_list *protocols; + }; */ + +static void +build_class_template () +{ + tree decl_specs, field_decl, field_decl_chain; + + objc_class_template + = start_struct (RECORD_TYPE, get_identifier (UTAG_CLASS)); + + /* struct objc_class *isa; */ + + decl_specs = build_tree_list (NULL_TREE, objc_class_template); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("isa")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* struct objc_class *super_class; */ + + decl_specs = build_tree_list (NULL_TREE, objc_class_template); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("super_class")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* char *name; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("name")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* long version; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); + field_decl = get_identifier ("version"); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* long info; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); + field_decl = get_identifier ("info"); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* long instance_size; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]); + field_decl = get_identifier ("instance_size"); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_ivar_list *ivars; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_IVAR_LIST))); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivars")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_method_list *methods; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_LIST))); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("methods")); + field_decl + = grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + if (flag_next_runtime) + { + /* struct objc_cache *cache; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier ("objc_cache"))); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("cache")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + } + else + { + /* struct sarray *dtable; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier ("sarray"))); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("dtable")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_class *subclass_list; */ + + decl_specs = build_tree_list (NULL_TREE, objc_class_template); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("subclass_list")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_class *sibling_class; */ + + decl_specs = build_tree_list (NULL_TREE, objc_class_template); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sibling_class")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + } + + /* struct objc_protocol **protocol_list; */ + + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("protocol_list")); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, field_decl); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + + finish_struct (objc_class_template, field_decl_chain, NULL_TREE); +} + +/* Generate appropriate forward declarations for an implementation. */ + +static void +synth_forward_declarations () +{ + tree sc_spec, decl_specs, an_id; + + /* extern struct objc_class _OBJC_CLASS_<my_name>; */ + + an_id = synth_id_with_class_suffix ("_OBJC_CLASS", implementation_context); + + sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]); + decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec); + UOBJC_CLASS_decl = define_decl (an_id, decl_specs); + TREE_USED (UOBJC_CLASS_decl) = 1; + DECL_ARTIFICIAL (UOBJC_CLASS_decl) = 1; + + /* extern struct objc_class _OBJC_METACLASS_<my_name>; */ + + an_id = synth_id_with_class_suffix ("_OBJC_METACLASS", + implementation_context); + + UOBJC_METACLASS_decl = define_decl (an_id, decl_specs); + TREE_USED (UOBJC_METACLASS_decl) = 1; + DECL_ARTIFICIAL(UOBJC_METACLASS_decl) = 1; + + /* Pre-build the following entities - for speed/convenience. */ + + an_id = get_identifier ("super_class"); + ucls_super_ref = build_component_ref (UOBJC_CLASS_decl, an_id); + uucls_super_ref = build_component_ref (UOBJC_METACLASS_decl, an_id); +} + +static void +error_with_ivar (message, decl, rawdecl) + char *message; + tree decl; + tree rawdecl; +{ + count_error (0); + + report_error_function (DECL_SOURCE_FILE (decl)); + + fprintf (stderr, "%s:%d: ", + DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); + bzero (errbuf, BUFSIZE); + fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf)); +} + +#define USERTYPE(t) \ + (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \ + || TREE_CODE (t) == ENUMERAL_TYPE) + +static void +check_ivars (inter, imp) + tree inter; + tree imp; +{ + tree intdecls = CLASS_IVARS (inter); + tree impdecls = CLASS_IVARS (imp); + tree rawintdecls = CLASS_RAW_IVARS (inter); + tree rawimpdecls = CLASS_RAW_IVARS (imp); + + while (1) + { + tree t1, t2; + + if (intdecls == 0 && impdecls == 0) + break; + if (intdecls == 0 || impdecls == 0) + { + error ("inconsistent instance variable specification"); + break; + } + + t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls); + + if (!comptypes (t1, t2)) + { + if (DECL_NAME (intdecls) == DECL_NAME (impdecls)) + { + error_with_ivar ("conflicting instance variable type", + impdecls, rawimpdecls); + error_with_ivar ("previous declaration of", + intdecls, rawintdecls); + } + else /* both the type and the name don't match */ + { + error ("inconsistent instance variable specification"); + break; + } + } + + else if (DECL_NAME (intdecls) != DECL_NAME (impdecls)) + { + error_with_ivar ("conflicting instance variable name", + impdecls, rawimpdecls); + error_with_ivar ("previous declaration of", + intdecls, rawintdecls); + } + + intdecls = TREE_CHAIN (intdecls); + impdecls = TREE_CHAIN (impdecls); + rawintdecls = TREE_CHAIN (rawintdecls); + rawimpdecls = TREE_CHAIN (rawimpdecls); + } +} + +/* Set super_type to the data type node for struct objc_super *, + first defining struct objc_super itself. + This needs to be done just once per compilation. */ + +static tree +build_super_template () +{ + tree record, decl_specs, field_decl, field_decl_chain; + + record = start_struct (RECORD_TYPE, get_identifier (UTAG_SUPER)); + + /* struct objc_object *self; */ + + decl_specs = build_tree_list (NULL_TREE, objc_object_reference); + field_decl = get_identifier ("self"); + field_decl = build1 (INDIRECT_REF, NULL_TREE, field_decl); + field_decl = grokfield (input_filename, lineno, + field_decl, decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* struct objc_class *class; */ + + decl_specs = get_identifier (UTAG_CLASS); + decl_specs = build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, decl_specs)); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("class")); + + field_decl = grokfield (input_filename, lineno, + field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (record, field_decl_chain, NULL_TREE); + + /* `struct objc_super *' */ + super_type = groktypename (build_tree_list (build_tree_list (NULL_TREE, + record), + build1 (INDIRECT_REF, + NULL_TREE, NULL_TREE))); + return record; +} + +/* struct objc_ivar { + char *ivar_name; + char *ivar_type; + int ivar_offset; + }; */ + +static tree +build_ivar_template () +{ + tree objc_ivar_id, objc_ivar_record; + tree decl_specs, field_decl, field_decl_chain; + + objc_ivar_id = get_identifier (UTAG_IVAR); + objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id); + + /* char *ivar_name; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_name")); + + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* char *ivar_type; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("ivar_type")); + + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* int ivar_offset; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); + field_decl = get_identifier ("ivar_offset"); + + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE); + + return objc_ivar_record; +} + +/* struct { + int ivar_count; + struct objc_ivar ivar_list[ivar_count]; + }; */ + +static tree +build_ivar_list_template (list_type, size) + tree list_type; + int size; +{ + tree objc_ivar_list_record; + tree decl_specs, field_decl, field_decl_chain; + + objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE); + + /* int ivar_count; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); + field_decl = get_identifier ("ivar_count"); + + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* struct objc_ivar ivar_list[]; */ + + decl_specs = build_tree_list (NULL_TREE, list_type); + field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"), + build_int_2 (size, 0)); + + field_decl = grokfield (input_filename, lineno, + field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE); + + return objc_ivar_list_record; +} + +/* struct { + int method_next; + int method_count; + struct objc_method method_list[method_count]; + }; */ + +static tree +build_method_list_template (list_type, size) + tree list_type; + int size; +{ + tree objc_ivar_list_record; + tree decl_specs, field_decl, field_decl_chain; + + objc_ivar_list_record = start_struct (RECORD_TYPE, NULL_TREE); + + /* int method_next; */ + + decl_specs + = build_tree_list + (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_PROTOTYPE_LIST))); + field_decl + = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("method_next")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + /* int method_count; */ + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]); + field_decl = get_identifier ("method_count"); + + field_decl = grokfield (input_filename, lineno, + field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* struct objc_method method_list[]; */ + + decl_specs = build_tree_list (NULL_TREE, list_type); + field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"), + build_int_2 (size, 0)); + + field_decl = grokfield (input_filename, lineno, + field_decl, decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE); + + return objc_ivar_list_record; +} + +static tree +build_ivar_list_initializer (type, field_decl) + tree type; + tree field_decl; +{ + tree initlist = NULL_TREE; + + do + { + tree ivar = NULL_TREE; + + /* Set name. */ + if (DECL_NAME (field_decl)) + ivar = tree_cons (NULL_TREE, + add_objc_string (DECL_NAME (field_decl), + meth_var_names), + ivar); + else + /* Unnamed bit-field ivar (yuck). */ + ivar = tree_cons (NULL_TREE, build_int_2 (0, 0), ivar); + + /* Set type. */ + encode_field_decl (field_decl, + obstack_object_size (&util_obstack), + OBJC_ENCODE_DONT_INLINE_DEFS); + + /* Null terminate string. */ + obstack_1grow (&util_obstack, 0); + ivar + = tree_cons + (NULL_TREE, + add_objc_string (get_identifier (obstack_finish (&util_obstack)), + meth_var_types), + ivar); + obstack_free (&util_obstack, util_firstobj); + + /* set offset */ + ivar + = tree_cons + (NULL_TREE, + build_int_2 ((TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) + / BITS_PER_UNIT), + 0), + ivar); + + initlist = tree_cons (NULL_TREE, + build_constructor (type, nreverse (ivar)), + initlist); + + field_decl = TREE_CHAIN (field_decl); + } + while (field_decl); + + return build_constructor (build_array_type (type, 0), nreverse (initlist)); +} + +static tree +generate_ivars_list (type, name, size, list) + tree type; + char *name; + int size; + tree list; +{ + tree sc_spec, decl_specs, decl, initlist; + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, type, sc_spec); + + decl = start_decl (synth_id_with_class_suffix (name, implementation_context), + decl_specs, 1, NULL_TREE, NULL_TREE); + + initlist = build_tree_list (NULL_TREE, build_int_2 (size, 0)); + initlist = tree_cons (NULL_TREE, list, initlist); + + finish_decl (decl, + build_constructor (TREE_TYPE (decl), nreverse (initlist)), + NULL_TREE); + + return decl; +} + +static void +generate_ivar_lists () +{ + tree initlist, ivar_list_template, chain; + tree cast, variable_length_type; + int size; + + generating_instance_variables = 1; + + if (!objc_ivar_template) + objc_ivar_template = build_ivar_template (); + + cast + = build_tree_list + (build_tree_list (NULL_TREE, xref_tag (RECORD_TYPE, + get_identifier (UTAG_IVAR_LIST))), + NULL_TREE); + variable_length_type = groktypename (cast); + + /* Only generate class variables for the root of the inheritance + hierarchy since these will be the same for every class. */ + + if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE + && (chain = TYPE_FIELDS (objc_class_template))) + { + size = list_length (chain); + + ivar_list_template = build_ivar_list_template (objc_ivar_template, size); + initlist = build_ivar_list_initializer (objc_ivar_template, chain); + + UOBJC_CLASS_VARIABLES_decl + = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES", + size, initlist); + TREE_TYPE (UOBJC_CLASS_VARIABLES_decl) = variable_length_type; + } + else + UOBJC_CLASS_VARIABLES_decl = 0; + + chain = CLASS_IVARS (implementation_template); + if (chain) + { + size = list_length (chain); + ivar_list_template = build_ivar_list_template (objc_ivar_template, size); + initlist = build_ivar_list_initializer (objc_ivar_template, chain); + + UOBJC_INSTANCE_VARIABLES_decl + = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES", + size, initlist); + TREE_TYPE (UOBJC_INSTANCE_VARIABLES_decl) = variable_length_type; + } + else + UOBJC_INSTANCE_VARIABLES_decl = 0; + + generating_instance_variables = 0; +} + +static tree +build_dispatch_table_initializer (type, entries) + tree type; + tree entries; +{ + tree initlist = NULL_TREE; + + do + { + tree elemlist = NULL_TREE; + + elemlist = tree_cons (NULL_TREE, + build_selector (METHOD_SEL_NAME (entries)), + NULL_TREE); + + elemlist = tree_cons (NULL_TREE, + add_objc_string (METHOD_ENCODING (entries), + meth_var_types), + elemlist); + + elemlist = tree_cons (NULL_TREE, + build_unary_op (ADDR_EXPR, + METHOD_DEFINITION (entries), 1), + elemlist); + + initlist = tree_cons (NULL_TREE, + build_constructor (type, nreverse (elemlist)), + initlist); + + entries = TREE_CHAIN (entries); + } + while (entries); + + return build_constructor (build_array_type (type, 0), nreverse (initlist)); +} + +/* To accomplish method prototyping without generating all kinds of + inane warnings, the definition of the dispatch table entries were + changed from: + + struct objc_method { SEL _cmd; ...; id (*_imp)(); }; + to: + struct objc_method { SEL _cmd; ...; void *_imp; }; */ + +static tree +build_method_template () +{ + tree _SLT_record; + tree decl_specs, field_decl, field_decl_chain; + + _SLT_record = start_struct (RECORD_TYPE, get_identifier (UTAG_METHOD)); + +#ifdef OBJC_INT_SELECTORS + /* unsigned int _cmd; */ + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_UNSIGNED], + NULL_TREE); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); + field_decl = get_identifier ("_cmd"); +#else /* not OBJC_INT_SELECTORS */ + /* struct objc_selector *_cmd; */ + decl_specs = tree_cons (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (TAG_SELECTOR)), + NULL_TREE); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_cmd")); +#endif /* not OBJC_INT_SELECTORS */ + + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + field_decl_chain = field_decl; + + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], NULL_TREE); + field_decl = build1 (INDIRECT_REF, NULL_TREE, + get_identifier ("method_types")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + /* void *_imp; */ + + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_VOID], NULL_TREE); + field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("_imp")); + field_decl = grokfield (input_filename, lineno, field_decl, + decl_specs, NULL_TREE); + chainon (field_decl_chain, field_decl); + + finish_struct (_SLT_record, field_decl_chain, NULL_TREE); + + return _SLT_record; +} + + +static tree +generate_dispatch_table (type, name, size, list) + tree type; + char *name; + int size; + tree list; +{ + tree sc_spec, decl_specs, decl, initlist; + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, type, sc_spec); + + decl = start_decl (synth_id_with_class_suffix (name, implementation_context), + decl_specs, 1, NULL_TREE, NULL_TREE); + + initlist = build_tree_list (NULL_TREE, build_int_2 (0, 0)); + initlist = tree_cons (NULL_TREE, build_int_2 (size, 0), initlist); + initlist = tree_cons (NULL_TREE, list, initlist); + + finish_decl (decl, + build_constructor (TREE_TYPE (decl), nreverse (initlist)), + NULL_TREE); + + return decl; +} + +static void +generate_dispatch_tables () +{ + tree initlist, chain, method_list_template; + tree cast, variable_length_type; + int size; + + if (!objc_method_template) + objc_method_template = build_method_template (); + + cast + = build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_METHOD_LIST))), + NULL_TREE); + + variable_length_type = groktypename (cast); + + chain = CLASS_CLS_METHODS (implementation_context); + if (chain) + { + size = list_length (chain); + + method_list_template + = build_method_list_template (objc_method_template, size); + initlist + = build_dispatch_table_initializer (objc_method_template, chain); + + UOBJC_CLASS_METHODS_decl + = generate_dispatch_table (method_list_template, + ((TREE_CODE (implementation_context) + == CLASS_IMPLEMENTATION_TYPE) + ? "_OBJC_CLASS_METHODS" + : "_OBJC_CATEGORY_CLASS_METHODS"), + size, initlist); + TREE_TYPE (UOBJC_CLASS_METHODS_decl) = variable_length_type; + } + else + UOBJC_CLASS_METHODS_decl = 0; + + chain = CLASS_NST_METHODS (implementation_context); + if (chain) + { + size = list_length (chain); + + method_list_template + = build_method_list_template (objc_method_template, size); + initlist + = build_dispatch_table_initializer (objc_method_template, chain); + + if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) + UOBJC_INSTANCE_METHODS_decl + = generate_dispatch_table (method_list_template, + "_OBJC_INSTANCE_METHODS", + size, initlist); + else + /* We have a category. */ + UOBJC_INSTANCE_METHODS_decl + = generate_dispatch_table (method_list_template, + "_OBJC_CATEGORY_INSTANCE_METHODS", + size, initlist); + TREE_TYPE (UOBJC_INSTANCE_METHODS_decl) = variable_length_type; + } + else + UOBJC_INSTANCE_METHODS_decl = 0; +} + +static tree +generate_protocol_list (i_or_p) + tree i_or_p; +{ + static tree cast_type = 0; + tree initlist, decl_specs, sc_spec; + tree refs_decl, expr_decl, lproto, e, plist; + int size = 0; + + if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE + || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE) + plist = CLASS_PROTOCOL_LIST (i_or_p); + else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE) + plist = PROTOCOL_LIST (i_or_p); + else + abort (); + + if (!cast_type) + cast_type + = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE))); + + /* Compute size. */ + for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) + if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE + && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto))) + size++; + + /* Build initializer. */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), NULL_TREE); + + e = build_int_2 (size, 0); + TREE_TYPE (e) = cast_type; + initlist = tree_cons (NULL_TREE, e, initlist); + + for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) + { + tree pval = TREE_VALUE (lproto); + + if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE + && PROTOCOL_FORWARD_DECL (pval)) + { + e = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (pval), 0); + initlist = tree_cons (NULL_TREE, e, initlist); + } + } + + /* static struct objc_protocol *refs[n]; */ + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL)), + sc_spec); + + if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE) + expr_decl = build_nt (ARRAY_REF, + synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", + i_or_p), + build_int_2 (size + 2, 0)); + else if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE) + expr_decl = build_nt (ARRAY_REF, + synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", + i_or_p), + build_int_2 (size + 2, 0)); + else if (TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE) + expr_decl + = build_nt (ARRAY_REF, + synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", + i_or_p), + build_int_2 (size + 2, 0)); + + expr_decl = build1 (INDIRECT_REF, NULL_TREE, expr_decl); + + refs_decl = start_decl (expr_decl, decl_specs, 1, NULL_TREE, NULL_TREE); + + finish_decl (refs_decl, build_constructor (TREE_TYPE (refs_decl), + nreverse (initlist)), + NULL_TREE); + + return refs_decl; +} + +static tree +build_category_initializer (type, cat_name, class_name, + instance_methods, class_methods, protocol_list) + tree type; + tree cat_name; + tree class_name; + tree instance_methods; + tree class_methods; + tree protocol_list; +{ + tree initlist = NULL_TREE, expr; + + initlist = tree_cons (NULL_TREE, cat_name, initlist); + initlist = tree_cons (NULL_TREE, class_name, initlist); + + if (!instance_methods) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + expr = build_unary_op (ADDR_EXPR, instance_methods, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + if (!class_methods) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + expr = build_unary_op (ADDR_EXPR, class_methods, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + /* protocol_list = */ + if (!protocol_list) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + static tree cast_type2; + + if (!cast_type2) + cast_type2 + = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))), + build1 (INDIRECT_REF, NULL_TREE, + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); + + expr = build_unary_op (ADDR_EXPR, protocol_list, 0); + TREE_TYPE (expr) = cast_type2; + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + return build_constructor (type, nreverse (initlist)); +} + +/* struct objc_class { + struct objc_class *isa; + struct objc_class *super_class; + char *name; + long version; + long info; + long instance_size; + struct objc_ivar_list *ivars; + struct objc_method_list *methods; + if (flag_next_runtime) + struct objc_cache *cache; + else { + struct sarray *dtable; + struct objc_class *subclass_list; + struct objc_class *sibling_class; + } + struct objc_protocol_list *protocols; + }; */ + +static tree +build_shared_structure_initializer (type, isa, super, name, size, status, + dispatch_table, ivar_list, protocol_list) + tree type; + tree isa; + tree super; + tree name; + tree size; + int status; + tree dispatch_table; + tree ivar_list; + tree protocol_list; +{ + tree initlist = NULL_TREE, expr; + + /* isa = */ + initlist = tree_cons (NULL_TREE, isa, initlist); + + /* super_class = */ + initlist = tree_cons (NULL_TREE, super, initlist); + + /* name = */ + initlist = tree_cons (NULL_TREE, default_conversion (name), initlist); + + /* version = */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + + /* info = */ + initlist = tree_cons (NULL_TREE, build_int_2 (status, 0), initlist); + + /* instance_size = */ + initlist = tree_cons (NULL_TREE, size, initlist); + + /* objc_ivar_list = */ + if (!ivar_list) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + expr = build_unary_op (ADDR_EXPR, ivar_list, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + /* objc_method_list = */ + if (!dispatch_table) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + expr = build_unary_op (ADDR_EXPR, dispatch_table, 0); + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + if (flag_next_runtime) + /* method_cache = */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + /* dtable = */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + + /* subclass_list = */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + + /* sibling_class = */ + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + } + + /* protocol_list = */ + if (! protocol_list) + initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist); + else + { + static tree cast_type2; + + if (!cast_type2) + cast_type2 + = groktypename + (build_tree_list + (build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (UTAG_PROTOCOL))), + build1 (INDIRECT_REF, NULL_TREE, + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)))); + + expr = build_unary_op (ADDR_EXPR, protocol_list, 0); + TREE_TYPE (expr) = cast_type2; + initlist = tree_cons (NULL_TREE, expr, initlist); + } + + return build_constructor (type, nreverse (initlist)); +} + +/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */ + +static void +generate_category (cat) + tree cat; +{ + tree sc_spec, decl_specs, decl; + tree initlist, cat_name_expr, class_name_expr; + tree protocol_decl, category; + + add_class_reference (CLASS_NAME (cat)); + cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names); + + class_name_expr = add_objc_string (CLASS_NAME (cat), class_names); + + category = CLASS_CATEGORY_LIST (implementation_template); + + /* find the category interface from the class it is associated with */ + while (category) + { + if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category)) + break; + category = CLASS_CATEGORY_LIST (category); + } + + if (category && CLASS_PROTOCOL_LIST (category)) + { + generate_protocol_references (CLASS_PROTOCOL_LIST (category)); + protocol_decl = generate_protocol_list (category); + } + else + protocol_decl = 0; + + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + decl_specs = tree_cons (NULL_TREE, objc_category_template, sc_spec); + + decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY", + implementation_context), + decl_specs, 1, NULL_TREE, NULL_TREE); + + initlist = build_category_initializer (TREE_TYPE (decl), + cat_name_expr, class_name_expr, + UOBJC_INSTANCE_METHODS_decl, + UOBJC_CLASS_METHODS_decl, + protocol_decl); + + TREE_USED (decl) = 1; + finish_decl (decl, initlist, NULL_TREE); +} + +/* static struct objc_class _OBJC_METACLASS_Foo={ ... }; + static struct objc_class _OBJC_CLASS_Foo={ ... }; */ + +static void +generate_shared_structures () +{ + tree sc_spec, decl_specs, decl; + tree name_expr, super_expr, root_expr; + tree my_root_id = NULL_TREE, my_super_id = NULL_TREE; + tree cast_type, initlist, protocol_decl; + + my_super_id = CLASS_SUPER_NAME (implementation_template); + if (my_super_id) + { + add_class_reference (my_super_id); + + /* Compute "my_root_id" - this is required for code generation. + the "isa" for all meta class structures points to the root of + the inheritance hierarchy (e.g. "__Object")... */ + my_root_id = my_super_id; + do + { + tree my_root_int = lookup_interface (my_root_id); + + if (my_root_int && CLASS_SUPER_NAME (my_root_int)) + my_root_id = CLASS_SUPER_NAME (my_root_int); + else + break; + } + while (1); + } + else + /* No super class. */ + my_root_id = CLASS_NAME (implementation_template); + + cast_type + = groktypename (build_tree_list (build_tree_list (NULL_TREE, + objc_class_template), + build1 (INDIRECT_REF, + NULL_TREE, NULL_TREE))); + + name_expr = add_objc_string (CLASS_NAME (implementation_template), + class_names); + + /* Install class `isa' and `super' pointers at runtime. */ + if (my_super_id) + { + super_expr = add_objc_string (my_super_id, class_names); + super_expr = build_c_cast (cast_type, super_expr); /* cast! */ + } + else + super_expr = build_int_2 (0, 0); + + root_expr = add_objc_string (my_root_id, class_names); + root_expr = build_c_cast (cast_type, root_expr); /* cast! */ + + if (CLASS_PROTOCOL_LIST (implementation_template)) + { + generate_protocol_references + (CLASS_PROTOCOL_LIST (implementation_template)); + protocol_decl = generate_protocol_list (implementation_template); + } + else + protocol_decl = 0; + + /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ + + sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); + decl_specs = tree_cons (NULL_TREE, objc_class_template, sc_spec); + + decl = start_decl (DECL_NAME (UOBJC_METACLASS_decl), decl_specs, 1, + NULL_TREE, NULL_TREE); + + initlist + = build_shared_structure_initializer + (TREE_TYPE (decl), + root_expr, super_expr, name_expr, + build_int_2 ((TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) + / BITS_PER_UNIT), + 0), + 2 /*CLS_META*/, + UOBJC_CLASS_METHODS_decl, + UOBJC_CLASS_VARIABLES_decl, + protocol_decl); + + finish_decl (decl, initlist, NULL_TREE); + + /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ + + decl = start_decl (DECL_NAME (UOBJC_CLASS_decl), decl_specs, 1, + NULL_TREE, NULL_TREE); + + initlist + = build_shared_structure_initializer + (TREE_TYPE (decl), + build_unary_op (ADDR_EXPR, UOBJC_METACLASS_decl, 0), + super_expr, name_expr, + build_int_2 + ((TREE_INT_CST_LOW + (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) + / BITS_PER_UNIT), + 0), + 1 /*CLS_FACTORY*/, + UOBJC_INSTANCE_METHODS_decl, + UOBJC_INSTANCE_VARIABLES_decl, + protocol_decl); + + finish_decl (decl, initlist, NULL_TREE); +} + +static tree +synth_id_with_class_suffix (preamble, ctxt) + char *preamble; + tree ctxt; +{ + char *string; + if (TREE_CODE (ctxt) == CLASS_IMPLEMENTATION_TYPE + || TREE_CODE (ctxt) == CLASS_INTERFACE_TYPE) + { + char *class_name + = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); + string = (char *) alloca (strlen (preamble) + strlen (class_name) + 3); + sprintf (string, "%s_%s", preamble, + IDENTIFIER_POINTER (CLASS_NAME (ctxt))); + } + else if (TREE_CODE (ctxt) == CATEGORY_IMPLEMENTATION_TYPE + || TREE_CODE (ctxt) == CATEGORY_INTERFACE_TYPE) + { + /* We have a category. */ + char *class_name + = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); + char *class_super_name + = IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)); + string = (char *) alloca (strlen (preamble) + + strlen (class_name) + + strlen (class_super_name) + + 3); + sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name); + } + else if (TREE_CODE (ctxt) == PROTOCOL_INTERFACE_TYPE) + { + char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt)); + string + = (char *) alloca (strlen (preamble) + strlen (protocol_name) + 3); + sprintf (string, "%s_%s", preamble, protocol_name); + } + return get_identifier (string); +} + +static int +is_objc_type_qualifier (node) + tree node; +{ + return (TREE_CODE (node) == IDENTIFIER_NODE + && (node == ridpointers [(int) RID_CONST] + || node == ridpointers [(int) RID_VOLATILE] + || node == ridpointers [(int) RID_IN] + || node == ridpointers [(int) RID_OUT] + || node == ridpointers [(int) RID_INOUT] + || node == ridpointers [(int) RID_BYCOPY] + || node == ridpointers [(int) RID_ONEWAY])); +} + +/* If type is empty or only type qualifiers are present, add default + type of id (otherwise grokdeclarator will default to int). */ + +static tree +adjust_type_for_id_default (type) + tree type; +{ + tree declspecs, chain; + + if (!type) + return build_tree_list (build_tree_list (NULL_TREE, objc_object_reference), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); + + declspecs = TREE_PURPOSE (type); + + /* Determine if a typespec is present. */ + for (chain = declspecs; + chain; + chain = TREE_CHAIN (chain)) + { + if (!is_objc_type_qualifier (TREE_VALUE (chain))) + return type; + } + + return build_tree_list (tree_cons (NULL_TREE, objc_object_reference, + declspecs), + build1 (INDIRECT_REF, NULL_TREE, NULL_TREE)); +} + +/* Usage: + keyworddecl: + selector ':' '(' typename ')' identifier + + Purpose: + Transform an Objective-C keyword argument into + the C equivalent parameter declarator. + + In: key_name, an "identifier_node" (optional). + arg_type, a "tree_list" (optional). + arg_name, an "identifier_node". + + Note: It would be really nice to strongly type the preceding + arguments in the function prototype; however, then I + could not use the "accessor" macros defined in "tree.h". + + Out: an instance of "keyword_decl". */ + +tree +build_keyword_decl (key_name, arg_type, arg_name) + tree key_name; + tree arg_type; + tree arg_name; +{ + tree keyword_decl; + + /* If no type is specified, default to "id". */ + arg_type = adjust_type_for_id_default (arg_type); + + keyword_decl = make_node (KEYWORD_DECL); + + TREE_TYPE (keyword_decl) = arg_type; + KEYWORD_ARG_NAME (keyword_decl) = arg_name; + KEYWORD_KEY_NAME (keyword_decl) = key_name; + + return keyword_decl; +} + +/* Given a chain of keyword_decl's, synthesize the full keyword selector. */ + +static tree +build_keyword_selector (selector) + tree selector; +{ + int len = 0; + tree key_chain, key_name; + char *buf; + + for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain)) + { + if (TREE_CODE (selector) == KEYWORD_DECL) + key_name = KEYWORD_KEY_NAME (key_chain); + else if (TREE_CODE (selector) == TREE_LIST) + key_name = TREE_PURPOSE (key_chain); + + if (key_name) + len += IDENTIFIER_LENGTH (key_name) + 1; + else + /* Just a ':' arg. */ + len++; + } + + buf = (char *)alloca (len + 1); + bzero (buf, len + 1); + + for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain)) + { + if (TREE_CODE (selector) == KEYWORD_DECL) + key_name = KEYWORD_KEY_NAME (key_chain); + else if (TREE_CODE (selector) == TREE_LIST) + key_name = TREE_PURPOSE (key_chain); + + if (key_name) + strcat (buf, IDENTIFIER_POINTER (key_name)); + strcat (buf, ":"); + } + + return get_identifier (buf); +} + +/* Used for declarations and definitions. */ + +tree +build_method_decl (code, ret_type, selector, add_args) + enum tree_code code; + tree ret_type; + tree selector; + tree add_args; +{ + tree method_decl; + + /* If no type is specified, default to "id". */ + ret_type = adjust_type_for_id_default (ret_type); + + method_decl = make_node (code); + TREE_TYPE (method_decl) = ret_type; + + /* If we have a keyword selector, create an identifier_node that + represents the full selector name (`:' included)... */ + if (TREE_CODE (selector) == KEYWORD_DECL) + { + METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector); + METHOD_SEL_ARGS (method_decl) = selector; + METHOD_ADD_ARGS (method_decl) = add_args; + } + else + { + METHOD_SEL_NAME (method_decl) = selector; + METHOD_SEL_ARGS (method_decl) = NULL_TREE; + METHOD_ADD_ARGS (method_decl) = NULL_TREE; + } + + return method_decl; +} + +#define METHOD_DEF 0 +#define METHOD_REF 1 + +/* Used by `build_message_expr' and `comp_method_types'. Return an + argument list for method METH. CONTEXT is either METHOD_DEF or + METHOD_REF, saying whether we are trying to define a method or call + one. SUPERFLAG says this is for a send to super; this makes a + difference for the NeXT calling sequence in which the lookup and + the method call are done together. */ + +static tree +get_arg_type_list (meth, context, superflag) + tree meth; + int context; + int superflag; +{ + tree arglist, akey; + + /* Receiver type. */ + if (flag_next_runtime && superflag) + arglist = build_tree_list (NULL_TREE, super_type); + else if (context == METHOD_DEF) + arglist = build_tree_list (NULL_TREE, TREE_TYPE (self_decl)); + else + arglist = build_tree_list (NULL_TREE, id_type); + + /* Selector type - will eventually change to `int'. */ + chainon (arglist, build_tree_list (NULL_TREE, selector_type)); + + /* Build a list of argument types. */ + for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey)) + { + tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey)); + chainon (arglist, build_tree_list (NULL_TREE, TREE_TYPE (arg_decl))); + } + + if (METHOD_ADD_ARGS (meth) == (tree)1) + /* We have a `, ...' immediately following the selector, + finalize the arglist...simulate get_parm_info (0). */ + ; + else if (METHOD_ADD_ARGS (meth)) + { + /* we have a variable length selector */ + tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth)); + chainon (arglist, add_arg_list); + } + else + /* finalize the arglist...simulate get_parm_info (1) */ + chainon (arglist, build_tree_list (NULL_TREE, void_type_node)); + + return arglist; +} + +static tree +check_duplicates (hsh) + hash hsh; +{ + tree meth = NULL_TREE; + + if (hsh) + { + meth = hsh->key; + + if (hsh->list) + { + /* We have two methods with the same name and different types. */ + attr loop; + char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+'; + + warning ("multiple declarations for method `%s'", + IDENTIFIER_POINTER (METHOD_SEL_NAME (meth))); + + warn_with_method ("using", type, meth); + for (loop = hsh->list; loop; loop = loop->next) + warn_with_method ("also found", type, loop->value); + } + } + return meth; +} + +/* If RECEIVER is a class reference, return the identifier node for the + referenced class. RECEIVER is created by get_class_reference, so we + check the exact form created depending on which runtimes are used. */ + +static tree +receiver_is_class_object (receiver) + tree receiver; +{ + tree chain, exp, arg; + if (flag_next_runtime) + { + /* The receiver is a variable created by build_class_reference_decl. */ + if (TREE_CODE (receiver) == VAR_DECL + && TREE_TYPE (receiver) == objc_class_type) + /* Look up the identifier. */ + for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain)) + if (TREE_PURPOSE (chain) == receiver) + return TREE_VALUE (chain); + } + else + { + /* The receiver is a function call that returns an id. Check if + it is a call to objc_getClass, if so, pick up the class name. */ + if ((exp = TREE_OPERAND (receiver, 0)) + && TREE_CODE (exp) == ADDR_EXPR + && (exp = TREE_OPERAND (exp, 0)) + && TREE_CODE (exp) == FUNCTION_DECL + && exp == objc_get_class_decl + /* we have a call to objc_getClass! */ + && (arg = TREE_OPERAND (receiver, 1)) + && TREE_CODE (arg) == TREE_LIST + && (arg = TREE_VALUE (arg))) + { + STRIP_NOPS (arg); + if (TREE_CODE (arg) == ADDR_EXPR + && (arg = TREE_OPERAND (arg, 0)) + && TREE_CODE (arg) == STRING_CST) + /* Finally, we have the class name. */ + return get_identifier (TREE_STRING_POINTER (arg)); + } + } + return 0; +} + +/* If we are currently building a message expr, this holds + the identifier of the selector of the message. This is + used when printing warnings about argument mismatches. */ + +static tree building_objc_message_expr = 0; + +tree +maybe_building_objc_message_expr () +{ + return building_objc_message_expr; +} + +/* Construct an expression for sending a message. + MESS has the object to send to in TREE_PURPOSE + and the argument list (including selector) in TREE_VALUE. + + (*(<abstract_decl>(*)())_msg)(receiver, selTransTbl[n], ...); + (*(<abstract_decl>(*)())_msgSuper)(receiver, selTransTbl[n], ...); */ + +tree +build_message_expr (mess) + tree mess; +{ + tree receiver = TREE_PURPOSE (mess); + tree selector, self_object; + tree rtype, sel_name; + tree args = TREE_VALUE (mess); + tree method_params = NULL_TREE; + tree method_prototype = NULL_TREE; + tree retval; + int statically_typed = 0, statically_allocated = 0; + tree class_ident = 0; + + /* 1 if this is sending to the superclass. */ + int super; + + if (!doing_objc_thang) + objc_fatal (); + + if (TREE_CODE (receiver) == ERROR_MARK) + return error_mark_node; + + /* Determine receiver type. */ + rtype = TREE_TYPE (receiver); + super = IS_SUPER (rtype); + + if (! super) + { + if (TREE_STATIC_TEMPLATE (rtype)) + statically_allocated = 1; + else if (TREE_CODE (rtype) == POINTER_TYPE + && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype))) + statically_typed = 1; + else if ((flag_next_runtime + || (TREE_CODE (receiver) == CALL_EXPR && IS_ID (rtype))) + && (class_ident = receiver_is_class_object (receiver))) + ; + else if (! IS_ID (rtype) + /* Allow any type that matches objc_class_type. */ + && ! comptypes (rtype, objc_class_type)) + { + bzero (errbuf, BUFSIZE); + warning ("invalid receiver type `%s'", + gen_declaration (rtype, errbuf)); + } + + if (statically_allocated) + receiver = build_unary_op (ADDR_EXPR, receiver, 0); + + /* Don't evaluate the receiver twice. */ + receiver = save_expr (receiver); + self_object = receiver; + } + else + /* If sending to `super', use current self as the object. */ + self_object = self_decl; + + /* Obtain the full selector name. */ + + if (TREE_CODE (args) == IDENTIFIER_NODE) + /* A unary selector. */ + sel_name = args; + else if (TREE_CODE (args) == TREE_LIST) + sel_name = build_keyword_selector (args); + + /* Build the parameter list to give to the method. */ + + method_params = NULL_TREE; + if (TREE_CODE (args) == TREE_LIST) + { + tree chain = args, prev = NULL_TREE; + + /* We have a keyword selector--check for comma expressions. */ + while (chain) + { + tree element = TREE_VALUE (chain); + + /* We have a comma expression, must collapse... */ + if (TREE_CODE (element) == TREE_LIST) + { + if (prev) + TREE_CHAIN (prev) = element; + else + args = element; + } + prev = chain; + chain = TREE_CHAIN (chain); + } + method_params = args; + } + + /* Determine operation return type. */ + + if (IS_SUPER (rtype)) + { + tree iface; + + if (CLASS_SUPER_NAME (implementation_template)) + { + iface + = lookup_interface (CLASS_SUPER_NAME (implementation_template)); + + if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL) + method_prototype = lookup_instance_method_static (iface, sel_name); + else + method_prototype = lookup_class_method_static (iface, sel_name); + + if (iface && !method_prototype) + warning ("`%s' does not respond to `%s'", + IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)), + IDENTIFIER_POINTER (sel_name)); + } + else + { + error ("no super class declared in interface for `%s'", + IDENTIFIER_POINTER (CLASS_NAME (implementation_template))); + return error_mark_node; + } + + } + else if (statically_allocated) + { + tree ctype = TREE_TYPE (rtype); + tree iface = lookup_interface (TYPE_NAME (rtype)); + + if (iface) + method_prototype = lookup_instance_method_static (iface, sel_name); + + if (! method_prototype && TYPE_PROTOCOL_LIST (ctype)) + method_prototype + = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype), + sel_name, 0); + + if (!method_prototype) + warning ("`%s' does not respond to `%s'", + IDENTIFIER_POINTER (TYPE_NAME (rtype)), + IDENTIFIER_POINTER (sel_name)); + } + else if (statically_typed) + { + tree ctype = TREE_TYPE (rtype); + + /* `self' is now statically_typed. All methods should be visible + within the context of the implementation. */ + if (implementation_context + && CLASS_NAME (implementation_context) == TYPE_NAME (ctype)) + { + method_prototype + = lookup_instance_method_static (implementation_template, + sel_name); + + if (! method_prototype && TYPE_PROTOCOL_LIST (ctype)) + method_prototype + = lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype), + sel_name, 0); + + if (! method_prototype + && implementation_template != implementation_context) + /* The method is not published in the interface. Check + locally. */ + method_prototype + = lookup_method (CLASS_NST_METHODS (implementation_context), + sel_name); + } + else + { + tree iface; + + if ((iface = lookup_interface (TYPE_NAME (ctype)))) + method_prototype = lookup_instance_method_static (iface, sel_name); + + if (! method_prototype) + { + tree protocol_list = TYPE_PROTOCOL_LIST (ctype); + if (protocol_list) + method_prototype + = lookup_method_in_protocol_list (protocol_list, + sel_name, 0); + } + } + + if (!method_prototype) + warning ("`%s' does not respond to `%s'", + IDENTIFIER_POINTER (TYPE_NAME (ctype)), + IDENTIFIER_POINTER (sel_name)); + } + else if (class_ident) + { + if (implementation_context + && CLASS_NAME (implementation_context) == class_ident) + { + method_prototype + = lookup_class_method_static (implementation_template, sel_name); + + if (!method_prototype + && implementation_template != implementation_context) + /* The method is not published in the interface. Check + locally. */ + method_prototype + = lookup_method (CLASS_CLS_METHODS (implementation_context), + sel_name); + } + else + { + tree iface; + + if ((iface = lookup_interface (class_ident))) + method_prototype = lookup_class_method_static (iface, sel_name); + } + + if (!method_prototype) + { + warning ("cannot find class (factory) method."); + warning ("return type for `%s' defaults to id", + IDENTIFIER_POINTER (sel_name)); + } + } + else if (IS_PROTOCOL_QUALIFIED_ID (rtype)) + { + /* An anonymous object that has been qualified with a protocol. */ + + tree protocol_list = TYPE_PROTOCOL_LIST (rtype); + + method_prototype = lookup_method_in_protocol_list (protocol_list, + sel_name, 0); + + if (!method_prototype) + { + hash hsh; + + warning ("method `%s' not implemented by protocol.", + IDENTIFIER_POINTER (sel_name)); + + /* Try and find the method signature in the global pools. */ + + if (!(hsh = hash_lookup (nst_method_hash_list, sel_name))) + hsh = hash_lookup (cls_method_hash_list, sel_name); + + if (!(method_prototype = check_duplicates (hsh))) + warning ("return type defaults to id"); + } + } + else + { + hash hsh; + + /* We think we have an instance...loophole: extern id Object; */ + hsh = hash_lookup (nst_method_hash_list, sel_name); + if (!hsh) + /* For various loopholes, like sending messages to self in a + factory context. */ + hsh = hash_lookup (cls_method_hash_list, sel_name); + + method_prototype = check_duplicates (hsh); + if (!method_prototype) + { + warning ("cannot find method."); + warning ("return type for `%s' defaults to id", + IDENTIFIER_POINTER (sel_name)); + } + } + + /* Save the selector name for printing error messages. */ + building_objc_message_expr = sel_name; + + /* Build the parameters list for looking up the method. + These are the object itself and the selector. */ + + if (flag_typed_selectors) + selector = build_typed_selector_reference (sel_name, method_prototype); + else + selector = build_selector_reference (sel_name); + + retval = build_objc_method_call (super, method_prototype, + receiver, self_object, + selector, method_params); + + building_objc_message_expr = 0; + + return retval; +} + +/* Build a tree expression to send OBJECT the operation SELECTOR, + looking up the method on object LOOKUP_OBJECT (often same as OBJECT), + assuming the method has prototype METHOD_PROTOTYPE. + (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.) + Use METHOD_PARAMS as list of args to pass to the method. + If SUPER_FLAG is nonzero, we look up the superclass's method. */ + +static tree +build_objc_method_call (super_flag, method_prototype, lookup_object, object, + selector, method_params) + int super_flag; + tree method_prototype, lookup_object, object, selector, method_params; +{ + tree sender = (super_flag ? umsg_super_decl : umsg_decl); + tree rcv_p = (super_flag + ? build_pointer_type (xref_tag (RECORD_TYPE, + get_identifier (TAG_SUPER))) + : id_type); + + if (flag_next_runtime) + { + if (! method_prototype) + { + method_params = tree_cons (NULL_TREE, lookup_object, + tree_cons (NULL_TREE, selector, + method_params)); + assemble_external (sender); + return build_function_call (sender, method_params); + } + else + { + /* This is a real kludge, but it is used only for the Next. + Clobber the data type of SENDER temporarily to accept + all the arguments for this operation, and to return + whatever this operation returns. */ + tree arglist = NULL_TREE; + tree retval; + + /* Save the proper contents of SENDER's data type. */ + tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender)); + tree savret = TREE_TYPE (TREE_TYPE (sender)); + + /* Install this method's argument types. */ + arglist = get_arg_type_list (method_prototype, METHOD_REF, + super_flag); + TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist; + + /* Install this method's return type. */ + TREE_TYPE (TREE_TYPE (sender)) + = groktypename (TREE_TYPE (method_prototype)); + + /* Call SENDER with all the parameters. This will do type + checking using the arg types for this method. */ + method_params = tree_cons (NULL_TREE, lookup_object, + tree_cons (NULL_TREE, selector, + method_params)); + assemble_external (sender); + retval = build_function_call (sender, method_params); + + /* Restore SENDER's return/argument types. */ + TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg; + TREE_TYPE (TREE_TYPE (sender)) = savret; + return retval; + } + } + else + { + /* This is the portable way. + First call the lookup function to get a pointer to the method, + then cast the pointer, then call it with the method arguments. */ + tree method; + + /* Avoid trouble since we may evaluate each of these twice. */ + object = save_expr (object); + selector = save_expr (selector); + + lookup_object = build_c_cast (rcv_p, lookup_object); + + assemble_external (sender); + method + = build_function_call (sender, + tree_cons (NULL_TREE, lookup_object, + tree_cons (NULL_TREE, selector, + NULL_TREE))); + + /* If we have a method prototype, construct the data type this + method needs, and cast what we got from SENDER into a pointer + to that type. */ + if (method_prototype) + { + tree arglist = get_arg_type_list (method_prototype, METHOD_REF, + super_flag); + tree valtype = groktypename (TREE_TYPE (method_prototype)); + tree fake_function_type = build_function_type (valtype, arglist); + TREE_TYPE (method) = build_pointer_type (fake_function_type); + } + else + TREE_TYPE (method) + = build_pointer_type (build_function_type (ptr_type_node, NULL_TREE)); + + /* Pass the object to the method. */ + assemble_external (method); + return build_function_call (method, + tree_cons (NULL_TREE, object, + tree_cons (NULL_TREE, selector, + method_params))); + } +} + +static void +build_protocol_reference (p) + tree p; +{ + tree decl, ident, ptype; + + push_obstacks_nochange (); + end_temporary_allocation (); + + /* extern struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ + + ident = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p); + ptype + = groktypename (build_tree_list (build_tree_list (NULL_TREE, + objc_protocol_template), + NULL_TREE)); + + if (IDENTIFIER_GLOBAL_VALUE (ident)) + decl = IDENTIFIER_GLOBAL_VALUE (ident); /* Set by pushdecl. */ + else + { + decl = build_decl (VAR_DECL, ident, ptype); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + TREE_USED (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + + make_decl_rtl (decl, 0, 1); + pushdecl_top_level (decl); + } + + PROTOCOL_FORWARD_DECL (p) = decl; + pop_obstacks (); +} + +tree +build_protocol_expr (protoname) + tree protoname; +{ + tree expr; + tree p; + + if (!doing_objc_thang) + objc_fatal (); + + p = lookup_protocol (protoname); + + if (!p) + { + error ("Cannot find protocol declaration for `%s'", + IDENTIFIER_POINTER (protoname)); + return error_mark_node; + } + + if (!PROTOCOL_FORWARD_DECL (p)) + build_protocol_reference (p); + + expr = build_unary_op (ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0); + + TREE_TYPE (expr) = protocol_type; + + return expr; +} + +tree +build_selector_expr (selnamelist) + tree selnamelist; +{ + tree selname; + + if (!doing_objc_thang) + objc_fatal (); + + /* Obtain the full selector name. */ + if (TREE_CODE (selnamelist) == IDENTIFIER_NODE) + /* A unary selector. */ + selname = selnamelist; + else if (TREE_CODE (selnamelist) == TREE_LIST) + selname = build_keyword_selector (selnamelist); + + if (flag_typed_selectors) + return build_typed_selector_reference (selname, 0); + else + return build_selector_reference (selname); +} + +tree +build_encode_expr (type) + tree type; +{ + tree result; + char *string; + + if (!doing_objc_thang) + objc_fatal (); + + encode_type (type, obstack_object_size (&util_obstack), + OBJC_ENCODE_INLINE_DEFS); + obstack_1grow (&util_obstack, 0); /* null terminate string */ + string = obstack_finish (&util_obstack); + + /* Synthesize a string that represents the encoded struct/union. */ + result = my_build_string (strlen (string) + 1, string); + obstack_free (&util_obstack, util_firstobj); + return result; +} + +tree +build_ivar_reference (id) + tree id; +{ + if (TREE_CODE (method_context) == CLASS_METHOD_DECL) + { + /* Historically, a class method that produced objects (factory + method) would assign `self' to the instance that it + allocated. This would effectively turn the class method into + an instance method. Following this assignment, the instance + variables could be accessed. That practice, while safe, + violates the simple rule that a class method should not refer + to an instance variable. It's better to catch the cases + where this is done unknowingly than to support the above + paradigm. */ + warning ("instance variable `%s' accessed in class method", + IDENTIFIER_POINTER (id)); + TREE_TYPE (self_decl) = instance_type; /* cast */ + } + + return build_component_ref (build_indirect_ref (self_decl, "->"), id); +} + +#define HASH_ALLOC_LIST_SIZE 170 +#define ATTR_ALLOC_LIST_SIZE 170 +#define SIZEHASHTABLE 257 + +/* make positive */ +#define HASHFUNCTION(key) ((HOST_WIDE_INT) key & 0x7fffffff) + +static void +hash_init () +{ + nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash)); + cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash)); + + if (!nst_method_hash_list || !cls_method_hash_list) + perror ("unable to allocate space in objc-tree.c"); + else + { + int i; + + for (i = 0; i < SIZEHASHTABLE; i++) + { + nst_method_hash_list[i] = 0; + cls_method_hash_list[i] = 0; + } + } +} + +static void +hash_enter (hashlist, method) + hash *hashlist; + tree method; +{ + static hash hash_alloc_list = 0; + static int hash_alloc_index = 0; + hash obj; + int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE; + + if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE) + { + hash_alloc_index = 0; + hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry) + * HASH_ALLOC_LIST_SIZE); + if (! hash_alloc_list) + perror ("unable to allocate in objc-tree.c"); + } + obj = &hash_alloc_list[hash_alloc_index++]; + obj->list = 0; + obj->next = hashlist[slot]; + obj->key = method; + + hashlist[slot] = obj; /* append to front */ +} + +static hash +hash_lookup (hashlist, sel_name) + hash *hashlist; + tree sel_name; +{ + hash target; + + target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE]; + + while (target) + { + if (sel_name == METHOD_SEL_NAME (target->key)) + return target; + + target = target->next; + } + return 0; +} + +static void +hash_add_attr (entry, value) + hash entry; + tree value; +{ + static attr attr_alloc_list = 0; + static int attr_alloc_index = 0; + attr obj; + + if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE) + { + attr_alloc_index = 0; + attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute) + * ATTR_ALLOC_LIST_SIZE); + if (! attr_alloc_list) + perror ("unable to allocate in objc-tree.c"); + } + obj = &attr_alloc_list[attr_alloc_index++]; + obj->next = entry->list; + obj->value = value; + + entry->list = obj; /* append to front */ +} + +static tree +lookup_method (mchain, method) + tree mchain; + tree method; +{ + tree key; + + if (TREE_CODE (method) == IDENTIFIER_NODE) + key = method; + else + key = METHOD_SEL_NAME (method); + + while (mchain) + { + if (METHOD_SEL_NAME (mchain) == key) + return mchain; + mchain = TREE_CHAIN (mchain); + } + return NULL_TREE; +} + +static tree +lookup_instance_method_static (interface, ident) + tree interface; + tree ident; +{ + tree inter = interface; + tree chain = CLASS_NST_METHODS (inter); + tree meth = NULL_TREE; + + do + { + if ((meth = lookup_method (chain, ident))) + return meth; + + if (CLASS_CATEGORY_LIST (inter)) + { + tree category = CLASS_CATEGORY_LIST (inter); + chain = CLASS_NST_METHODS (category); + + do + { + if ((meth = lookup_method (chain, ident))) + return meth; + + /* Check for instance methods in protocols in categories. */ + if (CLASS_PROTOCOL_LIST (category)) + { + if ((meth = (lookup_method_in_protocol_list + (CLASS_PROTOCOL_LIST (category), ident, 0)))) + return meth; + } + + if ((category = CLASS_CATEGORY_LIST (category))) + chain = CLASS_NST_METHODS (category); + } + while (category); + } + + if (CLASS_PROTOCOL_LIST (inter)) + { + if ((meth = (lookup_method_in_protocol_list + (CLASS_PROTOCOL_LIST (inter), ident, 0)))) + return meth; + } + + if ((inter = lookup_interface (CLASS_SUPER_NAME (inter)))) + chain = CLASS_NST_METHODS (inter); + } + while (inter); + + return meth; +} + +static tree +lookup_class_method_static (interface, ident) + tree interface; + tree ident; +{ + tree inter = interface; + tree chain = CLASS_CLS_METHODS (inter); + tree meth = NULL_TREE; + tree root_inter = NULL_TREE; + + do + { + if ((meth = lookup_method (chain, ident))) + return meth; + + if (CLASS_CATEGORY_LIST (inter)) + { + tree category = CLASS_CATEGORY_LIST (inter); + chain = CLASS_CLS_METHODS (category); + + do + { + if ((meth = lookup_method (chain, ident))) + return meth; + + /* Check for class methods in protocols in categories. */ + if (CLASS_PROTOCOL_LIST (category)) + { + if ((meth = (lookup_method_in_protocol_list + (CLASS_PROTOCOL_LIST (category), ident, 1)))) + return meth; + } + + if ((category = CLASS_CATEGORY_LIST (category))) + chain = CLASS_CLS_METHODS (category); + } + while (category); + } + + /* Check for class methods in protocols. */ + if (CLASS_PROTOCOL_LIST (inter)) + { + if ((meth = (lookup_method_in_protocol_list + (CLASS_PROTOCOL_LIST (inter), ident, 1)))) + return meth; + } + + root_inter = inter; + if ((inter = lookup_interface (CLASS_SUPER_NAME (inter)))) + chain = CLASS_CLS_METHODS (inter); + } + while (inter); + + /* Simulate wrap around. */ + return lookup_instance_method_static (root_inter, ident); +} + +tree +add_class_method (class, method) + tree class; + tree method; +{ + tree mth; + hash hsh; + + /* We will have allocated the method parameter declarations on the + maybepermanent_obstack. Need to make sure they stick around! */ + preserve_data (); + + if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method))) + { + /* put method on list in reverse order */ + TREE_CHAIN (method) = CLASS_CLS_METHODS (class); + CLASS_CLS_METHODS (class) = method; + } + else + { + if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) + error ("duplicate definition of class method `%s'.", + IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); + else + { + /* Check types; if different, complain. */ + if (!comp_proto_with_proto (method, mth)) + error ("duplicate declaration of class method `%s'.", + IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); + } + } + + if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method)))) + { + /* Install on a global chain. */ + hash_enter (cls_method_hash_list, method); + } + else + { + /* Check types; if different, add to a list. */ + if (!comp_proto_with_proto (method, hsh->key)) + hash_add_attr (hsh, method); + } + return method; +} + +tree +add_instance_method (class, method) + tree class; + tree method; +{ + tree mth; + hash hsh; + + /* We will have allocated the method parameter declarations on the + maybepermanent_obstack. Need to make sure they stick around! */ + preserve_data (); + + if (!(mth = lookup_method (CLASS_NST_METHODS (class), method))) + { + /* Put method on list in reverse order. */ + TREE_CHAIN (method) = CLASS_NST_METHODS (class); + CLASS_NST_METHODS (class) = method; + } + else + { + if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) + error ("duplicate definition of instance method `%s'.", + IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); + else + { + /* Check types; if different, complain. */ + if (!comp_proto_with_proto (method, mth)) + error ("duplicate declaration of instance method `%s'.", + IDENTIFIER_POINTER (METHOD_SEL_NAME (mth))); + } + } + + if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method)))) + { + /* Install on a global chain. */ + hash_enter (nst_method_hash_list, method); + } + else + { + /* Check types; if different, add to a list. */ + if (!comp_proto_with_proto (method, hsh->key)) + hash_add_attr (hsh, method); + } + return method; +} + +static tree +add_class (class) + tree class; +{ + /* Put interfaces on list in reverse order. */ + TREE_CHAIN (class) = interface_chain; + interface_chain = class; + return interface_chain; +} + +static void +add_category (class, category) + tree class; + tree category; +{ + /* Put categories on list in reverse order. */ + tree cat = CLASS_CATEGORY_LIST (class); + + while (cat) + { + if (CLASS_SUPER_NAME (cat) == CLASS_SUPER_NAME (category)) + warning ("duplicate interface declaration for category `%s(%s)'", + IDENTIFIER_POINTER (CLASS_NAME (class)), + IDENTIFIER_POINTER (CLASS_SUPER_NAME (category))); + cat = CLASS_CATEGORY_LIST (cat); + } + + CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class); + CLASS_CATEGORY_LIST (class) = category; +} + +/* Called after parsing each instance variable declaration. Necessary to + preserve typedefs and implement public/private... + + PUBLIC is 1 for public, 0 for protected, and 2 for private. */ + +tree +add_instance_variable (class, public, declarator, declspecs, width) + tree class; + int public; + tree declarator; + tree declspecs; + tree width; +{ + tree field_decl, raw_decl; + + raw_decl = build_tree_list (declspecs, declarator); + + if (CLASS_RAW_IVARS (class)) + chainon (CLASS_RAW_IVARS (class), raw_decl); + else + CLASS_RAW_IVARS (class) = raw_decl; + + field_decl = grokfield (input_filename, lineno, + declarator, declspecs, width); + + /* Overload the public attribute, it is not used for FIELD_DECLs. */ + switch (public) + { + case 0: + TREE_PUBLIC (field_decl) = 0; + TREE_PRIVATE (field_decl) = 0; + TREE_PROTECTED (field_decl) = 1; + break; + + case 1: + TREE_PUBLIC (field_decl) = 1; + TREE_PRIVATE (field_decl) = 0; + TREE_PROTECTED (field_decl) = 0; + break; + + case 2: + TREE_PUBLIC (field_decl) = 0; + TREE_PRIVATE (field_decl) = 1; + TREE_PROTECTED (field_decl) = 0; + break; + + } + + if (CLASS_IVARS (class)) + chainon (CLASS_IVARS (class), field_decl); + else + CLASS_IVARS (class) = field_decl; + + return class; +} + +tree +is_ivar (decl_chain, ident) + tree decl_chain; + tree ident; +{ + for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain)) + if (DECL_NAME (decl_chain) == ident) + return decl_chain; + return NULL_TREE; +} + +/* True if the ivar is private and we are not in its implementation. */ + +int +is_private (decl) + tree decl; +{ + if (TREE_PRIVATE (decl) + && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl))) + { + error ("instance variable `%s' is declared private", + IDENTIFIER_POINTER (DECL_NAME (decl))); + return 1; + } + else + return 0; +} + +/* We have an instance variable reference;, check to see if it is public. */ + +int +is_public (expr, identifier) + tree expr; + tree identifier; +{ + tree basetype = TREE_TYPE (expr); + enum tree_code code = TREE_CODE (basetype); + tree decl; + + if (code == RECORD_TYPE) + { + if (TREE_STATIC_TEMPLATE (basetype)) + { + if (!lookup_interface (TYPE_NAME (basetype))) + { + error ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER (TYPE_NAME (basetype))); + return 0; + } + + if ((decl = is_ivar (TYPE_FIELDS (basetype), identifier))) + { + if (TREE_PUBLIC (decl)) + return 1; + + /* Important difference between the Stepstone translator: + all instance variables should be public within the context + of the implementation. */ + if (implementation_context + && (((TREE_CODE (implementation_context) + == CLASS_IMPLEMENTATION_TYPE) + || (TREE_CODE (implementation_context) + == CATEGORY_IMPLEMENTATION_TYPE)) + && (CLASS_NAME (implementation_context) + == TYPE_NAME (basetype)))) + return ! is_private (decl); + + error ("instance variable `%s' is declared %s", + IDENTIFIER_POINTER (identifier), + TREE_PRIVATE (decl) ? "private" : "protected"); + return 0; + } + } + + else if (implementation_context && (basetype == objc_object_reference)) + { + TREE_TYPE (expr) = uprivate_record; + warning ("static access to object of type `id'"); + } + } + + return 1; +} + +/* Implement @defs (<classname>) within struct bodies. */ + +tree +get_class_ivars (interface) + tree interface; +{ + if (!doing_objc_thang) + objc_fatal (); + + return build_ivar_chain (interface, 1); +} + +/* Make sure all entries in CHAIN are also in LIST. */ + +static int +check_methods (chain, list, mtype) + tree chain; + tree list; + int mtype; +{ + int first = 1; + + while (chain) + { + if (!lookup_method (list, chain)) + { + if (first) + { + if (TREE_CODE (implementation_context) + == CLASS_IMPLEMENTATION_TYPE) + warning ("incomplete implementation of class `%s'", + IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); + else if (TREE_CODE (implementation_context) + == CATEGORY_IMPLEMENTATION_TYPE) + warning ("incomplete implementation of category `%s'", + IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); + first = 0; + } + + warning ("method definition for `%c%s' not found", + mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain))); + } + + chain = TREE_CHAIN (chain); + } + + return first; +} + +static int +conforms_to_protocol (class, protocol) + tree class; + tree protocol; +{ + while (protocol) + { + tree p = CLASS_PROTOCOL_LIST (class); + + while (p && TREE_VALUE (p) != TREE_VALUE (protocol)) + p = TREE_CHAIN (p); + + if (!p) + { + tree super = (CLASS_SUPER_NAME (class) + ? lookup_interface (CLASS_SUPER_NAME (class)) + : NULL_TREE); + int tmp = super ? conforms_to_protocol (super, protocol) : 0; + if (!tmp) + return 0; + } + + protocol = TREE_CHAIN (protocol); + } + + return 1; +} + +/* Make sure all methods in CHAIN are accessible as MTYPE methods in + CONTEXT. This is one of two mechanisms to check protocol integrity. */ + +static int +check_methods_accessible (chain, context, mtype) + tree chain; + tree context; + int mtype; +{ + int first = 1; + tree list; + tree base_context = context; + + while (chain) + { + context = base_context; + while (context) + { + if (mtype == '+') + list = CLASS_CLS_METHODS (context); + else + list = CLASS_NST_METHODS (context); + + if (lookup_method (list, chain)) + break; + + else if (TREE_CODE (context) == CLASS_IMPLEMENTATION_TYPE + || TREE_CODE (context) == CLASS_INTERFACE_TYPE) + context = (CLASS_SUPER_NAME (context) + ? lookup_interface (CLASS_SUPER_NAME (context)) + : NULL_TREE); + + else if (TREE_CODE (context) == CATEGORY_IMPLEMENTATION_TYPE + || TREE_CODE (context) == CATEGORY_INTERFACE_TYPE) + context = (CLASS_NAME (context) + ? lookup_interface (CLASS_NAME (context)) + : NULL_TREE); + else + abort (); + } + + if (context == NULL_TREE) + { + if (first) + { + if (TREE_CODE (implementation_context) + == CLASS_IMPLEMENTATION_TYPE) + warning ("incomplete implementation of class `%s'", + IDENTIFIER_POINTER + (CLASS_NAME (implementation_context))); + else if (TREE_CODE (implementation_context) + == CATEGORY_IMPLEMENTATION_TYPE) + warning ("incomplete implementation of category `%s'", + IDENTIFIER_POINTER + (CLASS_SUPER_NAME (implementation_context))); + first = 0; + } + warning ("method definition for `%c%s' not found", + mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain))); + } + + chain = TREE_CHAIN (chain); /* next method... */ + } + return first; +} + +static void +check_protocols (proto_list, type, name) + tree proto_list; + char *type; + char *name; +{ + for ( ; proto_list; proto_list = TREE_CHAIN (proto_list)) + { + tree p = TREE_VALUE (proto_list); + + if (TREE_CODE (p) == PROTOCOL_INTERFACE_TYPE) + { + int f1, f2; + + /* Ensure that all protocols have bodies. */ + if (flag_warn_protocol) { + f1 = check_methods (PROTOCOL_CLS_METHODS (p), + CLASS_CLS_METHODS (implementation_context), + '+'); + f2 = check_methods (PROTOCOL_NST_METHODS (p), + CLASS_NST_METHODS (implementation_context), + '-'); + } else { + f1 = check_methods_accessible (PROTOCOL_CLS_METHODS (p), + implementation_context, + '+'); + f2 = check_methods_accessible (PROTOCOL_NST_METHODS (p), + implementation_context, + '-'); + } + + if (!f1 || !f2) + warning ("%s `%s' does not fully implement the `%s' protocol", + type, name, IDENTIFIER_POINTER (PROTOCOL_NAME (p))); + + } + else + ; /* An identifier if we could not find a protocol. */ + + /* Check protocols recursively. */ + if (PROTOCOL_LIST (p)) + { + tree super_class + = lookup_interface (CLASS_SUPER_NAME (implementation_template)); + if (! conforms_to_protocol (super_class, PROTOCOL_LIST (p))) + check_protocols (PROTOCOL_LIST (p), type, name); + } + } +} + +/* Make sure that the class CLASS_NAME is defined + CODE says which kind of thing CLASS_NAME ought to be. + It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, + CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. + + If CODE is CLASS_INTERFACE_TYPE, we also do a push_obstacks_nochange + whose matching pop is in continue_class. */ + +tree +start_class (code, class_name, super_name, protocol_list) + enum tree_code code; + tree class_name; + tree super_name; + tree protocol_list; +{ + tree class, decl; + + if (code == CLASS_INTERFACE_TYPE) + { + push_obstacks_nochange (); + end_temporary_allocation (); + } + + if (!doing_objc_thang) + objc_fatal (); + + class = make_node (code); + TYPE_BINFO (class) = make_tree_vec (5); + + CLASS_NAME (class) = class_name; + CLASS_SUPER_NAME (class) = super_name; + CLASS_CLS_METHODS (class) = NULL_TREE; + + if (! is_class_name (class_name) && (decl = lookup_name (class_name))) + { + error ("`%s' redeclared as different kind of symbol", + IDENTIFIER_POINTER (class_name)); + error_with_decl (decl, "previous declaration of `%s'"); + } + + if (code == CLASS_IMPLEMENTATION_TYPE) + { + { + static tree implemented_classes = 0; + tree chain = implemented_classes; + for (chain = implemented_classes; chain; chain = TREE_CHAIN (chain)) + if (TREE_VALUE (chain) == class_name) + { + error ("reimplementation of class `%s'", + IDENTIFIER_POINTER (class_name)); + return error_mark_node; + } + implemented_classes = perm_tree_cons (NULL_TREE, class_name, + implemented_classes); + } + + /* Pre-build the following entities - for speed/convenience. */ + if (!self_id) + self_id = get_identifier ("self"); + if (!ucmd_id) + ucmd_id = get_identifier ("_cmd"); + if (!unused_list) + unused_list + = build_tree_list (get_identifier ("__unused__"), NULL_TREE); + if (!objc_super_template) + objc_super_template = build_super_template (); + + /* Reset for multiple classes per file. */ + method_slot = 0; + + implementation_context = class; + + /* Lookup the interface for this implementation. */ + + if (!(implementation_template = lookup_interface (class_name))) + { + warning ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER (class_name)); + add_class (implementation_template = implementation_context); + } + + /* If a super class has been specified in the implementation, + insure it conforms to the one specified in the interface. */ + + if (super_name + && (super_name != CLASS_SUPER_NAME (implementation_template))) + { + tree previous_name = CLASS_SUPER_NAME (implementation_template); + char *name = previous_name ? IDENTIFIER_POINTER (previous_name) : ""; + error ("conflicting super class name `%s'", + IDENTIFIER_POINTER (super_name)); + error ("previous declaration of `%s'", name); + } + + else if (! super_name) + { + CLASS_SUPER_NAME (implementation_context) + = CLASS_SUPER_NAME (implementation_template); + } + } + + else if (code == CLASS_INTERFACE_TYPE) + { + if (lookup_interface (class_name)) + warning ("duplicate interface declaration for class `%s'", + IDENTIFIER_POINTER (class_name)); + else + add_class (class); + + if (protocol_list) + CLASS_PROTOCOL_LIST (class) + = lookup_and_install_protocols (protocol_list); + } + + else if (code == CATEGORY_INTERFACE_TYPE) + { + tree class_category_is_assoc_with; + + /* For a category, class_name is really the name of the class that + the following set of methods will be associated with. We must + find the interface so that can derive the objects template. */ + + if (!(class_category_is_assoc_with = lookup_interface (class_name))) + { + error ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER (class_name)); + exit (FATAL_EXIT_CODE); + } + else + add_category (class_category_is_assoc_with, class); + + if (protocol_list) + CLASS_PROTOCOL_LIST (class) + = lookup_and_install_protocols (protocol_list); + } + + else if (code == CATEGORY_IMPLEMENTATION_TYPE) + { + /* Pre-build the following entities for speed/convenience. */ + if (!self_id) + self_id = get_identifier ("self"); + if (!ucmd_id) + ucmd_id = get_identifier ("_cmd"); + if (!unused_list) + unused_list + = build_tree_list (get_identifier ("__unused__"), NULL_TREE); + if (!objc_super_template) + objc_super_template = build_super_template (); + + /* Reset for multiple classes per file. */ + method_slot = 0; + + implementation_context = class; + + /* For a category, class_name is really the name of the class that + the following set of methods will be associated with. We must + find the interface so that can derive the objects template. */ + + if (!(implementation_template = lookup_interface (class_name))) + { + error ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER (class_name)); + exit (FATAL_EXIT_CODE); + } + } + return class; +} + +tree +continue_class (class) + tree class; +{ + if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE + || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE) + { + struct imp_entry *imp_entry; + tree ivar_context; + + /* Check consistency of the instance variables. */ + + if (CLASS_IVARS (class)) + check_ivars (implementation_template, class); + + /* code generation */ + + ivar_context = build_private_template (implementation_template); + + if (!objc_class_template) + build_class_template (); + + if (!(imp_entry + = (struct imp_entry *) xmalloc (sizeof (struct imp_entry)))) + perror ("unable to allocate in objc-tree.c"); + + imp_entry->next = imp_list; + imp_entry->imp_context = class; + imp_entry->imp_template = implementation_template; + + synth_forward_declarations (); + imp_entry->class_decl = UOBJC_CLASS_decl; + imp_entry->meta_decl = UOBJC_METACLASS_decl; + + /* Append to front and increment count. */ + imp_list = imp_entry; + if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) + imp_count++; + else + cat_count++; + + return ivar_context; + } + + else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) + { + tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class)); + + if (!TYPE_FIELDS (record)) + { + finish_struct (record, build_ivar_chain (class, 0), NULL_TREE); + CLASS_STATIC_TEMPLATE (class) = record; + + /* Mark this record as a class template for static typing. */ + TREE_STATIC_TEMPLATE (record) = 1; + } + + return NULL_TREE; + } + + else + return error_mark_node; +} + +/* This is called once we see the "@end" in an interface/implementation. */ + +void +finish_class (class) + tree class; +{ + if (TREE_CODE (class) == CLASS_IMPLEMENTATION_TYPE) + { + /* All code generation is done in finish_objc. */ + + if (implementation_template != implementation_context) + { + /* Ensure that all method listed in the interface contain bodies. */ + check_methods (CLASS_CLS_METHODS (implementation_template), + CLASS_CLS_METHODS (implementation_context), '+'); + check_methods (CLASS_NST_METHODS (implementation_template), + CLASS_NST_METHODS (implementation_context), '-'); + + if (CLASS_PROTOCOL_LIST (implementation_template)) + check_protocols (CLASS_PROTOCOL_LIST (implementation_template), + "class", + IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); + } + } + + else if (TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE) + { + tree category = CLASS_CATEGORY_LIST (implementation_template); + + /* Find the category interface from the class it is associated with. */ + while (category) + { + if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category)) + break; + category = CLASS_CATEGORY_LIST (category); + } + + if (category) + { + /* Ensure all method listed in the interface contain bodies. */ + check_methods (CLASS_CLS_METHODS (category), + CLASS_CLS_METHODS (implementation_context), '+'); + check_methods (CLASS_NST_METHODS (category), + CLASS_NST_METHODS (implementation_context), '-'); + + if (CLASS_PROTOCOL_LIST (category)) + check_protocols (CLASS_PROTOCOL_LIST (category), + "category", + IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); + } + } + + else if (TREE_CODE (class) == CLASS_INTERFACE_TYPE) + { + tree decl_specs; + char *class_name = IDENTIFIER_POINTER (CLASS_NAME (class)); + char *string = (char *) alloca (strlen (class_name) + 3); + + /* extern struct objc_object *_<my_name>; */ + + sprintf (string, "_%s", class_name); + + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]); + decl_specs = tree_cons (NULL_TREE, objc_object_reference, decl_specs); + define_decl (build1 (INDIRECT_REF, NULL_TREE, get_identifier (string)), + decl_specs); + } +} + +static tree +add_protocol (protocol) + tree protocol; +{ + /* Put protocol on list in reverse order. */ + TREE_CHAIN (protocol) = protocol_chain; + protocol_chain = protocol; + return protocol_chain; +} + +static tree +lookup_protocol (ident) + tree ident; +{ + tree chain; + + for (chain = protocol_chain; chain; chain = TREE_CHAIN (chain)) + { + if (ident == PROTOCOL_NAME (chain)) + return chain; + } + + return NULL_TREE; +} + +tree +start_protocol (code, name, list) + enum tree_code code; + tree name; + tree list; +{ + tree protocol; + + if (!doing_objc_thang) + objc_fatal (); + + /* This is as good a place as any. Need to invoke push_tag_toplevel. */ + if (!objc_protocol_template) + objc_protocol_template = build_protocol_template (); + + protocol = make_node (code); + TYPE_BINFO (protocol) = make_tree_vec (2); + + PROTOCOL_NAME (protocol) = name; + PROTOCOL_LIST (protocol) = list; + + lookup_and_install_protocols (list); + + if (lookup_protocol (name)) + warning ("duplicate declaration for protocol `%s'", + IDENTIFIER_POINTER (name)); + else + add_protocol (protocol); + + PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE; + + return protocol; +} + +void +finish_protocol (protocol) + tree protocol; +{ +} + + +/* "Encode" a data type into a string, which grows in util_obstack. + ??? What is the FORMAT? Someone please document this! */ + +static void +encode_type_qualifiers (declspecs) + tree declspecs; +{ + tree spec; + + for (spec = declspecs; spec; spec = TREE_CHAIN (spec)) + { + if (ridpointers[(int) RID_CONST] == TREE_VALUE (spec)) + obstack_1grow (&util_obstack, 'r'); + else if (ridpointers[(int) RID_IN] == TREE_VALUE (spec)) + obstack_1grow (&util_obstack, 'n'); + else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec)) + obstack_1grow (&util_obstack, 'N'); + else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec)) + obstack_1grow (&util_obstack, 'o'); + else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec)) + obstack_1grow (&util_obstack, 'O'); + else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec)) + obstack_1grow (&util_obstack, 'V'); + } +} + +/* Encode a pointer type. */ + +static void +encode_pointer (type, curtype, format) + tree type; + int curtype; + int format; +{ + tree pointer_to = TREE_TYPE (type); + + if (TREE_CODE (pointer_to) == RECORD_TYPE) + { + if (TYPE_NAME (pointer_to) + && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE) + { + char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to)); + + if (strcmp (name, TAG_OBJECT) == 0) /* '@' */ + { + obstack_1grow (&util_obstack, '@'); + return; + } + else if (TREE_STATIC_TEMPLATE (pointer_to)) + { + if (generating_instance_variables) + { + obstack_1grow (&util_obstack, '@'); + obstack_1grow (&util_obstack, '"'); + obstack_grow (&util_obstack, name, strlen (name)); + obstack_1grow (&util_obstack, '"'); + return; + } + else + { + obstack_1grow (&util_obstack, '@'); + return; + } + } + else if (strcmp (name, TAG_CLASS) == 0) /* '#' */ + { + obstack_1grow (&util_obstack, '#'); + return; + } +#ifndef OBJC_INT_SELECTORS + else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */ + { + obstack_1grow (&util_obstack, ':'); + return; + } +#endif /* OBJC_INT_SELECTORS */ + } + } + else if (TREE_CODE (pointer_to) == INTEGER_TYPE + && TYPE_MODE (pointer_to) == QImode) + { + obstack_1grow (&util_obstack, '*'); + return; + } + + /* We have a type that does not get special treatment. */ + + /* NeXT extension */ + obstack_1grow (&util_obstack, '^'); + encode_type (pointer_to, curtype, format); +} + +static void +encode_array (type, curtype, format) + tree type; + int curtype; + int format; +{ + tree an_int_cst = TYPE_SIZE (type); + tree array_of = TREE_TYPE (type); + char buffer[40]; + + /* An incomplete array is treated like a pointer. */ + if (an_int_cst == NULL) + { + encode_pointer (type, curtype, format); + return; + } + + sprintf (buffer, "[%d", + (TREE_INT_CST_LOW (an_int_cst) + / TREE_INT_CST_LOW (TYPE_SIZE (array_of)))); + + obstack_grow (&util_obstack, buffer, strlen (buffer)); + encode_type (array_of, curtype, format); + obstack_1grow (&util_obstack, ']'); + return; +} + +static void +encode_aggregate_within (type, curtype, format, left, right) + tree type; + int curtype; + int format; + char left; + char right; +{ + if (obstack_object_size (&util_obstack) > 0 + && *(obstack_next_free (&util_obstack) - 1) == '^') + { + tree name = TYPE_NAME (type); + + /* we have a reference; this is a NeXT extension. */ + + if (obstack_object_size (&util_obstack) - curtype == 1 + && format == OBJC_ENCODE_INLINE_DEFS) + { + /* Output format of struct for first level only. */ + tree fields = TYPE_FIELDS (type); + + if (name && TREE_CODE (name) == IDENTIFIER_NODE) + { + obstack_1grow (&util_obstack, left); + obstack_grow (&util_obstack, + IDENTIFIER_POINTER (name), + strlen (IDENTIFIER_POINTER (name))); + obstack_1grow (&util_obstack, '='); + } + else + { + obstack_1grow (&util_obstack, left); + obstack_grow (&util_obstack, "?=", 2); + } + + for ( ; fields; fields = TREE_CHAIN (fields)) + encode_field_decl (fields, curtype, format); + + obstack_1grow (&util_obstack, right); + } + + else if (name && TREE_CODE (name) == IDENTIFIER_NODE) + { + obstack_1grow (&util_obstack, left); + obstack_grow (&util_obstack, + IDENTIFIER_POINTER (name), + strlen (IDENTIFIER_POINTER (name))); + obstack_1grow (&util_obstack, right); + } + + else + { + /* We have an untagged structure or a typedef. */ + obstack_1grow (&util_obstack, left); + obstack_1grow (&util_obstack, '?'); + obstack_1grow (&util_obstack, right); + } + } + + else + { + tree name = TYPE_NAME (type); + tree fields = TYPE_FIELDS (type); + + if (format == OBJC_ENCODE_INLINE_DEFS + || generating_instance_variables) + { + obstack_1grow (&util_obstack, left); + if (name && TREE_CODE (name) == IDENTIFIER_NODE) + obstack_grow (&util_obstack, + IDENTIFIER_POINTER (name), + strlen (IDENTIFIER_POINTER (name))); + else + obstack_1grow (&util_obstack, '?'); + + obstack_1grow (&util_obstack, '='); + + for (; fields; fields = TREE_CHAIN (fields)) + { + if (generating_instance_variables) + { + tree fname = DECL_NAME (fields); + + obstack_1grow (&util_obstack, '"'); + if (fname && TREE_CODE (fname) == IDENTIFIER_NODE) + { + obstack_grow (&util_obstack, + IDENTIFIER_POINTER (fname), + strlen (IDENTIFIER_POINTER (fname))); + } + + obstack_1grow (&util_obstack, '"'); + } + + encode_field_decl (fields, curtype, format); + } + + obstack_1grow (&util_obstack, right); + } + + else + { + obstack_1grow (&util_obstack, left); + if (name && TREE_CODE (name) == IDENTIFIER_NODE) + obstack_grow (&util_obstack, + IDENTIFIER_POINTER (name), + strlen (IDENTIFIER_POINTER (name))); + else + /* We have an untagged structure or a typedef. */ + obstack_1grow (&util_obstack, '?'); + + obstack_1grow (&util_obstack, right); + } + } +} + +static void +encode_aggregate (type, curtype, format) + tree type; + int curtype; + int format; +{ + enum tree_code code = TREE_CODE (type); + + switch (code) + { + case RECORD_TYPE: + { + encode_aggregate_within(type, curtype, format, '{', '}'); + break; + } + case UNION_TYPE: + { + encode_aggregate_within(type, curtype, format, '(', ')'); + break; + } + + case ENUMERAL_TYPE: + obstack_1grow (&util_obstack, 'i'); + break; + } +} + +/* Support bitfields. The current version of Objective-C does not support + them. The string will consist of one or more "b:n"'s where n is an + integer describing the width of the bitfield. Currently, classes in + the kit implement a method "-(char *)describeBitfieldStruct:" that + simulates this. If they do not implement this method, the archiver + assumes the bitfield is 16 bits wide (padded if necessary) and packed + according to the GNU compiler. After looking at the "kit", it appears + that all classes currently rely on this default behavior, rather than + hand generating this string (which is tedious). */ + +static void +encode_bitfield (width, format) + int width; + int format; +{ + char buffer[40]; + sprintf (buffer, "b%d", width); + obstack_grow (&util_obstack, buffer, strlen (buffer)); +} + +/* FORMAT will be OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS. */ + +static void +encode_type (type, curtype, format) + tree type; + int curtype; + int format; +{ + enum tree_code code = TREE_CODE (type); + + if (code == INTEGER_TYPE) + { + if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0 + && TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0) + { + /* Unsigned integer types. */ + + if (TYPE_MODE (type) == QImode) + obstack_1grow (&util_obstack, 'C'); + else if (TYPE_MODE (type) == HImode) + obstack_1grow (&util_obstack, 'S'); + else if (TYPE_MODE (type) == SImode) + { + if (type == long_unsigned_type_node) + obstack_1grow (&util_obstack, 'L'); + else + obstack_1grow (&util_obstack, 'I'); + } + else if (TYPE_MODE (type) == DImode) + obstack_1grow (&util_obstack, 'Q'); + } + + else + /* Signed integer types. */ + { + if (TYPE_MODE (type) == QImode) + obstack_1grow (&util_obstack, 'c'); + else if (TYPE_MODE (type) == HImode) + obstack_1grow (&util_obstack, 's'); + else if (TYPE_MODE (type) == SImode) + { + if (type == long_integer_type_node) + obstack_1grow (&util_obstack, 'l'); + else + obstack_1grow (&util_obstack, 'i'); + } + + else if (TYPE_MODE (type) == DImode) + obstack_1grow (&util_obstack, 'q'); + } + } + + else if (code == REAL_TYPE) + { + /* Floating point types. */ + + if (TYPE_MODE (type) == SFmode) + obstack_1grow (&util_obstack, 'f'); + else if (TYPE_MODE (type) == DFmode + || TYPE_MODE (type) == TFmode) + obstack_1grow (&util_obstack, 'd'); + } + + else if (code == VOID_TYPE) + obstack_1grow (&util_obstack, 'v'); + + else if (code == ARRAY_TYPE) + encode_array (type, curtype, format); + + else if (code == POINTER_TYPE) + encode_pointer (type, curtype, format); + + else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) + encode_aggregate (type, curtype, format); + + else if (code == FUNCTION_TYPE) /* '?' */ + obstack_1grow (&util_obstack, '?'); +} + +static void +encode_field_decl (field_decl, curtype, format) + tree field_decl; + int curtype; + int format; +{ + tree type; + + /* If this field is obviously a bitfield, or is a bitfield that has been + clobbered to look like a ordinary integer mode, go ahead and generate + the bitfield typing information. */ + type = TREE_TYPE (field_decl); + if (DECL_BIT_FIELD (field_decl)) + encode_bitfield (DECL_FIELD_SIZE (field_decl), format); + else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST + && DECL_FIELD_SIZE (field_decl) + && TYPE_MODE (type) > DECL_MODE (field_decl)) + encode_bitfield (DECL_FIELD_SIZE (field_decl), format); + else + encode_type (TREE_TYPE (field_decl), curtype, format); +} + +static tree +expr_last (complex_expr) + tree complex_expr; +{ + tree next; + + if (complex_expr) + while ((next = TREE_OPERAND (complex_expr, 0))) + complex_expr = next; + + return complex_expr; +} + +/* The selector of the current method, + or NULL if we aren't compiling a method. */ + +tree +maybe_objc_method_name (decl) + tree decl; +{ + if (method_context) + return METHOD_SEL_NAME (method_context); + else + return 0; +} + +/* Transform a method definition into a function definition as follows: + - synthesize the first two arguments, "self" and "_cmd". */ + +void +start_method_def (method) + tree method; +{ + tree decl_specs; + + /* Required to implement _msgSuper. */ + method_context = method; + UOBJC_SUPER_decl = NULL_TREE; + + /* Must be called BEFORE start_function. */ + pushlevel (0); + + /* Generate prototype declarations for arguments..."new-style". */ + + if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL) + decl_specs = build_tree_list (NULL_TREE, uprivate_record); + else + /* Really a `struct objc_class *'. However, we allow people to + assign to self, which changes its type midstream. */ + decl_specs = build_tree_list (NULL_TREE, objc_object_reference); + + push_parm_decl (build_tree_list + (build_tree_list (decl_specs, + build1 (INDIRECT_REF, NULL_TREE, self_id)), + build_tree_list (unused_list, NULL_TREE))); + +#ifdef OBJC_INT_SELECTORS + decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]); + decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_INT], decl_specs); + push_parm_decl (build_tree_list (build_tree_list (decl_specs, ucmd_id), + build_tree_list (unused_list, NULL_TREE))); +#else /* not OBJC_INT_SELECTORS */ + decl_specs = build_tree_list (NULL_TREE, + xref_tag (RECORD_TYPE, + get_identifier (TAG_SELECTOR))); + push_parm_decl (build_tree_list + (build_tree_list (decl_specs, + build1 (INDIRECT_REF, NULL_TREE, ucmd_id)), + build_tree_list (unused_list, NULL_TREE))); +#endif /* not OBJC_INT_SELECTORS */ + + /* Generate argument declarations if a keyword_decl. */ + if (METHOD_SEL_ARGS (method)) + { + tree arglist = METHOD_SEL_ARGS (method); + do + { + tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist)); + tree arg_decl = TREE_VALUE (TREE_TYPE (arglist)); + + if (arg_decl) + { + tree last_expr = expr_last (arg_decl); + + /* Unite the abstract decl with its name. */ + TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist); + push_parm_decl (build_tree_list + (build_tree_list (arg_spec, arg_decl), + build_tree_list (NULL_TREE, NULL_TREE))); + + /* Unhook: restore the abstract declarator. */ + TREE_OPERAND (last_expr, 0) = NULL_TREE; + } + + else + push_parm_decl (build_tree_list + (build_tree_list (arg_spec, + KEYWORD_ARG_NAME (arglist)), + build_tree_list (NULL_TREE, NULL_TREE))); + + arglist = TREE_CHAIN (arglist); + } + while (arglist); + } + + if (METHOD_ADD_ARGS (method) > (tree)1) + { + /* We have a variable length selector - in "prototype" format. */ + tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method)); + while (akey) + { + /* This must be done prior to calling pushdecl. pushdecl is + going to change our chain on us. */ + tree nextkey = TREE_CHAIN (akey); + pushdecl (akey); + akey = nextkey; + } + } +} + +static void +warn_with_method (message, mtype, method) + char *message; + int mtype; + tree method; +{ + if (count_error (1) == 0) + return; + + report_error_function (DECL_SOURCE_FILE (method)); + + fprintf (stderr, "%s:%d: warning: ", + DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method)); + bzero (errbuf, BUFSIZE); + fprintf (stderr, "%s `%c%s'\n", + message, mtype, gen_method_decl (method, errbuf)); +} + +/* Return 1 if METHOD is consistent with PROTO. */ + +static int +comp_method_with_proto (method, proto) + tree method, proto; +{ + static tree function_type = 0; + + /* Create a function_type node once. */ + if (!function_type) + { + push_obstacks_nochange (); + end_temporary_allocation (); + function_type = make_node (FUNCTION_TYPE); + pop_obstacks (); + } + + /* Install argument types - normally set by build_function_type. */ + TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0); + + /* install return type */ + TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto)); + + return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type); +} + +/* Return 1 if PROTO1 is consistent with PROTO2. */ + +static int +comp_proto_with_proto (proto1, proto2) + tree proto1, proto2; +{ + static tree function_type1 = 0, function_type2 = 0; + + /* Create a couple function_type node's once. */ + if (!function_type1) + { + push_obstacks_nochange (); + end_temporary_allocation (); + function_type1 = make_node (FUNCTION_TYPE); + function_type2 = make_node (FUNCTION_TYPE); + pop_obstacks (); + } + + /* Install argument types; normally set by build_function_type. */ + TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0); + TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0); + + /* Install return type. */ + TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1)); + TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2)); + + return comptypes (function_type1, function_type2); +} + +/* - Generate an identifier for the function. the format is "_n_cls", + where 1 <= n <= nMethods, and cls is the name the implementation we + are processing. + - Install the return type from the method declaration. + - If we have a prototype, check for type consistency. */ + +static void +really_start_method (method, parmlist) + tree method, parmlist; +{ + tree sc_spec, ret_spec, ret_decl, decl_specs; + tree method_decl, method_id; + char *buf, *sel_name, *class_name, *cat_name; + + /* Synth the storage class & assemble the return type. */ + sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], NULL_TREE); + ret_spec = TREE_PURPOSE (TREE_TYPE (method)); + decl_specs = chainon (sc_spec, ret_spec); + + sel_name = IDENTIFIER_POINTER (METHOD_SEL_NAME (method)); + class_name = IDENTIFIER_POINTER (CLASS_NAME (implementation_context)); + cat_name = ((TREE_CODE (implementation_context) + == CLASS_IMPLEMENTATION_TYPE) + ? NULL + : IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); + method_slot++; + + /* Make sure this is big enough for any plausible method label. */ + buf = (char *) alloca (50 + strlen (sel_name) + strlen (class_name) + + (cat_name ? strlen (cat_name) : 0)); + + OBJC_GEN_METHOD_LABEL (buf, TREE_CODE (method) == INSTANCE_METHOD_DECL, + class_name, cat_name, sel_name, method_slot); + + method_id = get_identifier (buf); + + method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULL_TREE); + + /* Check the declarator portion of the return type for the method. */ + if ((ret_decl = TREE_VALUE (TREE_TYPE (method)))) + { + /* Unite the complex decl (specified in the abstract decl) with the + function decl just synthesized..(int *), (int (*)()), (int (*)[]). */ + tree save_expr = expr_last (ret_decl); + + TREE_OPERAND (save_expr, 0) = method_decl; + method_decl = ret_decl; + + /* Fool the parser into thinking it is starting a function. */ + start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0); + + /* Unhook: this has the effect of restoring the abstract declarator. */ + TREE_OPERAND (save_expr, 0) = NULL_TREE; + } + + else + { + TREE_VALUE (TREE_TYPE (method)) = method_decl; + + /* Fool the parser into thinking it is starting a function. */ + start_function (decl_specs, method_decl, NULL_TREE, NULL_TREE, 0); + + /* Unhook: this has the effect of restoring the abstract declarator. */ + TREE_VALUE (TREE_TYPE (method)) = NULL_TREE; + } + + METHOD_DEFINITION (method) = current_function_decl; + + if (implementation_template != implementation_context) + { + tree proto; + + if (TREE_CODE (method) == INSTANCE_METHOD_DECL) + proto = lookup_instance_method_static (implementation_template, + METHOD_SEL_NAME (method)); + else + proto = lookup_class_method_static (implementation_template, + METHOD_SEL_NAME (method)); + + if (proto && ! comp_method_with_proto (method, proto)) + { + char type = (TREE_CODE (method) == INSTANCE_METHOD_DECL ? '-' : '+'); + + warn_with_method ("conflicting types for", type, method); + warn_with_method ("previous declaration of", type, proto); + } + } +} + +/* The following routine is always called...this "architecture" is to + accommodate "old-style" variable length selectors. + + - a:a b:b // prototype ; id c; id d; // old-style. */ + +void +continue_method_def () +{ + tree parmlist; + + if (METHOD_ADD_ARGS (method_context) == (tree)1) + /* We have a `, ...' immediately following the selector. */ + parmlist = get_parm_info (0); + else + parmlist = get_parm_info (1); /* place a `void_at_end' */ + + /* Set self_decl from the first argument...this global is used by + build_ivar_reference calling build_indirect_ref. */ + self_decl = TREE_PURPOSE (parmlist); + + poplevel (0, 0, 0); + really_start_method (method_context, parmlist); + store_parm_decls (); +} + +/* Called by the parser, from the `pushlevel' production. */ + +void +add_objc_decls () +{ + if (!UOBJC_SUPER_decl) + { + UOBJC_SUPER_decl = start_decl (get_identifier (UTAG_SUPER), + build_tree_list (NULL_TREE, + objc_super_template), + 0, NULL_TREE, NULL_TREE); + + finish_decl (UOBJC_SUPER_decl, NULL_TREE, NULL_TREE); + + /* This prevents `unused variable' warnings when compiling with -Wall. */ + TREE_USED (UOBJC_SUPER_decl) = 1; + DECL_ARTIFICIAL (UOBJC_SUPER_decl) = 1; + } +} + +/* _n_Method (id self, SEL sel, ...) + { + struct objc_super _S; + _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...); + } */ + +tree +get_super_receiver () +{ + if (method_context) + { + tree super_expr, super_expr_list; + + /* Set receiver to self. */ + super_expr = build_component_ref (UOBJC_SUPER_decl, self_id); + super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl); + super_expr_list = build_tree_list (NULL_TREE, super_expr); + + /* Set class to begin searching. */ + super_expr = build_component_ref (UOBJC_SUPER_decl, + get_identifier ("class")); + + if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) + { + /* [_cls, __cls]Super are "pre-built" in + synth_forward_declarations. */ + + super_expr = build_modify_expr (super_expr, NOP_EXPR, + ((TREE_CODE (method_context) + == INSTANCE_METHOD_DECL) + ? ucls_super_ref + : uucls_super_ref)); + } + + else + /* We have a category. */ + { + tree super_name = CLASS_SUPER_NAME (implementation_template); + tree super_class; + + if (!super_name) + { + error ("no super class declared in interface for `%s'", + IDENTIFIER_POINTER (CLASS_NAME (implementation_template))); + return error_mark_node; + } + + if (flag_next_runtime) + { + super_class = get_class_reference (super_name); + if (TREE_CODE (method_context) == CLASS_METHOD_DECL) + super_class + = build_component_ref (build_indirect_ref (super_class, "->"), + get_identifier ("isa")); + } + else + { + add_class_reference (super_name); + super_class = (TREE_CODE (method_context) == INSTANCE_METHOD_DECL + ? objc_get_class_decl : objc_get_meta_class_decl); + assemble_external (super_class); + super_class + = build_function_call + (super_class, + build_tree_list + (NULL_TREE, + my_build_string (IDENTIFIER_LENGTH (super_name) + 1, + IDENTIFIER_POINTER (super_name)))); + } + + TREE_TYPE (super_class) = TREE_TYPE (ucls_super_ref); + super_expr = build_modify_expr (super_expr, NOP_EXPR, super_class); + } + + chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr)); + + super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0); + chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr)); + + return build_compound_expr (super_expr_list); + } + else + { + error ("[super ...] must appear in a method context"); + return error_mark_node; + } +} + +static tree +encode_method_def (func_decl) + tree func_decl; +{ + tree parms; + int stack_size; + int max_parm_end = 0; + char buffer[40]; + tree result; + + /* Return type. */ + encode_type (TREE_TYPE (TREE_TYPE (func_decl)), + obstack_object_size (&util_obstack), + OBJC_ENCODE_INLINE_DEFS); + + /* Stack size. */ + for (parms = DECL_ARGUMENTS (func_decl); parms; + parms = TREE_CHAIN (parms)) + { + int parm_end = (forwarding_offset (parms) + + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (parms))) + / BITS_PER_UNIT)); + + if (!offset_is_register && parm_end > max_parm_end) + max_parm_end = parm_end; + } + + stack_size = max_parm_end - OBJC_FORWARDING_MIN_OFFSET; + + sprintf (buffer, "%d", stack_size); + obstack_grow (&util_obstack, buffer, strlen (buffer)); + + /* Argument types. */ + for (parms = DECL_ARGUMENTS (func_decl); parms; + parms = TREE_CHAIN (parms)) + { + /* Type. */ + encode_type (TREE_TYPE (parms), + obstack_object_size (&util_obstack), + OBJC_ENCODE_INLINE_DEFS); + + /* Compute offset. */ + sprintf (buffer, "%d", forwarding_offset (parms)); + + /* Indicate register. */ + if (offset_is_register) + obstack_1grow (&util_obstack, '+'); + + obstack_grow (&util_obstack, buffer, strlen (buffer)); + } + + obstack_1grow (&util_obstack, 0); + result = get_identifier (obstack_finish (&util_obstack)); + obstack_free (&util_obstack, util_firstobj); + return result; +} + +void +finish_method_def () +{ + METHOD_ENCODING (method_context) = encode_method_def (current_function_decl); + + finish_function (0); + + /* Required to implement _msgSuper. This must be done AFTER finish_function, + since the optimizer may find "may be used before set" errors. */ + method_context = NULL_TREE; +} + +int +lang_report_error_function (decl) + tree decl; +{ + if (method_context) + { + fprintf (stderr, "In method `%s'\n", + IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context))); + return 1; + } + + else + return 0; +} + +static int +is_complex_decl (type) + tree type; +{ + return (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == FUNCTION_TYPE + || (TREE_CODE (type) == POINTER_TYPE && ! IS_ID (type))); +} + + +/* Code to convert a decl node into text for a declaration in C. */ + +static char tmpbuf[256]; + +static void +adorn_decl (decl, str) + tree decl; + char *str; +{ + enum tree_code code = TREE_CODE (decl); + + if (code == ARRAY_REF) + { + tree an_int_cst = TREE_OPERAND (decl, 1); + + if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_CST) + sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (an_int_cst)); + else + strcat (str, "[]"); + } + + else if (code == ARRAY_TYPE) + { + tree an_int_cst = TYPE_SIZE (decl); + tree array_of = TREE_TYPE (decl); + + if (an_int_cst && TREE_CODE (an_int_cst) == INTEGER_TYPE) + sprintf (str + strlen (str), "[%d]", + (TREE_INT_CST_LOW (an_int_cst) + / TREE_INT_CST_LOW (TYPE_SIZE (array_of)))); + else + strcat (str, "[]"); + } + + else if (code == CALL_EXPR) + { + tree chain = TREE_PURPOSE (TREE_OPERAND (decl, 1)); + + strcat (str, "("); + while (chain) + { + gen_declaration (chain, str); + chain = TREE_CHAIN (chain); + if (chain) + strcat (str, ", "); + } + strcat (str, ")"); + } + + else if (code == FUNCTION_TYPE) + { + tree chain = TYPE_ARG_TYPES (decl); + + strcat (str, "("); + while (chain && TREE_VALUE (chain) != void_type_node) + { + gen_declaration (TREE_VALUE (chain), str); + chain = TREE_CHAIN (chain); + if (chain && TREE_VALUE (chain) != void_type_node) + strcat (str, ", "); + } + strcat (str, ")"); + } + + else if (code == INDIRECT_REF) + { + strcpy (tmpbuf, "*"); + if (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == TREE_LIST) + { + tree chain; + + for (chain = nreverse (copy_list (TREE_TYPE (decl))); + chain; + chain = TREE_CHAIN (chain)) + { + if (TREE_CODE (TREE_VALUE (chain)) == IDENTIFIER_NODE) + { + strcat (tmpbuf, " "); + strcat (tmpbuf, IDENTIFIER_POINTER (TREE_VALUE (chain))); + } + } + if (str[0]) + strcat (tmpbuf, " "); + } + strcat (tmpbuf, str); + strcpy (str, tmpbuf); + } + + else if (code == POINTER_TYPE) + { + strcpy (tmpbuf, "*"); + if (TREE_READONLY (decl) || TYPE_VOLATILE (decl)) + { + if (TREE_READONLY (decl)) + strcat (tmpbuf, " const"); + if (TYPE_VOLATILE (decl)) + strcat (tmpbuf, " volatile"); + if (str[0]) + strcat (tmpbuf, " "); + } + strcat (tmpbuf, str); + strcpy (str, tmpbuf); + } +} + +static char * +gen_declarator (decl, buf, name) + tree decl; + char *buf; + char *name; +{ + if (decl) + { + enum tree_code code = TREE_CODE (decl); + char *str; + tree op; + int wrap = 0; + + switch (code) + { + case ARRAY_REF: + case INDIRECT_REF: + case CALL_EXPR: + op = TREE_OPERAND (decl, 0); + + /* We have a pointer to a function or array...(*)(), (*)[] */ + if ((code == ARRAY_REF || code == CALL_EXPR) + && op && TREE_CODE (op) == INDIRECT_REF) + wrap = 1; + + str = gen_declarator (op, buf, name); + + if (wrap) + { + strcpy (tmpbuf, "("); + strcat (tmpbuf, str); + strcat (tmpbuf, ")"); + strcpy (str, tmpbuf); + } + + adorn_decl (decl, str); + break; + + case ARRAY_TYPE: + case FUNCTION_TYPE: + case POINTER_TYPE: + strcpy (buf, name); + str = buf; + + /* This clause is done iteratively rather than recursively. */ + do + { + op = (is_complex_decl (TREE_TYPE (decl)) + ? TREE_TYPE (decl) : NULL_TREE); + + adorn_decl (decl, str); + + /* We have a pointer to a function or array...(*)(), (*)[] */ + if (code == POINTER_TYPE + && op && (TREE_CODE (op) == FUNCTION_TYPE + || TREE_CODE (op) == ARRAY_TYPE)) + { + strcpy (tmpbuf, "("); + strcat (tmpbuf, str); + strcat (tmpbuf, ")"); + strcpy (str, tmpbuf); + } + + decl = (is_complex_decl (TREE_TYPE (decl)) + ? TREE_TYPE (decl) : NULL_TREE); + } + + while (decl && (code = TREE_CODE (decl))) + ; + + break; + + case IDENTIFIER_NODE: + /* Will only happen if we are processing a "raw" expr-decl. */ + strcpy (buf, IDENTIFIER_POINTER (decl)); + return buf; + } + + return str; + } + + else + /* We have an abstract declarator or a _DECL node. */ + { + strcpy (buf, name); + return buf; + } +} + +static void +gen_declspecs (declspecs, buf, raw) + tree declspecs; + char *buf; + int raw; +{ + if (raw) + { + tree chain; + + for (chain = nreverse (copy_list (declspecs)); + chain; chain = TREE_CHAIN (chain)) + { + tree aspec = TREE_VALUE (chain); + + if (TREE_CODE (aspec) == IDENTIFIER_NODE) + strcat (buf, IDENTIFIER_POINTER (aspec)); + else if (TREE_CODE (aspec) == RECORD_TYPE) + { + if (TYPE_NAME (aspec)) + { + tree protocol_list = TYPE_PROTOCOL_LIST (aspec); + + if (! TREE_STATIC_TEMPLATE (aspec)) + strcat (buf, "struct "); + strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec))); + + /* NEW!!! */ + if (protocol_list) + { + tree chain = protocol_list; + + strcat (buf, " <"); + while (chain) + { + strcat (buf, + IDENTIFIER_POINTER + (PROTOCOL_NAME (TREE_VALUE (chain)))); + chain = TREE_CHAIN (chain); + if (chain) + strcat (buf, ", "); + } + strcat (buf, ">"); + } + } + + else + strcat (buf, "untagged struct"); + } + + else if (TREE_CODE (aspec) == UNION_TYPE) + { + if (TYPE_NAME (aspec)) + { + if (! TREE_STATIC_TEMPLATE (aspec)) + strcat (buf, "union "); + strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec))); + } + else + strcat (buf, "untagged union"); + } + + else if (TREE_CODE (aspec) == ENUMERAL_TYPE) + { + if (TYPE_NAME (aspec)) + { + if (! TREE_STATIC_TEMPLATE (aspec)) + strcat (buf, "enum "); + strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec))); + } + else + strcat (buf, "untagged enum"); + } + + else if (TREE_CODE (aspec) == TYPE_DECL && DECL_NAME (aspec)) + strcat (buf, IDENTIFIER_POINTER (DECL_NAME (aspec))); + + else if (IS_ID (aspec)) + { + tree protocol_list = TYPE_PROTOCOL_LIST (aspec); + + strcat (buf, "id"); + if (protocol_list) + { + tree chain = protocol_list; + + strcat (buf, " <"); + while (chain) + { + strcat (buf, + IDENTIFIER_POINTER + (PROTOCOL_NAME (TREE_VALUE (chain)))); + chain = TREE_CHAIN (chain); + if (chain) + strcat (buf, ", "); + } + strcat (buf, ">"); + } + } + if (TREE_CHAIN (chain)) + strcat (buf, " "); + } + } + else + { + /* Type qualifiers. */ + if (TREE_READONLY (declspecs)) + strcat (buf, "const "); + if (TYPE_VOLATILE (declspecs)) + strcat (buf, "volatile "); + + switch (TREE_CODE (declspecs)) + { + /* Type specifiers. */ + + case INTEGER_TYPE: + declspecs = TYPE_MAIN_VARIANT (declspecs); + + /* Signed integer types. */ + + if (declspecs == short_integer_type_node) + strcat (buf, "short int "); + else if (declspecs == integer_type_node) + strcat (buf, "int "); + else if (declspecs == long_integer_type_node) + strcat (buf, "long int "); + else if (declspecs == long_long_integer_type_node) + strcat (buf, "long long int "); + else if (declspecs == signed_char_type_node + || declspecs == char_type_node) + strcat (buf, "char "); + + /* Unsigned integer types. */ + + else if (declspecs == short_unsigned_type_node) + strcat (buf, "unsigned short "); + else if (declspecs == unsigned_type_node) + strcat (buf, "unsigned int "); + else if (declspecs == long_unsigned_type_node) + strcat (buf, "unsigned long "); + else if (declspecs == long_long_unsigned_type_node) + strcat (buf, "unsigned long long "); + else if (declspecs == unsigned_char_type_node) + strcat (buf, "unsigned char "); + break; + + case REAL_TYPE: + declspecs = TYPE_MAIN_VARIANT (declspecs); + + if (declspecs == float_type_node) + strcat (buf, "float "); + else if (declspecs == double_type_node) + strcat (buf, "double "); + else if (declspecs == long_double_type_node) + strcat (buf, "long double "); + break; + + case RECORD_TYPE: + if (TYPE_NAME (declspecs) + && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) + { + tree protocol_list = TYPE_PROTOCOL_LIST (declspecs); + + if (! TREE_STATIC_TEMPLATE (declspecs)) + strcat (buf, "struct "); + strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs))); + + if (protocol_list) + { + tree chain = protocol_list; + + strcat (buf, " <"); + while (chain) + { + strcat (buf, + IDENTIFIER_POINTER + (PROTOCOL_NAME (TREE_VALUE (chain)))); + chain = TREE_CHAIN (chain); + if (chain) + strcat (buf, ", "); + } + strcat (buf, ">"); + } + } + + else + strcat (buf, "untagged struct"); + + strcat (buf, " "); + break; + + case UNION_TYPE: + if (TYPE_NAME (declspecs) + && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) + { + strcat (buf, "union "); + strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs))); + strcat (buf, " "); + } + + else + strcat (buf, "untagged union "); + break; + + case ENUMERAL_TYPE: + if (TYPE_NAME (declspecs) + && TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE) + { + strcat (buf, "enum "); + strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs))); + strcat (buf, " "); + } + + else + strcat (buf, "untagged enum "); + break; + + case VOID_TYPE: + strcat (buf, "void "); + break; + + case POINTER_TYPE: + { + tree protocol_list = TYPE_PROTOCOL_LIST (declspecs); + + strcat (buf, "id"); + if (protocol_list) + { + tree chain = protocol_list; + + strcat (buf, " <"); + while (chain) + { + strcat (buf, + IDENTIFIER_POINTER + (PROTOCOL_NAME (TREE_VALUE (chain)))); + chain = TREE_CHAIN (chain); + if (chain) + strcat (buf, ", "); + } + + strcat (buf, ">"); + } + } + } + } +} + +static char * +gen_declaration (atype_or_adecl, buf) + tree atype_or_adecl; + char *buf; +{ + char declbuf[256]; + + if (TREE_CODE (atype_or_adecl) == TREE_LIST) + { + tree declspecs; /* "identifier_node", "record_type" */ + tree declarator; /* "array_ref", "indirect_ref", "call_expr"... */ + + /* We have a "raw", abstract declarator (typename). */ + declarator = TREE_VALUE (atype_or_adecl); + declspecs = TREE_PURPOSE (atype_or_adecl); + + gen_declspecs (declspecs, buf, 1); + if (declarator) + { + strcat (buf, " "); + strcat (buf, gen_declarator (declarator, declbuf, "")); + } + } + + else + { + tree atype; + tree declspecs; /* "integer_type", "real_type", "record_type"... */ + tree declarator; /* "array_type", "function_type", "pointer_type". */ + + if (TREE_CODE (atype_or_adecl) == FIELD_DECL + || TREE_CODE (atype_or_adecl) == PARM_DECL + || TREE_CODE (atype_or_adecl) == FUNCTION_DECL) + atype = TREE_TYPE (atype_or_adecl); + else + /* Assume we have a *_type node. */ + atype = atype_or_adecl; + + if (is_complex_decl (atype)) + { + tree chain; + + /* Get the declaration specifier; it is at the end of the list. */ + declarator = chain = atype; + do + chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */ + while (is_complex_decl (chain)); + declspecs = chain; + } + + else + { + declspecs = atype; + declarator = NULL_TREE; + } + + gen_declspecs (declspecs, buf, 0); + + if (TREE_CODE (atype_or_adecl) == FIELD_DECL + || TREE_CODE (atype_or_adecl) == PARM_DECL + || TREE_CODE (atype_or_adecl) == FUNCTION_DECL) + { + char *decl_name = (DECL_NAME (atype_or_adecl) + ? IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)) + : ""); + + if (declarator) + { + strcat (buf, " "); + strcat (buf, gen_declarator (declarator, declbuf, decl_name)); + } + + else if (decl_name[0]) + { + strcat (buf, " "); + strcat (buf, decl_name); + } + } + else if (declarator) + { + strcat (buf, " "); + strcat (buf, gen_declarator (declarator, declbuf, "")); + } + } + + return buf; +} + +#define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth)))) + +static char * +gen_method_decl (method, buf) + tree method; + char *buf; +{ + tree chain; + + if (RAW_TYPESPEC (method) != objc_object_reference) + { + strcpy (buf, "("); + gen_declaration (TREE_TYPE (method), buf); + strcat (buf, ")"); + } + + chain = METHOD_SEL_ARGS (method); + if (chain) + { + /* We have a chain of keyword_decls. */ + do + { + if (KEYWORD_KEY_NAME (chain)) + strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain))); + + strcat (buf, ":"); + if (RAW_TYPESPEC (chain) != objc_object_reference) + { + strcat (buf, "("); + gen_declaration (TREE_TYPE (chain), buf); + strcat (buf, ")"); + } + + strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain))); + if ((chain = TREE_CHAIN (chain))) + strcat (buf, " "); + } + while (chain); + + if (METHOD_ADD_ARGS (method) == (tree)1) + strcat (buf, ", ..."); + else if (METHOD_ADD_ARGS (method)) + { + /* We have a tree list node as generate by get_parm_info. */ + chain = TREE_PURPOSE (METHOD_ADD_ARGS (method)); + + /* Know we have a chain of parm_decls. */ + while (chain) + { + strcat (buf, ", "); + gen_declaration (chain, buf); + chain = TREE_CHAIN (chain); + } + } + } + + else + /* We have a unary selector. */ + strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method))); + + return buf; +} + +/* Debug info. */ + +static void +dump_interface (fp, chain) + FILE *fp; + tree chain; +{ + char *buf = (char *)xmalloc (256); + char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain)); + tree ivar_decls = CLASS_RAW_IVARS (chain); + tree nst_methods = CLASS_NST_METHODS (chain); + tree cls_methods = CLASS_CLS_METHODS (chain); + + fprintf (fp, "\n@interface %s", my_name); + + if (CLASS_SUPER_NAME (chain)) + { + char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain)); + fprintf (fp, " : %s\n", super_name); + } + else + fprintf (fp, "\n"); + + if (ivar_decls) + { + fprintf (fp, "{\n"); + do + { + bzero (buf, 256); + fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf)); + ivar_decls = TREE_CHAIN (ivar_decls); + } + while (ivar_decls); + fprintf (fp, "}\n"); + } + + while (nst_methods) + { + bzero (buf, 256); + fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf)); + nst_methods = TREE_CHAIN (nst_methods); + } + + while (cls_methods) + { + bzero (buf, 256); + fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf)); + cls_methods = TREE_CHAIN (cls_methods); + } + fprintf (fp, "\n@end"); +} + +/* Demangle function for Objective-C */ +static const char * +objc_demangle (mangled) + const char *mangled; +{ + char *demangled, *cp; + + if (mangled[0] == '_' && + (mangled[1] == 'i' || mangled[1] == 'c') && + mangled[2] == '_') + { + cp = demangled = xmalloc(strlen(mangled) + 2); + if (mangled[1] == 'i') + *cp++ = '-'; /* for instance method */ + else + *cp++ = '+'; /* for class method */ + *cp++ = '['; /* opening left brace */ + strcpy(cp, mangled+3); /* tack on the rest of the mangled name */ + while (*cp && *cp == '_') + cp++; /* skip any initial underbars in class name */ + cp = strchr(cp, '_'); /* find first non-initial underbar */ + if (cp == NULL) + { + free(demangled); /* not mangled name */ + return mangled; + } + if (cp[1] == '_') /* easy case: no category name */ + { + *cp++ = ' '; /* replace two '_' with one ' ' */ + strcpy(cp, mangled + (cp - demangled) + 2); + } + else + { + *cp++ = '('; /* less easy case: category name */ + cp = strchr(cp, '_'); + if (cp == 0) + { + free(demangled); /* not mangled name */ + return mangled; + } + *cp++ = ')'; + *cp++ = ' '; /* overwriting 1st char of method name... */ + strcpy(cp, mangled + (cp - demangled)); /* get it back */ + } + while (*cp && *cp == '_') + cp++; /* skip any initial underbars in method name */ + for (; *cp; cp++) + if (*cp == '_') + *cp = ':'; /* replace remaining '_' with ':' */ + *cp++ = ']'; /* closing right brace */ + *cp++ = 0; /* string terminator */ + return demangled; + } + else + return mangled; /* not an objc mangled name */ +} + +static const char * +objc_printable_name (decl, kind) + tree decl; + char **kind; +{ + return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl))); +} + +static void +init_objc () +{ + /* Add the special tree codes of Objective C to the tables. */ + +#define LAST_CODE LAST_AND_UNUSED_TREE_CODE + + gcc_obstack_init (&util_obstack); + util_firstobj = (char *) obstack_finish (&util_obstack); + + tree_code_type + = (char **) xrealloc (tree_code_type, + sizeof (char *) * LAST_OBJC_TREE_CODE); + tree_code_length + = (int *) xrealloc (tree_code_length, + sizeof (int) * LAST_OBJC_TREE_CODE); + tree_code_name + = (char **) xrealloc (tree_code_name, + sizeof (char *) * LAST_OBJC_TREE_CODE); + bcopy ((char *) objc_tree_code_type, + (char *) (tree_code_type + (int) LAST_CODE), + (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) + * sizeof (char *))); + bcopy ((char *) objc_tree_code_length, + (char *) (tree_code_length + (int) LAST_CODE), + (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) + * sizeof (int))); + bcopy ((char *) objc_tree_code_name, + (char *) (tree_code_name + (int) LAST_CODE), + (((int) LAST_OBJC_TREE_CODE - (int) LAST_CODE) + * sizeof (char *))); + + errbuf = (char *)xmalloc (BUFSIZE); + hash_init (); + synth_module_prologue (); + + /* Change the default error function */ + decl_printable_name = (char* (*)()) objc_printable_name; +} + +static void +finish_objc () +{ + struct imp_entry *impent; + tree chain; + /* The internally generated initializers appear to have missing braces. + Don't warn about this. */ + int save_warn_missing_braces = warn_missing_braces; + warn_missing_braces = 0; + + generate_forward_declaration_to_string_table (); + +#ifdef OBJC_PROLOGUE + OBJC_PROLOGUE; +#endif + + /* Process the static instances here because initialization of objc_symtab + depends on them. */ + if (objc_static_instances) + generate_static_references (); + + if (implementation_context || class_names_chain + || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) + generate_objc_symtab_decl (); + + for (impent = imp_list; impent; impent = impent->next) + { + implementation_context = impent->imp_context; + implementation_template = impent->imp_template; + + UOBJC_CLASS_decl = impent->class_decl; + UOBJC_METACLASS_decl = impent->meta_decl; + + if (TREE_CODE (implementation_context) == CLASS_IMPLEMENTATION_TYPE) + { + /* all of the following reference the string pool... */ + generate_ivar_lists (); + generate_dispatch_tables (); + generate_shared_structures (); + } + else + { + generate_dispatch_tables (); + generate_category (implementation_context); + } + } + + /* If we are using an array of selectors, we must always + finish up the array decl even if no selectors were used. */ + if (! flag_next_runtime || sel_ref_chain) + build_selector_translation_table (); + + if (protocol_chain) + generate_protocols (); + + if (implementation_context || class_names_chain || objc_static_instances + || meth_var_names_chain || meth_var_types_chain || sel_ref_chain) + { + /* Arrange for Objc data structures to be initialized at run time. */ + char *init_name = build_module_descriptor (); + if (init_name) + assemble_constructor (init_name); + } + + /* Dump the class references. This forces the appropriate classes + to be linked into the executable image, preserving unix archive + semantics. This can be removed when we move to a more dynamically + linked environment. */ + + for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain)) + { + handle_class_ref (chain); + if (TREE_PURPOSE (chain)) + generate_classref_translation_entry (chain); + } + + for (impent = imp_list; impent; impent = impent->next) + handle_impent (impent); + + /* Dump the string table last. */ + + generate_strings (); + + if (flag_gen_declaration) + { + add_class (implementation_context); + dump_interface (gen_declaration_file, implementation_context); + } + + if (warn_selector) + { + int slot; + hash hsh; + + /* Run through the selector hash tables and print a warning for any + selector which has multiple methods. */ + + for (slot = 0; slot < SIZEHASHTABLE; slot++) + for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next) + if (hsh->list) + { + tree meth = hsh->key; + char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL + ? '-' : '+'); + attr loop; + + warning ("potential selector conflict for method `%s'", + IDENTIFIER_POINTER (METHOD_SEL_NAME (meth))); + warn_with_method ("found", type, meth); + for (loop = hsh->list; loop; loop = loop->next) + warn_with_method ("found", type, loop->value); + } + + for (slot = 0; slot < SIZEHASHTABLE; slot++) + for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next) + if (hsh->list) + { + tree meth = hsh->key; + char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL + ? '-' : '+'); + attr loop; + + warning ("potential selector conflict for method `%s'", + IDENTIFIER_POINTER (METHOD_SEL_NAME (meth))); + warn_with_method ("found", type, meth); + for (loop = hsh->list; loop; loop = loop->next) + warn_with_method ("found", type, loop->value); + } + } + + warn_missing_braces = save_warn_missing_braces; +} + +/* Subroutines of finish_objc. */ + +static void +generate_classref_translation_entry (chain) + tree chain; +{ + tree expr, name, decl_specs, decl, sc_spec; + tree type; + + type = TREE_TYPE (TREE_PURPOSE (chain)); + + expr = add_objc_string (TREE_VALUE (chain), class_names); + expr = build_c_cast (type, expr); /* cast! */ + + name = DECL_NAME (TREE_PURPOSE (chain)); + + sc_spec = build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]); + + /* static struct objc_class * _OBJC_CLASS_REFERENCES_n = ...; */ + decl_specs = tree_cons (NULL_TREE, type, sc_spec); + + /* The decl that is returned from start_decl is the one that we + forward declared in build_class_reference. */ + decl = start_decl (name, decl_specs, 1, NULL_TREE, NULL_TREE); + finish_decl (decl, expr, NULL_TREE); + return; +} + +static void +handle_class_ref (chain) + tree chain; +{ + char *name = IDENTIFIER_POINTER (TREE_VALUE (chain)); + if (! flag_next_runtime) + { + tree decl; + char *string = (char *) alloca (strlen (name) + 30); + tree exp; + + sprintf (string, "%sobjc_class_name_%s", + (flag_next_runtime ? "." : "__"), name); + + /* Make a decl for this name, so we can use its address in a tree. */ + decl = build_decl (VAR_DECL, get_identifier (string), char_type_node); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + + pushdecl (decl); + rest_of_decl_compilation (decl, 0, 0, 0); + + /* Make following constant read-only (why not)? */ + readonly_data_section (); + + exp = build1 (ADDR_EXPR, string_type_node, decl); + + /* Align the section properly. */ + assemble_constant_align (exp); + + /* Inform the assembler about this new external thing. */ + assemble_external (decl); + + /* Output a constant to reference this address. */ + output_constant (exp, int_size_in_bytes (string_type_node)); + } + else + { + /* This overreliance on our assembler (i.e. lack of portability) + should be dealt with at some point. The GNU strategy (above) + won't work either, but it is a start. */ + char *string = (char *) alloca (strlen (name) + 30); + sprintf (string, ".reference .objc_class_name_%s", name); + assemble_asm (my_build_string (strlen (string) + 1, string)); + } +} + +static void +handle_impent (impent) + struct imp_entry *impent; +{ + implementation_context = impent->imp_context; + implementation_template = impent->imp_template; + + if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) + { + char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); + char *string = (char *) alloca (strlen (class_name) + 30); + + if (flag_next_runtime) + { + /* Grossly unportable. + People should know better than to assume + such things about assembler syntax! */ + sprintf (string, ".objc_class_name_%s=0", class_name); + assemble_asm (my_build_string (strlen (string) + 1, string)); + + sprintf (string, ".globl .objc_class_name_%s", class_name); + assemble_asm (my_build_string (strlen (string) + 1, string)); + } + + else + { + sprintf (string, "%sobjc_class_name_%s", + (flag_next_runtime ? "." : "__"), class_name); + assemble_global (string); + assemble_label (string); + } + } + + else if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) + { + char *class_name = IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)); + char *class_super_name + = IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)); + char *string = (char *) alloca (strlen (class_name) + + strlen (class_super_name) + 30); + + /* Do the same for categories. Even though no references to these + symbols are generated automatically by the compiler, it gives + you a handle to pull them into an archive by hand. */ + if (flag_next_runtime) + { + /* Grossly unportable. */ + sprintf (string, ".objc_category_name_%s_%s=0", + class_name, class_super_name); + assemble_asm (my_build_string (strlen (string) + 1, string)); + + sprintf (string, ".globl .objc_category_name_%s_%s", + class_name, class_super_name); + assemble_asm (my_build_string (strlen (string) + 1, string)); + } + + else + { + sprintf (string, "%sobjc_category_name_%s_%s", + (flag_next_runtime ? "." : "__"), + class_name, class_super_name); + assemble_global (string); + assemble_label (string); + } + } +} + +#ifdef DEBUG + +static void +objc_debug (fp) + FILE *fp; +{ + char *buf = (char *)xmalloc (256); + + { /* dump function prototypes */ + tree loop = UOBJC_MODULES_decl; + + fprintf (fp, "\n\nfunction prototypes:\n"); + while (loop) + { + if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop)) + { + /* We have a function definition: generate prototype. */ + bzero (errbuf, BUFSIZE); + gen_declaration (loop, errbuf); + fprintf (fp, "%s;\n", errbuf); + } + loop = TREE_CHAIN (loop); + } + } + { + /* Dump global chains. */ + tree loop; + int i, index = 0, offset = 0; + hash hashlist; + + for (i = 0; i < SIZEHASHTABLE; i++) + { + if (hashlist = nst_method_hash_list[i]) + { + fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i); + do + { + bzero (buf, 256); + fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf)); + hashlist = hashlist->next; + } + while (hashlist); + } + } + + for (i = 0; i < SIZEHASHTABLE; i++) + { + if (hashlist = cls_method_hash_list[i]) + { + fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i); + do + { + bzero (buf, 256); + fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf)); + hashlist = hashlist->next; + } + while (hashlist); + } + } + + fprintf (fp, "\nsel_refdef_chain:\n"); + for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop)) + { + fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset, + IDENTIFIER_POINTER (TREE_VALUE (loop))); + index++; + /* add one for the '\0' character */ + offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1; + } + + fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index); + } +} +#endif + +void +print_lang_statistics () +{ +} diff --git a/gnu/usr.bin/gcc/objc/objc-act.h b/gnu/usr.bin/gcc/objc/objc-act.h new file mode 100644 index 00000000000..65224de84f4 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc-act.h @@ -0,0 +1,117 @@ +/* Declarations for objc-act.c. + Copyright (C) 1990 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/*** Public Interface (procedures) ***/ + +/* used by yyparse */ + +void finish_file PROTO((void)); +tree start_class PROTO((enum tree_code, tree, tree, tree)); +tree continue_class PROTO((tree)); +void finish_class PROTO((tree)); +void start_method_def PROTO((tree)); +void continue_method_def PROTO((void)); +void finish_method_def PROTO((void)); +tree start_protocol PROTO((enum tree_code, tree, tree)); +void finish_protocol PROTO((tree)); +void add_objc_decls PROTO((void)); + +tree is_ivar PROTO((tree, tree)); +int is_private PROTO((tree)); +int is_public PROTO((tree, tree)); +tree add_instance_variable PROTO((tree, int, tree, tree, tree)); +tree add_class_method PROTO((tree, tree)); +tree add_instance_method PROTO((tree, tree)); +tree get_super_receiver PROTO((void)); +tree get_class_ivars PROTO((tree)); +tree get_class_reference PROTO((tree)); +tree get_static_reference PROTO((tree, tree)); +tree get_object_reference PROTO((tree)); +tree build_message_expr PROTO((tree)); +tree build_selector_expr PROTO((tree)); +tree build_ivar_reference PROTO((tree)); +tree build_keyword_decl PROTO((tree, tree, tree)); +tree build_method_decl PROTO((enum tree_code, tree, tree, tree)); +tree build_protocol_expr PROTO((tree)); +tree build_objc_string_object PROTO((tree)); + +extern tree objc_ivar_chain; +extern tree objc_method_context; + +void objc_declare_alias PROTO((tree, tree)); +void objc_declare_class PROTO((tree)); + +extern int objc_receiver_context; + +/* the following routines are used to implement statically typed objects */ + +int objc_comptypes PROTO((tree, tree, int)); +void objc_check_decl PROTO((tree)); + +/* NeXT extensions */ + +tree build_encode_expr PROTO((tree)); + +/* Objective-C structures */ + +/* KEYWORD_DECL */ +#define KEYWORD_KEY_NAME(DECL) ((DECL)->decl.name) +#define KEYWORD_ARG_NAME(DECL) ((DECL)->decl.arguments) + +/* INSTANCE_METHOD_DECL, CLASS_METHOD_DECL */ +#define METHOD_SEL_NAME(DECL) ((DECL)->decl.name) +#define METHOD_SEL_ARGS(DECL) ((DECL)->decl.arguments) +#define METHOD_ADD_ARGS(DECL) ((DECL)->decl.result) +#define METHOD_DEFINITION(DECL) ((DECL)->decl.initial) +#define METHOD_ENCODING(DECL) ((DECL)->decl.context) + +/* CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, + CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE, + PROTOCOL_INTERFACE_TYPE */ +#define CLASS_NAME(CLASS) ((CLASS)->type.name) +#define CLASS_SUPER_NAME(CLASS) ((CLASS)->type.context) +#define CLASS_IVARS(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 0) +#define CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1) +#define CLASS_NST_METHODS(CLASS) ((CLASS)->type.minval) +#define CLASS_CLS_METHODS(CLASS) ((CLASS)->type.maxval) +#define CLASS_STATIC_TEMPLATE(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 2) +#define CLASS_CATEGORY_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 3) +#define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 4) +#define PROTOCOL_NAME(CLASS) ((CLASS)->type.name) +#define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 0) +#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval) +#define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval) +#define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 1) +#define TYPE_PROTOCOL_LIST(TYPE) ((TYPE)->type.context) + +/* Define the Objective-C or Objective-C++ language-specific tree codes. */ + +#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, +enum objc_tree_code { +#ifdef OBJCPLUS + dummy_tree_code = LAST_CPLUS_TREE_CODE, +#else + dummy_tree_code = LAST_AND_UNUSED_TREE_CODE, +#endif +#include "objc-tree.def" + LAST_OBJC_TREE_CODE +}; +#undef DEFTREECODE diff --git a/gnu/usr.bin/gcc/objc/objc-list.h b/gnu/usr.bin/gcc/objc/objc-list.h new file mode 100644 index 00000000000..19760906238 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc-list.h @@ -0,0 +1,147 @@ +/* Generic single linked list to keep various information + Copyright (C) 1993, 1994, 1996 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. */ + +#ifndef __GNU_OBJC_LIST_H +#define __GNU_OBJC_LIST_H + +struct objc_list { + void *head; + struct objc_list *tail; +}; + +/* Return a cons cell produced from (head . tail) */ + +static inline struct objc_list* +list_cons(void* head, struct objc_list* tail) +{ + struct objc_list* cell; + + cell = (struct objc_list*)objc_malloc(sizeof(struct objc_list)); + cell->head = head; + cell->tail = tail; + return cell; +} + +/* Return the length of a list, list_length(NULL) returns zero */ + +static inline int +list_length(struct objc_list* list) +{ + int i = 0; + while(list) + { + i += 1; + list = list->tail; + } + return i; +} + +/* Return the Nth element of LIST, where N count from zero. If N + larger than the list length, NULL is returned */ + +static inline void* +list_nth(int index, struct objc_list* list) +{ + while(index-- != 0) + { + if(list->tail) + list = list->tail; + else + return 0; + } + return list->head; +} + +/* Remove the element at the head by replacing it by its successor */ + +static inline void +list_remove_head(struct objc_list** list) +{ + if ((*list)->tail) + { + struct objc_list* tail = (*list)->tail; /* fetch next */ + *(*list) = *tail; /* copy next to list head */ + objc_free(tail); /* free next */ + } + else /* only one element in list */ + { + objc_free(*list); + (*list) = 0; + } +} + + +/* Remove the element with `car' set to ELEMENT */ + +static inline void +list_remove_elem(struct objc_list** list, void* elem) +{ + while (*list) { + if ((*list)->head == elem) + list_remove_head(list); + list = &((*list)->tail); + } +} + +/* Map FUNCTION over all elements in LIST */ + +static inline void +list_mapcar(struct objc_list* list, void(*function)(void*)) +{ + while(list) + { + (*function)(list->head); + list = list->tail; + } +} + +/* Return element that has ELEM as car */ + +static inline struct objc_list** +list_find(struct objc_list** list, void* elem) +{ + while(*list) + { + if ((*list)->head == elem) + return list; + list = &((*list)->tail); + } + return NULL; +} + +/* Free list (backwards recursive) */ + +static void +list_free(struct objc_list* list) +{ + if(list) + { + list_free(list->tail); + objc_free(list); + } +} +#endif __GNU_OBJC_LIST_H diff --git a/gnu/usr.bin/gcc/objc/objc-parse.c b/gnu/usr.bin/gcc/objc/objc-parse.c new file mode 100644 index 00000000000..9c80c878ad4 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc-parse.c @@ -0,0 +1,5111 @@ + +/* A Bison parser, made from objc-parse.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define IDENTIFIER 258 +#define TYPENAME 259 +#define SCSPEC 260 +#define TYPESPEC 261 +#define TYPE_QUAL 262 +#define CONSTANT 263 +#define STRING 264 +#define ELLIPSIS 265 +#define SIZEOF 266 +#define ENUM 267 +#define STRUCT 268 +#define UNION 269 +#define IF 270 +#define ELSE 271 +#define WHILE 272 +#define DO 273 +#define FOR 274 +#define SWITCH 275 +#define CASE 276 +#define DEFAULT 277 +#define BREAK 278 +#define CONTINUE 279 +#define RETURN 280 +#define GOTO 281 +#define ASM_KEYWORD 282 +#define TYPEOF 283 +#define ALIGNOF 284 +#define ATTRIBUTE 285 +#define EXTENSION 286 +#define LABEL 287 +#define REALPART 288 +#define IMAGPART 289 +#define ASSIGN 290 +#define OROR 291 +#define ANDAND 292 +#define EQCOMPARE 293 +#define ARITHCOMPARE 294 +#define LSHIFT 295 +#define RSHIFT 296 +#define UNARY 297 +#define PLUSPLUS 298 +#define MINUSMINUS 299 +#define HYPERUNARY 300 +#define POINTSAT 301 +#define INTERFACE 302 +#define IMPLEMENTATION 303 +#define END 304 +#define SELECTOR 305 +#define DEFS 306 +#define ENCODE 307 +#define CLASSNAME 308 +#define PUBLIC 309 +#define PRIVATE 310 +#define PROTECTED 311 +#define PROTOCOL 312 +#define OBJECTNAME 313 +#define CLASS 314 +#define ALIAS 315 +#define OBJC_STRING 316 + +#line 33 "objc-parse.y" + +#include "config.h" + +#include <stdio.h> +#include <errno.h> +#include <setjmp.h> + +#include "tree.h" +#include "input.h" +#include "c-lex.h" +#include "c-tree.h" +#include "flags.h" + +#ifdef MULTIBYTE_CHARS +#include <stdlib.h> +#include <locale.h> +#endif + +#include "objc-act.h" + +/* Since parsers are distinct for each language, put the language string + definition here. */ +char *language_string = "GNU Obj-C"; + +#ifndef errno +extern int errno; +#endif + +void yyerror (); + +/* Like YYERROR but do call yyerror. */ +#define YYERROR1 { yyerror ("syntax error"); YYERROR; } + +/* Cause the `yydebug' variable to be defined. */ +#define YYDEBUG 1 + +#line 72 "objc-parse.y" +typedef union {long itype; tree ttype; enum tree_code code; + char *filename; int lineno; int ends_in_label; } YYSTYPE; +#line 199 "objc-parse.y" + +/* Number of statements (loosely speaking) and compound statements + seen so far. */ +static int stmt_count; +static int compstmt_count; + +/* Input file and line number of the end of the body of last simple_if; + used by the stmt-rule immediately after simple_if returns. */ +static char *if_stmt_file; +static int if_stmt_line; + +/* List of types and structure classes of the current declaration. */ +static tree current_declspecs = NULL_TREE; +static tree prefix_attributes = NULL_TREE; + +/* Stack of saved values of current_declspecs and prefix_attributes. */ +static tree declspec_stack; + +/* 1 if we explained undeclared var errors. */ +static int undeclared_variable_notice; + +/* Objective-C specific information */ + +tree objc_interface_context; +tree objc_implementation_context; +tree objc_method_context; +tree objc_ivar_chain; +tree objc_ivar_context; +enum tree_code objc_inherit_code; +int objc_receiver_context; +int objc_public_flag; + + +/* Tell yyparse how to print a token's value, if yydebug is set. */ + +#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL) +extern void yyprint (); + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include <stdio.h> + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 941 +#define YYFLAG -32768 +#define YYNTBASE 84 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 316 ? yytranslate[x] : 306) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 80, 2, 2, 2, 52, 43, 2, 59, + 76, 50, 48, 81, 49, 58, 51, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 38, 77, 2, + 36, 2, 37, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 60, 2, 83, 42, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 82, 41, 78, 79, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 39, 40, 44, 45, 46, 47, 53, 54, 55, 56, + 57, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 3, 4, 7, 8, 12, 14, 16, 18, + 24, 27, 31, 36, 41, 44, 47, 50, 53, 55, + 56, 57, 65, 70, 71, 72, 80, 85, 86, 87, + 94, 98, 100, 102, 104, 106, 108, 110, 112, 114, + 116, 118, 120, 122, 123, 125, 127, 131, 133, 136, + 139, 142, 145, 148, 153, 156, 161, 164, 167, 169, + 171, 173, 178, 179, 187, 189, 193, 197, 201, 205, + 209, 213, 217, 221, 225, 229, 233, 237, 238, 243, + 244, 249, 250, 251, 259, 260, 266, 270, 274, 276, + 278, 280, 284, 288, 289, 294, 299, 304, 308, 312, + 315, 318, 320, 322, 324, 326, 328, 330, 333, 335, + 338, 339, 341, 344, 348, 350, 352, 355, 358, 363, + 368, 371, 374, 378, 380, 382, 385, 388, 389, 390, + 395, 400, 404, 408, 411, 414, 417, 420, 424, 425, + 428, 431, 434, 437, 441, 442, 445, 448, 450, 452, + 455, 458, 460, 462, 465, 468, 471, 475, 476, 479, + 481, 483, 485, 488, 491, 493, 498, 503, 505, 507, + 509, 511, 515, 517, 521, 522, 527, 528, 535, 539, + 540, 547, 551, 552, 554, 556, 559, 566, 568, 572, + 573, 575, 580, 587, 592, 594, 596, 598, 600, 602, + 603, 608, 610, 611, 614, 616, 620, 622, 623, 628, + 630, 631, 636, 637, 643, 644, 645, 651, 652, 653, + 659, 661, 663, 667, 671, 676, 680, 684, 688, 690, + 692, 696, 701, 705, 709, 713, 715, 719, 723, 727, + 732, 736, 740, 742, 743, 751, 757, 760, 761, 769, + 775, 778, 779, 788, 789, 797, 800, 801, 803, 804, + 806, 808, 811, 812, 816, 819, 824, 828, 830, 834, + 836, 838, 841, 843, 847, 852, 859, 865, 867, 871, + 873, 875, 879, 882, 885, 886, 888, 890, 893, 894, + 897, 901, 905, 908, 912, 917, 921, 924, 928, 931, + 933, 935, 938, 941, 942, 944, 947, 948, 949, 951, + 953, 956, 960, 962, 965, 967, 970, 977, 983, 989, + 992, 995, 1000, 1001, 1006, 1007, 1008, 1012, 1017, 1021, + 1023, 1025, 1027, 1029, 1032, 1033, 1038, 1040, 1044, 1045, + 1046, 1054, 1060, 1063, 1064, 1065, 1066, 1079, 1080, 1087, + 1090, 1093, 1096, 1100, 1107, 1116, 1127, 1140, 1144, 1149, + 1151, 1153, 1154, 1161, 1165, 1171, 1174, 1177, 1178, 1180, + 1181, 1183, 1184, 1186, 1188, 1192, 1197, 1199, 1203, 1204, + 1207, 1210, 1211, 1216, 1219, 1220, 1222, 1224, 1228, 1230, + 1234, 1239, 1244, 1249, 1254, 1259, 1260, 1263, 1265, 1268, + 1270, 1274, 1276, 1280, 1282, 1284, 1286, 1288, 1290, 1292, + 1294, 1296, 1300, 1304, 1309, 1310, 1311, 1322, 1323, 1330, + 1331, 1332, 1345, 1346, 1355, 1356, 1363, 1366, 1367, 1376, + 1381, 1382, 1392, 1398, 1399, 1406, 1407, 1409, 1413, 1417, + 1419, 1421, 1423, 1425, 1426, 1430, 1433, 1437, 1441, 1443, + 1444, 1446, 1450, 1452, 1456, 1459, 1460, 1461, 1462, 1470, + 1471, 1472, 1473, 1481, 1482, 1483, 1486, 1488, 1490, 1493, + 1494, 1498, 1500, 1502, 1503, 1504, 1510, 1511, 1512, 1518, + 1523, 1525, 1531, 1534, 1535, 1538, 1539, 1541, 1543, 1545, + 1548, 1551, 1556, 1559, 1562, 1564, 1568, 1571, 1574, 1577, + 1578, 1581, 1582, 1586, 1588, 1590, 1593, 1595, 1597, 1599, + 1601, 1603, 1605, 1607, 1609, 1611, 1613, 1615, 1617, 1619, + 1621, 1623, 1625, 1627, 1629, 1631, 1633, 1635, 1637, 1639, + 1641, 1643, 1650, 1654, 1660, 1663, 1665, 1667, 1669, 1672, + 1674, 1678, 1681, 1683, 1685, 1686, 1687, 1694, 1696, 1698, + 1700, 1703, 1706, 1708, 1713, 1718 +}; + +static const short yyrhs[] = { -1, + 85, 0, 0, 86, 88, 0, 0, 85, 87, 88, + 0, 90, 0, 89, 0, 237, 0, 27, 59, 99, + 76, 77, 0, 236, 88, 0, 123, 137, 77, 0, + 130, 123, 137, 77, 0, 126, 123, 136, 77, 0, + 130, 77, 0, 126, 77, 0, 1, 77, 0, 1, + 78, 0, 77, 0, 0, 0, 126, 123, 163, 91, + 117, 92, 194, 0, 126, 123, 163, 1, 0, 0, + 0, 130, 123, 166, 93, 117, 94, 194, 0, 130, + 123, 166, 1, 0, 0, 0, 123, 166, 95, 117, + 96, 194, 0, 123, 166, 1, 0, 3, 0, 4, + 0, 72, 0, 67, 0, 43, 0, 49, 0, 48, + 0, 54, 0, 55, 0, 79, 0, 80, 0, 101, + 0, 0, 101, 0, 107, 0, 101, 81, 107, 0, + 113, 0, 50, 105, 0, 236, 105, 0, 98, 105, + 0, 40, 97, 0, 103, 102, 0, 103, 59, 181, + 76, 0, 104, 102, 0, 104, 59, 181, 76, 0, + 33, 105, 0, 34, 105, 0, 11, 0, 29, 0, + 102, 0, 59, 181, 76, 105, 0, 0, 59, 181, + 76, 82, 106, 151, 78, 0, 105, 0, 107, 48, + 107, 0, 107, 49, 107, 0, 107, 50, 107, 0, + 107, 51, 107, 0, 107, 52, 107, 0, 107, 46, + 107, 0, 107, 47, 107, 0, 107, 45, 107, 0, + 107, 44, 107, 0, 107, 43, 107, 0, 107, 41, + 107, 0, 107, 42, 107, 0, 0, 107, 40, 108, + 107, 0, 0, 107, 39, 109, 107, 0, 0, 0, + 107, 37, 110, 99, 38, 111, 107, 0, 0, 107, + 37, 112, 38, 107, 0, 107, 36, 107, 0, 107, + 35, 107, 0, 3, 0, 8, 0, 115, 0, 59, + 99, 76, 0, 59, 1, 76, 0, 0, 59, 114, + 196, 76, 0, 113, 59, 100, 76, 0, 113, 60, + 99, 83, 0, 113, 58, 97, 0, 113, 57, 97, + 0, 113, 54, 0, 113, 55, 0, 297, 0, 303, + 0, 304, 0, 305, 0, 116, 0, 9, 0, 115, + 9, 0, 75, 0, 116, 75, 0, 0, 119, 0, + 119, 10, 0, 201, 202, 120, 0, 118, 0, 189, + 0, 119, 118, 0, 118, 189, 0, 128, 123, 136, + 77, 0, 131, 123, 137, 77, 0, 128, 77, 0, + 131, 77, 0, 201, 202, 125, 0, 121, 0, 189, + 0, 122, 121, 0, 121, 189, 0, 0, 0, 126, + 123, 136, 77, 0, 130, 123, 137, 77, 0, 126, + 123, 157, 0, 130, 123, 160, 0, 126, 77, 0, + 130, 77, 0, 236, 125, 0, 134, 127, 0, 130, + 134, 127, 0, 0, 127, 135, 0, 127, 5, 0, + 127, 144, 0, 134, 129, 0, 131, 134, 129, 0, + 0, 129, 135, 0, 129, 5, 0, 131, 0, 144, + 0, 130, 131, 0, 130, 144, 0, 7, 0, 5, + 0, 131, 7, 0, 131, 5, 0, 134, 133, 0, + 183, 134, 133, 0, 0, 133, 135, 0, 6, 0, + 167, 0, 4, 0, 67, 253, 0, 72, 253, 0, + 254, 0, 28, 59, 99, 76, 0, 28, 59, 181, + 76, 0, 6, 0, 7, 0, 167, 0, 139, 0, + 136, 81, 139, 0, 141, 0, 137, 81, 139, 0, + 0, 27, 59, 115, 76, 0, 0, 163, 138, 143, + 36, 140, 149, 0, 163, 138, 143, 0, 0, 166, + 138, 143, 36, 142, 149, 0, 166, 138, 143, 0, + 0, 144, 0, 145, 0, 144, 145, 0, 30, 59, + 59, 146, 76, 76, 0, 147, 0, 146, 81, 147, + 0, 0, 148, 0, 148, 59, 3, 76, 0, 148, + 59, 3, 81, 101, 76, 0, 148, 59, 100, 76, + 0, 97, 0, 5, 0, 6, 0, 7, 0, 107, + 0, 0, 82, 150, 151, 78, 0, 1, 0, 0, + 152, 172, 0, 153, 0, 152, 81, 153, 0, 107, + 0, 0, 82, 154, 151, 78, 0, 1, 0, 0, + 97, 38, 155, 153, 0, 0, 58, 97, 36, 156, + 153, 0, 0, 0, 163, 158, 117, 159, 196, 0, + 0, 0, 166, 161, 117, 162, 196, 0, 164, 0, + 166, 0, 59, 164, 76, 0, 164, 59, 231, 0, + 164, 60, 99, 83, 0, 164, 60, 83, 0, 50, + 184, 164, 0, 144, 124, 164, 0, 4, 0, 72, + 0, 165, 59, 231, 0, 165, 60, 99, 83, 0, + 165, 60, 83, 0, 50, 184, 165, 0, 144, 124, + 165, 0, 4, 0, 166, 59, 231, 0, 59, 166, + 76, 0, 50, 184, 166, 0, 166, 60, 99, 83, + 0, 166, 60, 83, 0, 144, 124, 166, 0, 3, + 0, 0, 13, 97, 82, 168, 174, 78, 143, 0, + 13, 82, 174, 78, 143, 0, 13, 97, 0, 0, + 14, 97, 82, 169, 174, 78, 143, 0, 14, 82, + 174, 78, 143, 0, 14, 97, 0, 0, 12, 97, + 82, 170, 179, 173, 78, 143, 0, 0, 12, 82, + 171, 179, 173, 78, 143, 0, 12, 97, 0, 0, + 81, 0, 0, 81, 0, 175, 0, 175, 176, 0, + 0, 175, 176, 77, 0, 175, 77, 0, 65, 59, + 67, 76, 0, 132, 123, 177, 0, 132, 0, 183, + 123, 177, 0, 183, 0, 1, 0, 236, 176, 0, + 178, 0, 177, 81, 178, 0, 201, 202, 163, 143, + 0, 201, 202, 163, 38, 107, 143, 0, 201, 202, + 38, 107, 143, 0, 180, 0, 179, 81, 180, 0, + 1, 0, 97, 0, 97, 36, 107, 0, 132, 182, + 0, 183, 182, 0, 0, 185, 0, 7, 0, 183, + 7, 0, 0, 184, 7, 0, 59, 185, 76, 0, + 50, 184, 185, 0, 50, 184, 0, 185, 59, 224, + 0, 185, 60, 99, 83, 0, 185, 60, 83, 0, + 59, 224, 0, 60, 99, 83, 0, 60, 83, 0, + 187, 0, 204, 0, 187, 204, 0, 187, 189, 0, + 0, 186, 0, 1, 77, 0, 0, 0, 192, 0, + 193, 0, 192, 193, 0, 32, 235, 77, 0, 196, + 0, 1, 196, 0, 82, 0, 195, 78, 0, 195, + 190, 191, 122, 188, 78, 0, 195, 190, 191, 1, + 78, 0, 195, 190, 191, 186, 78, 0, 198, 203, + 0, 198, 1, 0, 15, 59, 99, 76, 0, 0, + 18, 200, 203, 17, 0, 0, 0, 201, 202, 206, + 0, 201, 202, 217, 203, 0, 201, 202, 205, 0, + 206, 0, 217, 0, 196, 0, 214, 0, 99, 77, + 0, 0, 197, 16, 207, 203, 0, 197, 0, 197, + 16, 1, 0, 0, 0, 17, 208, 59, 99, 76, + 209, 203, 0, 199, 59, 99, 76, 77, 0, 199, + 1, 0, 0, 0, 0, 19, 59, 219, 77, 210, + 219, 77, 211, 219, 76, 212, 203, 0, 0, 20, + 59, 99, 76, 213, 203, 0, 23, 77, 0, 24, + 77, 0, 25, 77, 0, 25, 99, 77, 0, 27, + 218, 59, 99, 76, 77, 0, 27, 218, 59, 99, + 38, 220, 76, 77, 0, 27, 218, 59, 99, 38, + 220, 38, 220, 76, 77, 0, 27, 218, 59, 99, + 38, 220, 38, 220, 38, 223, 76, 77, 0, 26, + 97, 77, 0, 26, 50, 99, 77, 0, 77, 0, + 215, 0, 0, 19, 59, 113, 76, 216, 203, 0, + 21, 107, 38, 0, 21, 107, 10, 107, 38, 0, + 22, 38, 0, 97, 38, 0, 0, 7, 0, 0, + 99, 0, 0, 221, 0, 222, 0, 221, 81, 222, + 0, 9, 59, 99, 76, 0, 115, 0, 223, 81, + 115, 0, 0, 225, 226, 0, 228, 76, 0, 0, + 229, 77, 227, 226, 0, 1, 76, 0, 0, 10, + 0, 229, 0, 229, 81, 10, 0, 230, 0, 229, + 81, 230, 0, 126, 123, 165, 143, 0, 126, 123, + 166, 143, 0, 126, 123, 182, 143, 0, 130, 123, + 166, 143, 0, 130, 123, 182, 143, 0, 0, 232, + 233, 0, 226, 0, 234, 76, 0, 3, 0, 234, + 81, 3, 0, 97, 0, 235, 81, 97, 0, 31, + 0, 241, 0, 239, 0, 240, 0, 251, 0, 261, + 0, 63, 0, 97, 0, 238, 81, 97, 0, 73, + 238, 77, 0, 74, 97, 97, 77, 0, 0, 0, + 61, 97, 253, 82, 242, 255, 78, 243, 268, 63, + 0, 0, 61, 97, 253, 244, 268, 63, 0, 0, + 0, 61, 97, 38, 97, 253, 82, 245, 255, 78, + 246, 268, 63, 0, 0, 61, 97, 38, 97, 253, + 247, 268, 63, 0, 0, 62, 97, 82, 248, 255, + 78, 0, 62, 97, 0, 0, 62, 97, 38, 97, + 82, 249, 255, 78, 0, 62, 97, 38, 97, 0, + 0, 61, 97, 59, 97, 76, 253, 250, 268, 63, + 0, 62, 97, 59, 97, 76, 0, 0, 71, 97, + 253, 252, 268, 63, 0, 0, 254, 0, 45, 238, + 45, 0, 255, 256, 257, 0, 257, 0, 69, 0, + 70, 0, 68, 0, 0, 257, 258, 77, 0, 257, + 77, 0, 132, 123, 259, 0, 183, 123, 259, 0, + 1, 0, 0, 260, 0, 259, 81, 260, 0, 163, + 0, 163, 38, 107, 0, 38, 107, 0, 0, 0, + 0, 48, 262, 278, 263, 279, 264, 194, 0, 0, + 0, 0, 49, 265, 278, 266, 279, 267, 194, 0, + 0, 0, 269, 270, 0, 273, 0, 89, 0, 270, + 273, 0, 0, 270, 271, 89, 0, 77, 0, 1, + 0, 0, 0, 48, 274, 278, 275, 272, 0, 0, + 0, 49, 276, 278, 277, 272, 0, 59, 181, 76, + 287, 0, 287, 0, 59, 181, 76, 288, 285, 0, + 288, 285, 0, 0, 77, 280, 0, 0, 281, 0, + 282, 0, 189, 0, 281, 282, 0, 282, 189, 0, + 126, 123, 283, 77, 0, 126, 77, 0, 130, 77, + 0, 284, 0, 283, 81, 284, 0, 165, 143, 0, + 166, 143, 0, 182, 143, 0, 0, 81, 10, 0, + 0, 81, 286, 228, 0, 289, 0, 291, 0, 288, + 291, 0, 3, 0, 4, 0, 72, 0, 290, 0, + 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, + 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, + 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, + 27, 0, 11, 0, 28, 0, 29, 0, 6, 0, + 7, 0, 289, 38, 59, 181, 76, 97, 0, 289, + 38, 97, 0, 38, 59, 181, 76, 97, 0, 38, + 97, 0, 289, 0, 293, 0, 295, 0, 293, 295, + 0, 101, 0, 289, 38, 294, 0, 38, 294, 0, + 99, 0, 67, 0, 0, 0, 60, 298, 296, 299, + 292, 83, 0, 289, 0, 301, 0, 302, 0, 301, + 302, 0, 289, 38, 0, 38, 0, 64, 59, 300, + 76, 0, 71, 59, 97, 76, 0, 66, 59, 181, + 76, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 239, 244, 258, 260, 260, 261, 263, 265, 266, 267, + 275, 279, 290, 295, 300, 302, 304, 305, 306, 311, + 318, 320, 325, 330, 336, 338, 343, 348, 354, 356, + 361, 368, 370, 371, 372, 375, 377, 379, 381, 383, + 385, 387, 391, 395, 398, 401, 404, 408, 410, 413, + 416, 420, 448, 454, 457, 460, 463, 465, 469, 473, + 477, 479, 482, 486, 513, 515, 517, 519, 521, 523, + 525, 527, 529, 531, 533, 535, 537, 539, 543, 545, + 549, 551, 554, 558, 560, 567, 570, 573, 579, 739, + 740, 742, 748, 750, 764, 787, 789, 791, 803, 817, + 819, 821, 823, 825, 827, 829, 834, 836, 842, 844, + 848, 850, 851, 861, 866, 868, 869, 870, 877, 883, + 888, 891, 899, 904, 906, 907, 908, 915, 926, 930, + 936, 941, 946, 951, 953, 955, 964, 967, 971, 973, + 975, 980, 984, 987, 991, 994, 996, 1008, 1011, 1013, + 1015, 1019, 1023, 1025, 1028, 1041, 1044, 1048, 1050, 1058, + 1059, 1060, 1064, 1066, 1071, 1073, 1075, 1081, 1082, 1083, + 1086, 1088, 1091, 1093, 1096, 1099, 1105, 1112, 1114, 1121, + 1128, 1131, 1138, 1141, 1145, 1148, 1152, 1157, 1160, 1164, + 1167, 1169, 1171, 1173, 1180, 1182, 1183, 1184, 1189, 1191, + 1196, 1204, 1209, 1213, 1216, 1218, 1223, 1226, 1228, 1230, + 1234, 1237, 1237, 1240, 1242, 1253, 1261, 1265, 1276, 1284, + 1291, 1293, 1298, 1301, 1306, 1308, 1310, 1317, 1319, 1320, + 1328, 1334, 1336, 1338, 1345, 1347, 1353, 1359, 1361, 1363, + 1365, 1372, 1374, 1377, 1382, 1384, 1388, 1390, 1392, 1394, + 1398, 1400, 1403, 1406, 1409, 1412, 1416, 1418, 1421, 1423, + 1427, 1430, 1435, 1437, 1439, 1443, 1467, 1474, 1479, 1485, + 1490, 1492, 1497, 1499, 1503, 1507, 1511, 1521, 1523, 1528, + 1533, 1536, 1540, 1543, 1547, 1550, 1553, 1556, 1560, 1563, + 1567, 1571, 1573, 1575, 1577, 1579, 1581, 1583, 1585, 1595, + 1603, 1605, 1607, 1611, 1613, 1616, 1619, 1632, 1634, 1639, + 1641, 1644, 1658, 1661, 1664, 1666, 1668, 1676, 1684, 1695, + 1700, 1703, 1717, 1726, 1730, 1734, 1738, 1744, 1748, 1753, + 1756, 1761, 1764, 1765, 1782, 1787, 1790, 1802, 1804, 1814, + 1824, 1825, 1833, 1836, 1848, 1852, 1869, 1879, 1888, 1893, + 1898, 1903, 1907, 1911, 1922, 1929, 1936, 1943, 1954, 1960, + 1963, 1968, 1991, 2025, 2050, 2081, 2096, 2107, 2111, 2115, + 2118, 2123, 2125, 2128, 2130, 2134, 2139, 2142, 2148, 2153, + 2158, 2160, 2169, 2170, 2176, 2178, 2188, 2190, 2194, 2197, + 2203, 2213, 2222, 2231, 2241, 2255, 2260, 2265, 2267, 2276, + 2279, 2284, 2287, 2291, 2299, 2301, 2302, 2303, 2304, 2305, + 2319, 2322, 2326, 2332, 2338, 2345, 2350, 2356, 2363, 2369, + 2375, 2380, 2386, 2393, 2399, 2405, 2411, 2419, 2425, 2431, + 2439, 2446, 2452, 2461, 2468, 2476, 2481, 2484, 2494, 2496, + 2499, 2501, 2502, 2505, 2510, 2511, 2528, 2535, 2541, 2545, + 2548, 2549, 2552, 2560, 2566, 2575, 2585, 2592, 2596, 2601, + 2610, 2617, 2621, 2631, 2633, 2634, 2636, 2638, 2639, 2640, + 2641, 2643, 2645, 2648, 2654, 2659, 2659, 2664, 2668, 2670, + 2676, 2681, 2686, 2695, 2697, 2703, 2705, 2708, 2710, 2711, + 2712, 2715, 2721, 2723, 2727, 2730, 2737, 2743, 2748, 2755, + 2760, 2765, 2770, 2777, 2781, 2784, 2790, 2792, 2793, 2794, + 2797, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, + 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, + 2817, 2820, 2826, 2831, 2836, 2842, 2844, 2847, 2849, 2856, + 2868, 2873, 2879, 2881, 2887, 2891, 2892, 2898, 2900, 2903, + 2905, 2911, 2916, 2922, 2929, 2938 +}; + +static const char * const yytname[] = { "$","error","$undefined.","IDENTIFIER", +"TYPENAME","SCSPEC","TYPESPEC","TYPE_QUAL","CONSTANT","STRING","ELLIPSIS","SIZEOF", +"ENUM","STRUCT","UNION","IF","ELSE","WHILE","DO","FOR","SWITCH","CASE","DEFAULT", +"BREAK","CONTINUE","RETURN","GOTO","ASM_KEYWORD","TYPEOF","ALIGNOF","ATTRIBUTE", +"EXTENSION","LABEL","REALPART","IMAGPART","ASSIGN","'='","'?'","':'","OROR", +"ANDAND","'|'","'^'","'&'","EQCOMPARE","ARITHCOMPARE","LSHIFT","RSHIFT","'+'", +"'-'","'*'","'/'","'%'","UNARY","PLUSPLUS","MINUSMINUS","HYPERUNARY","POINTSAT", +"'.'","'('","'['","INTERFACE","IMPLEMENTATION","END","SELECTOR","DEFS","ENCODE", +"CLASSNAME","PUBLIC","PRIVATE","PROTECTED","PROTOCOL","OBJECTNAME","CLASS","ALIAS", +"OBJC_STRING","')'","';'","'}'","'~'","'!'","','","'{'","']'","program","extdefs", +"@1","@2","extdef","datadef","fndef","@3","@4","@5","@6","@7","@8","identifier", +"unop","expr","exprlist","nonnull_exprlist","unary_expr","sizeof","alignof", +"cast_expr","@9","expr_no_commas","@10","@11","@12","@13","@14","primary","@15", +"string","objc_string","old_style_parm_decls","lineno_datadecl","datadecls", +"datadecl","lineno_decl","decls","setspecs","setattrs","decl","typed_declspecs", +"reserved_declspecs","typed_declspecs_no_prefix_attr","reserved_declspecs_no_prefix_attr", +"declmods","declmods_no_prefix_attr","typed_typespecs","reserved_typespecquals", +"typespec","typespecqual_reserved","initdecls","notype_initdecls","maybeasm", +"initdcl","@16","notype_initdcl","@17","maybe_attribute","attributes","attribute", +"attribute_list","attrib","any_word","init","@18","initlist_maybe_comma","initlist1", +"initelt","@19","@20","@21","nested_function","@22","@23","notype_nested_function", +"@24","@25","declarator","after_type_declarator","parm_declarator","notype_declarator", +"structsp","@26","@27","@28","@29","maybecomma","maybecomma_warn","component_decl_list", +"component_decl_list2","component_decl","components","component_declarator", +"enumlist","enumerator","typename","absdcl","nonempty_type_quals","type_quals", +"absdcl1","stmts","lineno_stmt_or_labels","xstmts","errstmt","pushlevel","maybe_label_decls", +"label_decls","label_decl","compstmt_or_error","compstmt_start","compstmt","simple_if", +"if_prefix","do_stmt_start","@30","save_filename","save_lineno","lineno_labeled_stmt", +"lineno_stmt_or_label","stmt_or_label","stmt","@31","@32","@33","@34","@35", +"@36","@37","all_iter_stmt","all_iter_stmt_simple","@38","label","maybe_type_qual", +"xexpr","asm_operands","nonnull_asm_operands","asm_operand","asm_clobbers","parmlist", +"@39","parmlist_1","@40","parmlist_2","parms","parm","parmlist_or_identifiers", +"@41","parmlist_or_identifiers_1","identifiers","identifiers_or_typenames","extension", +"objcdef","identifier_list","classdecl","aliasdecl","classdef","@42","@43","@44", +"@45","@46","@47","@48","@49","@50","protocoldef","@51","protocolrefs","non_empty_protocolrefs", +"ivar_decl_list","visibility_spec","ivar_decls","ivar_decl","ivars","ivar_declarator", +"methoddef","@52","@53","@54","@55","@56","@57","methodprotolist","@58","methodprotolist2", +"@59","semi_or_error","methodproto","@60","@61","@62","@63","methoddecl","optarglist", +"myxdecls","mydecls","mydecl","myparms","myparm","optparmlist","@64","unaryselector", +"keywordselector","selector","reservedwords","keyworddecl","messageargs","keywordarglist", +"keywordexpr","keywordarg","receiver","objcmessageexpr","@65","@66","selectorarg", +"keywordnamelist","keywordname","objcselectorexpr","objcprotocolexpr","objcencodeexpr", +"" +}; +#endif + +static const short yyr1[] = { 0, + 84, 84, 86, 85, 87, 85, 88, 88, 88, 88, + 88, 89, 89, 89, 89, 89, 89, 89, 89, 91, + 92, 90, 90, 93, 94, 90, 90, 95, 96, 90, + 90, 97, 97, 97, 97, 98, 98, 98, 98, 98, + 98, 98, 99, 100, 100, 101, 101, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 103, 104, + 105, 105, 106, 105, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 108, 107, 109, + 107, 110, 111, 107, 112, 107, 107, 107, 113, 113, + 113, 113, 113, 114, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 115, 115, 116, 116, + 117, 117, 117, 118, 119, 119, 119, 119, 120, 120, + 120, 120, 121, 122, 122, 122, 122, 123, 124, 125, + 125, 125, 125, 125, 125, 125, 126, 126, 127, 127, + 127, 127, 128, 128, 129, 129, 129, 130, 130, 130, + 130, 131, 131, 131, 131, 132, 132, 133, 133, 134, + 134, 134, 134, 134, 134, 134, 134, 135, 135, 135, + 136, 136, 137, 137, 138, 138, 140, 139, 139, 142, + 141, 141, 143, 143, 144, 144, 145, 146, 146, 147, + 147, 147, 147, 147, 148, 148, 148, 148, 149, 150, + 149, 149, 151, 151, 152, 152, 153, 154, 153, 153, + 155, 153, 156, 153, 158, 159, 157, 161, 162, 160, + 163, 163, 164, 164, 164, 164, 164, 164, 164, 164, + 165, 165, 165, 165, 165, 165, 166, 166, 166, 166, + 166, 166, 166, 168, 167, 167, 167, 169, 167, 167, + 167, 170, 167, 171, 167, 167, 172, 172, 173, 173, + 174, 174, 175, 175, 175, 175, 176, 176, 176, 176, + 176, 176, 177, 177, 178, 178, 178, 179, 179, 179, + 180, 180, 181, 181, 182, 182, 183, 183, 184, 184, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 186, + 187, 187, 187, 188, 188, 189, 190, 191, 191, 192, + 192, 193, 194, 194, 195, 196, 196, 196, 196, 197, + 197, 198, 200, 199, 201, 202, 203, 203, 204, 205, + 205, 206, 206, 206, 207, 206, 206, 206, 208, 209, + 206, 206, 206, 210, 211, 212, 206, 213, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 214, 216, 215, 217, 217, 217, 217, 218, 218, 219, + 219, 220, 220, 221, 221, 222, 223, 223, 225, 224, + 226, 227, 226, 226, 228, 228, 228, 228, 229, 229, + 230, 230, 230, 230, 230, 232, 231, 233, 233, 234, + 234, 235, 235, 236, 237, 237, 237, 237, 237, 237, + 238, 238, 239, 240, 242, 243, 241, 244, 241, 245, + 246, 241, 247, 241, 248, 241, 241, 249, 241, 241, + 250, 241, 241, 252, 251, 253, 253, 254, 255, 255, + 256, 256, 256, 257, 257, 257, 258, 258, 258, 259, + 259, 259, 260, 260, 260, 262, 263, 264, 261, 265, + 266, 267, 261, 268, 269, 268, 270, 270, 270, 271, + 270, 272, 272, 274, 275, 273, 276, 277, 273, 278, + 278, 278, 278, 279, 279, 280, 280, 281, 281, 281, + 281, 282, 282, 282, 283, 283, 284, 284, 284, 285, + 285, 286, 285, 287, 288, 288, 289, 289, 289, 289, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, + 290, 291, 291, 291, 291, 292, 292, 293, 293, 294, + 295, 295, 296, 296, 298, 299, 297, 300, 300, 301, + 301, 302, 302, 303, 304, 305 +}; + +static const short yyr2[] = { 0, + 0, 1, 0, 2, 0, 3, 1, 1, 1, 5, + 2, 3, 4, 4, 2, 2, 2, 2, 1, 0, + 0, 7, 4, 0, 0, 7, 4, 0, 0, 6, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 1, 1, 3, 1, 2, 2, + 2, 2, 2, 4, 2, 4, 2, 2, 1, 1, + 1, 4, 0, 7, 1, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 0, 4, 0, + 4, 0, 0, 7, 0, 5, 3, 3, 1, 1, + 1, 3, 3, 0, 4, 4, 4, 3, 3, 2, + 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, + 0, 1, 2, 3, 1, 1, 2, 2, 4, 4, + 2, 2, 3, 1, 1, 2, 2, 0, 0, 4, + 4, 3, 3, 2, 2, 2, 2, 3, 0, 2, + 2, 2, 2, 3, 0, 2, 2, 1, 1, 2, + 2, 1, 1, 2, 2, 2, 3, 0, 2, 1, + 1, 1, 2, 2, 1, 4, 4, 1, 1, 1, + 1, 3, 1, 3, 0, 4, 0, 6, 3, 0, + 6, 3, 0, 1, 1, 2, 6, 1, 3, 0, + 1, 4, 6, 4, 1, 1, 1, 1, 1, 0, + 4, 1, 0, 2, 1, 3, 1, 0, 4, 1, + 0, 4, 0, 5, 0, 0, 5, 0, 0, 5, + 1, 1, 3, 3, 4, 3, 3, 3, 1, 1, + 3, 4, 3, 3, 3, 1, 3, 3, 3, 4, + 3, 3, 1, 0, 7, 5, 2, 0, 7, 5, + 2, 0, 8, 0, 7, 2, 0, 1, 0, 1, + 1, 2, 0, 3, 2, 4, 3, 1, 3, 1, + 1, 2, 1, 3, 4, 6, 5, 1, 3, 1, + 1, 3, 2, 2, 0, 1, 1, 2, 0, 2, + 3, 3, 2, 3, 4, 3, 2, 3, 2, 1, + 1, 2, 2, 0, 1, 2, 0, 0, 1, 1, + 2, 3, 1, 2, 1, 2, 6, 5, 5, 2, + 2, 4, 0, 4, 0, 0, 3, 4, 3, 1, + 1, 1, 1, 2, 0, 4, 1, 3, 0, 0, + 7, 5, 2, 0, 0, 0, 12, 0, 6, 2, + 2, 2, 3, 6, 8, 10, 12, 3, 4, 1, + 1, 0, 6, 3, 5, 2, 2, 0, 1, 0, + 1, 0, 1, 1, 3, 4, 1, 3, 0, 2, + 2, 0, 4, 2, 0, 1, 1, 3, 1, 3, + 4, 4, 4, 4, 4, 0, 2, 1, 2, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 3, 4, 0, 0, 10, 0, 6, 0, + 0, 12, 0, 8, 0, 6, 2, 0, 8, 4, + 0, 9, 5, 0, 6, 0, 1, 3, 3, 1, + 1, 1, 1, 0, 3, 2, 3, 3, 1, 0, + 1, 3, 1, 3, 2, 0, 0, 0, 7, 0, + 0, 0, 7, 0, 0, 2, 1, 1, 2, 0, + 3, 1, 1, 0, 0, 5, 0, 0, 5, 4, + 1, 5, 2, 0, 2, 0, 1, 1, 1, 2, + 2, 4, 2, 2, 1, 3, 2, 2, 2, 0, + 2, 0, 3, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 6, 3, 5, 2, 1, 1, 1, 2, 1, + 3, 2, 1, 1, 0, 0, 6, 1, 1, 1, + 2, 2, 1, 4, 4, 4 +}; + +static const short yydefact[] = { 3, + 5, 0, 0, 0, 162, 153, 160, 152, 0, 0, + 0, 0, 0, 0, 404, 0, 456, 460, 0, 0, + 410, 436, 0, 436, 0, 0, 19, 4, 8, 7, + 0, 128, 128, 148, 139, 149, 185, 161, 0, 9, + 406, 407, 405, 408, 165, 409, 6, 17, 18, 32, + 33, 35, 34, 254, 256, 263, 247, 263, 251, 0, + 0, 0, 411, 0, 0, 0, 436, 427, 163, 437, + 436, 164, 0, 0, 243, 289, 0, 0, 173, 129, + 0, 16, 0, 15, 0, 150, 139, 151, 155, 154, + 137, 186, 11, 0, 252, 0, 0, 0, 244, 0, + 248, 89, 90, 107, 59, 60, 0, 0, 0, 36, + 38, 37, 0, 39, 40, 0, 545, 0, 0, 0, + 109, 41, 42, 0, 0, 43, 61, 0, 0, 65, + 46, 48, 91, 106, 0, 102, 103, 104, 105, 287, + 0, 285, 158, 0, 285, 190, 438, 0, 507, 508, + 530, 531, 527, 511, 512, 513, 514, 515, 516, 517, + 518, 519, 520, 521, 522, 523, 524, 525, 526, 528, + 529, 0, 0, 509, 457, 481, 500, 504, 510, 505, + 461, 0, 0, 418, 0, 0, 425, 434, 413, 0, + 0, 0, 12, 0, 0, 31, 0, 396, 0, 0, + 183, 229, 289, 0, 230, 0, 171, 129, 0, 221, + 222, 0, 0, 138, 141, 168, 169, 140, 142, 170, + 280, 281, 259, 278, 0, 0, 183, 271, 265, 128, + 262, 128, 0, 263, 183, 263, 57, 58, 52, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, + 0, 0, 53, 0, 55, 0, 0, 82, 80, 78, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 100, 101, 0, 0, 44, 0, 108, 110, + 50, 166, 289, 379, 0, 283, 286, 156, 167, 288, + 158, 284, 196, 197, 198, 195, 0, 188, 191, 412, + 0, 535, 0, 484, 502, 483, 0, 506, 0, 484, + 436, 0, 415, 465, 430, 0, 444, 465, 414, 290, + 239, 238, 174, 175, 242, 0, 237, 0, 241, 0, + 0, 29, 0, 325, 116, 326, 182, 184, 0, 0, + 14, 0, 0, 23, 0, 183, 396, 0, 13, 27, + 0, 0, 260, 0, 259, 0, 246, 325, 264, 325, + 272, 0, 250, 0, 93, 92, 315, 307, 0, 0, + 544, 543, 546, 553, 548, 0, 549, 550, 0, 0, + 10, 47, 0, 0, 88, 87, 0, 0, 0, 0, + 76, 77, 75, 74, 73, 71, 72, 66, 67, 68, + 69, 70, 99, 98, 0, 45, 0, 293, 0, 297, + 0, 299, 0, 379, 0, 159, 157, 0, 190, 44, + 0, 0, 0, 458, 501, 385, 0, 533, 462, 423, + 436, 444, 0, 0, 428, 433, 0, 0, 0, 0, + 0, 400, 386, 128, 128, 398, 0, 387, 389, 397, + 0, 240, 306, 0, 118, 113, 117, 0, 180, 227, + 223, 172, 228, 21, 179, 224, 226, 0, 25, 282, + 279, 183, 0, 266, 267, 273, 326, 269, 183, 183, + 316, 308, 95, 63, 62, 0, 552, 554, 0, 551, + 556, 555, 54, 56, 0, 0, 81, 79, 96, 97, + 292, 291, 380, 298, 294, 296, 0, 187, 189, 89, + 0, 0, 480, 500, 128, 0, 489, 485, 487, 0, + 0, 503, 387, 0, 0, 420, 465, 431, 0, 419, + 474, 477, 468, 0, 128, 128, 470, 467, 444, 443, + 441, 442, 426, 444, 449, 446, 128, 128, 0, 435, + 176, 384, 285, 285, 381, 382, 0, 399, 0, 0, + 30, 313, 114, 128, 128, 145, 0, 0, 177, 225, + 0, 255, 183, 325, 0, 245, 249, 0, 0, 309, + 310, 0, 0, 536, 0, 537, 538, 83, 86, 295, + 192, 0, 194, 534, 482, 493, 285, 494, 490, 491, + 459, 0, 463, 444, 0, 465, 416, 0, 0, 175, + 0, 0, 0, 469, 0, 0, 450, 450, 445, 236, + 289, 379, 129, 183, 183, 183, 289, 183, 183, 0, + 388, 390, 401, 314, 121, 0, 122, 0, 145, 143, + 202, 200, 199, 181, 22, 0, 26, 253, 274, 0, + 183, 402, 0, 0, 0, 325, 0, 0, 125, 326, + 301, 311, 210, 89, 0, 208, 0, 207, 0, 257, + 205, 540, 542, 0, 547, 0, 539, 0, 0, 183, + 183, 183, 0, 495, 532, 0, 424, 0, 465, 475, + 478, 471, 429, 0, 453, 447, 451, 448, 293, 0, + 396, 0, 391, 392, 393, 293, 394, 395, 383, 0, + 0, 144, 147, 146, 0, 178, 183, 0, 275, 312, + 0, 318, 127, 126, 305, 0, 319, 303, 326, 302, + 0, 0, 0, 211, 64, 0, 204, 541, 84, 193, + 497, 498, 499, 492, 285, 421, 432, 0, 0, 0, + 455, 0, 0, 234, 289, 235, 231, 233, 0, 119, + 120, 0, 277, 183, 403, 317, 0, 162, 0, 339, + 323, 0, 0, 0, 0, 0, 0, 0, 0, 368, + 436, 436, 360, 0, 0, 123, 128, 128, 332, 337, + 0, 0, 329, 330, 333, 361, 331, 0, 213, 0, + 0, 206, 496, 465, 417, 473, 472, 476, 479, 454, + 452, 0, 232, 201, 276, 0, 0, 325, 370, 0, + 0, 366, 350, 351, 352, 0, 0, 0, 369, 0, + 367, 334, 134, 0, 135, 0, 0, 321, 326, 320, + 343, 0, 136, 0, 209, 212, 0, 0, 0, 0, + 371, 48, 0, 0, 0, 364, 353, 0, 358, 0, + 0, 132, 215, 0, 133, 218, 338, 325, 0, 0, + 214, 422, 322, 0, 324, 362, 344, 348, 0, 359, + 0, 130, 0, 131, 0, 336, 327, 325, 0, 340, + 325, 370, 325, 365, 372, 0, 216, 219, 328, 342, + 325, 363, 0, 349, 0, 0, 373, 374, 354, 0, + 0, 341, 345, 0, 372, 0, 0, 217, 220, 370, + 0, 0, 355, 375, 0, 376, 0, 0, 346, 377, + 0, 356, 325, 0, 0, 347, 357, 378, 0, 0, + 0 +}; + +static const short yydefgoto[] = { 939, + 1, 2, 3, 28, 29, 30, 345, 568, 351, 571, + 200, 454, 667, 124, 242, 405, 126, 127, 128, 129, + 130, 582, 131, 390, 389, 387, 678, 388, 132, 243, + 133, 134, 332, 333, 334, 563, 655, 656, 31, 195, + 786, 444, 91, 564, 640, 445, 34, 142, 288, 35, + 218, 206, 78, 201, 207, 646, 79, 567, 337, 338, + 37, 297, 298, 299, 644, 715, 669, 670, 671, 733, + 801, 844, 862, 883, 910, 865, 885, 911, 324, 210, + 680, 211, 38, 234, 236, 225, 94, 737, 354, 97, + 98, 231, 475, 476, 223, 224, 144, 682, 145, 191, + 287, 657, 658, 726, 335, 482, 579, 580, 581, 561, + 368, 562, 790, 791, 792, 818, 839, 458, 840, 661, + 793, 794, 868, 817, 901, 892, 920, 933, 893, 795, + 796, 891, 797, 830, 853, 906, 907, 908, 931, 410, + 411, 446, 630, 447, 448, 449, 327, 328, 450, 451, + 653, 135, 40, 64, 41, 42, 43, 432, 689, 314, + 604, 804, 527, 317, 539, 606, 44, 318, 69, 45, + 437, 544, 438, 549, 696, 697, 46, 65, 304, 521, + 66, 310, 525, 433, 434, 537, 613, 808, 538, 608, + 749, 609, 750, 175, 424, 518, 519, 520, 683, 684, + 306, 426, 176, 177, 178, 179, 180, 585, 586, 673, + 587, 373, 136, 245, 486, 376, 377, 378, 137, 138, + 139 +}; + +static const short yypact[] = { 120, + 131, 2895, 2895, 468,-32768,-32768,-32768,-32768, 98, 118, + 257, 110, 122, 132,-32768, 266,-32768,-32768, 266, 266, +-32768, 158, 266, 158, 266, 266,-32768,-32768,-32768,-32768, + 234, 153, 2375, 497,-32768, 218,-32768,-32768, 2895,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768, 172, 210, 203, 210, 221, 2604, + 2442, 254,-32768, 61, 3182, 3182, 81, 133,-32768,-32768, + 158,-32768, 151, 266,-32768,-32768, 234, 253,-32768, 218, + 1662,-32768, 540,-32768, 234, 497,-32768, 218,-32768,-32768, + 879,-32768,-32768, 94,-32768, 263, 289, 1593,-32768, 298, +-32768,-32768,-32768,-32768,-32768,-32768, 2604, 2604, 266,-32768, +-32768,-32768, 2604,-32768,-32768, 933,-32768, 278, 323, 326, +-32768,-32768,-32768, 2604, 331, 361,-32768, 2658, 2712,-32768, + 3553, 1169, 403, 370, 2604,-32768,-32768,-32768,-32768,-32768, + 396, 267,-32768, 402, 3336, 302,-32768, 266,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768, 129, 3459,-32768,-32768,-32768, 2336, 457,-32768,-32768, +-32768, 266, 266, 449, 266, 266,-32768,-32768,-32768, 461, + 642, 54,-32768, 540, 234,-32768, 474,-32768, 1805, 683, + 218,-32768,-32768, 540,-32768, 259,-32768, 218, 1760, 526, + 529, 318, 1681, 879,-32768,-32768,-32768,-32768, 218,-32768, +-32768, 505, 470,-32768, 94, 491, 218,-32768,-32768, 525, + 486, 3078, 374, 210, 218, 210,-32768,-32768,-32768,-32768, + 490, 499, 495, 503, 2496, 3244, 3459, 266,-32768, 517, + 2604, 933,-32768, 933,-32768, 2604, 2604, 558,-32768,-32768, + 2604, 2604, 2604, 2604, 2604, 2604, 2604, 2604, 2604, 2604, + 2604, 2604,-32768,-32768, 266, 266, 2604, 2604,-32768,-32768, +-32768,-32768,-32768, 267, 1864,-32768, 547, 711,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768, 29,-32768, 539,-32768, + 3459,-32768, 537, 542, 618,-32768, 457,-32768, 147, 542, + 158, 559,-32768, 574, 573, 585,-32768, 574,-32768,-32768, + 529,-32768,-32768, 635, 529, 654,-32768, 3048,-32768, 582, + 589,-32768, 276, 82,-32768,-32768, 631, 218, 269, 219, +-32768, 540, 540,-32768, 683, 218,-32768, 1923,-32768,-32768, + 683, 2604, 266, 591, 470, 595,-32768,-32768,-32768,-32768, +-32768, 592,-32768, 596,-32768,-32768,-32768, 599, 597, 2256, +-32768,-32768,-32768,-32768, 640, 606, 3244,-32768, 607, 610, +-32768, 3553, 615, 617, 3553, 3553, 2604, 656, 2604, 2604, + 2834, 2942, 880, 784, 1653, 900, 900, 478, 478,-32768, +-32768,-32768,-32768,-32768, 622, 361, 616, 456, 242,-32768, + 3067,-32768, 621,-32768, 1982,-32768, 711, 624, 302, 2766, + 632, 3272, 851,-32768,-32768, 3347, 3459,-32768,-32768, 628, + 158,-32768, 658, 2970,-32768,-32768, 347, 2843, 666, 84, + 643,-32768,-32768,-32768, 3422,-32768, 659, 327,-32768,-32768, + 176,-32768,-32768, 86,-32768,-32768,-32768, 3441,-32768, 526, +-32768,-32768, 526,-32768, 701,-32768,-32768, 660,-32768, 3553, +-32768, 218, 663,-32768, 661,-32768,-32768, 661, 218, 218, +-32768, 713,-32768,-32768,-32768, 3308,-32768,-32768, 640,-32768, +-32768,-32768,-32768,-32768, 708, 2604, 2417, 1396,-32768,-32768, + 547,-32768,-32768,-32768,-32768,-32768, 668,-32768,-32768, 211, + 681, 266,-32768, 2336, 676, 3097,-32768,-32768, 3422, 1779, + 86,-32768, 679, 700, 86,-32768, 574,-32768, 352,-32768, +-32768,-32768,-32768, 234, 153, 2375, 262,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768, 3478, 705,-32768, +-32768,-32768, 464, 93,-32768,-32768, 3411,-32768, 780, 495, +-32768,-32768,-32768, 707, 726,-32768, 840, 86,-32768,-32768, + 86,-32768, 218,-32768, 368,-32768,-32768, 266, 1102, 713, +-32768, 1422, 2604, 750, 706, 3308,-32768,-32768, 1475,-32768, +-32768, 2604,-32768,-32768,-32768,-32768, 464,-32768,-32768,-32768, +-32768, 266,-32768,-32768, 729, 574,-32768, 3182, 3182, 76, + 540, 234, 2998,-32768, 430, 2861, 1377, 1377,-32768,-32768, +-32768, 93, 218, 238, 330, 218,-32768, 330, 218, 3067, +-32768,-32768,-32768,-32768,-32768, 540,-32768, 234,-32768, 767, +-32768,-32768, 3553,-32768,-32768, 840,-32768,-32768,-32768, 2604, + 212,-32768, 377, 545, 1022, 716, 717, 1182,-32768,-32768, +-32768,-32768,-32768, 758, 266,-32768, 762, 3553, 735, 737, +-32768, 361,-32768, 2604,-32768, 750,-32768, 2604, 273, 238, + 330, 218, 383,-32768,-32768, 442,-32768, 760, 574,-32768, +-32768,-32768,-32768, 2604, 789, 757,-32768, 757, 588, 677, +-32768, 2041,-32768,-32768,-32768, 594,-32768,-32768,-32768, 389, + 416, 767,-32768,-32768, 1422,-32768, 3186, 2604,-32768,-32768, + 266,-32768,-32768,-32768,-32768, 764,-32768,-32768,-32768,-32768, + 2122, 808, 1422,-32768,-32768, 1502,-32768,-32768, 1475,-32768, +-32768,-32768,-32768,-32768, 464,-32768,-32768, 782, 72, 72, + 3553, 2604, 1377, 583,-32768, 583,-32768,-32768, 763,-32768, +-32768, 775,-32768, 3186,-32768,-32768, 2202, 816, 800,-32768, +-32768, 802, 813, 2604, 829, 798, 805, 2550, 429, 890, + 79, 141,-32768, 849, 824,-32768, 825, 3147,-32768, 887, + 1262, 103,-32768,-32768,-32768,-32768,-32768, 2364,-32768, 827, + 1582,-32768,-32768, 574,-32768,-32768,-32768,-32768,-32768, 3553, +-32768, 601,-32768,-32768,-32768, 2604, 848,-32768, 2604, 2604, + 3517,-32768,-32768,-32768,-32768, 831, 2604, 833,-32768, 853, +-32768,-32768,-32768, 540,-32768, 234, 1342,-32768,-32768,-32768, +-32768, 2604,-32768, 1582,-32768,-32768, 854, 845, 2604, 899, +-32768, 752, 866, 878, 2604,-32768,-32768, 881,-32768, 2604, + 432,-32768, 320, 440,-32768, 332,-32768,-32768, 2202, 883, +-32768,-32768,-32768, 889,-32768,-32768,-32768,-32768, 3535,-32768, + 52,-32768, 683,-32768, 683,-32768,-32768,-32768, 886,-32768, +-32768, 2604,-32768,-32768, 946, 891,-32768,-32768,-32768,-32768, +-32768,-32768, 892,-32768, 898, 69, 893,-32768,-32768, 495, + 495,-32768,-32768, 2604, 946, 894, 946,-32768,-32768, 2604, + 901, 145,-32768,-32768, 903,-32768, 654, 907,-32768, 403, + 303,-32768,-32768, 908, 654,-32768,-32768, 403, 970, 975, +-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768, 192, -367,-32768,-32768,-32768,-32768,-32768, +-32768,-32768, -9,-32768, -52, 560, -231, 530,-32768,-32768, + -54,-32768, 220,-32768,-32768,-32768,-32768,-32768, 167,-32768, + -295,-32768, -312, 655,-32768,-32768, 334,-32768, 17, -195, + 193, 16, 909,-32768, 356, 21, -11, -61, 710, 11, + -276, -575, -58, -206, -118,-32768,-32768,-32768, 196, 3, + -6,-32768, 579,-32768, 357,-32768, -604,-32768, -657,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -68, -135, + -489, 14, -66,-32768,-32768,-32768,-32768,-32768, 647, 19, +-32768, 773, 649, 433, 785, 664, -27, -79, -55, -168, + -226, 355,-32768,-32768, -285,-32768,-32768,-32768, 434, -413, +-32768, -205,-32768,-32768,-32768,-32768, -122, -415, -734, 358, +-32768, 149,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768, 150,-32768, -658, 105,-32768, 107,-32768, 608, +-32768, -359,-32768, 612, 633, 475, -307,-32768,-32768,-32768, +-32768, 18,-32768, 1029,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -20, 4, + -364,-32768, 513,-32768, 443, 305,-32768,-32768,-32768,-32768, +-32768,-32768,-32768, -286,-32768,-32768,-32768, 310, 531,-32768, +-32768,-32768,-32768, -25, 753,-32768,-32768, 550,-32768, 321, + 564,-32768, 651, 652, -121,-32768, -148,-32768,-32768, 405, + 494,-32768,-32768,-32768,-32768,-32768,-32768, 714,-32768,-32768, +-32768 +}; + + +#define YYLAST 3605 + + +static const short yytable[] = { 55, + 57, 59, 346, 72, 36, 36, 63, 125, 141, 67, + 68, 416, 343, 71, 209, 63, 74, 32, 32, 39, + 39, 86, 33, 33, 220, 70, 212, 70, 308, 92, + 440, 439, 464, 80, 339, 88, 230, 369, 469, 466, + 181, 36, 232, 87, 81, 406, 184, 455, 83, 85, + 188, 503, 237, 238, 32, 307, 39, 409, 240, 33, + 710, 575, 286, 624, 190, 292, 533, 529, 340, 249, + 70, 143, 806, 92, 70, 323, 100, 336, 802, 80, + 281, 92, -112, 850, 222, 208, 560, 80, 244, 895, + 192, 456, 279, 219, 221, 75, 50, 51, 213, 239, + 50, 51, 197, 841, 418, 147, 915, 601, 143, 419, + 762, 603, 198, 199, 408, 233, -35, 346, 182, -1, + 50, 51, 14, 16, 375, 16, 143, 896, 800, 322, + -2, 50, 51, 886, 198, 199, 296, 517, 300, 183, + 416, 148, 627, 846, 916, 303, 330, 220, 807, 50, + 51, 622, 285, 899, 645, 291, 902, 647, 904, 551, + 52, 842, 302, -112, 52, 53, 912, 367, 60, 53, + 185, 230, 311, 312, 615, 315, 316, 232, -34, 54, + 61, 501, 927, 143, 52, 16, 871, 301, 406, 53, + 62, 186, 372, 80, 47, 52, 208, 80, 936, 56, + 53, 92, 16, 460, 321, 427, 208, 463, 325, 754, + 756, 336, 92, 52, 187, 222, 219, 192, 53, 379, + 928, 220, 336, 462, 383, 407, 384, 189, 336, 82, + 93, 148, 413, 903, 600, 477, 75, 477, 380, 686, + 605, 14, 291, 143, 731, 692, 358, 14, 360, 718, + 233, 558, 362, 95, 364, 489, 559, 143, 861, 50, + 51, 925, 143, 14, 143, 403, 404, 14, 50, 51, + 709, 75, 202, 421, 96, 320, 331, 347, 348, -115, + -115, -115, -115, 76, 99, -115, 591, -115, -115, -115, + 430, 592, 77, 659, 461, 468, 701, 702, 14, 428, + 414, 415, 101, -115, 50, 51, 293, 294, 295, 531, + 532, 143, 146, 767, 70, 485, 283, 502, 203, 688, + -115, 226, 754, 52, -466, 284, 285, 204, 53, 193, + 36, 92, 52, 194, 495, 341, 246, 53, 58, 342, + 205, 208, -115, 222, 208, 208, 197, -115, 740, -175, + 220, 672, 321, 251, 634, -175, 325, -115, 197, 14, + 679, -175, 507, 714, 584, 308, 227, -175, 52, 723, + 75, 202, 728, 53, 228, 235, 547, 5, 934, 7, + 140, 247, 548, 935, 248, 9, 10, 11, 198, 199, + 198, 199, 307, 757, 349, 409, -175, 14, 194, 524, + -175, 13, 748, 556, 15, 650, 250, 557, -175, 296, + 528, 279, -175, 36, 540, 541, 542, 203, 16, 540, + 541, 542, 357, 869, 543, 36, 204, 700, 36, 607, + 363, 50, 51, 86, 70, 714, 36, 143, 515, 205, + 22, 251, 672, 516, 280, 24, 565, 88, 143, 535, + 534, 477, 699, 720, 536, 87, 660, 721, 706, 744, + 553, 554, 320, 745, 676, 760, 75, 620, 566, 342, + 382, 282, 501, 626, 629, 385, 386, 289, 827, 501, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 761, 14, 309, 52, 194, 540, 541, 542, + 53, 89, 594, 90, 86, 283, 651, 693, 882, 540, + 541, 542, 342, 621, 284, 285, 884, 847, 88, 746, + 194, 36, 622, 285, 86, 789, 87, 270, 271, 272, + 313, 597, 326, 660, 515, 729, 80, 319, 88, 516, + 352, 465, 75, 202, 48, 49, 87, 610, 695, 695, + 353, 611, 612, 212, 547, 623, 80, 356, 291, 36, + 548, 789, 359, 617, 618, 365, 625, 628, 652, 14, + 897, 470, 898, 220, 366, 639, 367, 208, 370, 711, + 636, 638, 690, 691, 347, 348, 812, 198, 199, 203, + 75, 620, 685, 381, 320, -85, 75, 420, 204, 623, + 320, -268, -268, 75, 620, 414, 415, 320, 497, 498, + 681, 205, 422, 208, 80, 36, 92, 14, 423, 208, + 208, 453, 722, 14, 80, 610, 143, 425, 535, 534, + 14, 930, 36, 536, 431, 192, -464, 621, 208, 938, + 80, 701, 702, 627, 75, 220, 622, 285, 320, 759, + 755, 610, 622, 285, 435, 732, 346, 253, 255, 77, + 436, 197, 104, 789, 452, 453, 459, 572, 472, 479, + 474, 14, 483, 480, 576, 577, 481, 487, 785, 75, + 620, 488, 491, 331, 695, 492, -325, -325, -325, -325, + 493, 76, 494, 496, -325, -325, -325, 499, 500, 508, + 77, 623, 623, 504, 918, 919, 14, 512, 80, 526, + -325, 765, 321, 325, 785, 589, 216, 217, 552, 321, + 530, 784, 9, 10, 11, 826, 755, -325, 550, 5, + 89, 7, 90, 36, 555, 77, 569, 9, 10, 11, + 573, 574, 570, 281, 578, 588, 787, 623, 798, -325, + 590, 788, 596, 13, -325, 208, 593, 784, 681, 557, + 336, 72, 336, 848, -111, 863, 851, 854, 648, 828, + 16, 713, 216, 217, 858, 602, 86, 864, 9, 10, + 11, 619, 633, 635, 70, 70, 643, 674, 675, 870, + 88, 687, 22, -304, 727, -32, 874, 24, 87, 734, + 36, 668, 637, 834, 836, 273, 274, 881, 275, 276, + 277, 278, 735, 787, 623, 798, 785, 736, 788, 703, + 704, 705, 747, 707, 708, 321, 752, 876, 265, 266, + 267, 268, 269, 270, 271, 272, 208, 753, 80, 851, + 641, 766, 102, 799, 805, 813, 719, 103, 104, 866, + 105, 331, 814, -33, 5, 6, 7, 8, 816, 784, + 819, 921, 9, 10, 11, 643, 822, 851, 106, 717, + 15, 820, 107, 108, 823, 741, 742, 743, 13, 109, + 14, 824, 110, 215, 216, 217, 831, 111, 112, 113, + 9, 10, 11, 114, 115, 16, 829, 739, 116, 117, + 832, 833, 837, 118, 845, 119, 849, 857, 14, 859, + 120, 860, 763, 751, 121, 875, 872, 22, 122, 123, + 873, 642, 24, 264, 265, 266, 267, 268, 269, 270, + 271, 272, -486, 241, 668, 102, 5, 764, 7, 140, + 103, 104, 877, 105, 9, 10, 11, 268, 269, 270, + 271, 272, 668, 878, 905, 668, 914, 880, 889, 815, + 13, 106, 900, 15, 890, 107, 108, 909, 913, 940, + 923, 810, 109, 917, 941, 110, 926, 16, 929, 511, + 111, 112, 113, 932, 937, 852, 114, 115, 457, 724, + 843, 116, 117, 821, 712, 214, 118, 509, 119, 22, + 417, 473, 716, 120, 24, 361, 649, 121, 478, 355, + 725, 122, 123, 662, -94, 730, 471, 887, 888, 922, + 668, 505, 331, 924, -124, -124, -124, -124, -124, -124, + -124, 632, -124, -124, -124, -124, -124, 522, -124, -124, + -124, -124, -124, -124, -124, -124, -124, -124, -124, -124, + -124, -124, -124, 73, -124, -124, 616, 811, 523, 809, + 698, -124, 429, 668, -124, 803, -124, 614, 599, -124, + -124, -124, 513, 514, 879, -124, -124, 595, 738, 677, + -124, -124, 0, 0, 0, -124, 0, -124, -124, 0, + 490, 0, -124, -124, 0, 0, -124, 0, -124, -124, + -124, -124, 654, -124, -325, -325, -325, -325, -325, -325, + -325, 0, -325, -325, -325, -325, -325, 0, -325, -325, + -325, -325, -325, -325, -325, -325, -325, -325, -325, -325, + -325, -325, -325, 0, -325, -325, 0, 0, 0, 0, + 0, -325, 0, 0, -325, 0, -325, 0, 0, -325, + -325, -325, 0, 0, 0, -325, -325, 0, 0, 0, + -325, -325, 0, 0, 0, -325, 0, -325, -325, 0, + 0, 0, -325, -325, 0, 0, -325, 0, -325, 0, + -325, -325, 331, -325, -325, -325, 0, 0, 0, -325, + -325, 0, -325, 0, 0, 0, -325, 0, -325, -325, + -325, -325, -325, -325, -325, -325, -325, -325, -325, 0, + -325, 0, -325, 0, -325, -325, 0, 0, 0, 0, + 0, -325, 273, 274, -325, 275, 276, 277, 278, -325, + -325, -325, 0, 0, 0, -325, -325, 0, 0, 0, + -325, -325, 0, 0, 0, -325, 0, -325, -325, 0, + 0, 0, -325, -325, 0, 0, -325, 0, -325, -300, + -325, -325, 838, -325, -325, -325, 0, 0, 0, -325, + -325, 0, -325, 0, 0, 0, -325, 0, -325, -325, + -325, -325, -325, -325, -325, -325, -325, -325, -325, 0, + -325, 0, -325, 0, -325, -325, 0, 0, 0, 0, + 0, -325, 0, 0, -325, 0, 0, 0, 0, -325, + -325, -325, 0, 0, 0, -325, -325, 0, 0, 0, + -325, -325, 0, 0, 0, -325, 0, -325, -325, 0, + 0, 0, -325, -325, 0, 0, -325, 0, -325, 0, + -325, -325, 867, -325, -335, -335, 0, 0, 0, -335, + -335, 0, -335, 0, 0, 0, -335, 0, -335, -335, + -335, -335, -335, -335, -335, -335, -335, -335, -335, 0, + -335, 0, -335, 0, -335, -335, 0, 0, 0, 75, + 202, -335, 0, 0, -335, 0, 0, 0, 0, -335, + -335, -335, 0, 0, 0, -335, -335, 0, 0, 0, + -335, -335, 0, 0, 0, -335, 14, -335, -335, 0, + 0, 0, -335, -335, 694, 0, -335, 0, -335, 0, + -335, -335, 663, -335, 664, 51, 203, 0, 0, 103, + 104, 0, 105, 0, 0, 204, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 205, 0, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 0, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 0, 665, + 116, 117, 0, 0, 0, 118, 0, 119, 52, 0, + 0, 0, 120, 53, 0, 0, 121, 0, 0, -203, + 122, 123, 663, 666, 664, 51, 0, 0, 0, 103, + 104, 258, 105, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 0, 0, 0, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 0, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 0, 665, + 116, 117, 0, 0, 0, 118, 0, 119, 52, 0, + 0, 0, 120, 53, 0, 0, 121, 0, 0, -258, + 122, 123, 663, 666, 664, 51, 0, 0, 0, 103, + 104, 0, 105, 228, 0, 0, 5, 0, 7, 140, + 0, 0, 0, 0, 9, 10, 11, 0, 0, 0, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 13, 109, 0, 15, 110, 0, 0, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 16, 0, 665, + 116, 117, 0, 0, 0, 118, 0, 119, 52, 0, + 0, 0, 120, 53, 0, 0, 121, 0, 0, 22, + 122, 123, 196, 666, 24, -28, -28, -28, -28, 229, + -261, 0, 0, -28, -28, -28, 0, 0, 0, 0, + 0, 350, 0, 0, -24, -24, -24, -24, 197, -28, + 0, -175, -24, -24, -24, 0, 0, -175, 266, 267, + 268, 269, 270, 271, 272, 0, -28, 197, -24, 0, + -175, 0, 0, 0, 0, 0, -175, 0, 0, 0, + 198, 199, 0, 0, 0, -24, 0, 0, -28, 0, + 0, 0, 0, -28, 0, 0, 0, 0, -175, 198, + 199, 0, -175, -28, 0, 0, 0, -24, 0, 0, + 0, 0, -24, 0, 0, 0, 0, -175, 0, 0, + 344, -175, -24, -20, -20, -20, -20, 0, 0, 0, + 0, -20, -20, -20, 0, 0, 0, 0, 0, 331, + 0, 0, -488, -488, -488, -488, 197, -20, 0, -175, + -488, -488, -488, 0, 0, -175, 0, 0, 0, 0, + 0, 0, 0, 0, -20, 0, -488, 102, -488, 0, + 0, 0, 103, 104, 0, 105, 0, 0, 0, 0, + 0, 0, 0, -488, 0, 0, -20, 0, 0, 0, + 0, -20, 0, 106, 0, 15, -175, 107, 108, 0, + -175, -20, 0, 0, 109, -488, 0, 110, 0, 0, + -488, 0, 111, 112, 113, 0, 0, 0, 114, 115, + -488, 0, 0, 116, 117, 0, 102, 0, 118, 0, + 119, 103, 104, 0, 105, 120, 0, 0, 0, 121, + 0, 0, 0, 122, 123, 0, 0, 329, 0, 0, + 0, 0, 106, 0, 15, 0, 107, 108, 0, 0, + 0, 0, 0, 109, 0, 0, 110, 0, 0, 0, + 0, 111, 112, 113, 0, 0, 0, 114, 115, 0, + 0, 0, 116, 117, 0, 102, 0, 118, 0, 119, + 103, 104, 0, 105, 120, 0, 0, 0, 121, 0, + 0, 0, 122, 123, 0, 0, 412, 0, 0, 0, + 0, 106, 0, 15, 0, 107, 108, 0, 0, 0, + 0, 0, 109, 0, 0, 110, 0, 0, 0, 0, + 111, 112, 113, 0, 0, 0, 114, 115, 0, 0, + 0, 116, 117, 0, 102, 0, 118, 0, 119, 103, + 104, 0, 105, 120, 0, 0, 0, 121, 0, 0, + 0, 122, 123, 0, 0, 467, 0, 0, 0, 0, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 0, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 0, 0, + 116, 117, 0, 102, 0, 118, 0, 119, 103, 104, + 0, 105, 120, 0, 0, 0, 121, 0, 0, 0, + 122, 123, 0, 0, 506, 0, 0, 0, 0, 106, + 0, 15, 0, 107, 108, 0, 0, 0, 0, 0, + 109, 0, 0, 110, 0, 0, 0, 0, 111, 112, + 113, 0, 0, 0, 114, 115, 0, 0, 0, 116, + 117, 0, 0, 0, 118, 0, 119, 0, 0, 0, + 0, 120, 0, 0, 0, 121, 0, 0, 0, 122, + 123, 0, 0, 758, 664, 768, 6, 7, 8, 103, + 104, 0, 105, 9, 10, 11, 769, 0, 770, 771, + 772, 773, 774, 775, 776, 777, 778, 779, 780, 13, + 106, 14, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 16, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 0, 0, + 116, 117, 0, 0, 0, 118, 0, 119, 781, 0, + 0, 0, 120, 782, 0, 0, 121, 0, 783, 0, + 122, 123, 0, 367, 664, 51, 0, 0, 0, 103, + 104, 0, 105, 0, 0, 0, 769, 0, 770, 771, + 772, 773, 774, 775, 776, 777, 778, 779, 780, 0, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 0, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 102, 0, + 116, 117, 0, 103, 104, 118, 105, 119, 52, 0, + 0, 0, 120, 53, 0, 0, 121, 0, 783, 0, + 122, 123, 0, 367, 106, 0, 15, 0, 107, 108, + 0, 0, 0, 0, 0, 109, 0, 0, 110, 0, + 0, 0, 0, 111, 112, 113, 0, 0, 0, 114, + 115, 0, 0, 0, 116, 117, 0, 0, 0, 118, + 0, 119, 0, 0, 0, 0, 120, 0, 0, 0, + 121, 0, 0, 0, 122, 123, 0, 484, 149, 150, + 0, 151, 152, 0, 0, 0, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 0, 102, 5, 6, 7, + 8, 103, 104, 172, 105, 9, 10, 11, 5, 6, + 7, 8, 0, 0, 0, 0, 9, 10, 11, 0, + 0, 13, 106, 14, 15, 0, 107, 108, 0, 0, + 0, 0, 13, 109, 14, 0, 110, 174, 16, 0, + 0, 111, 112, 113, 0, 0, 305, 114, 115, 16, + 0, 0, 116, 117, 0, 0, 0, 118, 0, 119, + 22, 0, 0, 0, 120, 24, 0, 0, 121, 0, + 0, 22, 122, 123, 102, 5, 24, 7, 140, 103, + 104, 84, 105, 9, 10, 11, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 13, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 16, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 102, 0, + 116, 117, 0, 103, 104, 118, 105, 119, 22, 0, + 0, 0, 120, 24, 0, 0, 121, 0, 0, 0, + 122, 123, 0, 0, 106, 0, 15, 0, 107, 108, + 0, 0, 0, 0, 0, 109, 0, 0, 110, 0, + 0, 0, 0, 111, 112, 113, 0, 0, 0, 114, + 115, 0, 102, 0, 116, 117, 0, 103, 104, 118, + 105, 119, 371, 0, 0, 0, 120, 0, 0, 0, + 121, 0, 0, 0, 122, 123, 0, 0, 106, 0, + 15, 0, 107, 108, 0, 0, 0, 0, 0, 109, + 0, 0, 110, 0, 0, 0, 0, 111, 112, 113, + 0, 0, 0, 114, 115, 0, 102, 0, 116, 117, + 0, 103, 104, 118, 105, 119, 0, 0, 0, 0, + 120, 0, 0, 0, 121, 0, 825, 0, 122, 123, + 0, 0, 106, 0, 15, 0, 107, 108, 0, 0, + 0, 0, 0, 109, 0, 0, 110, 0, 0, 0, + 0, 111, 112, 113, 0, 0, 0, 114, 115, 0, + 102, 0, 116, 117, 0, 103, 104, 118, 105, 119, + 0, 0, 0, 0, 120, 0, 0, 0, 121, 0, + 0, 0, 122, 123, 0, 0, 106, 0, 15, 0, + 107, 108, 0, 0, 0, 0, 0, 109, 0, 0, + 110, 0, 0, 0, 0, 111, 112, 113, 0, 0, + 0, 114, 115, 0, 102, 0, 252, 117, 0, 103, + 104, 118, 105, 119, 0, 0, 0, 0, 120, 0, + 0, 0, 121, 0, 0, 0, 122, 123, 0, 0, + 106, 0, 15, 0, 107, 108, 0, 0, 0, 0, + 0, 109, 0, 0, 110, 0, 0, 0, 0, 111, + 112, 113, 0, 0, 0, 114, 115, 0, 510, 0, + 254, 117, 0, 103, 104, 118, 105, 119, 0, 0, + 0, 0, 120, 0, 0, 0, 121, 0, 0, 0, + 122, 123, 0, 0, 106, 0, 15, 0, 107, 108, + 0, 0, 0, 0, 0, 109, 0, 0, 110, 0, + 0, 0, 0, 111, 112, 113, 0, 0, 0, 114, + 115, 0, 0, 0, 116, 117, 0, 0, 0, 118, + 0, 119, 0, 0, 0, 0, 120, 0, 0, 0, + 121, 0, 0, 545, 122, 123, 5, 0, 7, 140, + 0, 0, 0, 0, 9, 10, 11, 0, 0, 0, + 0, 545, 0, 0, 5, 0, 7, 140, 0, 0, + 13, 0, 9, 10, 11, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 0, 16, 13, 0, + 0, 0, 0, 0, 0, 4, 0, -128, 5, 6, + 7, 8, 0, 0, 0, 16, 9, 10, 11, 22, + -440, -440, -440, 0, 24, 0, 0, 0, 0, 546, + -440, 12, 13, 0, 14, 15, 0, 22, -439, -439, + -439, 0, 24, 0, 0, 0, 0, 546, -439, 16, + 0, 0, 17, 18, -128, 0, 0, 0, 0, 0, + 0, 0, 0, -128, 0, 19, 20, 21, 0, 0, + 0, 22, 0, 0, 0, 23, 24, 25, 26, 0, + 4, 27, -128, 5, 6, 7, 8, 0, 0, 0, + 0, 9, 10, 11, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 0, 0, 0, 13, 4, 14, + -128, 5, 6, 7, 8, 0, 0, 0, 0, 9, + 10, 11, 0, 0, 16, 0, 0, 531, 532, -128, + 0, 0, 0, 0, 0, 13, 0, 14, -128, 0, + 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, + 0, 24, 16, 0, 0, 0, 27, -128, 441, 0, + 442, 5, 6, 7, 8, 0, -128, 443, 0, 9, + 10, 11, 0, 0, 22, 0, 0, 441, 0, 24, + 5, 6, 7, 8, 27, 13, 443, 14, 9, 10, + 11, 5, 0, 7, 290, 0, 0, 0, 0, 9, + 10, 11, 16, 0, 13, 0, 14, 0, 0, 0, + 5, 6, 7, 8, 0, 13, 0, 0, 9, 10, + 11, 16, 0, 0, 22, 0, 0, 0, 0, 24, + 0, 0, 16, -385, 13, 0, 14, 0, 0, 0, + 0, 0, 0, 22, 0, 0, 0, 0, 24, 0, + 0, 16, -385, 0, 22, 0, 0, 0, 0, 24, + 5, 6, 7, 8, -270, -270, 0, 0, 9, 10, + 11, 0, 0, 22, 0, 0, 0, 0, 24, 0, + 0, 0, 0, 598, 13, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 149, 150, 0, 151, 152, 0, + 0, 16, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 0, 0, 22, 0, 14, 0, 0, 24, 172, + 256, 257, 258, 835, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 0, 0, + 173, 0, 0, 0, 0, 0, 149, 150, 0, 151, + 152, 0, 0, 174, 153, 154, 155, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 0, 149, 150, 0, 151, 152, 0, + 0, 374, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 0, 0, 0, 0, 0, 0, 0, 0, 172, + 149, 150, 0, 151, 152, 174, 0, 0, 153, 154, + 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 0, 0, 5, + 0, 7, 290, 174, 0, 583, 0, 9, 10, 11, + 5, 6, 7, 8, 0, 0, 443, 0, 9, 10, + 11, 0, 0, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, 14, 0, 0, 174, + 16, 0, 0, 0, 0, 283, 0, 0, 0, 0, + 0, 16, 0, 0, 284, 285, 0, 0, 0, 0, + 0, 0, 22, 0, 0, 0, 0, 24, 0, 0, + 0, 0, 0, 22, 5, 6, 7, 8, 24, 0, + 631, 0, 9, 10, 11, 5, 6, 7, 8, 0, + 0, 0, 0, 9, 10, 11, 0, 0, 13, 0, + 14, 0, 0, 0, 5, 6, 7, 8, 0, 13, + 0, 14, 9, 10, 11, 16, 0, 0, 0, 0, + 0, 0, 5, 0, 7, 140, 16, 0, 13, 0, + 9, 10, 11, 0, 0, 0, 0, 22, 0, 0, + 0, 5, 24, 7, 290, 16, 13, 0, 22, 9, + 10, 11, 0, 24, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 13, 0, 22, 0, 0, + 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 22, 855, 0, 0, 0, + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 22, 0, 0, 0, 0, 24, + 0, 256, 257, 258, 856, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 256, + 257, 258, 894, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 256, 257, 258, + 0, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272 +}; + +static const short yycheck[] = { 9, + 10, 11, 209, 24, 2, 3, 16, 60, 61, 19, + 20, 288, 208, 23, 83, 25, 26, 2, 3, 2, + 3, 33, 2, 3, 91, 22, 85, 24, 177, 36, + 326, 318, 345, 31, 203, 33, 98, 243, 351, 347, + 66, 39, 98, 33, 31, 277, 67, 333, 32, 33, + 71, 411, 107, 108, 39, 177, 39, 284, 113, 39, + 636, 477, 142, 553, 74, 145, 434, 432, 204, 124, + 67, 61, 1, 80, 71, 194, 58, 200, 736, 77, + 135, 88, 1, 818, 94, 83, 1, 85, 116, 38, + 77, 10, 9, 91, 1, 3, 3, 4, 85, 109, + 3, 4, 27, 1, 76, 45, 38, 521, 98, 81, + 715, 525, 59, 60, 283, 98, 38, 324, 38, 0, + 3, 4, 30, 45, 246, 45, 116, 76, 733, 76, + 0, 3, 4, 868, 59, 60, 146, 423, 148, 59, + 417, 81, 50, 801, 76, 173, 199, 214, 77, 3, + 4, 59, 60, 888, 568, 145, 891, 571, 893, 76, + 67, 59, 172, 82, 67, 72, 901, 82, 59, 72, + 38, 233, 182, 183, 539, 185, 186, 233, 38, 82, + 59, 408, 38, 173, 67, 45, 844, 59, 420, 72, + 59, 59, 245, 191, 3, 67, 194, 195, 933, 82, + 72, 208, 45, 339, 191, 59, 204, 343, 195, 699, + 700, 334, 219, 67, 82, 225, 214, 204, 72, 247, + 76, 288, 345, 342, 252, 278, 254, 77, 351, 77, + 39, 81, 285, 892, 520, 358, 3, 360, 248, 604, + 527, 30, 232, 233, 660, 613, 230, 30, 232, 38, + 233, 76, 234, 82, 236, 377, 81, 247, 834, 3, + 4, 920, 252, 30, 254, 275, 276, 30, 3, 4, + 630, 3, 4, 301, 65, 7, 1, 59, 60, 4, + 5, 6, 7, 50, 82, 10, 76, 12, 13, 14, + 311, 81, 59, 579, 76, 348, 59, 60, 30, 309, + 59, 60, 82, 28, 3, 4, 5, 6, 7, 48, + 49, 301, 59, 729, 311, 370, 50, 76, 50, 606, + 45, 59, 812, 67, 63, 59, 60, 59, 72, 77, + 328, 338, 67, 81, 387, 77, 59, 72, 82, 81, + 72, 339, 67, 353, 342, 343, 27, 72, 76, 30, + 417, 583, 339, 81, 560, 36, 343, 82, 27, 30, + 592, 30, 415, 640, 486, 514, 78, 36, 67, 655, + 3, 4, 658, 72, 1, 78, 438, 4, 76, 6, + 7, 59, 438, 81, 59, 12, 13, 14, 59, 60, + 59, 60, 514, 701, 77, 622, 77, 30, 81, 427, + 81, 28, 689, 77, 31, 38, 76, 81, 77, 419, + 431, 9, 81, 411, 68, 69, 70, 50, 45, 68, + 69, 70, 227, 839, 78, 423, 59, 623, 426, 78, + 235, 3, 4, 445, 431, 712, 434, 427, 423, 72, + 67, 81, 674, 423, 75, 72, 458, 445, 438, 434, + 434, 574, 621, 77, 434, 445, 579, 81, 627, 77, + 444, 445, 7, 81, 586, 77, 3, 4, 458, 81, + 251, 76, 699, 553, 554, 256, 257, 76, 50, 706, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 77, 30, 38, 67, 81, 68, 69, 70, + 72, 5, 512, 7, 516, 50, 575, 78, 77, 68, + 69, 70, 81, 50, 59, 60, 77, 804, 516, 78, + 81, 519, 59, 60, 536, 731, 516, 50, 51, 52, + 82, 515, 59, 656, 519, 658, 534, 77, 536, 519, + 36, 346, 3, 4, 77, 78, 536, 534, 617, 618, + 81, 535, 536, 612, 616, 553, 554, 67, 548, 557, + 616, 767, 77, 547, 548, 76, 553, 554, 578, 30, + 883, 352, 885, 640, 76, 565, 82, 575, 76, 638, + 564, 565, 608, 609, 59, 60, 755, 59, 60, 50, + 3, 4, 602, 77, 7, 38, 3, 59, 59, 597, + 7, 77, 78, 3, 4, 59, 60, 7, 389, 390, + 597, 72, 76, 611, 612, 613, 623, 30, 77, 617, + 618, 77, 78, 30, 622, 612, 616, 10, 613, 613, + 30, 927, 630, 613, 76, 622, 63, 50, 636, 935, + 638, 59, 60, 50, 3, 712, 59, 60, 7, 702, + 50, 638, 59, 60, 82, 665, 863, 128, 129, 59, + 76, 27, 9, 869, 83, 77, 36, 472, 78, 78, + 76, 30, 76, 78, 479, 480, 78, 38, 731, 3, + 4, 76, 76, 1, 753, 76, 4, 5, 6, 7, + 76, 50, 76, 38, 12, 13, 14, 76, 83, 76, + 59, 699, 700, 83, 910, 911, 30, 76, 706, 82, + 28, 721, 699, 700, 767, 496, 6, 7, 76, 706, + 63, 731, 12, 13, 14, 778, 50, 45, 63, 4, + 5, 6, 7, 731, 76, 59, 36, 12, 13, 14, + 78, 81, 83, 798, 32, 38, 731, 745, 731, 67, + 83, 731, 77, 28, 72, 753, 76, 767, 745, 81, + 883, 782, 885, 816, 82, 834, 819, 820, 573, 779, + 45, 5, 6, 7, 827, 76, 788, 836, 12, 13, + 14, 77, 3, 77, 781, 782, 567, 38, 83, 842, + 788, 63, 67, 78, 78, 38, 849, 72, 788, 38, + 798, 582, 77, 787, 788, 54, 55, 860, 57, 58, + 59, 60, 78, 798, 812, 798, 869, 81, 798, 624, + 625, 626, 63, 628, 629, 812, 38, 76, 45, 46, + 47, 48, 49, 50, 51, 52, 834, 81, 836, 892, + 1, 78, 3, 36, 63, 83, 651, 8, 9, 836, + 11, 1, 78, 38, 4, 5, 6, 7, 59, 869, + 59, 914, 12, 13, 14, 646, 38, 920, 29, 650, + 31, 59, 33, 34, 77, 680, 681, 682, 28, 40, + 30, 77, 43, 5, 6, 7, 38, 48, 49, 50, + 12, 13, 14, 54, 55, 45, 7, 678, 59, 60, + 77, 77, 16, 64, 78, 66, 59, 77, 30, 77, + 71, 59, 717, 694, 75, 17, 63, 67, 79, 80, + 76, 82, 72, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 82, 1, 715, 3, 4, 718, 6, 7, + 8, 9, 77, 11, 12, 13, 14, 48, 49, 50, + 51, 52, 733, 76, 9, 736, 59, 77, 76, 764, + 28, 29, 77, 31, 76, 33, 34, 77, 77, 0, + 77, 752, 40, 81, 0, 43, 76, 45, 76, 420, + 48, 49, 50, 77, 77, 819, 54, 55, 334, 656, + 798, 59, 60, 774, 639, 87, 64, 419, 66, 67, + 291, 355, 646, 71, 72, 233, 574, 75, 360, 225, + 656, 79, 80, 580, 82, 658, 353, 869, 869, 915, + 801, 414, 1, 917, 3, 4, 5, 6, 7, 8, + 9, 557, 11, 12, 13, 14, 15, 426, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 25, 33, 34, 544, 753, 426, 750, + 618, 40, 310, 844, 43, 745, 45, 537, 519, 48, + 49, 50, 422, 422, 855, 54, 55, 514, 674, 586, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + 377, -1, 71, 72, -1, -1, 75, -1, 77, 78, + 79, 80, 1, 82, 3, 4, 5, 6, 7, 8, + 9, -1, 11, 12, 13, 14, 15, -1, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, 45, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, -1, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, 77, -1, + 79, 80, 1, 82, 3, 4, -1, -1, -1, 8, + 9, -1, 11, -1, -1, -1, 15, -1, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, 54, 55, 43, 57, 58, 59, 60, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, -1, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, 77, 78, + 79, 80, 1, 82, 3, 4, -1, -1, -1, 8, + 9, -1, 11, -1, -1, -1, 15, -1, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, -1, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, 77, -1, + 79, 80, 1, 82, 3, 4, -1, -1, -1, 8, + 9, -1, 11, -1, -1, -1, 15, -1, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, 3, + 4, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, -1, + 59, 60, -1, -1, -1, 64, 30, 66, 67, -1, + -1, -1, 71, 72, 38, -1, 75, -1, 77, -1, + 79, 80, 1, 82, 3, 4, 50, -1, -1, 8, + 9, -1, 11, -1, -1, 59, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 72, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, 58, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, -1, 78, + 79, 80, 1, 82, 3, 4, -1, -1, -1, 8, + 9, 37, 11, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, -1, -1, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, 58, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, -1, 78, + 79, 80, 1, 82, 3, 4, -1, -1, -1, 8, + 9, -1, 11, 1, -1, -1, 4, -1, 6, 7, + -1, -1, -1, -1, 12, 13, 14, -1, -1, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + 28, 40, -1, 31, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, 45, -1, 58, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, -1, 67, + 79, 80, 1, 82, 72, 4, 5, 6, 7, 77, + 78, -1, -1, 12, 13, 14, -1, -1, -1, -1, + -1, 1, -1, -1, 4, 5, 6, 7, 27, 28, + -1, 30, 12, 13, 14, -1, -1, 36, 46, 47, + 48, 49, 50, 51, 52, -1, 45, 27, 28, -1, + 30, -1, -1, -1, -1, -1, 36, -1, -1, -1, + 59, 60, -1, -1, -1, 45, -1, -1, 67, -1, + -1, -1, -1, 72, -1, -1, -1, -1, 77, 59, + 60, -1, 81, 82, -1, -1, -1, 67, -1, -1, + -1, -1, 72, -1, -1, -1, -1, 77, -1, -1, + 1, 81, 82, 4, 5, 6, 7, -1, -1, -1, + -1, 12, 13, 14, -1, -1, -1, -1, -1, 1, + -1, -1, 4, 5, 6, 7, 27, 28, -1, 30, + 12, 13, 14, -1, -1, 36, -1, -1, -1, -1, + -1, -1, -1, -1, 45, -1, 28, 3, 30, -1, + -1, -1, 8, 9, -1, 11, -1, -1, -1, -1, + -1, -1, -1, 45, -1, -1, 67, -1, -1, -1, + -1, 72, -1, 29, -1, 31, 77, 33, 34, -1, + 81, 82, -1, -1, 40, 67, -1, 43, -1, -1, + 72, -1, 48, 49, 50, -1, -1, -1, 54, 55, + 82, -1, -1, 59, 60, -1, 3, -1, 64, -1, + 66, 8, 9, -1, 11, 71, -1, -1, -1, 75, + -1, -1, -1, 79, 80, -1, -1, 83, -1, -1, + -1, -1, 29, -1, 31, -1, 33, 34, -1, -1, + -1, -1, -1, 40, -1, -1, 43, -1, -1, -1, + -1, 48, 49, 50, -1, -1, -1, 54, 55, -1, + -1, -1, 59, 60, -1, 3, -1, 64, -1, 66, + 8, 9, -1, 11, 71, -1, -1, -1, 75, -1, + -1, -1, 79, 80, -1, -1, 83, -1, -1, -1, + -1, 29, -1, 31, -1, 33, 34, -1, -1, -1, + -1, -1, 40, -1, -1, 43, -1, -1, -1, -1, + 48, 49, 50, -1, -1, -1, 54, 55, -1, -1, + -1, 59, 60, -1, 3, -1, 64, -1, 66, 8, + 9, -1, 11, 71, -1, -1, -1, 75, -1, -1, + -1, 79, 80, -1, -1, 83, -1, -1, -1, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, -1, + 59, 60, -1, 3, -1, 64, -1, 66, 8, 9, + -1, 11, 71, -1, -1, -1, 75, -1, -1, -1, + 79, 80, -1, -1, 83, -1, -1, -1, -1, 29, + -1, 31, -1, 33, 34, -1, -1, -1, -1, -1, + 40, -1, -1, 43, -1, -1, -1, -1, 48, 49, + 50, -1, -1, -1, 54, 55, -1, -1, -1, 59, + 60, -1, -1, -1, 64, -1, 66, -1, -1, -1, + -1, 71, -1, -1, -1, 75, -1, -1, -1, 79, + 80, -1, -1, 83, 3, 4, 5, 6, 7, 8, + 9, -1, 11, 12, 13, 14, 15, -1, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, 45, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, -1, -1, + 59, 60, -1, -1, -1, 64, -1, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, 77, -1, + 79, 80, -1, 82, 3, 4, -1, -1, -1, 8, + 9, -1, 11, -1, -1, -1, 15, -1, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, 3, -1, + 59, 60, -1, 8, 9, 64, 11, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, 77, -1, + 79, 80, -1, 82, 29, -1, 31, -1, 33, 34, + -1, -1, -1, -1, -1, 40, -1, -1, 43, -1, + -1, -1, -1, 48, 49, 50, -1, -1, -1, 54, + 55, -1, -1, -1, 59, 60, -1, -1, -1, 64, + -1, 66, -1, -1, -1, -1, 71, -1, -1, -1, + 75, -1, -1, -1, 79, 80, -1, 82, 3, 4, + -1, 6, 7, -1, -1, -1, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, -1, 3, 4, 5, 6, + 7, 8, 9, 38, 11, 12, 13, 14, 4, 5, + 6, 7, -1, -1, -1, -1, 12, 13, 14, -1, + -1, 28, 29, 30, 31, -1, 33, 34, -1, -1, + -1, -1, 28, 40, 30, -1, 43, 72, 45, -1, + -1, 48, 49, 50, -1, -1, 81, 54, 55, 45, + -1, -1, 59, 60, -1, -1, -1, 64, -1, 66, + 67, -1, -1, -1, 71, 72, -1, -1, 75, -1, + -1, 67, 79, 80, 3, 4, 72, 6, 7, 8, + 9, 77, 11, 12, 13, 14, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 28, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, 45, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, 3, -1, + 59, 60, -1, 8, 9, 64, 11, 66, 67, -1, + -1, -1, 71, 72, -1, -1, 75, -1, -1, -1, + 79, 80, -1, -1, 29, -1, 31, -1, 33, 34, + -1, -1, -1, -1, -1, 40, -1, -1, 43, -1, + -1, -1, -1, 48, 49, 50, -1, -1, -1, 54, + 55, -1, 3, -1, 59, 60, -1, 8, 9, 64, + 11, 66, 67, -1, -1, -1, 71, -1, -1, -1, + 75, -1, -1, -1, 79, 80, -1, -1, 29, -1, + 31, -1, 33, 34, -1, -1, -1, -1, -1, 40, + -1, -1, 43, -1, -1, -1, -1, 48, 49, 50, + -1, -1, -1, 54, 55, -1, 3, -1, 59, 60, + -1, 8, 9, 64, 11, 66, -1, -1, -1, -1, + 71, -1, -1, -1, 75, -1, 77, -1, 79, 80, + -1, -1, 29, -1, 31, -1, 33, 34, -1, -1, + -1, -1, -1, 40, -1, -1, 43, -1, -1, -1, + -1, 48, 49, 50, -1, -1, -1, 54, 55, -1, + 3, -1, 59, 60, -1, 8, 9, 64, 11, 66, + -1, -1, -1, -1, 71, -1, -1, -1, 75, -1, + -1, -1, 79, 80, -1, -1, 29, -1, 31, -1, + 33, 34, -1, -1, -1, -1, -1, 40, -1, -1, + 43, -1, -1, -1, -1, 48, 49, 50, -1, -1, + -1, 54, 55, -1, 3, -1, 59, 60, -1, 8, + 9, 64, 11, 66, -1, -1, -1, -1, 71, -1, + -1, -1, 75, -1, -1, -1, 79, 80, -1, -1, + 29, -1, 31, -1, 33, 34, -1, -1, -1, -1, + -1, 40, -1, -1, 43, -1, -1, -1, -1, 48, + 49, 50, -1, -1, -1, 54, 55, -1, 3, -1, + 59, 60, -1, 8, 9, 64, 11, 66, -1, -1, + -1, -1, 71, -1, -1, -1, 75, -1, -1, -1, + 79, 80, -1, -1, 29, -1, 31, -1, 33, 34, + -1, -1, -1, -1, -1, 40, -1, -1, 43, -1, + -1, -1, -1, 48, 49, 50, -1, -1, -1, 54, + 55, -1, -1, -1, 59, 60, -1, -1, -1, 64, + -1, 66, -1, -1, -1, -1, 71, -1, -1, -1, + 75, -1, -1, 1, 79, 80, 4, -1, 6, 7, + -1, -1, -1, -1, 12, 13, 14, -1, -1, -1, + -1, 1, -1, -1, 4, -1, 6, 7, -1, -1, + 28, -1, 12, 13, 14, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, -1, 45, 28, -1, + -1, -1, -1, -1, -1, 1, -1, 3, 4, 5, + 6, 7, -1, -1, -1, 45, 12, 13, 14, 67, + 68, 69, 70, -1, 72, -1, -1, -1, -1, 77, + 78, 27, 28, -1, 30, 31, -1, 67, 68, 69, + 70, -1, 72, -1, -1, -1, -1, 77, 78, 45, + -1, -1, 48, 49, 50, -1, -1, -1, -1, -1, + -1, -1, -1, 59, -1, 61, 62, 63, -1, -1, + -1, 67, -1, -1, -1, 71, 72, 73, 74, -1, + 1, 77, 3, 4, 5, 6, 7, -1, -1, -1, + -1, 12, 13, 14, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, -1, -1, -1, 28, 1, 30, + 3, 4, 5, 6, 7, -1, -1, -1, -1, 12, + 13, 14, -1, -1, 45, -1, -1, 48, 49, 50, + -1, -1, -1, -1, -1, 28, -1, 30, 59, -1, + -1, -1, -1, -1, -1, -1, 67, -1, -1, -1, + -1, 72, 45, -1, -1, -1, 77, 50, 1, -1, + 3, 4, 5, 6, 7, -1, 59, 10, -1, 12, + 13, 14, -1, -1, 67, -1, -1, 1, -1, 72, + 4, 5, 6, 7, 77, 28, 10, 30, 12, 13, + 14, 4, -1, 6, 7, -1, -1, -1, -1, 12, + 13, 14, 45, -1, 28, -1, 30, -1, -1, -1, + 4, 5, 6, 7, -1, 28, -1, -1, 12, 13, + 14, 45, -1, -1, 67, -1, -1, -1, -1, 72, + -1, -1, 45, 76, 28, -1, 30, -1, -1, -1, + -1, -1, -1, 67, -1, -1, -1, -1, 72, -1, + -1, 45, 76, -1, 67, -1, -1, -1, -1, 72, + 4, 5, 6, 7, 77, 78, -1, -1, 12, 13, + 14, -1, -1, 67, -1, -1, -1, -1, 72, -1, + -1, -1, -1, 77, 28, -1, 30, -1, -1, -1, + -1, -1, -1, -1, 3, 4, -1, 6, 7, -1, + -1, 45, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, -1, -1, 67, -1, 30, -1, -1, 72, 38, + 35, 36, 37, 77, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, -1, -1, + 59, -1, -1, -1, -1, -1, 3, 4, -1, 6, + 7, -1, -1, 72, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, -1, 3, 4, -1, 6, 7, -1, + -1, 38, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, -1, -1, -1, -1, -1, -1, -1, -1, 38, + 3, 4, -1, 6, 7, 72, -1, -1, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, -1, -1, 4, + -1, 6, 7, 72, -1, 38, -1, 12, 13, 14, + 4, 5, 6, 7, -1, -1, 10, -1, 12, 13, + 14, -1, -1, 28, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 28, -1, 30, -1, -1, 72, + 45, -1, -1, -1, -1, 50, -1, -1, -1, -1, + -1, 45, -1, -1, 59, 60, -1, -1, -1, -1, + -1, -1, 67, -1, -1, -1, -1, 72, -1, -1, + -1, -1, -1, 67, 4, 5, 6, 7, 72, -1, + 10, -1, 12, 13, 14, 4, 5, 6, 7, -1, + -1, -1, -1, 12, 13, 14, -1, -1, 28, -1, + 30, -1, -1, -1, 4, 5, 6, 7, -1, 28, + -1, 30, 12, 13, 14, 45, -1, -1, -1, -1, + -1, -1, 4, -1, 6, 7, 45, -1, 28, -1, + 12, 13, 14, -1, -1, -1, -1, 67, -1, -1, + -1, 4, 72, 6, 7, 45, 28, -1, 67, 12, + 13, 14, -1, 72, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 45, -1, 28, -1, 67, -1, -1, + -1, -1, 72, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 45, -1, -1, 67, 10, -1, -1, -1, + 72, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 67, -1, -1, -1, -1, 72, + -1, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 35, 36, 37, + -1, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/local/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include <alloca.h> +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include <malloc.h> +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include <malloc.h> + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "/usr/local/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 240 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids an empty source file"); + finish_file (); + ; + break;} +case 2: +#line 245 "objc-parse.y" +{ + /* In case there were missing closebraces, + get us back to the global binding level. */ + while (! global_bindings_p ()) + poplevel (0, 0, 0); + finish_file (); + ; + break;} +case 3: +#line 259 "objc-parse.y" +{yyval.ttype = NULL_TREE; ; + break;} +case 5: +#line 260 "objc-parse.y" +{yyval.ttype = NULL_TREE; ; + break;} +case 10: +#line 268 "objc-parse.y" +{ STRIP_NOPS (yyvsp[-2].ttype); + if ((TREE_CODE (yyvsp[-2].ttype) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (yyvsp[-2].ttype, 0)) == STRING_CST) + || TREE_CODE (yyvsp[-2].ttype) == STRING_CST) + assemble_asm (yyvsp[-2].ttype); + else + error ("argument of `asm' is not a constant string"); ; + break;} +case 11: +#line 276 "objc-parse.y" +{ pedantic = yyvsp[-1].itype; ; + break;} +case 12: +#line 281 "objc-parse.y" +{ if (pedantic) + error ("ANSI C forbids data definition with no type or storage class"); + else if (!flag_traditional) + warning ("data definition has no type or storage class"); + + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 13: +#line 291 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 14: +#line 296 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 15: +#line 301 "objc-parse.y" +{ pedwarn ("empty declaration"); ; + break;} +case 16: +#line 303 "objc-parse.y" +{ shadow_tag (yyvsp[-1].ttype); ; + break;} +case 19: +#line 307 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C does not allow extra `;' outside of a function"); ; + break;} +case 20: +#line 313 "objc-parse.y" +{ if (! start_function (current_declspecs, yyvsp[0].ttype, + prefix_attributes, NULL_TREE, 0)) + YYERROR1; + reinit_parse_for_function (); ; + break;} +case 21: +#line 318 "objc-parse.y" +{ store_parm_decls (); ; + break;} +case 22: +#line 320 "objc-parse.y" +{ finish_function (0); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-5].itype); ; + break;} +case 23: +#line 326 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 24: +#line 331 "objc-parse.y" +{ if (! start_function (current_declspecs, yyvsp[0].ttype, + prefix_attributes, NULL_TREE, 0)) + YYERROR1; + reinit_parse_for_function (); ; + break;} +case 25: +#line 336 "objc-parse.y" +{ store_parm_decls (); ; + break;} +case 26: +#line 338 "objc-parse.y" +{ finish_function (0); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-5].itype); ; + break;} +case 27: +#line 344 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 28: +#line 349 "objc-parse.y" +{ if (! start_function (NULL_TREE, yyvsp[0].ttype, + prefix_attributes, NULL_TREE, 0)) + YYERROR1; + reinit_parse_for_function (); ; + break;} +case 29: +#line 354 "objc-parse.y" +{ store_parm_decls (); ; + break;} +case 30: +#line 356 "objc-parse.y" +{ finish_function (0); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-5].itype); ; + break;} +case 31: +#line 362 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 36: +#line 376 "objc-parse.y" +{ yyval.code = ADDR_EXPR; ; + break;} +case 37: +#line 378 "objc-parse.y" +{ yyval.code = NEGATE_EXPR; ; + break;} +case 38: +#line 380 "objc-parse.y" +{ yyval.code = CONVERT_EXPR; ; + break;} +case 39: +#line 382 "objc-parse.y" +{ yyval.code = PREINCREMENT_EXPR; ; + break;} +case 40: +#line 384 "objc-parse.y" +{ yyval.code = PREDECREMENT_EXPR; ; + break;} +case 41: +#line 386 "objc-parse.y" +{ yyval.code = BIT_NOT_EXPR; ; + break;} +case 42: +#line 388 "objc-parse.y" +{ yyval.code = TRUTH_NOT_EXPR; ; + break;} +case 43: +#line 392 "objc-parse.y" +{ yyval.ttype = build_compound_expr (yyvsp[0].ttype); ; + break;} +case 44: +#line 397 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 46: +#line 403 "objc-parse.y" +{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ; + break;} +case 47: +#line 405 "objc-parse.y" +{ chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ; + break;} +case 49: +#line 411 "objc-parse.y" +{ yyval.ttype = build_indirect_ref (yyvsp[0].ttype, "unary *"); ; + break;} +case 50: +#line 414 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + pedantic = yyvsp[-1].itype; ; + break;} +case 51: +#line 417 "objc-parse.y" +{ yyval.ttype = build_unary_op (yyvsp[-1].code, yyvsp[0].ttype, 0); + overflow_warning (yyval.ttype); ; + break;} +case 52: +#line 421 "objc-parse.y" +{ tree label = lookup_label (yyvsp[0].ttype); + if (pedantic) + pedwarn ("ANSI C forbids `&&'"); + if (label == 0) + yyval.ttype = null_pointer_node; + else + { + TREE_USED (label) = 1; + yyval.ttype = build1 (ADDR_EXPR, ptr_type_node, label); + TREE_CONSTANT (yyval.ttype) = 1; + } + ; + break;} +case 53: +#line 449 "objc-parse.y" +{ skip_evaluation--; + if (TREE_CODE (yyvsp[0].ttype) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (yyvsp[0].ttype, 1))) + error ("`sizeof' applied to a bit-field"); + yyval.ttype = c_sizeof (TREE_TYPE (yyvsp[0].ttype)); ; + break;} +case 54: +#line 455 "objc-parse.y" +{ skip_evaluation--; + yyval.ttype = c_sizeof (groktypename (yyvsp[-1].ttype)); ; + break;} +case 55: +#line 458 "objc-parse.y" +{ skip_evaluation--; + yyval.ttype = c_alignof_expr (yyvsp[0].ttype); ; + break;} +case 56: +#line 461 "objc-parse.y" +{ skip_evaluation--; + yyval.ttype = c_alignof (groktypename (yyvsp[-1].ttype)); ; + break;} +case 57: +#line 464 "objc-parse.y" +{ yyval.ttype = build_unary_op (REALPART_EXPR, yyvsp[0].ttype, 0); ; + break;} +case 58: +#line 466 "objc-parse.y" +{ yyval.ttype = build_unary_op (IMAGPART_EXPR, yyvsp[0].ttype, 0); ; + break;} +case 59: +#line 470 "objc-parse.y" +{ skip_evaluation++; ; + break;} +case 60: +#line 474 "objc-parse.y" +{ skip_evaluation++; ; + break;} +case 62: +#line 480 "objc-parse.y" +{ tree type = groktypename (yyvsp[-2].ttype); + yyval.ttype = build_c_cast (type, yyvsp[0].ttype); ; + break;} +case 63: +#line 483 "objc-parse.y" +{ start_init (NULL_TREE, NULL, 0); + yyvsp[-2].ttype = groktypename (yyvsp[-2].ttype); + really_start_incremental_init (yyvsp[-2].ttype); ; + break;} +case 64: +#line 487 "objc-parse.y" +{ char *name; + tree result = pop_init_level (0); + tree type = yyvsp[-5].ttype; + finish_init (); + + if (pedantic) + pedwarn ("ANSI C forbids constructor expressions"); + if (TYPE_NAME (type) != 0) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + name = IDENTIFIER_POINTER (TYPE_NAME (type)); + else + name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); + } + else + name = ""; + yyval.ttype = result; + if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) + { + int failure = complete_array_type (type, yyval.ttype, 1); + if (failure) + abort (); + } + ; + break;} +case 66: +#line 516 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 67: +#line 518 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 68: +#line 520 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 69: +#line 522 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 70: +#line 524 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 71: +#line 526 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 72: +#line 528 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 73: +#line 530 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 74: +#line 532 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 75: +#line 534 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 76: +#line 536 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 77: +#line 538 "objc-parse.y" +{ yyval.ttype = parser_build_binary_op (yyvsp[-1].code, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 78: +#line 540 "objc-parse.y" +{ yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[-1].ttype)); + skip_evaluation += yyvsp[-1].ttype == boolean_false_node; ; + break;} +case 79: +#line 543 "objc-parse.y" +{ skip_evaluation -= yyvsp[-3].ttype == boolean_false_node; + yyval.ttype = parser_build_binary_op (TRUTH_ANDIF_EXPR, yyvsp[-3].ttype, yyvsp[0].ttype); ; + break;} +case 80: +#line 546 "objc-parse.y" +{ yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[-1].ttype)); + skip_evaluation += yyvsp[-1].ttype == boolean_true_node; ; + break;} +case 81: +#line 549 "objc-parse.y" +{ skip_evaluation -= yyvsp[-3].ttype == boolean_true_node; + yyval.ttype = parser_build_binary_op (TRUTH_ORIF_EXPR, yyvsp[-3].ttype, yyvsp[0].ttype); ; + break;} +case 82: +#line 552 "objc-parse.y" +{ yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[-1].ttype)); + skip_evaluation += yyvsp[-1].ttype == boolean_false_node; ; + break;} +case 83: +#line 555 "objc-parse.y" +{ skip_evaluation += ((yyvsp[-4].ttype == boolean_true_node) + - (yyvsp[-4].ttype == boolean_false_node)); ; + break;} +case 84: +#line 558 "objc-parse.y" +{ skip_evaluation -= yyvsp[-6].ttype == boolean_true_node; + yyval.ttype = build_conditional_expr (yyvsp[-6].ttype, yyvsp[-3].ttype, yyvsp[0].ttype); ; + break;} +case 85: +#line 561 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids omitting the middle term of a ?: expression"); + /* Make sure first operand is calculated only once. */ + yyvsp[0].ttype = save_expr (yyvsp[-1].ttype); + yyvsp[-1].ttype = truthvalue_conversion (default_conversion (yyvsp[0].ttype)); + skip_evaluation += yyvsp[-1].ttype == boolean_true_node; ; + break;} +case 86: +#line 568 "objc-parse.y" +{ skip_evaluation -= yyvsp[-4].ttype == boolean_true_node; + yyval.ttype = build_conditional_expr (yyvsp[-4].ttype, yyvsp[-3].ttype, yyvsp[0].ttype); ; + break;} +case 87: +#line 571 "objc-parse.y" +{ yyval.ttype = build_modify_expr (yyvsp[-2].ttype, NOP_EXPR, yyvsp[0].ttype); + C_SET_EXP_ORIGINAL_CODE (yyval.ttype, MODIFY_EXPR); ; + break;} +case 88: +#line 574 "objc-parse.y" +{ yyval.ttype = build_modify_expr (yyvsp[-2].ttype, yyvsp[-1].code, yyvsp[0].ttype); + /* This inhibits warnings in truthvalue_conversion. */ + C_SET_EXP_ORIGINAL_CODE (yyval.ttype, ERROR_MARK); ; + break;} +case 89: +#line 581 "objc-parse.y" +{ + yyval.ttype = lastiddecl; + if (!yyval.ttype || yyval.ttype == error_mark_node) + { + if (yychar == YYEMPTY) + yychar = YYLEX; + if (yychar == '(') + { + tree decl; + + if (objc_receiver_context + && ! (objc_receiver_context + && strcmp (IDENTIFIER_POINTER (yyvsp[0].ttype), "super"))) + /* we have a message to super */ + yyval.ttype = get_super_receiver (); + else if (objc_method_context + && (decl = is_ivar (objc_ivar_chain, yyvsp[0].ttype))) + { + if (is_private (decl)) + yyval.ttype = error_mark_node; + else + yyval.ttype = build_ivar_reference (yyvsp[0].ttype); + } + else + { + /* Ordinary implicit function declaration. */ + yyval.ttype = implicitly_declare (yyvsp[0].ttype); + assemble_external (yyval.ttype); + TREE_USED (yyval.ttype) = 1; + } + } + else if (current_function_decl == 0) + { + error ("`%s' undeclared here (not in a function)", + IDENTIFIER_POINTER (yyvsp[0].ttype)); + yyval.ttype = error_mark_node; + } + else + { + tree decl; + + if (objc_receiver_context + && ! strcmp (IDENTIFIER_POINTER (yyvsp[0].ttype), "super")) + /* we have a message to super */ + yyval.ttype = get_super_receiver (); + else if (objc_method_context + && (decl = is_ivar (objc_ivar_chain, yyvsp[0].ttype))) + { + if (is_private (decl)) + yyval.ttype = error_mark_node; + else + yyval.ttype = build_ivar_reference (yyvsp[0].ttype); + } + else + { + if (IDENTIFIER_GLOBAL_VALUE (yyvsp[0].ttype) != error_mark_node + || IDENTIFIER_ERROR_LOCUS (yyvsp[0].ttype) != current_function_decl) + { + error ("`%s' undeclared (first use this function)", + IDENTIFIER_POINTER (yyvsp[0].ttype)); + + if (! undeclared_variable_notice) + { + error ("(Each undeclared identifier is reported only once"); + error ("for each function it appears in.)"); + undeclared_variable_notice = 1; + } + } + yyval.ttype = error_mark_node; + /* Prevent repeated error messages. */ + IDENTIFIER_GLOBAL_VALUE (yyvsp[0].ttype) = error_mark_node; + IDENTIFIER_ERROR_LOCUS (yyvsp[0].ttype) = current_function_decl; + } + } + } + else if (TREE_TYPE (yyval.ttype) == error_mark_node) + yyval.ttype = error_mark_node; + else if (C_DECL_ANTICIPATED (yyval.ttype)) + { + /* The first time we see a build-in function used, + if it has not been declared. */ + C_DECL_ANTICIPATED (yyval.ttype) = 0; + if (yychar == YYEMPTY) + yychar = YYLEX; + if (yychar == '(') + { + /* Omit the implicit declaration we + would ordinarily do, so we don't lose + the actual built in type. + But print a diagnostic for the mismatch. */ + if (objc_method_context + && is_ivar (objc_ivar_chain, yyvsp[0].ttype)) + error ("Instance variable `%s' implicitly declared as function", + IDENTIFIER_POINTER (DECL_NAME (yyval.ttype))); + else + if (TREE_CODE (yyval.ttype) != FUNCTION_DECL) + error ("`%s' implicitly declared as function", + IDENTIFIER_POINTER (DECL_NAME (yyval.ttype))); + else if ((TYPE_MODE (TREE_TYPE (TREE_TYPE (yyval.ttype))) + != TYPE_MODE (integer_type_node)) + && (TREE_TYPE (TREE_TYPE (yyval.ttype)) + != void_type_node)) + pedwarn ("type mismatch in implicit declaration for built-in function `%s'", + IDENTIFIER_POINTER (DECL_NAME (yyval.ttype))); + /* If it really returns void, change that to int. */ + if (TREE_TYPE (TREE_TYPE (yyval.ttype)) == void_type_node) + TREE_TYPE (yyval.ttype) + = build_function_type (integer_type_node, + TYPE_ARG_TYPES (TREE_TYPE (yyval.ttype))); + } + else + pedwarn ("built-in function `%s' used without declaration", + IDENTIFIER_POINTER (DECL_NAME (yyval.ttype))); + + /* Do what we would ordinarily do when a fn is used. */ + assemble_external (yyval.ttype); + TREE_USED (yyval.ttype) = 1; + } + else + { + assemble_external (yyval.ttype); + TREE_USED (yyval.ttype) = 1; + /* we have a definition - still check if iVariable */ + + if (!objc_receiver_context + || (objc_receiver_context + && strcmp (IDENTIFIER_POINTER (yyvsp[0].ttype), "super"))) + { + tree decl; + + if (objc_method_context + && (decl = is_ivar (objc_ivar_chain, yyvsp[0].ttype))) + { + if (IDENTIFIER_LOCAL_VALUE (yyvsp[0].ttype)) + warning ("local declaration of `%s' hides instance variable", + IDENTIFIER_POINTER (yyvsp[0].ttype)); + else + { + if (is_private (decl)) + yyval.ttype = error_mark_node; + else + yyval.ttype = build_ivar_reference (yyvsp[0].ttype); + } + } + } + else /* we have a message to super */ + yyval.ttype = get_super_receiver (); + } + + if (TREE_CODE (yyval.ttype) == CONST_DECL) + { + yyval.ttype = DECL_INITIAL (yyval.ttype); + /* This is to prevent an enum whose value is 0 + from being considered a null pointer constant. */ + yyval.ttype = build1 (NOP_EXPR, TREE_TYPE (yyval.ttype), yyval.ttype); + TREE_CONSTANT (yyval.ttype) = 1; + } + ; + break;} +case 91: +#line 741 "objc-parse.y" +{ yyval.ttype = combine_strings (yyvsp[0].ttype); ; + break;} +case 92: +#line 743 "objc-parse.y" +{ char class = TREE_CODE_CLASS (TREE_CODE (yyvsp[-1].ttype)); + if (class == 'e' || class == '1' + || class == '2' || class == '<') + C_SET_EXP_ORIGINAL_CODE (yyvsp[-1].ttype, ERROR_MARK); + yyval.ttype = yyvsp[-1].ttype; ; + break;} +case 93: +#line 749 "objc-parse.y" +{ yyval.ttype = error_mark_node; ; + break;} +case 94: +#line 751 "objc-parse.y" +{ if (current_function_decl == 0) + { + error ("braced-group within expression allowed only inside a function"); + YYERROR; + } + /* We must force a BLOCK for this level + so that, if it is not expanded later, + there is a way to turn off the entire subtree of blocks + that are contained in it. */ + keep_next_level (); + push_iterator_stack (); + push_label_level (); + yyval.ttype = expand_start_stmt_expr (); ; + break;} +case 95: +#line 765 "objc-parse.y" +{ tree rtl_exp; + if (pedantic) + pedwarn ("ANSI C forbids braced-groups within expressions"); + pop_iterator_stack (); + pop_label_level (); + rtl_exp = expand_end_stmt_expr (yyvsp[-2].ttype); + /* The statements have side effects, so the group does. */ + TREE_SIDE_EFFECTS (rtl_exp) = 1; + + if (TREE_CODE (yyvsp[-1].ttype) == BLOCK) + { + /* Make a BIND_EXPR for the BLOCK already made. */ + yyval.ttype = build (BIND_EXPR, TREE_TYPE (rtl_exp), + NULL_TREE, rtl_exp, yyvsp[-1].ttype); + /* Remove the block from the tree at this point. + It gets put back at the proper place + when the BIND_EXPR is expanded. */ + delete_block (yyvsp[-1].ttype); + } + else + yyval.ttype = yyvsp[-1].ttype; + ; + break;} +case 96: +#line 788 "objc-parse.y" +{ yyval.ttype = build_function_call (yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 97: +#line 790 "objc-parse.y" +{ yyval.ttype = build_array_ref (yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 98: +#line 792 "objc-parse.y" +{ + if (doing_objc_thang) + { + if (is_public (yyvsp[-2].ttype, yyvsp[0].ttype)) + yyval.ttype = build_component_ref (yyvsp[-2].ttype, yyvsp[0].ttype); + else + yyval.ttype = error_mark_node; + } + else + yyval.ttype = build_component_ref (yyvsp[-2].ttype, yyvsp[0].ttype); + ; + break;} +case 99: +#line 804 "objc-parse.y" +{ + tree expr = build_indirect_ref (yyvsp[-2].ttype, "->"); + + if (doing_objc_thang) + { + if (is_public (expr, yyvsp[0].ttype)) + yyval.ttype = build_component_ref (expr, yyvsp[0].ttype); + else + yyval.ttype = error_mark_node; + } + else + yyval.ttype = build_component_ref (expr, yyvsp[0].ttype); + ; + break;} +case 100: +#line 818 "objc-parse.y" +{ yyval.ttype = build_unary_op (POSTINCREMENT_EXPR, yyvsp[-1].ttype, 0); ; + break;} +case 101: +#line 820 "objc-parse.y" +{ yyval.ttype = build_unary_op (POSTDECREMENT_EXPR, yyvsp[-1].ttype, 0); ; + break;} +case 102: +#line 822 "objc-parse.y" +{ yyval.ttype = build_message_expr (yyvsp[0].ttype); ; + break;} +case 103: +#line 824 "objc-parse.y" +{ yyval.ttype = build_selector_expr (yyvsp[0].ttype); ; + break;} +case 104: +#line 826 "objc-parse.y" +{ yyval.ttype = build_protocol_expr (yyvsp[0].ttype); ; + break;} +case 105: +#line 828 "objc-parse.y" +{ yyval.ttype = build_encode_expr (yyvsp[0].ttype); ; + break;} +case 106: +#line 830 "objc-parse.y" +{ yyval.ttype = build_objc_string_object (yyvsp[0].ttype); ; + break;} +case 108: +#line 837 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 110: +#line 845 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 113: +#line 853 "objc-parse.y" +{ c_mark_varargs (); + if (pedantic) + pedwarn ("ANSI C does not permit use of `varargs.h'"); ; + break;} +case 114: +#line 863 "objc-parse.y" +{ ; + break;} +case 119: +#line 879 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 120: +#line 884 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 121: +#line 889 "objc-parse.y" +{ shadow_tag_warned (yyvsp[-1].ttype, 1); + pedwarn ("empty declaration"); ; + break;} +case 122: +#line 892 "objc-parse.y" +{ pedwarn ("empty declaration"); ; + break;} +case 123: +#line 901 "objc-parse.y" +{ ; + break;} +case 128: +#line 916 "objc-parse.y" +{ yyval.itype = suspend_momentary (); + pending_xref_error (); + declspec_stack = tree_cons (prefix_attributes, + current_declspecs, + declspec_stack); + split_specs_attrs (yyvsp[0].ttype, + ¤t_declspecs, &prefix_attributes); ; + break;} +case 129: +#line 927 "objc-parse.y" +{ prefix_attributes = chainon (prefix_attributes, yyvsp[0].ttype); ; + break;} +case 130: +#line 932 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 131: +#line 937 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 132: +#line 942 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-1].itype); ; + break;} +case 133: +#line 947 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-1].itype); ; + break;} +case 134: +#line 952 "objc-parse.y" +{ shadow_tag (yyvsp[-1].ttype); ; + break;} +case 135: +#line 954 "objc-parse.y" +{ pedwarn ("empty declaration"); ; + break;} +case 136: +#line 956 "objc-parse.y" +{ pedantic = yyvsp[-1].itype; ; + break;} +case 137: +#line 966 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 138: +#line 968 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[0].ttype, tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[-2].ttype)); ; + break;} +case 139: +#line 972 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 140: +#line 974 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 141: +#line 976 "objc-parse.y" +{ if (extra_warnings) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER (yyvsp[0].ttype)); + yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 142: +#line 981 "objc-parse.y" +{ yyval.ttype = tree_cons (yyvsp[0].ttype, NULL_TREE, yyvsp[-1].ttype); ; + break;} +case 143: +#line 986 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 144: +#line 988 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[0].ttype, tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[-2].ttype)); ; + break;} +case 145: +#line 993 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 146: +#line 995 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 147: +#line 997 "objc-parse.y" +{ if (extra_warnings) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER (yyvsp[0].ttype)); + yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 148: +#line 1010 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 149: +#line 1012 "objc-parse.y" +{ yyval.ttype = tree_cons (yyvsp[0].ttype, NULL_TREE, NULL_TREE); ; + break;} +case 150: +#line 1014 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 151: +#line 1016 "objc-parse.y" +{ yyval.ttype = tree_cons (yyvsp[0].ttype, NULL_TREE, yyvsp[-1].ttype); ; + break;} +case 152: +#line 1021 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE); + TREE_STATIC (yyval.ttype) = 1; ; + break;} +case 153: +#line 1024 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 154: +#line 1026 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); + TREE_STATIC (yyval.ttype) = 1; ; + break;} +case 155: +#line 1029 "objc-parse.y" +{ if (extra_warnings && TREE_STATIC (yyvsp[-1].ttype)) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER (yyvsp[0].ttype)); + yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); + TREE_STATIC (yyval.ttype) = TREE_STATIC (yyvsp[-1].ttype); ; + break;} +case 156: +#line 1043 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 157: +#line 1045 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[0].ttype, tree_cons (NULL_TREE, yyvsp[-1].ttype, yyvsp[-2].ttype)); ; + break;} +case 158: +#line 1049 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 159: +#line 1051 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 162: +#line 1061 "objc-parse.y" +{ /* For a typedef name, record the meaning, not the name. + In case of `foo foo, bar;'. */ + yyval.ttype = lookup_name (yyvsp[0].ttype); ; + break;} +case 163: +#line 1065 "objc-parse.y" +{ yyval.ttype = get_static_reference (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 164: +#line 1067 "objc-parse.y" +{ yyval.ttype = get_object_reference (yyvsp[0].ttype); ; + break;} +case 165: +#line 1072 "objc-parse.y" +{ yyval.ttype = get_object_reference (yyvsp[0].ttype); ; + break;} +case 166: +#line 1074 "objc-parse.y" +{ yyval.ttype = TREE_TYPE (yyvsp[-1].ttype); ; + break;} +case 167: +#line 1076 "objc-parse.y" +{ yyval.ttype = groktypename (yyvsp[-1].ttype); ; + break;} +case 175: +#line 1098 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 176: +#line 1100 "objc-parse.y" +{ if (TREE_CHAIN (yyvsp[-1].ttype)) yyvsp[-1].ttype = combine_strings (yyvsp[-1].ttype); + yyval.ttype = yyvsp[-1].ttype; + ; + break;} +case 177: +#line 1107 "objc-parse.y" +{ yyval.ttype = start_decl (yyvsp[-3].ttype, current_declspecs, 1, + yyvsp[-1].ttype, prefix_attributes); + start_init (yyval.ttype, yyvsp[-2].ttype, global_bindings_p ()); ; + break;} +case 178: +#line 1112 "objc-parse.y" +{ finish_init (); + finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype); ; + break;} +case 179: +#line 1115 "objc-parse.y" +{ tree d = start_decl (yyvsp[-2].ttype, current_declspecs, 0, + yyvsp[0].ttype, prefix_attributes); + finish_decl (d, NULL_TREE, yyvsp[-1].ttype); + ; + break;} +case 180: +#line 1123 "objc-parse.y" +{ yyval.ttype = start_decl (yyvsp[-3].ttype, current_declspecs, 1, + yyvsp[-1].ttype, prefix_attributes); + start_init (yyval.ttype, yyvsp[-2].ttype, global_bindings_p ()); ; + break;} +case 181: +#line 1128 "objc-parse.y" +{ finish_init (); + decl_attributes (yyvsp[-1].ttype, yyvsp[-3].ttype, prefix_attributes); + finish_decl (yyvsp[-1].ttype, yyvsp[0].ttype, yyvsp[-4].ttype); ; + break;} +case 182: +#line 1132 "objc-parse.y" +{ tree d = start_decl (yyvsp[-2].ttype, current_declspecs, 0, + yyvsp[0].ttype, prefix_attributes); + finish_decl (d, NULL_TREE, yyvsp[-1].ttype); ; + break;} +case 183: +#line 1140 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 184: +#line 1142 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 185: +#line 1147 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 186: +#line 1149 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 187: +#line 1154 "objc-parse.y" +{ yyval.ttype = yyvsp[-2].ttype; ; + break;} +case 188: +#line 1159 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 189: +#line 1161 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 190: +#line 1166 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 191: +#line 1168 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[0].ttype, NULL_TREE); ; + break;} +case 192: +#line 1170 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[-3].ttype, build_tree_list (NULL_TREE, yyvsp[-1].ttype)); ; + break;} +case 193: +#line 1172 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[-5].ttype, tree_cons (NULL_TREE, yyvsp[-3].ttype, yyvsp[-1].ttype)); ; + break;} +case 194: +#line 1174 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 200: +#line 1192 "objc-parse.y" +{ really_start_incremental_init (NULL_TREE); + /* Note that the call to clear_momentary + is in process_init_element. */ + push_momentary (); ; + break;} +case 201: +#line 1197 "objc-parse.y" +{ yyval.ttype = pop_init_level (0); + if (yyval.ttype == error_mark_node + && ! (yychar == STRING || yychar == CONSTANT)) + pop_momentary (); + else + pop_momentary_nofree (); ; + break;} +case 202: +#line 1205 "objc-parse.y" +{ yyval.ttype = error_mark_node; ; + break;} +case 203: +#line 1211 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids empty initializer braces"); ; + break;} +case 207: +#line 1225 "objc-parse.y" +{ process_init_element (yyvsp[0].ttype); ; + break;} +case 208: +#line 1227 "objc-parse.y" +{ push_init_level (0); ; + break;} +case 209: +#line 1229 "objc-parse.y" +{ process_init_element (pop_init_level (0)); ; + break;} +case 211: +#line 1235 "objc-parse.y" +{ set_init_label (yyvsp[-1].ttype); ; + break;} +case 213: +#line 1238 "objc-parse.y" +{ set_init_label (yyvsp[-1].ttype); ; + break;} +case 215: +#line 1244 "objc-parse.y" +{ push_c_function_context (); + if (! start_function (current_declspecs, yyvsp[0].ttype, + prefix_attributes, NULL_TREE, 1)) + { + pop_c_function_context (); + YYERROR1; + } + reinit_parse_for_function (); ; + break;} +case 216: +#line 1253 "objc-parse.y" +{ store_parm_decls (); ; + break;} +case 217: +#line 1261 "objc-parse.y" +{ finish_function (1); + pop_c_function_context (); ; + break;} +case 218: +#line 1267 "objc-parse.y" +{ push_c_function_context (); + if (! start_function (current_declspecs, yyvsp[0].ttype, + prefix_attributes, NULL_TREE, 1)) + { + pop_c_function_context (); + YYERROR1; + } + reinit_parse_for_function (); ; + break;} +case 219: +#line 1276 "objc-parse.y" +{ store_parm_decls (); ; + break;} +case 220: +#line 1284 "objc-parse.y" +{ finish_function (1); + pop_c_function_context (); ; + break;} +case 223: +#line 1300 "objc-parse.y" +{ yyval.ttype = yyvsp[-1].ttype; ; + break;} +case 224: +#line 1302 "objc-parse.y" +{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 225: +#line 1307 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 226: +#line 1309 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ; + break;} +case 227: +#line 1311 "objc-parse.y" +{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 228: +#line 1318 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 231: +#line 1330 "objc-parse.y" +{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 232: +#line 1335 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 233: +#line 1337 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ; + break;} +case 234: +#line 1339 "objc-parse.y" +{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 235: +#line 1346 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 237: +#line 1355 "objc-parse.y" +{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 238: +#line 1360 "objc-parse.y" +{ yyval.ttype = yyvsp[-1].ttype; ; + break;} +case 239: +#line 1362 "objc-parse.y" +{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 240: +#line 1364 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 241: +#line 1366 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ; + break;} +case 242: +#line 1373 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 244: +#line 1379 "objc-parse.y" +{ yyval.ttype = start_struct (RECORD_TYPE, yyvsp[-1].ttype); + /* Start scope of tag before parsing components. */ + ; + break;} +case 245: +#line 1383 "objc-parse.y" +{ yyval.ttype = finish_struct (yyvsp[-3].ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 246: +#line 1385 "objc-parse.y" +{ yyval.ttype = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), + yyvsp[-2].ttype, yyvsp[0].ttype); + ; + break;} +case 247: +#line 1389 "objc-parse.y" +{ yyval.ttype = xref_tag (RECORD_TYPE, yyvsp[0].ttype); ; + break;} +case 248: +#line 1391 "objc-parse.y" +{ yyval.ttype = start_struct (UNION_TYPE, yyvsp[-1].ttype); ; + break;} +case 249: +#line 1393 "objc-parse.y" +{ yyval.ttype = finish_struct (yyvsp[-3].ttype, yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 250: +#line 1395 "objc-parse.y" +{ yyval.ttype = finish_struct (start_struct (UNION_TYPE, NULL_TREE), + yyvsp[-2].ttype, yyvsp[0].ttype); + ; + break;} +case 251: +#line 1399 "objc-parse.y" +{ yyval.ttype = xref_tag (UNION_TYPE, yyvsp[0].ttype); ; + break;} +case 252: +#line 1401 "objc-parse.y" +{ yyvsp[0].itype = suspend_momentary (); + yyval.ttype = start_enum (yyvsp[-1].ttype); ; + break;} +case 253: +#line 1404 "objc-parse.y" +{ yyval.ttype = finish_enum (yyvsp[-4].ttype, nreverse (yyvsp[-3].ttype), yyvsp[0].ttype); + resume_momentary (yyvsp[-5].itype); ; + break;} +case 254: +#line 1407 "objc-parse.y" +{ yyvsp[0].itype = suspend_momentary (); + yyval.ttype = start_enum (NULL_TREE); ; + break;} +case 255: +#line 1410 "objc-parse.y" +{ yyval.ttype = finish_enum (yyvsp[-4].ttype, nreverse (yyvsp[-3].ttype), yyvsp[0].ttype); + resume_momentary (yyvsp[-5].itype); ; + break;} +case 256: +#line 1413 "objc-parse.y" +{ yyval.ttype = xref_tag (ENUMERAL_TYPE, yyvsp[0].ttype); ; + break;} +case 260: +#line 1424 "objc-parse.y" +{ if (pedantic) pedwarn ("comma at end of enumerator list"); ; + break;} +case 261: +#line 1429 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 262: +#line 1431 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); + pedwarn ("no semicolon at end of struct or union"); ; + break;} +case 263: +#line 1436 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 264: +#line 1438 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[-1].ttype); ; + break;} +case 265: +#line 1440 "objc-parse.y" +{ if (pedantic) + pedwarn ("extra semicolon in struct or union specified"); ; + break;} +case 266: +#line 1444 "objc-parse.y" +{ + tree interface = lookup_interface (yyvsp[-1].ttype); + + if (interface) + yyval.ttype = get_class_ivars (interface); + else + { + error ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER (yyvsp[-1].ttype)); + yyval.ttype = NULL_TREE; + } + ; + break;} +case 267: +#line 1469 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-1].itype); ; + break;} +case 268: +#line 1475 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids member declarations with no members"); + shadow_tag(yyvsp[0].ttype); + yyval.ttype = NULL_TREE; ; + break;} +case 269: +#line 1480 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-1].itype); ; + break;} +case 270: +#line 1486 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids member declarations with no members"); + shadow_tag(yyvsp[0].ttype); + yyval.ttype = NULL_TREE; ; + break;} +case 271: +#line 1491 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 272: +#line 1493 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + pedantic = yyvsp[-1].itype; ; + break;} +case 274: +#line 1500 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 275: +#line 1505 "objc-parse.y" +{ yyval.ttype = grokfield (yyvsp[-3].filename, yyvsp[-2].lineno, yyvsp[-1].ttype, current_declspecs, NULL_TREE); + decl_attributes (yyval.ttype, yyvsp[0].ttype, prefix_attributes); ; + break;} +case 276: +#line 1509 "objc-parse.y" +{ yyval.ttype = grokfield (yyvsp[-5].filename, yyvsp[-4].lineno, yyvsp[-3].ttype, current_declspecs, yyvsp[-1].ttype); + decl_attributes (yyval.ttype, yyvsp[0].ttype, prefix_attributes); ; + break;} +case 277: +#line 1512 "objc-parse.y" +{ yyval.ttype = grokfield (yyvsp[-4].filename, yyvsp[-3].lineno, NULL_TREE, current_declspecs, yyvsp[-1].ttype); + decl_attributes (yyval.ttype, yyvsp[0].ttype, prefix_attributes); ; + break;} +case 279: +#line 1524 "objc-parse.y" +{ if (yyvsp[-2].ttype == error_mark_node) + yyval.ttype = yyvsp[-2].ttype; + else + yyval.ttype = chainon (yyvsp[0].ttype, yyvsp[-2].ttype); ; + break;} +case 280: +#line 1529 "objc-parse.y" +{ yyval.ttype = error_mark_node; ; + break;} +case 281: +#line 1535 "objc-parse.y" +{ yyval.ttype = build_enumerator (yyvsp[0].ttype, NULL_TREE); ; + break;} +case 282: +#line 1537 "objc-parse.y" +{ yyval.ttype = build_enumerator (yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 283: +#line 1542 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 284: +#line 1544 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 285: +#line 1549 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 287: +#line 1555 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 288: +#line 1557 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 289: +#line 1562 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 290: +#line 1564 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, yyvsp[0].ttype, yyvsp[-1].ttype); ; + break;} +case 291: +#line 1569 "objc-parse.y" +{ yyval.ttype = yyvsp[-1].ttype; ; + break;} +case 292: +#line 1572 "objc-parse.y" +{ yyval.ttype = make_pointer_declarator (yyvsp[-1].ttype, yyvsp[0].ttype); ; + break;} +case 293: +#line 1574 "objc-parse.y" +{ yyval.ttype = make_pointer_declarator (yyvsp[0].ttype, NULL_TREE); ; + break;} +case 294: +#line 1576 "objc-parse.y" +{ yyval.ttype = build_nt (CALL_EXPR, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 295: +#line 1578 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 296: +#line 1580 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, yyvsp[-2].ttype, NULL_TREE); ; + break;} +case 297: +#line 1582 "objc-parse.y" +{ yyval.ttype = build_nt (CALL_EXPR, NULL_TREE, yyvsp[0].ttype, NULL_TREE); ; + break;} +case 298: +#line 1584 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, NULL_TREE, yyvsp[-1].ttype); ; + break;} +case 299: +#line 1586 "objc-parse.y" +{ yyval.ttype = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); ; + break;} +case 300: +#line 1597 "objc-parse.y" +{ + if (pedantic && yyvsp[0].ends_in_label) + pedwarn ("ANSI C forbids label at end of compound statement"); + ; + break;} +case 302: +#line 1606 "objc-parse.y" +{ yyval.ends_in_label = yyvsp[0].ends_in_label; ; + break;} +case 303: +#line 1608 "objc-parse.y" +{ yyval.ends_in_label = 0; ; + break;} +case 307: +#line 1620 "objc-parse.y" +{ emit_line_note (input_filename, lineno); + pushlevel (0); + clear_last_expr (); + push_momentary (); + expand_start_bindings (0); + if (objc_method_context) + add_objc_decls (); + ; + break;} +case 309: +#line 1635 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids label declarations"); ; + break;} +case 312: +#line 1646 "objc-parse.y" +{ tree link; + for (link = yyvsp[-1].ttype; link; link = TREE_CHAIN (link)) + { + tree label = shadow_label (TREE_VALUE (link)); + C_DECLARED_LABEL_FLAG (label) = 1; + declare_nonlocal_label (label); + } + ; + break;} +case 313: +#line 1660 "objc-parse.y" +{; + break;} +case 315: +#line 1664 "objc-parse.y" +{ compstmt_count++; ; + break;} +case 316: +#line 1667 "objc-parse.y" +{ yyval.ttype = convert (void_type_node, integer_zero_node); ; + break;} +case 317: +#line 1669 "objc-parse.y" +{ emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), 1, 0); + yyval.ttype = poplevel (1, 1, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); ; + break;} +case 318: +#line 1677 "objc-parse.y" +{ emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), kept_level_p (), 0); + yyval.ttype = poplevel (kept_level_p (), 0, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); ; + break;} +case 319: +#line 1685 "objc-parse.y" +{ emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), kept_level_p (), 0); + yyval.ttype = poplevel (kept_level_p (), 0, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); ; + break;} +case 322: +#line 1705 "objc-parse.y" +{ emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno); + c_expand_start_cond (truthvalue_conversion (yyvsp[-1].ttype), 0, + compstmt_count); + yyval.itype = stmt_count; + if_stmt_file = yyvsp[-5].filename; + if_stmt_line = yyvsp[-4].lineno; + position_after_white_space (); ; + break;} +case 323: +#line 1719 "objc-parse.y" +{ stmt_count++; + compstmt_count++; + emit_line_note (yyvsp[-2].filename, yyvsp[-1].lineno); + /* See comment in `while' alternative, above. */ + emit_nop (); + expand_start_loop_continue_elsewhere (1); + position_after_white_space (); ; + break;} +case 324: +#line 1727 "objc-parse.y" +{ expand_loop_continue_here (); ; + break;} +case 325: +#line 1731 "objc-parse.y" +{ yyval.filename = input_filename; ; + break;} +case 326: +#line 1735 "objc-parse.y" +{ yyval.lineno = lineno; ; + break;} +case 327: +#line 1740 "objc-parse.y" +{ ; + break;} +case 328: +#line 1745 "objc-parse.y" +{ ; + break;} +case 329: +#line 1750 "objc-parse.y" +{ yyval.ends_in_label = yyvsp[0].ends_in_label; ; + break;} +case 330: +#line 1755 "objc-parse.y" +{ yyval.ends_in_label = 0; ; + break;} +case 331: +#line 1757 "objc-parse.y" +{ yyval.ends_in_label = 1; ; + break;} +case 332: +#line 1763 "objc-parse.y" +{ stmt_count++; ; + break;} +case 334: +#line 1766 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno); +/* It appears that this should not be done--that a non-lvalue array + shouldn't get an error if the value isn't used. + Section 3.2.2.1 says that an array lvalue gets converted to a pointer + if it appears as a top-level expression, + but says nothing about non-lvalue arrays. */ +#if 0 + /* Call default_conversion to get an error + on referring to a register array if pedantic. */ + if (TREE_CODE (TREE_TYPE (yyvsp[-1].ttype)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (yyvsp[-1].ttype)) == FUNCTION_TYPE) + yyvsp[-1].ttype = default_conversion (yyvsp[-1].ttype); +#endif + iterator_expand (yyvsp[-1].ttype); + clear_momentary (); ; + break;} +case 335: +#line 1783 "objc-parse.y" +{ c_expand_start_else (); + yyvsp[-1].itype = stmt_count; + position_after_white_space (); ; + break;} +case 336: +#line 1787 "objc-parse.y" +{ c_expand_end_cond (); + if (extra_warnings && stmt_count == yyvsp[-3].itype) + warning ("empty body in an else-statement"); ; + break;} +case 337: +#line 1791 "objc-parse.y" +{ c_expand_end_cond (); + /* This warning is here instead of in simple_if, because we + do not want a warning if an empty if is followed by an + else statement. Increment stmt_count so we don't + give a second error if this is a nested `if'. */ + if (extra_warnings && stmt_count++ == yyvsp[0].itype) + warning_with_file_and_line (if_stmt_file, if_stmt_line, + "empty body in an if-statement"); ; + break;} +case 338: +#line 1803 "objc-parse.y" +{ c_expand_end_cond (); ; + break;} +case 339: +#line 1805 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-2].filename, yyvsp[-1].lineno); + /* The emit_nop used to come before emit_line_note, + but that made the nop seem like part of the preceding line. + And that was confusing when the preceding line was + inside of an if statement and was not really executed. + I think it ought to work to put the nop after the line number. + We will see. --rms, July 15, 1991. */ + emit_nop (); ; + break;} +case 340: +#line 1815 "objc-parse.y" +{ /* Don't start the loop till we have succeeded + in parsing the end test. This is to make sure + that we end every loop we start. */ + expand_start_loop (1); + emit_line_note (input_filename, lineno); + expand_exit_loop_if_false (NULL_PTR, + truthvalue_conversion (yyvsp[-1].ttype)); + position_after_white_space (); ; + break;} +case 341: +#line 1824 "objc-parse.y" +{ expand_end_loop (); ; + break;} +case 342: +#line 1827 "objc-parse.y" +{ emit_line_note (input_filename, lineno); + expand_exit_loop_if_false (NULL_PTR, + truthvalue_conversion (yyvsp[-2].ttype)); + expand_end_loop (); + clear_momentary (); ; + break;} +case 343: +#line 1834 "objc-parse.y" +{ expand_end_loop (); + clear_momentary (); ; + break;} +case 344: +#line 1838 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno); + /* See comment in `while' alternative, above. */ + emit_nop (); + if (yyvsp[-1].ttype) c_expand_expr_stmt (yyvsp[-1].ttype); + /* Next step is to call expand_start_loop_continue_elsewhere, + but wait till after we parse the entire for (...). + Otherwise, invalid input might cause us to call that + fn without calling expand_end_loop. */ + ; + break;} +case 345: +#line 1850 "objc-parse.y" +{ yyvsp[0].lineno = lineno; + yyval.filename = input_filename; ; + break;} +case 346: +#line 1853 "objc-parse.y" +{ + /* Start the loop. Doing this after parsing + all the expressions ensures we will end the loop. */ + expand_start_loop_continue_elsewhere (1); + /* Emit the end-test, with a line number. */ + emit_line_note (yyvsp[-2].filename, yyvsp[-3].lineno); + if (yyvsp[-4].ttype) + expand_exit_loop_if_false (NULL_PTR, + truthvalue_conversion (yyvsp[-4].ttype)); + /* Don't let the tree nodes for $9 be discarded by + clear_momentary during the parsing of the next stmt. */ + push_momentary (); + yyvsp[-3].lineno = lineno; + yyvsp[-2].filename = input_filename; + position_after_white_space (); ; + break;} +case 347: +#line 1869 "objc-parse.y" +{ /* Emit the increment expression, with a line number. */ + emit_line_note (yyvsp[-4].filename, yyvsp[-5].lineno); + expand_loop_continue_here (); + if (yyvsp[-3].ttype) + c_expand_expr_stmt (yyvsp[-3].ttype); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); + expand_end_loop (); ; + break;} +case 348: +#line 1880 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno); + c_expand_start_case (yyvsp[-1].ttype); + /* Don't let the tree nodes for $3 be discarded by + clear_momentary during the parsing of the next stmt. */ + push_momentary (); + position_after_white_space (); ; + break;} +case 349: +#line 1888 "objc-parse.y" +{ expand_end_case (yyvsp[-3].ttype); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); ; + break;} +case 350: +#line 1894 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno); + if ( ! expand_exit_something ()) + error ("break statement not within loop or switch"); ; + break;} +case 351: +#line 1899 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno); + if (! expand_continue_loop (NULL_PTR)) + error ("continue statement not within a loop"); ; + break;} +case 352: +#line 1904 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-3].filename, yyvsp[-2].lineno); + c_expand_return (NULL_TREE); ; + break;} +case 353: +#line 1908 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-4].filename, yyvsp[-3].lineno); + c_expand_return (yyvsp[-1].ttype); ; + break;} +case 354: +#line 1912 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-7].filename, yyvsp[-6].lineno); + STRIP_NOPS (yyvsp[-2].ttype); + if ((TREE_CODE (yyvsp[-2].ttype) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (yyvsp[-2].ttype, 0)) == STRING_CST) + || TREE_CODE (yyvsp[-2].ttype) == STRING_CST) + expand_asm (yyvsp[-2].ttype); + else + error ("argument of `asm' is not a constant string"); ; + break;} +case 355: +#line 1923 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-9].filename, yyvsp[-8].lineno); + c_expand_asm_operands (yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, NULL_TREE, + yyvsp[-6].ttype == ridpointers[(int)RID_VOLATILE], + input_filename, lineno); ; + break;} +case 356: +#line 1930 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-11].filename, yyvsp[-10].lineno); + c_expand_asm_operands (yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype, NULL_TREE, + yyvsp[-8].ttype == ridpointers[(int)RID_VOLATILE], + input_filename, lineno); ; + break;} +case 357: +#line 1938 "objc-parse.y" +{ stmt_count++; + emit_line_note (yyvsp[-13].filename, yyvsp[-12].lineno); + c_expand_asm_operands (yyvsp[-8].ttype, yyvsp[-6].ttype, yyvsp[-4].ttype, yyvsp[-2].ttype, + yyvsp[-10].ttype == ridpointers[(int)RID_VOLATILE], + input_filename, lineno); ; + break;} +case 358: +#line 1944 "objc-parse.y" +{ tree decl; + stmt_count++; + emit_line_note (yyvsp[-4].filename, yyvsp[-3].lineno); + decl = lookup_label (yyvsp[-1].ttype); + if (decl != 0) + { + TREE_USED (decl) = 1; + expand_goto (decl); + } + ; + break;} +case 359: +#line 1955 "objc-parse.y" +{ if (pedantic) + pedwarn ("ANSI C forbids `goto *expr;'"); + stmt_count++; + emit_line_note (yyvsp[-5].filename, yyvsp[-4].lineno); + expand_computed_goto (convert (ptr_type_node, yyvsp[-1].ttype)); ; + break;} +case 362: +#line 1970 "objc-parse.y" +{ + /* The value returned by this action is */ + /* 1 if everything is OK */ + /* 0 in case of error or already bound iterator */ + + yyval.itype = 0; + if (TREE_CODE (yyvsp[-1].ttype) != VAR_DECL) + error ("invalid `for (ITERATOR)' syntax"); + else if (! ITERATOR_P (yyvsp[-1].ttype)) + error ("`%s' is not an iterator", + IDENTIFIER_POINTER (DECL_NAME (yyvsp[-1].ttype))); + else if (ITERATOR_BOUND_P (yyvsp[-1].ttype)) + error ("`for (%s)' inside expansion of same iterator", + IDENTIFIER_POINTER (DECL_NAME (yyvsp[-1].ttype))); + else + { + yyval.itype = 1; + iterator_for_loop_start (yyvsp[-1].ttype); + } + ; + break;} +case 363: +#line 1991 "objc-parse.y" +{ + if (yyvsp[-1].itype) + iterator_for_loop_end (yyvsp[-3].ttype); + ; + break;} +case 364: +#line 2026 "objc-parse.y" +{ register tree value = check_case_value (yyvsp[-1].ttype); + register tree label + = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + stmt_count++; + + if (value != error_mark_node) + { + tree duplicate; + int success = pushcase (value, convert_and_check, + label, &duplicate); + if (success == 1) + error ("case label not within a switch statement"); + else if (success == 2) + { + error ("duplicate case value"); + error_with_decl (duplicate, "this is the first entry for that value"); + } + else if (success == 3) + warning ("case value out of range"); + else if (success == 5) + error ("case label within scope of cleanup or variable array"); + } + position_after_white_space (); ; + break;} +case 365: +#line 2051 "objc-parse.y" +{ register tree value1 = check_case_value (yyvsp[-3].ttype); + register tree value2 = check_case_value (yyvsp[-1].ttype); + register tree label + = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + if (pedantic) + pedwarn ("ANSI C forbids case ranges"); + stmt_count++; + + if (value1 != error_mark_node && value2 != error_mark_node) + { + tree duplicate; + int success = pushcase_range (value1, value2, + convert_and_check, label, + &duplicate); + if (success == 1) + error ("case label not within a switch statement"); + else if (success == 2) + { + error ("duplicate case value"); + error_with_decl (duplicate, "this is the first entry for that value"); + } + else if (success == 3) + warning ("case value out of range"); + else if (success == 4) + warning ("empty case range"); + else if (success == 5) + error ("case label within scope of cleanup or variable array"); + } + position_after_white_space (); ; + break;} +case 366: +#line 2082 "objc-parse.y" +{ + tree duplicate; + register tree label + = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + int success = pushcase (NULL_TREE, 0, label, &duplicate); + stmt_count++; + if (success == 1) + error ("default label not within a switch statement"); + else if (success == 2) + { + error ("multiple default labels in one switch"); + error_with_decl (duplicate, "this is the first default label"); + } + position_after_white_space (); ; + break;} +case 367: +#line 2097 "objc-parse.y" +{ tree label = define_label (input_filename, lineno, yyvsp[-1].ttype); + stmt_count++; + emit_nop (); + if (label) + expand_label (label); + position_after_white_space (); ; + break;} +case 368: +#line 2109 "objc-parse.y" +{ emit_line_note (input_filename, lineno); + yyval.ttype = NULL_TREE; ; + break;} +case 369: +#line 2112 "objc-parse.y" +{ emit_line_note (input_filename, lineno); ; + break;} +case 370: +#line 2117 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 372: +#line 2124 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 375: +#line 2131 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, yyvsp[0].ttype); ; + break;} +case 376: +#line 2136 "objc-parse.y" +{ yyval.ttype = build_tree_list (yyvsp[-3].ttype, yyvsp[-1].ttype); ; + break;} +case 377: +#line 2141 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, combine_strings (yyvsp[0].ttype), NULL_TREE); ; + break;} +case 378: +#line 2143 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, combine_strings (yyvsp[0].ttype), yyvsp[-2].ttype); ; + break;} +case 379: +#line 2149 "objc-parse.y" +{ pushlevel (0); + clear_parm_order (); + declare_parm_level (0); ; + break;} +case 380: +#line 2153 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + parmlist_tags_warning (); + poplevel (0, 0, 0); ; + break;} +case 382: +#line 2161 "objc-parse.y" +{ tree parm; + if (pedantic) + pedwarn ("ANSI C forbids forward parameter declarations"); + /* Mark the forward decls as such. */ + for (parm = getdecls (); parm; parm = TREE_CHAIN (parm)) + TREE_ASM_WRITTEN (parm) = 1; + clear_parm_order (); ; + break;} +case 383: +#line 2169 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; ; + break;} +case 384: +#line 2171 "objc-parse.y" +{ yyval.ttype = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); ; + break;} +case 385: +#line 2177 "objc-parse.y" +{ yyval.ttype = get_parm_info (0); ; + break;} +case 386: +#line 2179 "objc-parse.y" +{ yyval.ttype = get_parm_info (0); + /* Gcc used to allow this as an extension. However, it does + not work for all targets, and thus has been disabled. + Also, since func (...) and func () are indistinguishable, + it caused problems with the code in expand_builtin which + tries to verify that BUILT_IN_NEXT_ARG is being used + correctly. */ + error ("ANSI C requires a named argument before `...'"); + ; + break;} +case 387: +#line 2189 "objc-parse.y" +{ yyval.ttype = get_parm_info (1); ; + break;} +case 388: +#line 2191 "objc-parse.y" +{ yyval.ttype = get_parm_info (0); ; + break;} +case 389: +#line 2196 "objc-parse.y" +{ push_parm_decl (yyvsp[0].ttype); ; + break;} +case 390: +#line 2198 "objc-parse.y" +{ push_parm_decl (yyvsp[0].ttype); ; + break;} +case 391: +#line 2205 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 392: +#line 2214 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 393: +#line 2223 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 394: +#line 2232 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 395: +#line 2242 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 396: +#line 2256 "objc-parse.y" +{ pushlevel (0); + clear_parm_order (); + declare_parm_level (1); ; + break;} +case 397: +#line 2260 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + parmlist_tags_warning (); + poplevel (0, 0, 0); ; + break;} +case 399: +#line 2268 "objc-parse.y" +{ tree t; + for (t = yyvsp[-1].ttype; t; t = TREE_CHAIN (t)) + if (TREE_VALUE (t) == NULL_TREE) + error ("`...' in old-style identifier list"); + yyval.ttype = tree_cons (NULL_TREE, NULL_TREE, yyvsp[-1].ttype); ; + break;} +case 400: +#line 2278 "objc-parse.y" +{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ; + break;} +case 401: +#line 2280 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ; + break;} +case 402: +#line 2286 "objc-parse.y" +{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ; + break;} +case 403: +#line 2288 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ; + break;} +case 404: +#line 2293 "objc-parse.y" +{ yyval.itype = pedantic; + pedantic = 0; ; + break;} +case 410: +#line 2306 "objc-parse.y" +{ + if (objc_implementation_context) + { + finish_class (objc_implementation_context); + objc_ivar_chain = NULL_TREE; + objc_implementation_context = NULL_TREE; + } + else + warning ("`@end' must appear in an implementation context"); + ; + break;} +case 411: +#line 2321 "objc-parse.y" +{ yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); ; + break;} +case 412: +#line 2323 "objc-parse.y" +{ yyval.ttype = chainon (yyvsp[-2].ttype, build_tree_list (NULL_TREE, yyvsp[0].ttype)); ; + break;} +case 413: +#line 2328 "objc-parse.y" +{ + objc_declare_class (yyvsp[-1].ttype); + ; + break;} +case 414: +#line 2334 "objc-parse.y" +{ + objc_declare_alias (yyvsp[-2].ttype, yyvsp[-1].ttype); + ; + break;} +case 415: +#line 2340 "objc-parse.y" +{ + objc_interface_context = objc_ivar_context + = start_class (CLASS_INTERFACE_TYPE, yyvsp[-2].ttype, NULL_TREE, yyvsp[-1].ttype); + objc_public_flag = 0; + ; + break;} +case 416: +#line 2346 "objc-parse.y" +{ + continue_class (objc_interface_context); + ; + break;} +case 417: +#line 2351 "objc-parse.y" +{ + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + ; + break;} +case 418: +#line 2357 "objc-parse.y" +{ + objc_interface_context + = start_class (CLASS_INTERFACE_TYPE, yyvsp[-1].ttype, NULL_TREE, yyvsp[0].ttype); + continue_class (objc_interface_context); + ; + break;} +case 419: +#line 2364 "objc-parse.y" +{ + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + ; + break;} +case 420: +#line 2370 "objc-parse.y" +{ + objc_interface_context = objc_ivar_context + = start_class (CLASS_INTERFACE_TYPE, yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[-1].ttype); + objc_public_flag = 0; + ; + break;} +case 421: +#line 2376 "objc-parse.y" +{ + continue_class (objc_interface_context); + ; + break;} +case 422: +#line 2381 "objc-parse.y" +{ + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + ; + break;} +case 423: +#line 2387 "objc-parse.y" +{ + objc_interface_context + = start_class (CLASS_INTERFACE_TYPE, yyvsp[-3].ttype, yyvsp[-1].ttype, yyvsp[0].ttype); + continue_class (objc_interface_context); + ; + break;} +case 424: +#line 2394 "objc-parse.y" +{ + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + ; + break;} +case 425: +#line 2400 "objc-parse.y" +{ + objc_implementation_context = objc_ivar_context + = start_class (CLASS_IMPLEMENTATION_TYPE, yyvsp[-1].ttype, NULL_TREE, NULL_TREE); + objc_public_flag = 0; + ; + break;} +case 426: +#line 2406 "objc-parse.y" +{ + objc_ivar_chain + = continue_class (objc_implementation_context); + ; + break;} +case 427: +#line 2412 "objc-parse.y" +{ + objc_implementation_context + = start_class (CLASS_IMPLEMENTATION_TYPE, yyvsp[0].ttype, NULL_TREE, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + ; + break;} +case 428: +#line 2420 "objc-parse.y" +{ + objc_implementation_context = objc_ivar_context + = start_class (CLASS_IMPLEMENTATION_TYPE, yyvsp[-3].ttype, yyvsp[-1].ttype, NULL_TREE); + objc_public_flag = 0; + ; + break;} +case 429: +#line 2426 "objc-parse.y" +{ + objc_ivar_chain + = continue_class (objc_implementation_context); + ; + break;} +case 430: +#line 2432 "objc-parse.y" +{ + objc_implementation_context + = start_class (CLASS_IMPLEMENTATION_TYPE, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + ; + break;} +case 431: +#line 2440 "objc-parse.y" +{ + objc_interface_context + = start_class (CATEGORY_INTERFACE_TYPE, yyvsp[-4].ttype, yyvsp[-2].ttype, yyvsp[0].ttype); + continue_class (objc_interface_context); + ; + break;} +case 432: +#line 2447 "objc-parse.y" +{ + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + ; + break;} +case 433: +#line 2453 "objc-parse.y" +{ + objc_implementation_context + = start_class (CATEGORY_IMPLEMENTATION_TYPE, yyvsp[-3].ttype, yyvsp[-1].ttype, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + ; + break;} +case 434: +#line 2463 "objc-parse.y" +{ + remember_protocol_qualifiers (); + objc_interface_context + = start_protocol(PROTOCOL_INTERFACE_TYPE, yyvsp[-1].ttype, yyvsp[0].ttype); + ; + break;} +case 435: +#line 2469 "objc-parse.y" +{ + forget_protocol_qualifiers(); + finish_protocol(objc_interface_context); + objc_interface_context = NULL_TREE; + ; + break;} +case 436: +#line 2478 "objc-parse.y" +{ + yyval.ttype = NULL_TREE; + ; + break;} +case 438: +#line 2486 "objc-parse.y" +{ + if (yyvsp[-2].code == LT_EXPR && yyvsp[0].code == GT_EXPR) + yyval.ttype = yyvsp[-1].ttype; + else + YYERROR1; + ; + break;} +case 441: +#line 2500 "objc-parse.y" +{ objc_public_flag = 2; ; + break;} +case 442: +#line 2501 "objc-parse.y" +{ objc_public_flag = 0; ; + break;} +case 443: +#line 2502 "objc-parse.y" +{ objc_public_flag = 1; ; + break;} +case 444: +#line 2507 "objc-parse.y" +{ + yyval.ttype = NULL_TREE; + ; + break;} +case 446: +#line 2512 "objc-parse.y" +{ + if (pedantic) + pedwarn ("extra semicolon in struct or union specified"); + ; + break;} +case 447: +#line 2530 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-1].itype); ; + break;} +case 448: +#line 2536 "objc-parse.y" +{ yyval.ttype = yyvsp[0].ttype; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-1].itype); ; + break;} +case 449: +#line 2542 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 450: +#line 2547 "objc-parse.y" +{ yyval.ttype = NULL_TREE; ; + break;} +case 453: +#line 2554 "objc-parse.y" +{ + yyval.ttype = add_instance_variable (objc_ivar_context, + objc_public_flag, + yyvsp[0].ttype, current_declspecs, + NULL_TREE); + ; + break;} +case 454: +#line 2561 "objc-parse.y" +{ + yyval.ttype = add_instance_variable (objc_ivar_context, + objc_public_flag, + yyvsp[-2].ttype, current_declspecs, yyvsp[0].ttype); + ; + break;} +case 455: +#line 2567 "objc-parse.y" +{ + yyval.ttype = add_instance_variable (objc_ivar_context, + objc_public_flag, + NULL_TREE, + current_declspecs, yyvsp[0].ttype); + ; + break;} +case 456: +#line 2577 "objc-parse.y" +{ + remember_protocol_qualifiers (); + if (objc_implementation_context) + objc_inherit_code = CLASS_METHOD_DECL; + else + fatal ("method definition not in class context"); + ; + break;} +case 457: +#line 2585 "objc-parse.y" +{ + forget_protocol_qualifiers (); + add_class_method (objc_implementation_context, yyvsp[0].ttype); + start_method_def (yyvsp[0].ttype); + objc_method_context = yyvsp[0].ttype; + ; + break;} +case 458: +#line 2592 "objc-parse.y" +{ + continue_method_def (); + ; + break;} +case 459: +#line 2596 "objc-parse.y" +{ + finish_method_def (); + objc_method_context = NULL_TREE; + ; + break;} +case 460: +#line 2602 "objc-parse.y" +{ + remember_protocol_qualifiers (); + if (objc_implementation_context) + objc_inherit_code = INSTANCE_METHOD_DECL; + else + fatal ("method definition not in class context"); + ; + break;} +case 461: +#line 2610 "objc-parse.y" +{ + forget_protocol_qualifiers (); + add_instance_method (objc_implementation_context, yyvsp[0].ttype); + start_method_def (yyvsp[0].ttype); + objc_method_context = yyvsp[0].ttype; + ; + break;} +case 462: +#line 2617 "objc-parse.y" +{ + continue_method_def (); + ; + break;} +case 463: +#line 2621 "objc-parse.y" +{ + finish_method_def (); + objc_method_context = NULL_TREE; + ; + break;} +case 465: +#line 2633 "objc-parse.y" +{yyval.ttype = NULL_TREE; ; + break;} +case 470: +#line 2640 "objc-parse.y" +{yyval.ttype = NULL_TREE; ; + break;} +case 474: +#line 2650 "objc-parse.y" +{ + objc_inherit_code = CLASS_METHOD_DECL; + ; + break;} +case 475: +#line 2654 "objc-parse.y" +{ + add_class_method (objc_interface_context, yyvsp[0].ttype); + ; + break;} +case 477: +#line 2660 "objc-parse.y" +{ + objc_inherit_code = INSTANCE_METHOD_DECL; + ; + break;} +case 478: +#line 2664 "objc-parse.y" +{ + add_instance_method (objc_interface_context, yyvsp[0].ttype); + ; + break;} +case 480: +#line 2672 "objc-parse.y" +{ + yyval.ttype = build_method_decl (objc_inherit_code, yyvsp[-2].ttype, yyvsp[0].ttype, NULL_TREE); + ; + break;} +case 481: +#line 2677 "objc-parse.y" +{ + yyval.ttype = build_method_decl (objc_inherit_code, NULL_TREE, yyvsp[0].ttype, NULL_TREE); + ; + break;} +case 482: +#line 2682 "objc-parse.y" +{ + yyval.ttype = build_method_decl (objc_inherit_code, yyvsp[-3].ttype, yyvsp[-1].ttype, yyvsp[0].ttype); + ; + break;} +case 483: +#line 2687 "objc-parse.y" +{ + yyval.ttype = build_method_decl (objc_inherit_code, NULL_TREE, yyvsp[-1].ttype, yyvsp[0].ttype); + ; + break;} +case 492: +#line 2717 "objc-parse.y" +{ current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary (yyvsp[-2].itype); ; + break;} +case 493: +#line 2722 "objc-parse.y" +{ shadow_tag (yyvsp[-1].ttype); ; + break;} +case 494: +#line 2724 "objc-parse.y" +{ pedwarn ("empty declaration"); ; + break;} +case 495: +#line 2729 "objc-parse.y" +{ push_parm_decl (yyvsp[0].ttype); ; + break;} +case 496: +#line 2731 "objc-parse.y" +{ push_parm_decl (yyvsp[0].ttype); ; + break;} +case 497: +#line 2739 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); ; + break;} +case 498: +#line 2744 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); ; + break;} +case 499: +#line 2749 "objc-parse.y" +{ yyval.ttype = build_tree_list (build_tree_list (current_declspecs, + yyvsp[-1].ttype), + build_tree_list (prefix_attributes, + yyvsp[0].ttype)); ; + break;} +case 500: +#line 2757 "objc-parse.y" +{ + yyval.ttype = NULL_TREE; + ; + break;} +case 501: +#line 2761 "objc-parse.y" +{ + /* oh what a kludge! */ + yyval.ttype = (tree)1; + ; + break;} +case 502: +#line 2766 "objc-parse.y" +{ + pushlevel (0); + ; + break;} +case 503: +#line 2770 "objc-parse.y" +{ + /* returns a tree list node generated by get_parm_info */ + yyval.ttype = yyvsp[0].ttype; + poplevel (0, 0, 0); + ; + break;} +case 506: +#line 2785 "objc-parse.y" +{ + yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); + ; + break;} +case 511: +#line 2798 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 512: +#line 2799 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 513: +#line 2800 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 514: +#line 2801 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 515: +#line 2802 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 516: +#line 2803 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 517: +#line 2804 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 518: +#line 2805 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 519: +#line 2806 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 520: +#line 2807 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 521: +#line 2808 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 522: +#line 2809 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 523: +#line 2810 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 524: +#line 2811 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 525: +#line 2812 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 526: +#line 2813 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 527: +#line 2814 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 528: +#line 2815 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 529: +#line 2816 "objc-parse.y" +{ yyval.ttype = get_identifier (token_buffer); ; + break;} +case 532: +#line 2822 "objc-parse.y" +{ + yyval.ttype = build_keyword_decl (yyvsp[-5].ttype, yyvsp[-2].ttype, yyvsp[0].ttype); + ; + break;} +case 533: +#line 2827 "objc-parse.y" +{ + yyval.ttype = build_keyword_decl (yyvsp[-2].ttype, NULL_TREE, yyvsp[0].ttype); + ; + break;} +case 534: +#line 2832 "objc-parse.y" +{ + yyval.ttype = build_keyword_decl (NULL_TREE, yyvsp[-2].ttype, yyvsp[0].ttype); + ; + break;} +case 535: +#line 2837 "objc-parse.y" +{ + yyval.ttype = build_keyword_decl (NULL_TREE, NULL_TREE, yyvsp[0].ttype); + ; + break;} +case 539: +#line 2850 "objc-parse.y" +{ + yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); + ; + break;} +case 540: +#line 2858 "objc-parse.y" +{ + if (TREE_CHAIN (yyvsp[0].ttype) == NULL_TREE) + /* just return the expr., remove a level of indirection */ + yyval.ttype = TREE_VALUE (yyvsp[0].ttype); + else + /* we have a comma expr., we will collapse later */ + yyval.ttype = yyvsp[0].ttype; + ; + break;} +case 541: +#line 2870 "objc-parse.y" +{ + yyval.ttype = build_tree_list (yyvsp[-2].ttype, yyvsp[0].ttype); + ; + break;} +case 542: +#line 2874 "objc-parse.y" +{ + yyval.ttype = build_tree_list (NULL_TREE, yyvsp[0].ttype); + ; + break;} +case 544: +#line 2882 "objc-parse.y" +{ + yyval.ttype = get_class_reference (yyvsp[0].ttype); + ; + break;} +case 545: +#line 2889 "objc-parse.y" +{ objc_receiver_context = 1; ; + break;} +case 546: +#line 2891 "objc-parse.y" +{ objc_receiver_context = 0; ; + break;} +case 547: +#line 2893 "objc-parse.y" +{ + yyval.ttype = build_tree_list (yyvsp[-3].ttype, yyvsp[-1].ttype); + ; + break;} +case 551: +#line 2906 "objc-parse.y" +{ + yyval.ttype = chainon (yyvsp[-1].ttype, yyvsp[0].ttype); + ; + break;} +case 552: +#line 2913 "objc-parse.y" +{ + yyval.ttype = build_tree_list (yyvsp[-1].ttype, NULL_TREE); + ; + break;} +case 553: +#line 2917 "objc-parse.y" +{ + yyval.ttype = build_tree_list (NULL_TREE, NULL_TREE); + ; + break;} +case 554: +#line 2924 "objc-parse.y" +{ + yyval.ttype = yyvsp[-1].ttype; + ; + break;} +case 555: +#line 2931 "objc-parse.y" +{ + yyval.ttype = yyvsp[-1].ttype; + ; + break;} +case 556: +#line 2940 "objc-parse.y" +{ + yyval.ttype = groktypename (yyvsp[-1].ttype); + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "/usr/local/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 2945 "objc-parse.y" + diff --git a/gnu/usr.bin/gcc/objc/objc-parse.y b/gnu/usr.bin/gcc/objc/objc-parse.y new file mode 100644 index 00000000000..4dc0bcf95ca --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc-parse.y @@ -0,0 +1,2945 @@ +/*WARNING: This file is automatically generated!*/ +/* YACC parser for C syntax and for Objective C. -*-c-*- + Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file defines the grammar of C and that of Objective C. + ifobjc ... end ifobjc conditionals contain code for Objective C only. + ifc ... end ifc conditionals contain code for C only. + Sed commands in Makefile.in are used to convert this file into + c-parse.y and into objc-parse.y. */ + +/* To whomever it may concern: I have heard that such a thing was once + written by AT&T, but I have never seen it. */ + +%expect 66 + +%{ +#include "config.h" + +#include <stdio.h> +#include <errno.h> +#include <setjmp.h> + +#include "tree.h" +#include "input.h" +#include "c-lex.h" +#include "c-tree.h" +#include "flags.h" + +#ifdef MULTIBYTE_CHARS +#include <stdlib.h> +#include <locale.h> +#endif + +#include "objc-act.h" + +/* Since parsers are distinct for each language, put the language string + definition here. */ +char *language_string = "GNU Obj-C"; + +#ifndef errno +extern int errno; +#endif + +void yyerror (); + +/* Like YYERROR but do call yyerror. */ +#define YYERROR1 { yyerror ("syntax error"); YYERROR; } + +/* Cause the `yydebug' variable to be defined. */ +#define YYDEBUG 1 +%} + +%start program + +%union {long itype; tree ttype; enum tree_code code; + char *filename; int lineno; int ends_in_label; } + +/* All identifiers that are not reserved words + and are not declared typedefs in the current block */ +%token IDENTIFIER + +/* All identifiers that are declared typedefs in the current block. + In some contexts, they are treated just like IDENTIFIER, + but they can also serve as typespecs in declarations. */ +%token TYPENAME + +/* Reserved words that specify storage class. + yylval contains an IDENTIFIER_NODE which indicates which one. */ +%token SCSPEC + +/* Reserved words that specify type. + yylval contains an IDENTIFIER_NODE which indicates which one. */ +%token TYPESPEC + +/* Reserved words that qualify type: "const" or "volatile". + yylval contains an IDENTIFIER_NODE which indicates which one. */ +%token TYPE_QUAL + +/* Character or numeric constants. + yylval is the node for the constant. */ +%token CONSTANT + +/* String constants in raw form. + yylval is a STRING_CST node. */ +%token STRING + +/* "...", used for functions with variable arglists. */ +%token ELLIPSIS + +/* the reserved words */ +/* SCO include files test "ASM", so use something else. */ +%token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT +%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF +%token ATTRIBUTE EXTENSION LABEL +%token REALPART IMAGPART + +/* Add precedence rules to solve dangling else s/r conflict */ +%nonassoc IF +%nonassoc ELSE + +/* Define the operator tokens and their precedences. + The value is an integer because, if used, it is the tree code + to use in the expression made from the operator. */ + +%right <code> ASSIGN '=' +%right <code> '?' ':' +%left <code> OROR +%left <code> ANDAND +%left <code> '|' +%left <code> '^' +%left <code> '&' +%left <code> EQCOMPARE +%left <code> ARITHCOMPARE +%left <code> LSHIFT RSHIFT +%left <code> '+' '-' +%left <code> '*' '/' '%' +%right <code> UNARY PLUSPLUS MINUSMINUS +%left HYPERUNARY +%left <code> POINTSAT '.' '(' '[' + +/* The Objective-C keywords. These are included in C and in + Objective C, so that the token codes are the same in both. */ +%token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE +%token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS + +/* Objective-C string constants in raw form. + yylval is an OBJC_STRING_CST node. */ +%token OBJC_STRING + + +%type <code> unop + +%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist +%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING +%type <ttype> typed_declspecs reserved_declspecs +%type <ttype> typed_typespecs reserved_typespecquals +%type <ttype> declmods typespec typespecqual_reserved +%type <ttype> typed_declspecs_no_prefix_attr reserved_declspecs_no_prefix_attr +%type <ttype> declmods_no_prefix_attr +%type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual +%type <ttype> initdecls notype_initdecls initdcl notype_initdcl +%type <ttype> init maybeasm +%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers +%type <ttype> maybe_attribute attributes attribute attribute_list attrib +%type <ttype> any_word + +%type <ttype> compstmt + +%type <ttype> declarator +%type <ttype> notype_declarator after_type_declarator +%type <ttype> parm_declarator + +%type <ttype> structsp component_decl_list component_decl_list2 +%type <ttype> component_decl components component_declarator +%type <ttype> enumlist enumerator +%type <ttype> typename absdcl absdcl1 type_quals +%type <ttype> xexpr parms parm identifiers + +%type <ttype> parmlist parmlist_1 parmlist_2 +%type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1 +%type <ttype> identifiers_or_typenames + +%type <itype> setspecs + +%type <ends_in_label> lineno_stmt_or_label lineno_stmt_or_labels stmt_or_label + +%type <filename> save_filename +%type <lineno> save_lineno + +/* the Objective-C nonterminals */ + +%type <ttype> ivar_decl_list ivar_decls ivar_decl ivars ivar_declarator +%type <ttype> methoddecl unaryselector keywordselector selector +%type <ttype> keyworddecl receiver objcmessageexpr messageargs +%type <ttype> keywordexpr keywordarglist keywordarg +%type <ttype> myparms myparm optparmlist reservedwords objcselectorexpr +%type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr +%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr + +%type <ttype> CLASSNAME OBJC_STRING OBJECTNAME + +%{ +/* Number of statements (loosely speaking) and compound statements + seen so far. */ +static int stmt_count; +static int compstmt_count; + +/* Input file and line number of the end of the body of last simple_if; + used by the stmt-rule immediately after simple_if returns. */ +static char *if_stmt_file; +static int if_stmt_line; + +/* List of types and structure classes of the current declaration. */ +static tree current_declspecs = NULL_TREE; +static tree prefix_attributes = NULL_TREE; + +/* Stack of saved values of current_declspecs and prefix_attributes. */ +static tree declspec_stack; + +/* 1 if we explained undeclared var errors. */ +static int undeclared_variable_notice; + +/* Objective-C specific information */ + +tree objc_interface_context; +tree objc_implementation_context; +tree objc_method_context; +tree objc_ivar_chain; +tree objc_ivar_context; +enum tree_code objc_inherit_code; +int objc_receiver_context; +int objc_public_flag; + + +/* Tell yyparse how to print a token's value, if yydebug is set. */ + +#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL) +extern void yyprint (); +%} + +%% +program: /* empty */ + { if (pedantic) + pedwarn ("ANSI C forbids an empty source file"); + finish_file (); + } + | extdefs + { + /* In case there were missing closebraces, + get us back to the global binding level. */ + while (! global_bindings_p ()) + poplevel (0, 0, 0); + finish_file (); + } + ; + +/* the reason for the strange actions in this rule + is so that notype_initdecls when reached via datadef + can find a valid list of type and sc specs in $0. */ + +extdefs: + {$<ttype>$ = NULL_TREE; } extdef + | extdefs {$<ttype>$ = NULL_TREE; } extdef + ; + +extdef: + fndef + | datadef + | objcdef + | ASM_KEYWORD '(' expr ')' ';' + { STRIP_NOPS ($3); + if ((TREE_CODE ($3) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND ($3, 0)) == STRING_CST) + || TREE_CODE ($3) == STRING_CST) + assemble_asm ($3); + else + error ("argument of `asm' is not a constant string"); } + | extension extdef + { pedantic = $<itype>1; } + ; + +datadef: + setspecs notype_initdecls ';' + { if (pedantic) + error ("ANSI C forbids data definition with no type or storage class"); + else if (!flag_traditional) + warning ("data definition has no type or storage class"); + + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($1); } + | declmods setspecs notype_initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs setspecs initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods ';' + { pedwarn ("empty declaration"); } + | typed_declspecs ';' + { shadow_tag ($1); } + | error ';' + | error '}' + | ';' + { if (pedantic) + pedwarn ("ANSI C does not allow extra `;' outside of a function"); } + ; + +fndef: + typed_declspecs setspecs declarator + { if (! start_function (current_declspecs, $3, + prefix_attributes, NULL_TREE, 0)) + YYERROR1; + reinit_parse_for_function (); } + old_style_parm_decls + { store_parm_decls (); } + compstmt_or_error + { finish_function (0); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs setspecs declarator error + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_declarator + { if (! start_function (current_declspecs, $3, + prefix_attributes, NULL_TREE, 0)) + YYERROR1; + reinit_parse_for_function (); } + old_style_parm_decls + { store_parm_decls (); } + compstmt_or_error + { finish_function (0); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_declarator error + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | setspecs notype_declarator + { if (! start_function (NULL_TREE, $2, + prefix_attributes, NULL_TREE, 0)) + YYERROR1; + reinit_parse_for_function (); } + old_style_parm_decls + { store_parm_decls (); } + compstmt_or_error + { finish_function (0); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($1); } + | setspecs notype_declarator error + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($1); } + ; + +identifier: + IDENTIFIER + | TYPENAME + | OBJECTNAME + | CLASSNAME + ; + +unop: '&' + { $$ = ADDR_EXPR; } + | '-' + { $$ = NEGATE_EXPR; } + | '+' + { $$ = CONVERT_EXPR; } + | PLUSPLUS + { $$ = PREINCREMENT_EXPR; } + | MINUSMINUS + { $$ = PREDECREMENT_EXPR; } + | '~' + { $$ = BIT_NOT_EXPR; } + | '!' + { $$ = TRUTH_NOT_EXPR; } + ; + +expr: nonnull_exprlist + { $$ = build_compound_expr ($1); } + ; + +exprlist: + /* empty */ + { $$ = NULL_TREE; } + | nonnull_exprlist + ; + +nonnull_exprlist: + expr_no_commas + { $$ = build_tree_list (NULL_TREE, $1); } + | nonnull_exprlist ',' expr_no_commas + { chainon ($1, build_tree_list (NULL_TREE, $3)); } + ; + +unary_expr: + primary + | '*' cast_expr %prec UNARY + { $$ = build_indirect_ref ($2, "unary *"); } + /* __extension__ turns off -pedantic for following primary. */ + | extension cast_expr %prec UNARY + { $$ = $2; + pedantic = $<itype>1; } + | unop cast_expr %prec UNARY + { $$ = build_unary_op ($1, $2, 0); + overflow_warning ($$); } + /* Refer to the address of a label as a pointer. */ + | ANDAND identifier + { tree label = lookup_label ($2); + if (pedantic) + pedwarn ("ANSI C forbids `&&'"); + if (label == 0) + $$ = null_pointer_node; + else + { + TREE_USED (label) = 1; + $$ = build1 (ADDR_EXPR, ptr_type_node, label); + TREE_CONSTANT ($$) = 1; + } + } +/* This seems to be impossible on some machines, so let's turn it off. + You can use __builtin_next_arg to find the anonymous stack args. + | '&' ELLIPSIS + { tree types = TYPE_ARG_TYPES (TREE_TYPE (current_function_decl)); + $$ = error_mark_node; + if (TREE_VALUE (tree_last (types)) == void_type_node) + error ("`&...' used in function with fixed number of arguments"); + else + { + if (pedantic) + pedwarn ("ANSI C forbids `&...'"); + $$ = tree_last (DECL_ARGUMENTS (current_function_decl)); + $$ = build_unary_op (ADDR_EXPR, $$, 0); + } } +*/ + | sizeof unary_expr %prec UNARY + { skip_evaluation--; + if (TREE_CODE ($2) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1))) + error ("`sizeof' applied to a bit-field"); + $$ = c_sizeof (TREE_TYPE ($2)); } + | sizeof '(' typename ')' %prec HYPERUNARY + { skip_evaluation--; + $$ = c_sizeof (groktypename ($3)); } + | alignof unary_expr %prec UNARY + { skip_evaluation--; + $$ = c_alignof_expr ($2); } + | alignof '(' typename ')' %prec HYPERUNARY + { skip_evaluation--; + $$ = c_alignof (groktypename ($3)); } + | REALPART cast_expr %prec UNARY + { $$ = build_unary_op (REALPART_EXPR, $2, 0); } + | IMAGPART cast_expr %prec UNARY + { $$ = build_unary_op (IMAGPART_EXPR, $2, 0); } + ; + +sizeof: + SIZEOF { skip_evaluation++; } + ; + +alignof: + ALIGNOF { skip_evaluation++; } + ; + +cast_expr: + unary_expr + | '(' typename ')' cast_expr %prec UNARY + { tree type = groktypename ($2); + $$ = build_c_cast (type, $4); } + | '(' typename ')' '{' + { start_init (NULL_TREE, NULL, 0); + $2 = groktypename ($2); + really_start_incremental_init ($2); } + initlist_maybe_comma '}' %prec UNARY + { char *name; + tree result = pop_init_level (0); + tree type = $2; + finish_init (); + + if (pedantic) + pedwarn ("ANSI C forbids constructor expressions"); + if (TYPE_NAME (type) != 0) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + name = IDENTIFIER_POINTER (TYPE_NAME (type)); + else + name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); + } + else + name = ""; + $$ = result; + if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) + { + int failure = complete_array_type (type, $$, 1); + if (failure) + abort (); + } + } + ; + +expr_no_commas: + cast_expr + | expr_no_commas '+' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '-' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '*' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '/' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '%' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas LSHIFT expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas RSHIFT expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas ARITHCOMPARE expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas EQCOMPARE expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '&' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '|' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas '^' expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | expr_no_commas ANDAND + { $1 = truthvalue_conversion (default_conversion ($1)); + skip_evaluation += $1 == boolean_false_node; } + expr_no_commas + { skip_evaluation -= $1 == boolean_false_node; + $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); } + | expr_no_commas OROR + { $1 = truthvalue_conversion (default_conversion ($1)); + skip_evaluation += $1 == boolean_true_node; } + expr_no_commas + { skip_evaluation -= $1 == boolean_true_node; + $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); } + | expr_no_commas '?' + { $1 = truthvalue_conversion (default_conversion ($1)); + skip_evaluation += $1 == boolean_false_node; } + expr ':' + { skip_evaluation += (($1 == boolean_true_node) + - ($1 == boolean_false_node)); } + expr_no_commas + { skip_evaluation -= $1 == boolean_true_node; + $$ = build_conditional_expr ($1, $4, $7); } + | expr_no_commas '?' + { if (pedantic) + pedwarn ("ANSI C forbids omitting the middle term of a ?: expression"); + /* Make sure first operand is calculated only once. */ + $<ttype>2 = save_expr ($1); + $1 = truthvalue_conversion (default_conversion ($<ttype>2)); + skip_evaluation += $1 == boolean_true_node; } + ':' expr_no_commas + { skip_evaluation -= $1 == boolean_true_node; + $$ = build_conditional_expr ($1, $<ttype>2, $5); } + | expr_no_commas '=' expr_no_commas + { $$ = build_modify_expr ($1, NOP_EXPR, $3); + C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } + | expr_no_commas ASSIGN expr_no_commas + { $$ = build_modify_expr ($1, $2, $3); + /* This inhibits warnings in truthvalue_conversion. */ + C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); } + ; + +primary: + IDENTIFIER + { + $$ = lastiddecl; + if (!$$ || $$ == error_mark_node) + { + if (yychar == YYEMPTY) + yychar = YYLEX; + if (yychar == '(') + { + tree decl; + + if (objc_receiver_context + && ! (objc_receiver_context + && strcmp (IDENTIFIER_POINTER ($1), "super"))) + /* we have a message to super */ + $$ = get_super_receiver (); + else if (objc_method_context + && (decl = is_ivar (objc_ivar_chain, $1))) + { + if (is_private (decl)) + $$ = error_mark_node; + else + $$ = build_ivar_reference ($1); + } + else + { + /* Ordinary implicit function declaration. */ + $$ = implicitly_declare ($1); + assemble_external ($$); + TREE_USED ($$) = 1; + } + } + else if (current_function_decl == 0) + { + error ("`%s' undeclared here (not in a function)", + IDENTIFIER_POINTER ($1)); + $$ = error_mark_node; + } + else + { + tree decl; + + if (objc_receiver_context + && ! strcmp (IDENTIFIER_POINTER ($1), "super")) + /* we have a message to super */ + $$ = get_super_receiver (); + else if (objc_method_context + && (decl = is_ivar (objc_ivar_chain, $1))) + { + if (is_private (decl)) + $$ = error_mark_node; + else + $$ = build_ivar_reference ($1); + } + else + { + if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node + || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl) + { + error ("`%s' undeclared (first use this function)", + IDENTIFIER_POINTER ($1)); + + if (! undeclared_variable_notice) + { + error ("(Each undeclared identifier is reported only once"); + error ("for each function it appears in.)"); + undeclared_variable_notice = 1; + } + } + $$ = error_mark_node; + /* Prevent repeated error messages. */ + IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node; + IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl; + } + } + } + else if (TREE_TYPE ($$) == error_mark_node) + $$ = error_mark_node; + else if (C_DECL_ANTICIPATED ($$)) + { + /* The first time we see a build-in function used, + if it has not been declared. */ + C_DECL_ANTICIPATED ($$) = 0; + if (yychar == YYEMPTY) + yychar = YYLEX; + if (yychar == '(') + { + /* Omit the implicit declaration we + would ordinarily do, so we don't lose + the actual built in type. + But print a diagnostic for the mismatch. */ + if (objc_method_context + && is_ivar (objc_ivar_chain, $1)) + error ("Instance variable `%s' implicitly declared as function", + IDENTIFIER_POINTER (DECL_NAME ($$))); + else + if (TREE_CODE ($$) != FUNCTION_DECL) + error ("`%s' implicitly declared as function", + IDENTIFIER_POINTER (DECL_NAME ($$))); + else if ((TYPE_MODE (TREE_TYPE (TREE_TYPE ($$))) + != TYPE_MODE (integer_type_node)) + && (TREE_TYPE (TREE_TYPE ($$)) + != void_type_node)) + pedwarn ("type mismatch in implicit declaration for built-in function `%s'", + IDENTIFIER_POINTER (DECL_NAME ($$))); + /* If it really returns void, change that to int. */ + if (TREE_TYPE (TREE_TYPE ($$)) == void_type_node) + TREE_TYPE ($$) + = build_function_type (integer_type_node, + TYPE_ARG_TYPES (TREE_TYPE ($$))); + } + else + pedwarn ("built-in function `%s' used without declaration", + IDENTIFIER_POINTER (DECL_NAME ($$))); + + /* Do what we would ordinarily do when a fn is used. */ + assemble_external ($$); + TREE_USED ($$) = 1; + } + else + { + assemble_external ($$); + TREE_USED ($$) = 1; + /* we have a definition - still check if iVariable */ + + if (!objc_receiver_context + || (objc_receiver_context + && strcmp (IDENTIFIER_POINTER ($1), "super"))) + { + tree decl; + + if (objc_method_context + && (decl = is_ivar (objc_ivar_chain, $1))) + { + if (IDENTIFIER_LOCAL_VALUE ($1)) + warning ("local declaration of `%s' hides instance variable", + IDENTIFIER_POINTER ($1)); + else + { + if (is_private (decl)) + $$ = error_mark_node; + else + $$ = build_ivar_reference ($1); + } + } + } + else /* we have a message to super */ + $$ = get_super_receiver (); + } + + if (TREE_CODE ($$) == CONST_DECL) + { + $$ = DECL_INITIAL ($$); + /* This is to prevent an enum whose value is 0 + from being considered a null pointer constant. */ + $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$); + TREE_CONSTANT ($$) = 1; + } + } + | CONSTANT + | string + { $$ = combine_strings ($1); } + | '(' expr ')' + { char class = TREE_CODE_CLASS (TREE_CODE ($2)); + if (class == 'e' || class == '1' + || class == '2' || class == '<') + C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK); + $$ = $2; } + | '(' error ')' + { $$ = error_mark_node; } + | '(' + { if (current_function_decl == 0) + { + error ("braced-group within expression allowed only inside a function"); + YYERROR; + } + /* We must force a BLOCK for this level + so that, if it is not expanded later, + there is a way to turn off the entire subtree of blocks + that are contained in it. */ + keep_next_level (); + push_iterator_stack (); + push_label_level (); + $<ttype>$ = expand_start_stmt_expr (); } + compstmt ')' + { tree rtl_exp; + if (pedantic) + pedwarn ("ANSI C forbids braced-groups within expressions"); + pop_iterator_stack (); + pop_label_level (); + rtl_exp = expand_end_stmt_expr ($<ttype>2); + /* The statements have side effects, so the group does. */ + TREE_SIDE_EFFECTS (rtl_exp) = 1; + + if (TREE_CODE ($3) == BLOCK) + { + /* Make a BIND_EXPR for the BLOCK already made. */ + $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), + NULL_TREE, rtl_exp, $3); + /* Remove the block from the tree at this point. + It gets put back at the proper place + when the BIND_EXPR is expanded. */ + delete_block ($3); + } + else + $$ = $3; + } + | primary '(' exprlist ')' %prec '.' + { $$ = build_function_call ($1, $3); } + | primary '[' expr ']' %prec '.' + { $$ = build_array_ref ($1, $3); } + | primary '.' identifier + { + if (doing_objc_thang) + { + if (is_public ($1, $3)) + $$ = build_component_ref ($1, $3); + else + $$ = error_mark_node; + } + else + $$ = build_component_ref ($1, $3); + } + | primary POINTSAT identifier + { + tree expr = build_indirect_ref ($1, "->"); + + if (doing_objc_thang) + { + if (is_public (expr, $3)) + $$ = build_component_ref (expr, $3); + else + $$ = error_mark_node; + } + else + $$ = build_component_ref (expr, $3); + } + | primary PLUSPLUS + { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } + | primary MINUSMINUS + { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); } + | objcmessageexpr + { $$ = build_message_expr ($1); } + | objcselectorexpr + { $$ = build_selector_expr ($1); } + | objcprotocolexpr + { $$ = build_protocol_expr ($1); } + | objcencodeexpr + { $$ = build_encode_expr ($1); } + | objc_string + { $$ = build_objc_string_object ($1); } + ; + +/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */ +string: + STRING + | string STRING + { $$ = chainon ($1, $2); } + ; + +/* Produces an OBJC_STRING_CST with perhaps more OBJC_STRING_CSTs chained + onto it. */ +objc_string: + OBJC_STRING + | objc_string OBJC_STRING + { $$ = chainon ($1, $2); } + ; + +old_style_parm_decls: + /* empty */ + | datadecls + | datadecls ELLIPSIS + /* ... is used here to indicate a varargs function. */ + { c_mark_varargs (); + if (pedantic) + pedwarn ("ANSI C does not permit use of `varargs.h'"); } + ; + +/* The following are analogous to lineno_decl, decls and decl + except that they do not allow nested functions. + They are used for old-style parm decls. */ +lineno_datadecl: + save_filename save_lineno datadecl + { } + ; + +datadecls: + lineno_datadecl + | errstmt + | datadecls lineno_datadecl + | lineno_datadecl errstmt + ; + +/* We don't allow prefix attributes here because they cause reduce/reduce + conflicts: we can't know whether we're parsing a function decl with + attribute suffix, or function defn with attribute prefix on first old + style parm. */ +datadecl: + typed_declspecs_no_prefix_attr setspecs initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods_no_prefix_attr setspecs notype_initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs_no_prefix_attr ';' + { shadow_tag_warned ($1, 1); + pedwarn ("empty declaration"); } + | declmods_no_prefix_attr ';' + { pedwarn ("empty declaration"); } + ; + +/* This combination which saves a lineno before a decl + is the normal thing to use, rather than decl itself. + This is to avoid shift/reduce conflicts in contexts + where statement labels are allowed. */ +lineno_decl: + save_filename save_lineno decl + { } + ; + +decls: + lineno_decl + | errstmt + | decls lineno_decl + | lineno_decl errstmt + ; + +/* records the type and storage class specs to use for processing + the declarators that follow. + Maintains a stack of outer-level values of current_declspecs, + for the sake of parm declarations nested in function declarators. */ +setspecs: /* empty */ + { $$ = suspend_momentary (); + pending_xref_error (); + declspec_stack = tree_cons (prefix_attributes, + current_declspecs, + declspec_stack); + split_specs_attrs ($<ttype>0, + ¤t_declspecs, &prefix_attributes); } + ; + +/* ??? Yuck. See after_type_declarator. */ +setattrs: /* empty */ + { prefix_attributes = chainon (prefix_attributes, $<ttype>0); } + ; + +decl: + typed_declspecs setspecs initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs setspecs nested_function + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_nested_function + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs ';' + { shadow_tag ($1); } + | declmods ';' + { pedwarn ("empty declaration"); } + | extension decl + { pedantic = $<itype>1; } + ; + +/* Declspecs which contain at least one type specifier or typedef name. + (Just `const' or `volatile' is not enough.) + A typedef'd name following these is taken as a name to be declared. + Declspecs have a non-NULL TREE_VALUE, attributes do not. */ + +typed_declspecs: + typespec reserved_declspecs + { $$ = tree_cons (NULL_TREE, $1, $2); } + | declmods typespec reserved_declspecs + { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } + ; + +reserved_declspecs: /* empty */ + { $$ = NULL_TREE; } + | reserved_declspecs typespecqual_reserved + { $$ = tree_cons (NULL_TREE, $2, $1); } + | reserved_declspecs SCSPEC + { if (extra_warnings) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER ($2)); + $$ = tree_cons (NULL_TREE, $2, $1); } + | reserved_declspecs attributes + { $$ = tree_cons ($2, NULL_TREE, $1); } + ; + +typed_declspecs_no_prefix_attr: + typespec reserved_declspecs_no_prefix_attr + { $$ = tree_cons (NULL_TREE, $1, $2); } + | declmods_no_prefix_attr typespec reserved_declspecs_no_prefix_attr + { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } + ; + +reserved_declspecs_no_prefix_attr: + /* empty */ + { $$ = NULL_TREE; } + | reserved_declspecs_no_prefix_attr typespecqual_reserved + { $$ = tree_cons (NULL_TREE, $2, $1); } + | reserved_declspecs_no_prefix_attr SCSPEC + { if (extra_warnings) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER ($2)); + $$ = tree_cons (NULL_TREE, $2, $1); } + ; + +/* List of just storage classes, type modifiers, and prefix attributes. + A declaration can start with just this, but then it cannot be used + to redeclare a typedef-name. + Declspecs have a non-NULL TREE_VALUE, attributes do not. */ + +declmods: + declmods_no_prefix_attr + { $$ = $1; } + | attributes + { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); } + | declmods declmods_no_prefix_attr + { $$ = chainon ($2, $1); } + | declmods attributes + { $$ = tree_cons ($2, NULL_TREE, $1); } + ; + +declmods_no_prefix_attr: + TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); + TREE_STATIC ($$) = 1; } + | SCSPEC + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } + | declmods_no_prefix_attr TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $2, $1); + TREE_STATIC ($$) = 1; } + | declmods_no_prefix_attr SCSPEC + { if (extra_warnings && TREE_STATIC ($1)) + warning ("`%s' is not at beginning of declaration", + IDENTIFIER_POINTER ($2)); + $$ = tree_cons (NULL_TREE, $2, $1); + TREE_STATIC ($$) = TREE_STATIC ($1); } + ; + + +/* Used instead of declspecs where storage classes are not allowed + (that is, for typenames and structure components). + Don't accept a typedef-name if anything but a modifier precedes it. */ + +typed_typespecs: + typespec reserved_typespecquals + { $$ = tree_cons (NULL_TREE, $1, $2); } + | nonempty_type_quals typespec reserved_typespecquals + { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); } + ; + +reserved_typespecquals: /* empty */ + { $$ = NULL_TREE; } + | reserved_typespecquals typespecqual_reserved + { $$ = tree_cons (NULL_TREE, $2, $1); } + ; + +/* A typespec (but not a type qualifier). + Once we have seen one of these in a declaration, + if a typedef name appears then it is being redeclared. */ + +typespec: TYPESPEC + | structsp + | TYPENAME + { /* For a typedef name, record the meaning, not the name. + In case of `foo foo, bar;'. */ + $$ = lookup_name ($1); } + | CLASSNAME protocolrefs + { $$ = get_static_reference ($1, $2); } + | OBJECTNAME protocolrefs + { $$ = get_object_reference ($2); } + +/* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" + - nisse@lysator.liu.se */ + | non_empty_protocolrefs + { $$ = get_object_reference ($1); } + | TYPEOF '(' expr ')' + { $$ = TREE_TYPE ($3); } + | TYPEOF '(' typename ')' + { $$ = groktypename ($3); } + ; + +/* A typespec that is a reserved word, or a type qualifier. */ + +typespecqual_reserved: TYPESPEC + | TYPE_QUAL + | structsp + ; + +initdecls: + initdcl + | initdecls ',' initdcl + ; + +notype_initdecls: + notype_initdcl + | notype_initdecls ',' initdcl + ; + +maybeasm: + /* empty */ + { $$ = NULL_TREE; } + | ASM_KEYWORD '(' string ')' + { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); + $$ = $3; + } + ; + +initdcl: + declarator maybeasm maybe_attribute '=' + { $<ttype>$ = start_decl ($1, current_declspecs, 1, + $3, prefix_attributes); + start_init ($<ttype>$, $2, global_bindings_p ()); } + init +/* Note how the declaration of the variable is in effect while its init is parsed! */ + { finish_init (); + finish_decl ($<ttype>5, $6, $2); } + | declarator maybeasm maybe_attribute + { tree d = start_decl ($1, current_declspecs, 0, + $3, prefix_attributes); + finish_decl (d, NULL_TREE, $2); + } + ; + +notype_initdcl: + notype_declarator maybeasm maybe_attribute '=' + { $<ttype>$ = start_decl ($1, current_declspecs, 1, + $3, prefix_attributes); + start_init ($<ttype>$, $2, global_bindings_p ()); } + init +/* Note how the declaration of the variable is in effect while its init is parsed! */ + { finish_init (); + decl_attributes ($<ttype>5, $3, prefix_attributes); + finish_decl ($<ttype>5, $6, $2); } + | notype_declarator maybeasm maybe_attribute + { tree d = start_decl ($1, current_declspecs, 0, + $3, prefix_attributes); + finish_decl (d, NULL_TREE, $2); } + ; +/* the * rules are dummies to accept the Apollo extended syntax + so that the header files compile. */ +maybe_attribute: + /* empty */ + { $$ = NULL_TREE; } + | attributes + { $$ = $1; } + ; + +attributes: + attribute + { $$ = $1; } + | attributes attribute + { $$ = chainon ($1, $2); } + ; + +attribute: + ATTRIBUTE '(' '(' attribute_list ')' ')' + { $$ = $4; } + ; + +attribute_list: + attrib + { $$ = $1; } + | attribute_list ',' attrib + { $$ = chainon ($1, $3); } + ; + +attrib: + /* empty */ + { $$ = NULL_TREE; } + | any_word + { $$ = build_tree_list ($1, NULL_TREE); } + | any_word '(' IDENTIFIER ')' + { $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); } + | any_word '(' IDENTIFIER ',' nonnull_exprlist ')' + { $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); } + | any_word '(' exprlist ')' + { $$ = build_tree_list ($1, $3); } + ; + +/* This still leaves out most reserved keywords, + shouldn't we include them? */ + +any_word: + identifier + | SCSPEC + | TYPESPEC + | TYPE_QUAL + ; + +/* Initializers. `init' is the entry point. */ + +init: + expr_no_commas + | '{' + { really_start_incremental_init (NULL_TREE); + /* Note that the call to clear_momentary + is in process_init_element. */ + push_momentary (); } + initlist_maybe_comma '}' + { $$ = pop_init_level (0); + if ($$ == error_mark_node + && ! (yychar == STRING || yychar == CONSTANT)) + pop_momentary (); + else + pop_momentary_nofree (); } + + | error + { $$ = error_mark_node; } + ; + +/* `initlist_maybe_comma' is the guts of an initializer in braces. */ +initlist_maybe_comma: + /* empty */ + { if (pedantic) + pedwarn ("ANSI C forbids empty initializer braces"); } + | initlist1 maybecomma + ; + +initlist1: + initelt + | initlist1 ',' initelt + ; + +/* `initelt' is a single element of an initializer. + It may use braces. */ +initelt: + expr_no_commas + { process_init_element ($1); } + | '{' + { push_init_level (0); } + initlist_maybe_comma '}' + { process_init_element (pop_init_level (0)); } + | error + /* These are for labeled elements. The syntax for an array element + initializer conflicts with the syntax for an Objective-C message, + so don't include these productions in the Objective-C grammar. */ + | identifier ':' + { set_init_label ($1); } + initelt + | '.' identifier '=' + { set_init_label ($2); } + initelt + ; + +nested_function: + declarator + { push_c_function_context (); + if (! start_function (current_declspecs, $1, + prefix_attributes, NULL_TREE, 1)) + { + pop_c_function_context (); + YYERROR1; + } + reinit_parse_for_function (); } + old_style_parm_decls + { store_parm_decls (); } +/* This used to use compstmt_or_error. + That caused a bug with input `f(g) int g {}', + where the use of YYERROR1 above caused an error + which then was handled by compstmt_or_error. + There followed a repeated execution of that same rule, + which called YYERROR1 again, and so on. */ + compstmt + { finish_function (1); + pop_c_function_context (); } + ; + +notype_nested_function: + notype_declarator + { push_c_function_context (); + if (! start_function (current_declspecs, $1, + prefix_attributes, NULL_TREE, 1)) + { + pop_c_function_context (); + YYERROR1; + } + reinit_parse_for_function (); } + old_style_parm_decls + { store_parm_decls (); } +/* This used to use compstmt_or_error. + That caused a bug with input `f(g) int g {}', + where the use of YYERROR1 above caused an error + which then was handled by compstmt_or_error. + There followed a repeated execution of that same rule, + which called YYERROR1 again, and so on. */ + compstmt + { finish_function (1); + pop_c_function_context (); } + ; + +/* Any kind of declarator (thus, all declarators allowed + after an explicit typespec). */ + +declarator: + after_type_declarator + | notype_declarator + ; + +/* A declarator that is allowed only after an explicit typespec. */ + +after_type_declarator: + '(' after_type_declarator ')' + { $$ = $2; } + | after_type_declarator '(' parmlist_or_identifiers %prec '.' + { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); } +/* | after_type_declarator '(' error ')' %prec '.' + { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE); + poplevel (0, 0, 0); } */ + | after_type_declarator '[' expr ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, $3); } + | after_type_declarator '[' ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } + | '*' type_quals after_type_declarator %prec UNARY + { $$ = make_pointer_declarator ($2, $3); } + /* ??? Yuck. setattrs is a quick hack. We can't use + prefix_attributes because $1 only applies to this + declarator. We assume setspecs has already been done. + setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple + attributes could be recognized here or in `attributes'). */ + | attributes setattrs after_type_declarator + { $$ = $3; } + | TYPENAME + | OBJECTNAME + ; + +/* Kinds of declarator that can appear in a parameter list + in addition to notype_declarator. This is like after_type_declarator + but does not allow a typedef name in parentheses as an identifier + (because it would conflict with a function with that typedef as arg). */ + +parm_declarator: + parm_declarator '(' parmlist_or_identifiers %prec '.' + { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); } +/* | parm_declarator '(' error ')' %prec '.' + { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE); + poplevel (0, 0, 0); } */ + | parm_declarator '[' expr ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, $3); } + | parm_declarator '[' ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } + | '*' type_quals parm_declarator %prec UNARY + { $$ = make_pointer_declarator ($2, $3); } + /* ??? Yuck. setattrs is a quick hack. We can't use + prefix_attributes because $1 only applies to this + declarator. We assume setspecs has already been done. + setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple + attributes could be recognized here or in `attributes'). */ + | attributes setattrs parm_declarator + { $$ = $3; } + | TYPENAME + ; + +/* A declarator allowed whether or not there has been + an explicit typespec. These cannot redeclare a typedef-name. */ + +notype_declarator: + notype_declarator '(' parmlist_or_identifiers %prec '.' + { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); } +/* | notype_declarator '(' error ')' %prec '.' + { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE); + poplevel (0, 0, 0); } */ + | '(' notype_declarator ')' + { $$ = $2; } + | '*' type_quals notype_declarator %prec UNARY + { $$ = make_pointer_declarator ($2, $3); } + | notype_declarator '[' expr ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, $3); } + | notype_declarator '[' ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } + /* ??? Yuck. setattrs is a quick hack. We can't use + prefix_attributes because $1 only applies to this + declarator. We assume setspecs has already been done. + setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple + attributes could be recognized here or in `attributes'). */ + | attributes setattrs notype_declarator + { $$ = $3; } + | IDENTIFIER + ; + +structsp: + STRUCT identifier '{' + { $$ = start_struct (RECORD_TYPE, $2); + /* Start scope of tag before parsing components. */ + } + component_decl_list '}' maybe_attribute + { $$ = finish_struct ($<ttype>4, $5, $7); } + | STRUCT '{' component_decl_list '}' maybe_attribute + { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), + $3, $5); + } + | STRUCT identifier + { $$ = xref_tag (RECORD_TYPE, $2); } + | UNION identifier '{' + { $$ = start_struct (UNION_TYPE, $2); } + component_decl_list '}' maybe_attribute + { $$ = finish_struct ($<ttype>4, $5, $7); } + | UNION '{' component_decl_list '}' maybe_attribute + { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE), + $3, $5); + } + | UNION identifier + { $$ = xref_tag (UNION_TYPE, $2); } + | ENUM identifier '{' + { $<itype>3 = suspend_momentary (); + $$ = start_enum ($2); } + enumlist maybecomma_warn '}' maybe_attribute + { $$ = finish_enum ($<ttype>4, nreverse ($5), $8); + resume_momentary ($<itype>3); } + | ENUM '{' + { $<itype>2 = suspend_momentary (); + $$ = start_enum (NULL_TREE); } + enumlist maybecomma_warn '}' maybe_attribute + { $$ = finish_enum ($<ttype>3, nreverse ($4), $7); + resume_momentary ($<itype>2); } + | ENUM identifier + { $$ = xref_tag (ENUMERAL_TYPE, $2); } + ; + +maybecomma: + /* empty */ + | ',' + ; + +maybecomma_warn: + /* empty */ + | ',' + { if (pedantic) pedwarn ("comma at end of enumerator list"); } + ; + +component_decl_list: + component_decl_list2 + { $$ = $1; } + | component_decl_list2 component_decl + { $$ = chainon ($1, $2); + pedwarn ("no semicolon at end of struct or union"); } + ; + +component_decl_list2: /* empty */ + { $$ = NULL_TREE; } + | component_decl_list2 component_decl ';' + { $$ = chainon ($1, $2); } + | component_decl_list2 ';' + { if (pedantic) + pedwarn ("extra semicolon in struct or union specified"); } + /* foo(sizeof(struct{ @defs(ClassName)})); */ + | DEFS '(' CLASSNAME ')' + { + tree interface = lookup_interface ($3); + + if (interface) + $$ = get_class_ivars (interface); + else + { + error ("Cannot find interface declaration for `%s'", + IDENTIFIER_POINTER ($3)); + $$ = NULL_TREE; + } + } + ; + +/* There is a shift-reduce conflict here, because `components' may + start with a `typename'. It happens that shifting (the default resolution) + does the right thing, because it treats the `typename' as part of + a `typed_typespecs'. + + It is possible that this same technique would allow the distinction + between `notype_initdecls' and `initdecls' to be eliminated. + But I am being cautious and not trying it. */ + +component_decl: + typed_typespecs setspecs components + { $$ = $3; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_typespecs + { if (pedantic) + pedwarn ("ANSI C forbids member declarations with no members"); + shadow_tag($1); + $$ = NULL_TREE; } + | nonempty_type_quals setspecs components + { $$ = $3; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | nonempty_type_quals + { if (pedantic) + pedwarn ("ANSI C forbids member declarations with no members"); + shadow_tag($1); + $$ = NULL_TREE; } + | error + { $$ = NULL_TREE; } + | extension component_decl + { $$ = $2; + pedantic = $<itype>1; } + ; + +components: + component_declarator + | components ',' component_declarator + { $$ = chainon ($1, $3); } + ; + +component_declarator: + save_filename save_lineno declarator maybe_attribute + { $$ = grokfield ($1, $2, $3, current_declspecs, NULL_TREE); + decl_attributes ($$, $4, prefix_attributes); } + | save_filename save_lineno + declarator ':' expr_no_commas maybe_attribute + { $$ = grokfield ($1, $2, $3, current_declspecs, $5); + decl_attributes ($$, $6, prefix_attributes); } + | save_filename save_lineno ':' expr_no_commas maybe_attribute + { $$ = grokfield ($1, $2, NULL_TREE, current_declspecs, $4); + decl_attributes ($$, $5, prefix_attributes); } + ; + +/* We chain the enumerators in reverse order. + They are put in forward order where enumlist is used. + (The order used to be significant, but no longer is so. + However, we still maintain the order, just to be clean.) */ + +enumlist: + enumerator + | enumlist ',' enumerator + { if ($1 == error_mark_node) + $$ = $1; + else + $$ = chainon ($3, $1); } + | error + { $$ = error_mark_node; } + ; + + +enumerator: + identifier + { $$ = build_enumerator ($1, NULL_TREE); } + | identifier '=' expr_no_commas + { $$ = build_enumerator ($1, $3); } + ; + +typename: + typed_typespecs absdcl + { $$ = build_tree_list ($1, $2); } + | nonempty_type_quals absdcl + { $$ = build_tree_list ($1, $2); } + ; + +absdcl: /* an absolute declarator */ + /* empty */ + { $$ = NULL_TREE; } + | absdcl1 + ; + +nonempty_type_quals: + TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } + | nonempty_type_quals TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $2, $1); } + ; + +type_quals: + /* empty */ + { $$ = NULL_TREE; } + | type_quals TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $2, $1); } + ; + +absdcl1: /* a nonempty absolute declarator */ + '(' absdcl1 ')' + { $$ = $2; } + /* `(typedef)1' is `int'. */ + | '*' type_quals absdcl1 %prec UNARY + { $$ = make_pointer_declarator ($2, $3); } + | '*' type_quals %prec UNARY + { $$ = make_pointer_declarator ($2, NULL_TREE); } + | absdcl1 '(' parmlist %prec '.' + { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); } + | absdcl1 '[' expr ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, $3); } + | absdcl1 '[' ']' %prec '.' + { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); } + | '(' parmlist %prec '.' + { $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); } + | '[' expr ']' %prec '.' + { $$ = build_nt (ARRAY_REF, NULL_TREE, $2); } + | '[' ']' %prec '.' + { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); } + /* ??? It appears we have to support attributes here, however + using prefix_attributes is wrong. */ + ; + +/* at least one statement, the first of which parses without error. */ +/* stmts is used only after decls, so an invalid first statement + is actually regarded as an invalid decl and part of the decls. */ + +stmts: + lineno_stmt_or_labels + { + if (pedantic && $1) + pedwarn ("ANSI C forbids label at end of compound statement"); + } + ; + +lineno_stmt_or_labels: + lineno_stmt_or_label + | lineno_stmt_or_labels lineno_stmt_or_label + { $$ = $2; } + | lineno_stmt_or_labels errstmt + { $$ = 0; } + ; + +xstmts: + /* empty */ + | stmts + ; + +errstmt: error ';' + ; + +pushlevel: /* empty */ + { emit_line_note (input_filename, lineno); + pushlevel (0); + clear_last_expr (); + push_momentary (); + expand_start_bindings (0); + if (objc_method_context) + add_objc_decls (); + } + ; + +/* Read zero or more forward-declarations for labels + that nested functions can jump to. */ +maybe_label_decls: + /* empty */ + | label_decls + { if (pedantic) + pedwarn ("ANSI C forbids label declarations"); } + ; + +label_decls: + label_decl + | label_decls label_decl + ; + +label_decl: + LABEL identifiers_or_typenames ';' + { tree link; + for (link = $2; link; link = TREE_CHAIN (link)) + { + tree label = shadow_label (TREE_VALUE (link)); + C_DECLARED_LABEL_FLAG (label) = 1; + declare_nonlocal_label (label); + } + } + ; + +/* This is the body of a function definition. + It causes syntax errors to ignore to the next openbrace. */ +compstmt_or_error: + compstmt + {} + | error compstmt + ; + +compstmt_start: '{' { compstmt_count++; } + +compstmt: compstmt_start '}' + { $$ = convert (void_type_node, integer_zero_node); } + | compstmt_start pushlevel maybe_label_decls decls xstmts '}' + { emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), 1, 0); + $$ = poplevel (1, 1, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); } + | compstmt_start pushlevel maybe_label_decls error '}' + { emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), kept_level_p (), 0); + $$ = poplevel (kept_level_p (), 0, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); } + | compstmt_start pushlevel maybe_label_decls stmts '}' + { emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), kept_level_p (), 0); + $$ = poplevel (kept_level_p (), 0, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); } + ; + +/* Value is number of statements counted as of the closeparen. */ +simple_if: + if_prefix lineno_labeled_stmt +/* Make sure c_expand_end_cond is run once + for each call to c_expand_start_cond. + Otherwise a crash is likely. */ + | if_prefix error + ; + +if_prefix: + IF '(' expr ')' + { emit_line_note ($<filename>-1, $<lineno>0); + c_expand_start_cond (truthvalue_conversion ($3), 0, + compstmt_count); + $<itype>$ = stmt_count; + if_stmt_file = $<filename>-1; + if_stmt_line = $<lineno>0; + position_after_white_space (); } + ; + +/* This is a subroutine of stmt. + It is used twice, once for valid DO statements + and once for catching errors in parsing the end test. */ +do_stmt_start: + DO + { stmt_count++; + compstmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + /* See comment in `while' alternative, above. */ + emit_nop (); + expand_start_loop_continue_elsewhere (1); + position_after_white_space (); } + lineno_labeled_stmt WHILE + { expand_loop_continue_here (); } + ; + +save_filename: + { $$ = input_filename; } + ; + +save_lineno: + { $$ = lineno; } + ; + +lineno_labeled_stmt: + save_filename save_lineno stmt + { } +/* | save_filename save_lineno error + { } +*/ + | save_filename save_lineno label lineno_labeled_stmt + { } + ; + +lineno_stmt_or_label: + save_filename save_lineno stmt_or_label + { $$ = $3; } + ; + +stmt_or_label: + stmt + { $$ = 0; } + | label + { $$ = 1; } + ; + +/* Parse a single real statement, not including any labels. */ +stmt: + compstmt + { stmt_count++; } + | all_iter_stmt + | expr ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); +/* It appears that this should not be done--that a non-lvalue array + shouldn't get an error if the value isn't used. + Section 3.2.2.1 says that an array lvalue gets converted to a pointer + if it appears as a top-level expression, + but says nothing about non-lvalue arrays. */ +#if 0 + /* Call default_conversion to get an error + on referring to a register array if pedantic. */ + if (TREE_CODE (TREE_TYPE ($1)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE) + $1 = default_conversion ($1); +#endif + iterator_expand ($1); + clear_momentary (); } + | simple_if ELSE + { c_expand_start_else (); + $<itype>1 = stmt_count; + position_after_white_space (); } + lineno_labeled_stmt + { c_expand_end_cond (); + if (extra_warnings && stmt_count == $<itype>1) + warning ("empty body in an else-statement"); } + | simple_if %prec IF + { c_expand_end_cond (); + /* This warning is here instead of in simple_if, because we + do not want a warning if an empty if is followed by an + else statement. Increment stmt_count so we don't + give a second error if this is a nested `if'. */ + if (extra_warnings && stmt_count++ == $<itype>1) + warning_with_file_and_line (if_stmt_file, if_stmt_line, + "empty body in an if-statement"); } +/* Make sure c_expand_end_cond is run once + for each call to c_expand_start_cond. + Otherwise a crash is likely. */ + | simple_if ELSE error + { c_expand_end_cond (); } + | WHILE + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + /* The emit_nop used to come before emit_line_note, + but that made the nop seem like part of the preceding line. + And that was confusing when the preceding line was + inside of an if statement and was not really executed. + I think it ought to work to put the nop after the line number. + We will see. --rms, July 15, 1991. */ + emit_nop (); } + '(' expr ')' + { /* Don't start the loop till we have succeeded + in parsing the end test. This is to make sure + that we end every loop we start. */ + expand_start_loop (1); + emit_line_note (input_filename, lineno); + expand_exit_loop_if_false (NULL_PTR, + truthvalue_conversion ($4)); + position_after_white_space (); } + lineno_labeled_stmt + { expand_end_loop (); } + | do_stmt_start + '(' expr ')' ';' + { emit_line_note (input_filename, lineno); + expand_exit_loop_if_false (NULL_PTR, + truthvalue_conversion ($3)); + expand_end_loop (); + clear_momentary (); } +/* This rule is needed to make sure we end every loop we start. */ + | do_stmt_start error + { expand_end_loop (); + clear_momentary (); } + | FOR + '(' xexpr ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + /* See comment in `while' alternative, above. */ + emit_nop (); + if ($3) c_expand_expr_stmt ($3); + /* Next step is to call expand_start_loop_continue_elsewhere, + but wait till after we parse the entire for (...). + Otherwise, invalid input might cause us to call that + fn without calling expand_end_loop. */ + } + xexpr ';' + /* Can't emit now; wait till after expand_start_loop... */ + { $<lineno>7 = lineno; + $<filename>$ = input_filename; } + xexpr ')' + { + /* Start the loop. Doing this after parsing + all the expressions ensures we will end the loop. */ + expand_start_loop_continue_elsewhere (1); + /* Emit the end-test, with a line number. */ + emit_line_note ($<filename>8, $<lineno>7); + if ($6) + expand_exit_loop_if_false (NULL_PTR, + truthvalue_conversion ($6)); + /* Don't let the tree nodes for $9 be discarded by + clear_momentary during the parsing of the next stmt. */ + push_momentary (); + $<lineno>7 = lineno; + $<filename>8 = input_filename; + position_after_white_space (); } + lineno_labeled_stmt + { /* Emit the increment expression, with a line number. */ + emit_line_note ($<filename>8, $<lineno>7); + expand_loop_continue_here (); + if ($9) + c_expand_expr_stmt ($9); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); + expand_end_loop (); } + | SWITCH '(' expr ')' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + c_expand_start_case ($3); + /* Don't let the tree nodes for $3 be discarded by + clear_momentary during the parsing of the next stmt. */ + push_momentary (); + position_after_white_space (); } + lineno_labeled_stmt + { expand_end_case ($3); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); } + | BREAK ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + if ( ! expand_exit_something ()) + error ("break statement not within loop or switch"); } + | CONTINUE ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + if (! expand_continue_loop (NULL_PTR)) + error ("continue statement not within a loop"); } + | RETURN ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + c_expand_return (NULL_TREE); } + | RETURN expr ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + c_expand_return ($2); } + | ASM_KEYWORD maybe_type_qual '(' expr ')' ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + STRIP_NOPS ($4); + if ((TREE_CODE ($4) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND ($4, 0)) == STRING_CST) + || TREE_CODE ($4) == STRING_CST) + expand_asm ($4); + else + error ("argument of `asm' is not a constant string"); } + /* This is the case with just output operands. */ + | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE, + $2 == ridpointers[(int)RID_VOLATILE], + input_filename, lineno); } + /* This is the case with input operands as well. */ + | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' asm_operands ')' ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + c_expand_asm_operands ($4, $6, $8, NULL_TREE, + $2 == ridpointers[(int)RID_VOLATILE], + input_filename, lineno); } + /* This is the case with clobbered registers as well. */ + | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' + asm_operands ':' asm_clobbers ')' ';' + { stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + c_expand_asm_operands ($4, $6, $8, $10, + $2 == ridpointers[(int)RID_VOLATILE], + input_filename, lineno); } + | GOTO identifier ';' + { tree decl; + stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + decl = lookup_label ($2); + if (decl != 0) + { + TREE_USED (decl) = 1; + expand_goto (decl); + } + } + | GOTO '*' expr ';' + { if (pedantic) + pedwarn ("ANSI C forbids `goto *expr;'"); + stmt_count++; + emit_line_note ($<filename>-1, $<lineno>0); + expand_computed_goto (convert (ptr_type_node, $3)); } + | ';' + ; + +all_iter_stmt: + all_iter_stmt_simple +/* | all_iter_stmt_with_decl */ + ; + +all_iter_stmt_simple: + FOR '(' primary ')' + { + /* The value returned by this action is */ + /* 1 if everything is OK */ + /* 0 in case of error or already bound iterator */ + + $<itype>$ = 0; + if (TREE_CODE ($3) != VAR_DECL) + error ("invalid `for (ITERATOR)' syntax"); + else if (! ITERATOR_P ($3)) + error ("`%s' is not an iterator", + IDENTIFIER_POINTER (DECL_NAME ($3))); + else if (ITERATOR_BOUND_P ($3)) + error ("`for (%s)' inside expansion of same iterator", + IDENTIFIER_POINTER (DECL_NAME ($3))); + else + { + $<itype>$ = 1; + iterator_for_loop_start ($3); + } + } + lineno_labeled_stmt + { + if ($<itype>5) + iterator_for_loop_end ($3); + } + +/* This really should allow any kind of declaration, + for generality. Fix it before turning it back on. + +all_iter_stmt_with_decl: + FOR '(' ITERATOR pushlevel setspecs iterator_spec ')' + { +*/ /* The value returned by this action is */ + /* 1 if everything is OK */ + /* 0 in case of error or already bound iterator */ +/* + iterator_for_loop_start ($6); + } + lineno_labeled_stmt + { + iterator_for_loop_end ($6); + emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), 1, 0); + $<ttype>$ = poplevel (1, 1, 0); + if (yychar == CONSTANT || yychar == STRING) + pop_momentary_nofree (); + else + pop_momentary (); + } +*/ + +/* Any kind of label, including jump labels and case labels. + ANSI C accepts labels only before statements, but we allow them + also at the end of a compound statement. */ + +label: CASE expr_no_commas ':' + { register tree value = check_case_value ($2); + register tree label + = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + stmt_count++; + + if (value != error_mark_node) + { + tree duplicate; + int success = pushcase (value, convert_and_check, + label, &duplicate); + if (success == 1) + error ("case label not within a switch statement"); + else if (success == 2) + { + error ("duplicate case value"); + error_with_decl (duplicate, "this is the first entry for that value"); + } + else if (success == 3) + warning ("case value out of range"); + else if (success == 5) + error ("case label within scope of cleanup or variable array"); + } + position_after_white_space (); } + | CASE expr_no_commas ELLIPSIS expr_no_commas ':' + { register tree value1 = check_case_value ($2); + register tree value2 = check_case_value ($4); + register tree label + = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + + if (pedantic) + pedwarn ("ANSI C forbids case ranges"); + stmt_count++; + + if (value1 != error_mark_node && value2 != error_mark_node) + { + tree duplicate; + int success = pushcase_range (value1, value2, + convert_and_check, label, + &duplicate); + if (success == 1) + error ("case label not within a switch statement"); + else if (success == 2) + { + error ("duplicate case value"); + error_with_decl (duplicate, "this is the first entry for that value"); + } + else if (success == 3) + warning ("case value out of range"); + else if (success == 4) + warning ("empty case range"); + else if (success == 5) + error ("case label within scope of cleanup or variable array"); + } + position_after_white_space (); } + | DEFAULT ':' + { + tree duplicate; + register tree label + = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + int success = pushcase (NULL_TREE, 0, label, &duplicate); + stmt_count++; + if (success == 1) + error ("default label not within a switch statement"); + else if (success == 2) + { + error ("multiple default labels in one switch"); + error_with_decl (duplicate, "this is the first default label"); + } + position_after_white_space (); } + | identifier ':' + { tree label = define_label (input_filename, lineno, $1); + stmt_count++; + emit_nop (); + if (label) + expand_label (label); + position_after_white_space (); } + ; + +/* Either a type-qualifier or nothing. First thing in an `asm' statement. */ + +maybe_type_qual: + /* empty */ + { emit_line_note (input_filename, lineno); + $$ = NULL_TREE; } + | TYPE_QUAL + { emit_line_note (input_filename, lineno); } + ; + +xexpr: + /* empty */ + { $$ = NULL_TREE; } + | expr + ; + +/* These are the operands other than the first string and colon + in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */ +asm_operands: /* empty */ + { $$ = NULL_TREE; } + | nonnull_asm_operands + ; + +nonnull_asm_operands: + asm_operand + | nonnull_asm_operands ',' asm_operand + { $$ = chainon ($1, $3); } + ; + +asm_operand: + STRING '(' expr ')' + { $$ = build_tree_list ($1, $3); } + ; + +asm_clobbers: + string + { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE); } + | asm_clobbers ',' string + { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); } + ; + +/* This is what appears inside the parens in a function declarator. + Its value is a list of ..._TYPE nodes. */ +parmlist: + { pushlevel (0); + clear_parm_order (); + declare_parm_level (0); } + parmlist_1 + { $$ = $2; + parmlist_tags_warning (); + poplevel (0, 0, 0); } + ; + +parmlist_1: + parmlist_2 ')' + | parms ';' + { tree parm; + if (pedantic) + pedwarn ("ANSI C forbids forward parameter declarations"); + /* Mark the forward decls as such. */ + for (parm = getdecls (); parm; parm = TREE_CHAIN (parm)) + TREE_ASM_WRITTEN (parm) = 1; + clear_parm_order (); } + parmlist_1 + { $$ = $4; } + | error ')' + { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); } + ; + +/* This is what appears inside the parens in a function declarator. + Is value is represented in the format that grokdeclarator expects. */ +parmlist_2: /* empty */ + { $$ = get_parm_info (0); } + | ELLIPSIS + { $$ = get_parm_info (0); + /* Gcc used to allow this as an extension. However, it does + not work for all targets, and thus has been disabled. + Also, since func (...) and func () are indistinguishable, + it caused problems with the code in expand_builtin which + tries to verify that BUILT_IN_NEXT_ARG is being used + correctly. */ + error ("ANSI C requires a named argument before `...'"); + } + | parms + { $$ = get_parm_info (1); } + | parms ',' ELLIPSIS + { $$ = get_parm_info (0); } + ; + +parms: + parm + { push_parm_decl ($1); } + | parms ',' parm + { push_parm_decl ($3); } + ; + +/* A single parameter declaration or parameter type name, + as found in a parmlist. */ +parm: + typed_declspecs setspecs parm_declarator maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $3), + build_tree_list (prefix_attributes, + $4)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs setspecs notype_declarator maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $3), + build_tree_list (prefix_attributes, + $4)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs setspecs absdcl maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $3), + build_tree_list (prefix_attributes, + $4)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_declarator maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $3), + build_tree_list (prefix_attributes, + $4)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + + | declmods setspecs absdcl maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $3), + build_tree_list (prefix_attributes, + $4)); + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + ; + +/* This is used in a function definition + where either a parmlist or an identifier list is ok. + Its value is a list of ..._TYPE nodes or a list of identifiers. */ +parmlist_or_identifiers: + { pushlevel (0); + clear_parm_order (); + declare_parm_level (1); } + parmlist_or_identifiers_1 + { $$ = $2; + parmlist_tags_warning (); + poplevel (0, 0, 0); } + ; + +parmlist_or_identifiers_1: + parmlist_1 + | identifiers ')' + { tree t; + for (t = $1; t; t = TREE_CHAIN (t)) + if (TREE_VALUE (t) == NULL_TREE) + error ("`...' in old-style identifier list"); + $$ = tree_cons (NULL_TREE, NULL_TREE, $1); } + ; + +/* A nonempty list of identifiers. */ +identifiers: + IDENTIFIER + { $$ = build_tree_list (NULL_TREE, $1); } + | identifiers ',' IDENTIFIER + { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } + ; + +/* A nonempty list of identifiers, including typenames. */ +identifiers_or_typenames: + identifier + { $$ = build_tree_list (NULL_TREE, $1); } + | identifiers_or_typenames ',' identifier + { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } + ; + +extension: + EXTENSION + { $<itype>$ = pedantic; + pedantic = 0; } + ; + +/* Objective-C productions. */ + +objcdef: + classdef + | classdecl + | aliasdecl + | protocoldef + | methoddef + | END + { + if (objc_implementation_context) + { + finish_class (objc_implementation_context); + objc_ivar_chain = NULL_TREE; + objc_implementation_context = NULL_TREE; + } + else + warning ("`@end' must appear in an implementation context"); + } + ; + +/* A nonempty list of identifiers. */ +identifier_list: + identifier + { $$ = build_tree_list (NULL_TREE, $1); } + | identifier_list ',' identifier + { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } + ; + +classdecl: + CLASS identifier_list ';' + { + objc_declare_class ($2); + } + +aliasdecl: + ALIAS identifier identifier ';' + { + objc_declare_alias ($2, $3); + } + +classdef: + INTERFACE identifier protocolrefs '{' + { + objc_interface_context = objc_ivar_context + = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3); + objc_public_flag = 0; + } + ivar_decl_list '}' + { + continue_class (objc_interface_context); + } + methodprotolist + END + { + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + } + + | INTERFACE identifier protocolrefs + { + objc_interface_context + = start_class (CLASS_INTERFACE_TYPE, $2, NULL_TREE, $3); + continue_class (objc_interface_context); + } + methodprotolist + END + { + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + } + + | INTERFACE identifier ':' identifier protocolrefs '{' + { + objc_interface_context = objc_ivar_context + = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5); + objc_public_flag = 0; + } + ivar_decl_list '}' + { + continue_class (objc_interface_context); + } + methodprotolist + END + { + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + } + + | INTERFACE identifier ':' identifier protocolrefs + { + objc_interface_context + = start_class (CLASS_INTERFACE_TYPE, $2, $4, $5); + continue_class (objc_interface_context); + } + methodprotolist + END + { + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + } + + | IMPLEMENTATION identifier '{' + { + objc_implementation_context = objc_ivar_context + = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE); + objc_public_flag = 0; + } + ivar_decl_list '}' + { + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | IMPLEMENTATION identifier + { + objc_implementation_context + = start_class (CLASS_IMPLEMENTATION_TYPE, $2, NULL_TREE, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | IMPLEMENTATION identifier ':' identifier '{' + { + objc_implementation_context = objc_ivar_context + = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE); + objc_public_flag = 0; + } + ivar_decl_list '}' + { + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | IMPLEMENTATION identifier ':' identifier + { + objc_implementation_context + = start_class (CLASS_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | INTERFACE identifier '(' identifier ')' protocolrefs + { + objc_interface_context + = start_class (CATEGORY_INTERFACE_TYPE, $2, $4, $6); + continue_class (objc_interface_context); + } + methodprotolist + END + { + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + } + + | IMPLEMENTATION identifier '(' identifier ')' + { + objc_implementation_context + = start_class (CATEGORY_IMPLEMENTATION_TYPE, $2, $4, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + } + ; + +protocoldef: + PROTOCOL identifier protocolrefs + { + remember_protocol_qualifiers (); + objc_interface_context + = start_protocol(PROTOCOL_INTERFACE_TYPE, $2, $3); + } + methodprotolist END + { + forget_protocol_qualifiers(); + finish_protocol(objc_interface_context); + objc_interface_context = NULL_TREE; + } + ; + +protocolrefs: + /* empty */ + { + $$ = NULL_TREE; + } + | non_empty_protocolrefs + ; + +non_empty_protocolrefs: + ARITHCOMPARE identifier_list ARITHCOMPARE + { + if ($1 == LT_EXPR && $3 == GT_EXPR) + $$ = $2; + else + YYERROR1; + } + ; + +ivar_decl_list: + ivar_decl_list visibility_spec ivar_decls + | ivar_decls + ; + +visibility_spec: + PRIVATE { objc_public_flag = 2; } + | PROTECTED { objc_public_flag = 0; } + | PUBLIC { objc_public_flag = 1; } + ; + +ivar_decls: + /* empty */ + { + $$ = NULL_TREE; + } + | ivar_decls ivar_decl ';' + | ivar_decls ';' + { + if (pedantic) + pedwarn ("extra semicolon in struct or union specified"); + } + ; + + +/* There is a shift-reduce conflict here, because `components' may + start with a `typename'. It happens that shifting (the default resolution) + does the right thing, because it treats the `typename' as part of + a `typed_typespecs'. + + It is possible that this same technique would allow the distinction + between `notype_initdecls' and `initdecls' to be eliminated. + But I am being cautious and not trying it. */ + +ivar_decl: + typed_typespecs setspecs ivars + { $$ = $3; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | nonempty_type_quals setspecs ivars + { $$ = $3; + current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | error + { $$ = NULL_TREE; } + ; + +ivars: + /* empty */ + { $$ = NULL_TREE; } + | ivar_declarator + | ivars ',' ivar_declarator + ; + +ivar_declarator: + declarator + { + $$ = add_instance_variable (objc_ivar_context, + objc_public_flag, + $1, current_declspecs, + NULL_TREE); + } + | declarator ':' expr_no_commas + { + $$ = add_instance_variable (objc_ivar_context, + objc_public_flag, + $1, current_declspecs, $3); + } + | ':' expr_no_commas + { + $$ = add_instance_variable (objc_ivar_context, + objc_public_flag, + NULL_TREE, + current_declspecs, $2); + } + ; + +methoddef: + '+' + { + remember_protocol_qualifiers (); + if (objc_implementation_context) + objc_inherit_code = CLASS_METHOD_DECL; + else + fatal ("method definition not in class context"); + } + methoddecl + { + forget_protocol_qualifiers (); + add_class_method (objc_implementation_context, $3); + start_method_def ($3); + objc_method_context = $3; + } + optarglist + { + continue_method_def (); + } + compstmt_or_error + { + finish_method_def (); + objc_method_context = NULL_TREE; + } + + | '-' + { + remember_protocol_qualifiers (); + if (objc_implementation_context) + objc_inherit_code = INSTANCE_METHOD_DECL; + else + fatal ("method definition not in class context"); + } + methoddecl + { + forget_protocol_qualifiers (); + add_instance_method (objc_implementation_context, $3); + start_method_def ($3); + objc_method_context = $3; + } + optarglist + { + continue_method_def (); + } + compstmt_or_error + { + finish_method_def (); + objc_method_context = NULL_TREE; + } + ; + +/* the reason for the strange actions in this rule + is so that notype_initdecls when reached via datadef + can find a valid list of type and sc specs in $0. */ + +methodprotolist: + /* empty */ + | {$<ttype>$ = NULL_TREE; } methodprotolist2 + ; + +methodprotolist2: /* eliminates a shift/reduce conflict */ + methodproto + | datadef + | methodprotolist2 methodproto + | methodprotolist2 {$<ttype>$ = NULL_TREE; } datadef + ; + +semi_or_error: + ';' + | error + ; + +methodproto: + '+' + { + objc_inherit_code = CLASS_METHOD_DECL; + } + methoddecl + { + add_class_method (objc_interface_context, $3); + } + semi_or_error + + | '-' + { + objc_inherit_code = INSTANCE_METHOD_DECL; + } + methoddecl + { + add_instance_method (objc_interface_context, $3); + } + semi_or_error + ; + +methoddecl: + '(' typename ')' unaryselector + { + $$ = build_method_decl (objc_inherit_code, $2, $4, NULL_TREE); + } + + | unaryselector + { + $$ = build_method_decl (objc_inherit_code, NULL_TREE, $1, NULL_TREE); + } + + | '(' typename ')' keywordselector optparmlist + { + $$ = build_method_decl (objc_inherit_code, $2, $4, $5); + } + + | keywordselector optparmlist + { + $$ = build_method_decl (objc_inherit_code, NULL_TREE, $1, $2); + } + ; + +/* "optarglist" assumes that start_method_def has already been called... + if it is not, the "xdecls" will not be placed in the proper scope */ + +optarglist: + /* empty */ + | ';' myxdecls + ; + +/* to get around the following situation: "int foo (int a) int b; {}" that + is synthesized when parsing "- a:a b:b; id c; id d; { ... }" */ + +myxdecls: + /* empty */ + | mydecls + ; + +mydecls: + mydecl + | errstmt + | mydecls mydecl + | mydecl errstmt + ; + +mydecl: + typed_declspecs setspecs myparms ';' + { current_declspecs = TREE_VALUE (declspec_stack); + prefix_attributes = TREE_PURPOSE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs ';' + { shadow_tag ($1); } + | declmods ';' + { pedwarn ("empty declaration"); } + ; + +myparms: + myparm + { push_parm_decl ($1); } + | myparms ',' myparm + { push_parm_decl ($3); } + ; + +/* A single parameter declaration or parameter type name, + as found in a parmlist. DOES NOT ALLOW AN INITIALIZER OR ASMSPEC */ + +myparm: + parm_declarator maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $1), + build_tree_list (prefix_attributes, + $2)); } + | notype_declarator maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $1), + build_tree_list (prefix_attributes, + $2)); } + | absdcl maybe_attribute + { $$ = build_tree_list (build_tree_list (current_declspecs, + $1), + build_tree_list (prefix_attributes, + $2)); } + ; + +optparmlist: + /* empty */ + { + $$ = NULL_TREE; + } + | ',' ELLIPSIS + { + /* oh what a kludge! */ + $$ = (tree)1; + } + | ',' + { + pushlevel (0); + } + parmlist_2 + { + /* returns a tree list node generated by get_parm_info */ + $$ = $3; + poplevel (0, 0, 0); + } + ; + +unaryselector: + selector + ; + +keywordselector: + keyworddecl + + | keywordselector keyworddecl + { + $$ = chainon ($1, $2); + } + ; + +selector: + IDENTIFIER + | TYPENAME + | OBJECTNAME + | reservedwords + ; + +reservedwords: + ENUM { $$ = get_identifier (token_buffer); } + | STRUCT { $$ = get_identifier (token_buffer); } + | UNION { $$ = get_identifier (token_buffer); } + | IF { $$ = get_identifier (token_buffer); } + | ELSE { $$ = get_identifier (token_buffer); } + | WHILE { $$ = get_identifier (token_buffer); } + | DO { $$ = get_identifier (token_buffer); } + | FOR { $$ = get_identifier (token_buffer); } + | SWITCH { $$ = get_identifier (token_buffer); } + | CASE { $$ = get_identifier (token_buffer); } + | DEFAULT { $$ = get_identifier (token_buffer); } + | BREAK { $$ = get_identifier (token_buffer); } + | CONTINUE { $$ = get_identifier (token_buffer); } + | RETURN { $$ = get_identifier (token_buffer); } + | GOTO { $$ = get_identifier (token_buffer); } + | ASM_KEYWORD { $$ = get_identifier (token_buffer); } + | SIZEOF { $$ = get_identifier (token_buffer); } + | TYPEOF { $$ = get_identifier (token_buffer); } + | ALIGNOF { $$ = get_identifier (token_buffer); } + | TYPESPEC | TYPE_QUAL + ; + +keyworddecl: + selector ':' '(' typename ')' identifier + { + $$ = build_keyword_decl ($1, $4, $6); + } + + | selector ':' identifier + { + $$ = build_keyword_decl ($1, NULL_TREE, $3); + } + + | ':' '(' typename ')' identifier + { + $$ = build_keyword_decl (NULL_TREE, $3, $5); + } + + | ':' identifier + { + $$ = build_keyword_decl (NULL_TREE, NULL_TREE, $2); + } + ; + +messageargs: + selector + | keywordarglist + ; + +keywordarglist: + keywordarg + | keywordarglist keywordarg + { + $$ = chainon ($1, $2); + } + ; + + +keywordexpr: + nonnull_exprlist + { + if (TREE_CHAIN ($1) == NULL_TREE) + /* just return the expr., remove a level of indirection */ + $$ = TREE_VALUE ($1); + else + /* we have a comma expr., we will collapse later */ + $$ = $1; + } + ; + +keywordarg: + selector ':' keywordexpr + { + $$ = build_tree_list ($1, $3); + } + | ':' keywordexpr + { + $$ = build_tree_list (NULL_TREE, $2); + } + ; + +receiver: + expr + | CLASSNAME + { + $$ = get_class_reference ($1); + } + ; + +objcmessageexpr: + '[' + { objc_receiver_context = 1; } + receiver + { objc_receiver_context = 0; } + messageargs ']' + { + $$ = build_tree_list ($3, $5); + } + ; + +selectorarg: + selector + | keywordnamelist + ; + +keywordnamelist: + keywordname + | keywordnamelist keywordname + { + $$ = chainon ($1, $2); + } + ; + +keywordname: + selector ':' + { + $$ = build_tree_list ($1, NULL_TREE); + } + | ':' + { + $$ = build_tree_list (NULL_TREE, NULL_TREE); + } + ; + +objcselectorexpr: + SELECTOR '(' selectorarg ')' + { + $$ = $3; + } + ; + +objcprotocolexpr: + PROTOCOL '(' identifier ')' + { + $$ = $3; + } + ; + +/* extension to support C-structures in the archiver */ + +objcencodeexpr: + ENCODE '(' typename ')' + { + $$ = groktypename ($3); + } + ; + +%% diff --git a/gnu/usr.bin/gcc/objc/objc-tree.def b/gnu/usr.bin/gcc/objc/objc-tree.def new file mode 100644 index 00000000000..03f0c715776 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc-tree.def @@ -0,0 +1,37 @@ +/* This file contains the definitions and documentation for the + additional tree codes used in the Objective C front end (see tree.def + for the standard codes). + Copyright (C) 1990 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* Objective-C types. */ +DEFTREECODE (CLASS_INTERFACE_TYPE, "class_interface_type", "t", 0) +DEFTREECODE (CLASS_IMPLEMENTATION_TYPE, "class_implementation_type", "t", 0) +DEFTREECODE (CATEGORY_INTERFACE_TYPE, "category_interface_type", "t", 0) +DEFTREECODE (CATEGORY_IMPLEMENTATION_TYPE,"category_implementation_type","t",0) +DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", "t", 0) + +/* Objective-C decls. */ +DEFTREECODE (KEYWORD_DECL, "keyword_decl", "d", 0) +DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", "d", 0) +DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", "d", 0) + +/* Objective-C constants. */ +DEFTREECODE (OBJC_STRING_CST, "objc_string_cst", "c", 3) diff --git a/gnu/usr.bin/gcc/objc/objc.gperf b/gnu/usr.bin/gcc/objc/objc.gperf new file mode 100644 index 00000000000..407459f1589 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/objc.gperf @@ -0,0 +1,64 @@ +%{ +/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ objc.gperf */ +%} +struct resword { char *name; short token; enum rid rid; }; +%% +@defs, DEFS, NORID +@encode, ENCODE, NORID +@end, END, NORID +@implementation, IMPLEMENTATION, NORID +@interface, INTERFACE, NORID +@public, PUBLIC, NORID +@selector, SELECTOR, NORID +__alignof, ALIGNOF, NORID +__alignof__, ALIGNOF, NORID +__asm, ASM, NORID +__asm__, ASM, NORID +__attribute, ATTRIBUTE, NORID +__attribute__, ATTRIBUTE, NORID +__const, TYPE_QUAL, RID_CONST +__const__, TYPE_QUAL, RID_CONST +__extension__, EXTENSION, NORID +__inline, SCSPEC, RID_INLINE +__inline__, SCSPEC, RID_INLINE +__signed, TYPESPEC, RID_SIGNED +__signed__, TYPESPEC, RID_SIGNED +__typeof, TYPEOF, NORID +__typeof__, TYPEOF, NORID +__volatile, TYPE_QUAL, RID_VOLATILE +__volatile__, TYPE_QUAL, RID_VOLATILE +asm, ASM, NORID +auto, SCSPEC, RID_AUTO +break, BREAK, NORID +case, CASE, NORID +char, TYPESPEC, RID_CHAR +const, TYPE_QUAL, RID_CONST +continue, CONTINUE, NORID +default, DEFAULT, NORID +do, DO, NORID +double, TYPESPEC, RID_DOUBLE +else, ELSE, NORID +enum, ENUM, NORID +extern, SCSPEC, RID_EXTERN +float, TYPESPEC, RID_FLOAT +for, FOR, NORID +goto, GOTO, NORID +if, IF, NORID +inline, SCSPEC, RID_INLINE +int, TYPESPEC, RID_INT +long, TYPESPEC, RID_LONG +register, SCSPEC, RID_REGISTER +return, RETURN, NORID +short, TYPESPEC, RID_SHORT +signed, TYPESPEC, RID_SIGNED +sizeof, SIZEOF, NORID +static, SCSPEC, RID_STATIC +struct, STRUCT, NORID +switch, SWITCH, NORID +typedef, SCSPEC, RID_TYPEDEF +typeof, TYPEOF, NORID +union, UNION, NORID +unsigned, TYPESPEC, RID_UNSIGNED +void, TYPESPEC, RID_VOID +volatile, TYPE_QUAL, RID_VOLATILE +while, WHILE, NORID diff --git a/gnu/usr.bin/gcc/objc/thr-decosf1.c b/gnu/usr.bin/gcc/objc/thr-decosf1.c new file mode 100644 index 00000000000..0f7063b7e83 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-decosf1.c @@ -0,0 +1,281 @@ +/* GNU Objective C Runtime Thread Interface + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.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. */ + +/* 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. */ + +#include <pthread.h> +#include <objc/thr.h> +#include "runtime.h" + +/* Key structure for maintaining thread specific storage */ +static pthread_key_t _objc_thread_storage; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* Initialize the thread storage key */ + return pthread_keycreate(&_objc_thread_storage, NULL); +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + /* Destroy the thread storage key */ + /* Not implemented yet */ + /* return pthread_key_delete(&_objc_thread_storage); */ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + objc_thread_t thread_id; + pthread_t new_thread_handle; + + if (pthread_create(&new_thread_handle, pthread_attr_default, + (void *)func, arg) == 0) + { + /* ??? May not work! (64bit) */ + thread_id = *(objc_thread_t *)&new_thread_handle; + pthread_detach(&new_thread_handle); /* Fully detach thread. */ + } + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + int sys_priority = 0; + + switch (priority) + { + case OBJC_THREAD_INTERACTIVE_PRIORITY: + sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2; + break; + default: + case OBJC_THREAD_BACKGROUND_PRIORITY: + sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; + break; + case OBJC_THREAD_LOW_PRIORITY: + sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; + break; + } + + /* Change the priority. */ + if (pthread_setprio(pthread_self(), sys_priority) >= 0) + return 0; + else + /* Failed */ + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + int sys_priority; + + if ((sys_priority = pthread_getprio(pthread_self())) >= 0) { + if (sys_priority >= PRI_FG_MIN_NP && sys_priority <= PRI_FG_MAX_NP) + return OBJC_THREAD_INTERACTIVE_PRIORITY; + if (sys_priority >= PRI_BG_MIN_NP && sys_priority <= PRI_BG_MAX_NP) + return OBJC_THREAD_BACKGROUND_PRIORITY; + return OBJC_THREAD_LOW_PRIORITY; + } + + /* Failed */ + return -1; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + pthread_yield(); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* exit the thread */ + pthread_exit(&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + pthread_t self = pthread_self(); + + return (objc_thread_t) pthread_getunique_np (&self); +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + return pthread_setspecific(_objc_thread_storage, value); +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + void *value = NULL; + + if ( !(pthread_getspecific(_objc_thread_storage, &value)) ) + return value; + + return NULL; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + if (pthread_mutex_init((pthread_mutex_t *)(&(mutex->backend)), + pthread_mutexattr_default)) + return -1; + else + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + if (pthread_mutex_destroy((pthread_mutex_t *)(&(mutex->backend)))) + return -1; + else + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + return pthread_mutex_lock((pthread_mutex_t *)(&(mutex->backend))); +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + if (pthread_mutex_trylock((pthread_mutex_t *)(&(mutex->backend))) != 1) + return -1; + else + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + return pthread_mutex_unlock((pthread_mutex_t *)(&(mutex->backend))); +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; + + /* + if (pthread_cond_init((pthread_cond_t *)(&(condition->backend)), NULL)) + return -1; + else + return 0; + */ +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; + + /* + return pthread_cond_destroy((pthread_cond_t *)(&(condition->backend))); + */ +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + /* Unimplemented. */ + return -1; + + /* + return pthread_cond_wait((pthread_cond_t *)(&(condition->backend)), + (pthread_mutex_t *)(&(mutex->backend))); + */ +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; + + /* + return pthread_cond_broadcast((pthread_cond_t *)(&(condition->backend))); + */ +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; + + /* + return pthread_cond_signal((pthread_cond_t *)(&(condition->backend))); + */ +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-irix.c b/gnu/usr.bin/gcc/objc/thr-irix.c new file mode 100644 index 00000000000..528a3e3a434 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-irix.c @@ -0,0 +1,235 @@ +/* GNU Objective C Runtime Thread Interface - SGI IRIX Implementation + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.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. */ + +/* 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. */ + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/sysmp.h> +#include <sys/prctl.h> +#include <ulocks.h> +#include <objc/thr.h> +#include "runtime.h" + +/* Key structure for maintaining thread specific storage */ +static void * __objc_shared_arena_handle = NULL; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* Name of IRIX arena. */ + char arena_name[64]; + + DEBUG_PRINTF("__objc_init_thread_system\n"); + + /* Construct a temporary name for arena. */ + sprintf(arena_name, "/usr/tmp/objc_%05u", (unsigned)getpid()); + + /* Up to 256 threads. Arena only for threads. */ + usconfig(CONF_INITUSERS, 256); + usconfig(CONF_ARENATYPE, US_SHAREDONLY); + + /* Initialize the arena */ + if (!(__objc_shared_arena_handle = usinit(arena_name))) + /* Failed */ + return -1; + + return 0; +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + objc_thread_t thread_id; + int sys_id; + + if ((sys_id = sproc((void *)func, PR_SALL, arg)) >= 0) + thread_id = (objc_thread_t)sys_id; + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + /* Not implemented yet */ + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + /* Not implemented yet */ + return OBJC_THREAD_INTERACTIVE_PRIORITY; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + sginap(0); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* IRIX only has exit. */ + exit(__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + /* Threads are processes. */ + return (objc_thread_t)get_pid(); +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + *((void **)&PRDA->usr_prda) = value; + return 0; +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + return *((void **)&PRDA->usr_prda); +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + if (!( (ulock_t)(mutex->backend) = usnewlock(__objc_shared_arena_handle) )) + return -1; + else + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + usfreelock((ulock_t)(mutex->backend), __objc_shared_arena_handle); + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + if (ussetlock((ulock_t)(mutex->backend)) == 0) + return -1; + else + return 0; +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + if (ustestlock((ulock_t)(mutex->backend)) == 0) + return -1; + else + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + usunsetlock((ulock_t)(mutex->backend)); + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + /* Unimplemented. */ + return -1; +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-mach.c b/gnu/usr.bin/gcc/objc/thr-mach.c new file mode 100644 index 00000000000..44af0c1e286 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-mach.c @@ -0,0 +1,312 @@ +/* GNU Objective C Runtime Thread Implementation + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.edu) + Modified for Mach threads by Bill Bumgarner <bbum@friday.com> + Condition functions added by Mircea Oancea <mircea@first.elcom.pub.ro> + +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. */ + +#include <mach/mach.h> +#include <mach/cthreads.h> +#include <objc/thr.h> +#include "runtime.h" + +/* + Obtain the maximum thread priority that can set for t. Under the + mach threading model, it is possible for the developer to adjust the + maximum priority downward only-- cannot be raised without superuser + privileges. Once lowered, it cannot be raised. + */ +static int __mach_get_max_thread_priority(cthread_t t, int *base) +{ + thread_t threadP; + kern_return_t error; + struct thread_sched_info info; + unsigned int info_count=THREAD_SCHED_INFO_COUNT; + + if (t == NULL) + return -1; + + threadP = cthread_thread(t); /* get thread underlying */ + + error=thread_info(threadP, THREAD_SCHED_INFO, + (thread_info_t)&info, &info_count); + + if (error != KERN_SUCCESS) + return -1; + + if (base != NULL) + *base = info.base_priority; + + return info.max_priority; +} + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + return 0; +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + objc_thread_t thread_id; + cthread_t new_thread_handle; + + /* create thread */ + new_thread_handle = cthread_fork((cthread_fn_t)func, arg); + + if(new_thread_handle) + { + /* this is not terribly portable */ + thread_id = *(objc_thread_t *)&new_thread_handle; + cthread_detach(new_thread_handle); + } + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + objc_thread_t *t = objc_thread_id(); + cthread_t cT = (cthread_t) t; + int maxPriority = __mach_get_max_thread_priority(cT, NULL); + int sys_priority = 0; + + if (maxPriority == -1) + return -1; + + switch (priority) + { + case OBJC_THREAD_INTERACTIVE_PRIORITY: + sys_priority = maxPriority; + break; + case OBJC_THREAD_BACKGROUND_PRIORITY: + sys_priority = (maxPriority * 2) / 3; + break; + case OBJC_THREAD_LOW_PRIORITY: + sys_priority = maxPriority / 3; + break; + default: + return -1; + } + + if (sys_priority == 0) + return -1; + + /* Change the priority */ + if (cthread_priority(cT, sys_priority, 0) == KERN_SUCCESS) + return 0; + else + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + objc_thread_t *t = objc_thread_id(); + cthread_t cT = (cthread_t) t; /* see objc_thread_id() */ + int basePriority; + int maxPriority; + int sys_priority = 0; + + int interactiveT, backgroundT, lowT; /* thresholds */ + + maxPriority = __mach_get_max_thread_priority(cT, &basePriority); + + if(maxPriority == -1) + return -1; + + if (basePriority > ( (maxPriority * 2) / 3)) + return OBJC_THREAD_INTERACTIVE_PRIORITY; + + if (basePriority > ( maxPriority / 3)) + return OBJC_THREAD_BACKGROUND_PRIORITY; + + return OBJC_THREAD_LOW_PRIORITY; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + cthread_yield(); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* exit the thread */ + cthread_exit(&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + cthread_t self = cthread_self(); + + return *(objc_thread_t *)&self; +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + cthread_set_data(cthread_self(), (any_t) value); + return 0; +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + return (void *) cthread_data(cthread_self()); +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + int err = 0; + mutex->backend = objc_malloc(sizeof(struct mutex)); + + err = mutex_init((mutex_t)(mutex->backend)); + + if (err != 0) + { + objc_free(mutex->backend); + return -1; + } + else + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + mutex_clear((mutex_t)(mutex->backend)); + + objc_free(mutex->backend); + mutex->backend = NULL; + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + mutex_lock((mutex_t)(mutex->backend)); + return 0; +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + if (mutex_try_lock((mutex_t)(mutex->backend)) == 0) + return -1; + else + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + mutex_unlock((mutex_t)(mutex->backend)); + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + condition->backend = objc_malloc(sizeof(struct condition)); + condition_init((condition_t)(condition->backend)); + return 0; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + condition_clear((condition_t)(condition->backend)); + objc_free(condition->backend); + condition->backend = NULL; + return 0; +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + condition_wait((condition_t)(condition->backend), + (mutex_t)(mutex->backend)); + return 0; +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + condition_broadcast((condition_t)(condition->backend)); + return 0; +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + condition_signal((condition_t)(condition->backend)); + return 0; +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-os2.c b/gnu/usr.bin/gcc/objc/thr-os2.c new file mode 100644 index 00000000000..a0d7d436613 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-os2.c @@ -0,0 +1,267 @@ +/* GNU Objective C Runtime Thread Interface - OS/2 emx Implementation + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Thomas Baier (baier@ci.tuwien.ac.at) + +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. */ + +#include <objc/thr.h> +#include "runtime.h" + +#define INCL_DOSSEMAPHORES +#define INCL_DOSPROCESS + +/* + * conflicts with objc.h: SEL, BOOL, id + * solution: prefixing those with _OS2_ before including <os2.h> + */ +#define SEL _OS2_SEL +#define BOOL _OS2_BOOL +#define id _OS2_id +#include <os2.h> +#undef id +#undef SEL +#undef BOOL + +#include <stdlib.h> + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + return 0; +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + int thread_id = 0; + + if ((thread_id = _beginthread (func,NULL,32768,arg)) < 0) + thread_id = 0; + + return (objc_thread_t)thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + ULONG sys_class = 0; + ULONG sys_priority = 0; + + /* OBJC_THREAD_INTERACTIVE_PRIORITY -> PRTYC_FOREGROUNDSERVER + * OBJC_THREAD_BACKGROUND_PRIORITY -> PRTYC_REGULAR + * OBJC_THREAD_LOW_PRIORITY -> PRTYC_IDLETIME */ + + switch (priority) { + case OBJC_THREAD_INTERACTIVE_PRIORITY: + sys_class = PRTYC_REGULAR; + sys_priority = 10; + break; + default: + case OBJC_THREAD_BACKGROUND_PRIORITY: + sys_class = PRTYC_IDLETIME; + sys_priority = 25; + break; + case OBJC_THREAD_LOW_PRIORITY: + sys_class = PRTYC_IDLETIME; + sys_priority = 0; + break; + } + + /* Change priority */ + if (!DosSetPriority (PRTYS_THREAD,sys_class,sys_priority,*_threadid)) + return 0; + else + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + PTIB ptib; + PPIB ppib; + + /* get information about current thread */ + DosGetInfoBlocks (&ptib,&ppib); + + switch (ptib->tib_ptib2->tib2_ulpri) + { + case PRTYC_IDLETIME: + case PRTYC_REGULAR: + case PRTYC_TIMECRITICAL: + case PRTYC_FOREGROUNDSERVER: + default: + return OBJC_THREAD_INTERACTIVE_PRIORITY; + } + + return -1; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + DosSleep (0); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* terminate the thread, NEVER use DosExit () */ + _endthread (); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + return (objc_thread_t) *_threadid; +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + *_threadstore () = value; + + return 0; +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + return *_threadstore (); +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + if (DosCreateMutexSem (NULL, (HMTX)(&(mutex->backend)),0L,0) > 0) + return -1; + else + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + DosCloseMutexSem ((HMTX)(mutex->backend)); + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + if (DosRequestMutexSem ((HMTX)(mutex->backend),-1L) != 0) + return -1; + else + return 0; +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + if (DosRequestMutexSem ((HMTX)(mutex->backend),0L) != 0) + return -1; + else + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + if (DosReleaseMutexSem((HMTX)(mutex->backend)) != 0) + return -1; + else + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + /* Unimplemented. */ + return -1; +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-posix.c b/gnu/usr.bin/gcc/objc/thr-posix.c new file mode 100644 index 00000000000..5b40f711be8 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-posix.c @@ -0,0 +1,229 @@ +/* GNU Objective C Runtime Thread Interface for POSIX compliant threads + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.edu) + Modified for Linux/Pthreads by Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.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. */ + +/* 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. */ + +#include <objc/thr.h> +#include "runtime.h" +#include <pthread.h> + +/* Key structure for maintaining thread specific storage */ +static pthread_key_t _objc_thread_storage; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* Initialize the thread storage key */ + return pthread_key_create(&_objc_thread_storage, NULL); +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + objc_thread_t thread_id; + pthread_t new_thread_handle; + + if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) ) + thread_id = *(objc_thread_t *)&new_thread_handle; + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + /* Not implemented yet */ + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + /* Not implemented yet */ + return -1; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + sched_yield(); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* exit the thread */ + pthread_exit(&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + pthread_t self = pthread_self(); + + return *(objc_thread_t *)&self; +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + return pthread_setspecific(_objc_thread_storage, value); +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + return pthread_getspecific(_objc_thread_storage); +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + mutex->backend = objc_malloc(sizeof(pthread_mutex_t)); + + if (pthread_mutex_init((pthread_mutex_t *)mutex->backend, NULL)) + { + objc_free(mutex->backend); + mutex->backend = NULL; + return -1; + } + + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend)) + return -1; + + objc_free(mutex->backend); + mutex->backend = NULL; + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + return pthread_mutex_lock((pthread_mutex_t *)mutex->backend); +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + return pthread_mutex_trylock((pthread_mutex_t *)mutex->backend); +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + return pthread_mutex_unlock((pthread_mutex_t *)mutex->backend); +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + condition->backend = objc_malloc(sizeof(pthread_cond_t)); + + if (pthread_cond_init((pthread_cond_t *)condition->backend, NULL)) + { + objc_free(condition->backend); + condition->backend = NULL; + return -1; + } + + return 0; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + if (pthread_cond_destroy((pthread_cond_t *)condition->backend)) + return -1; + + objc_free(condition->backend); + condition->backend = NULL; + return 0; +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + return pthread_cond_wait((pthread_cond_t *)condition->backend, + (pthread_mutex_t *)mutex->backend); +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + return pthread_cond_broadcast((pthread_cond_t *)condition->backend); +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + return pthread_cond_signal((pthread_cond_t *)condition->backend); +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-pthreads.c b/gnu/usr.bin/gcc/objc/thr-pthreads.c new file mode 100644 index 00000000000..2efdd15bc54 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-pthreads.c @@ -0,0 +1,218 @@ +/* GNU Objective C Runtime Thread Implementation for PCThreads under GNU/Linux. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Scott Christley <scottc@net-community.com> + Condition functions added by: Mircea Oancea <mircea@first.elcom.pub.ro> + +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. */ + +#include <pcthread.h> +#include <objc/thr.h> +#include "runtime.h" + +/* Key structure for maintaining thread specific storage */ +static pthread_key_t _objc_thread_storage; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* Initialize the thread storage key */ + return pthread_key_create(&_objc_thread_storage, NULL); +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + /* Destroy the thread storage key */ + /* Not implemented yet */ + /* return pthread_key_delete(&_objc_thread_storage); */ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + objc_thread_t thread_id; + pthread_t new_thread_handle; + + if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) ) + thread_id = *(objc_thread_t *)&new_thread_handle; + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + /* Not implemented yet */ + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + /* Not implemented yet */ + return OBJC_THREAD_INTERACTIVE_PRIORITY; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + pthread_yield(NULL); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* exit the thread */ + pthread_exit(&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + pthread_t self = pthread_self(); + + return *(objc_thread_t *)&self; +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + return pthread_setspecific(_objc_thread_storage, value); +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + void *value = NULL; + + if ( !(pthread_getspecific(_objc_thread_storage, &value)) ) + return value; + + return NULL; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + if (pthread_mutex_init((pthread_mutex_t *)(&(mutex->backend)), NULL)) + return -1; + else + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + if (pthread_mutex_destroy((pthread_mutex_t *)(&(mutex->backend)))) + return -1; + else + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + return pthread_mutex_lock((pthread_mutex_t *)(&(mutex->backend))); +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + return pthread_mutex_trylock((pthread_mutex_t *)(&(mutex->backend))); +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + return pthread_mutex_unlock((pthread_mutex_t *)(&(mutex->backend))); +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + if (pthread_cond_init((pthread_cond_t *)(&(condition->backend)), NULL)) + return -1; + else + return 0; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + return pthread_cond_destroy((pthread_cond_t *)(&(condition->backend))); +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + return pthread_cond_wait((pthread_cond_t *)(&(condition->backend)), + (pthread_mutex_t *)(&(mutex->backend))); +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + return pthread_cond_broadcast((pthread_cond_t *)(&(condition->backend))); +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + return pthread_cond_signal((pthread_cond_t *)(&(condition->backend))); +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-single.c b/gnu/usr.bin/gcc/objc/thr-single.c new file mode 100644 index 00000000000..b196677c6b6 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-single.c @@ -0,0 +1,192 @@ +/* GNU Objective C Runtime Thread Implementation + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.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. */ + +/* 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. */ + +#include <objc/thr.h> +#include "runtime.h" + +/* Thread local storage for a single thread */ +static void *thread_local_storage = NULL; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* No thread support available */ + return -1; +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + /* No thread support available */ + return -1; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + /* No thread support available */ + return NULL; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + /* No thread support available */ + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + return OBJC_THREAD_INTERACTIVE_PRIORITY; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + return; +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* No thread support available */ + /* Should we really exit the program */ + /* exit(&__objc_thread_exit_status); */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + /* No thread support, use 1. */ + return (objc_thread_t)1; +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + thread_local_storage = value; + return 0; +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + return thread_local_storage; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + /* There can only be one thread, so we always get the lock */ + return 0; +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + /* There can only be one thread, so we always get the lock */ + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + return 0; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + return 0; +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + return 0; +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + return 0; +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + return 0; +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-solaris.c b/gnu/usr.bin/gcc/objc/thr-solaris.c new file mode 100644 index 00000000000..90351b43cf6 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-solaris.c @@ -0,0 +1,259 @@ +/* GNU Objective C Runtime Thread Interface + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.edu) + Conditions added by Mircea Oancea (mircea@first.elcom.pub.ro) + +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. */ + +#include <objc/thr.h> +#include "runtime.h" + +#include <thread.h> +#include <synch.h> +#include <errno.h> + +/* Key structure for maintaining thread specific storage */ +static thread_key_t __objc_thread_data_key; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* Initialize the thread storage key */ + if (thr_keycreate(&__objc_thread_data_key, NULL) == 0) + return 0; + else + return -1; +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + objc_thread_t thread_id; + thread_t new_thread_id = 0; + + if (thr_create(NULL, 0, (void *)func, arg, + THR_DETACHED | THR_NEW_LWP, + &new_thread_id) == 0) + thread_id = *(objc_thread_t *)&new_thread_id; + else + thread_id = NULL; + + return thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + int sys_priority = 0; + + switch (priority) + { + case OBJC_THREAD_INTERACTIVE_PRIORITY: + sys_priority = 300; + break; + default: + case OBJC_THREAD_BACKGROUND_PRIORITY: + sys_priority = 200; + break; + case OBJC_THREAD_LOW_PRIORITY: + sys_priority = 1000; + break; + } + + /* Change priority */ + if (thr_setprio(thr_self(), sys_priority) == 0) + return 0; + else + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + int sys_priority; + + if (thr_getprio(thr_self(), &sys_priority) == 0) + { + if (sys_priority >= 250) + return OBJC_THREAD_INTERACTIVE_PRIORITY; + else if (sys_priority >= 150) + return OBJC_THREAD_BACKGROUND_PRIORITY; + return OBJC_THREAD_LOW_PRIORITY; + } + + /* Couldn't get priority. */ + return -1; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + thr_yield(); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* exit the thread */ + thr_exit(&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + return (objc_thread_t)thr_self(); +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + if (thr_setspecific(__objc_thread_data_key, value) == 0) + return 0; + else + return -1; +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + void *value = NULL; + + if (thr_getspecific(__objc_thread_data_key, &value) == 0) + return value; + + return NULL; +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + if (mutex_init( (mutex_t *)(&(mutex->backend)), USYNC_THREAD, 0)) + return -1; + else + return 0; +} + + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + mutex_destroy((mutex_t *)(&(mutex->backend))); + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + if (mutex_lock((mutex_t *)(&(mutex->backend))) != 0) + return -1; + else + return 0; +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + if (mutex_trylock((mutex_t *)(&(mutex->backend))) != 0) + return -1; + else + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + if (mutex_unlock((mutex_t *)(&(mutex->backend))) != 0) + return -1; + else + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + return cond_init((cond_t *)(&(condition->backend)), USYNC_THREAD, NULL); +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + return cond_destroy((cond_t *)(&(condition->backend))); +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + return cond_wait((cond_t *)(&(condition->backend)), + (mutex_t *)(&(mutex->backend))); +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + return cond_broadcast((cond_t *)(&(condition->backend))); +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + return cond_signal((cond_t *)(&(condition->backend))); +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr-win32.c b/gnu/usr.bin/gcc/objc/thr-win32.c new file mode 100644 index 00000000000..8570ffd997e --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr-win32.c @@ -0,0 +1,272 @@ +/* GNU Objective C Runtime Thread Interface - Win32 Implementation + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.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. */ + +/* 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. */ + +#include <objc/thr.h> +#include "runtime.h" + +#ifndef __OBJC__ +#define __OBJC__ +#endif +#include <windows.h> + +/* Key structure for maintaining thread specific storage */ +static DWORD __objc_data_tls = (DWORD)-1; + +/* Backend initialization functions */ + +/* Initialize the threads subsystem. */ +int +__objc_init_thread_system(void) +{ + /* Initialize the thread storage key */ + if ((__objc_data_tls = TlsAlloc()) != (DWORD)-1) + return 0; + else + return -1; +} + +/* Close the threads subsystem. */ +int +__objc_close_thread_system(void) +{ + if (__objc_data_tls != (DWORD)-1) + TlsFree(__objc_data_tls); + return 0; +} + +/* Backend thread functions */ + +/* Create a new thread of execution. */ +objc_thread_t +__objc_thread_detach(void (*func)(void *arg), void *arg) +{ + DWORD thread_id = 0; + HANDLE win32_handle; + + if (!(win32_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, + arg, 0, &thread_id))) + thread_id = 0; + + return (objc_thread_t)thread_id; +} + +/* Set the current thread's priority. */ +int +__objc_thread_set_priority(int priority) +{ + int sys_priority = 0; + + switch (priority) + { + case OBJC_THREAD_INTERACTIVE_PRIORITY: + sys_priority = THREAD_PRIORITY_NORMAL; + break; + default: + case OBJC_THREAD_BACKGROUND_PRIORITY: + sys_priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case OBJC_THREAD_LOW_PRIORITY: + sys_priority = THREAD_PRIORITY_LOWEST; + break; + } + + /* Change priority */ + if (SetThreadPriority(GetCurrentThread(), sys_priority)) + return 0; + else + return -1; +} + +/* Return the current thread's priority. */ +int +__objc_thread_get_priority(void) +{ + int sys_priority; + + sys_priority = GetThreadPriority(GetCurrentThread()); + + switch (sys_priority) + { + case THREAD_PRIORITY_HIGHEST: + case THREAD_PRIORITY_TIME_CRITICAL: + case THREAD_PRIORITY_ABOVE_NORMAL: + case THREAD_PRIORITY_NORMAL: + return OBJC_THREAD_INTERACTIVE_PRIORITY; + + default: + case THREAD_PRIORITY_BELOW_NORMAL: + return OBJC_THREAD_BACKGROUND_PRIORITY; + + case THREAD_PRIORITY_IDLE: + case THREAD_PRIORITY_LOWEST: + return OBJC_THREAD_LOW_PRIORITY; + } + + /* Couldn't get priority. */ + return -1; +} + +/* Yield our process time to another thread. */ +void +__objc_thread_yield(void) +{ + Sleep(0); +} + +/* Terminate the current thread. */ +int +__objc_thread_exit(void) +{ + /* exit the thread */ + ExitThread(__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +} + +/* Returns an integer value which uniquely describes a thread. */ +objc_thread_t +__objc_thread_id(void) +{ + return (objc_thread_t)GetCurrentThreadId(); +} + +/* Sets the thread's local storage pointer. */ +int +__objc_thread_set_data(void *value) +{ + if (TlsSetValue(__objc_data_tls, value)) + return 0; + else + return -1; +} + +/* Returns the thread's local storage pointer. */ +void * +__objc_thread_get_data(void) +{ + return TlsGetValue(__objc_data_tls); /* Return thread data. */ +} + +/* Backend mutex functions */ + +/* Allocate a mutex. */ +int +__objc_mutex_allocate(objc_mutex_t mutex) +{ + if ((mutex->backend = (void *)CreateMutex(NULL, 0, NULL)) == NULL) + return -1; + else + return 0; +} + +/* Deallocate a mutex. */ +int +__objc_mutex_deallocate(objc_mutex_t mutex) +{ + CloseHandle((HANDLE)(mutex->backend)); + return 0; +} + +/* Grab a lock on a mutex. */ +int +__objc_mutex_lock(objc_mutex_t mutex) +{ + int status; + + status = WaitForSingleObject((HANDLE)(mutex->backend), INFINITE); + if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED) + return -1; + else + return 0; +} + +/* Try to grab a lock on a mutex. */ +int +__objc_mutex_trylock(objc_mutex_t mutex) +{ + int status; + + status = WaitForSingleObject((HANDLE)(mutex->backend), 0); + if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED) + return -1; + else + return 0; +} + +/* Unlock the mutex */ +int +__objc_mutex_unlock(objc_mutex_t mutex) +{ + if (ReleaseMutex((HANDLE)(mutex->backend)) == 0) + return -1; + else + return 0; +} + +/* Backend condition mutex functions */ + +/* Allocate a condition. */ +int +__objc_condition_allocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Deallocate a condition. */ +int +__objc_condition_deallocate(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Wait on the condition */ +int +__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + /* Unimplemented. */ + return -1; +} + +/* Wake up all threads waiting on this condition. */ +int +__objc_condition_broadcast(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* Wake up one thread waiting on this condition. */ +int +__objc_condition_signal(objc_condition_t condition) +{ + /* Unimplemented. */ + return -1; +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr.c b/gnu/usr.bin/gcc/objc/thr.c new file mode 100644 index 00000000000..f1c957aaa15 --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr.c @@ -0,0 +1,534 @@ +/* GNU Objective C Runtime Thread Interface + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.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. */ + +/* 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. */ + +#include <stdlib.h> +#include "runtime.h" + +/* Global exit status. */ +int __objc_thread_exit_status = 0; + +/* Flag which lets us know if we ever became multi threaded */ +int __objc_is_multi_threaded = 0; + +/* The hook function called when the runtime becomes multi threaded */ +objc_thread_callback _objc_became_multi_threaded = NULL; + +/* + Use this to set the hook function that will be called when the + runtime initially becomes multi threaded. + The hook function is only called once, meaning only when the + 2nd thread is spawned, not for each and every thread. + + It returns the previous hook function or NULL if there is none. + + A program outside of the runtime could set this to some function so + it can be informed; for example, the GNUstep Base Library sets it + so it can implement the NSBecomingMultiThreaded notification. + */ +objc_thread_callback objc_set_thread_callback(objc_thread_callback func) +{ + objc_thread_callback temp = _objc_became_multi_threaded; + _objc_became_multi_threaded = func; + return temp; +} + +/* + Private functions + + These functions are utilized by the frontend, but they are not + considered part of the public interface. + */ + +/* + First function called in a thread, starts everything else. + + This function is passed to the backend by objc_thread_detach + as the starting function for a new thread. + */ +struct __objc_thread_start_state +{ + SEL selector; + id object; + id argument; +}; + +static volatile void +__objc_thread_detach_function(struct __objc_thread_start_state *istate) +{ + /* Valid state? */ + if (istate) { + id (*imp)(id,SEL,id); + SEL selector = istate->selector; + id object = istate->object; + id argument = istate->argument; + + /* Don't need anymore so free it */ + objc_free(istate); + + /* Clear out the thread local storage */ + objc_thread_set_data(NULL); + + /* Check to see if we just became multi threaded */ + if (!__objc_is_multi_threaded) + { + __objc_is_multi_threaded = 1; + + /* Call the hook function */ + if (_objc_became_multi_threaded != NULL) + (*_objc_became_multi_threaded)(); + } + + /* Call the method */ + if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector))) + (*imp)(object, selector, argument); + else + objc_error(object, OBJC_ERR_UNIMPLEMENTED, + "objc_thread_detach called with bad selector.\n"); + } + else + objc_error(nil, OBJC_ERR_BAD_STATE, + "objc_thread_detach called with NULL state.\n"); + + /* Exit the thread */ + objc_thread_exit(); +} + +/* + Frontend functions + + These functions constitute the public interface to the Objective-C thread + and mutex functionality. + */ + +/* Frontend thread functions */ + +/* + Detach a new thread of execution and return its id. Returns NULL if fails. + Thread is started by sending message with selector to object. Message + takes a single argument. + */ +objc_thread_t +objc_thread_detach(SEL selector, id object, id argument) +{ + struct __objc_thread_start_state *istate; + objc_thread_t thread_id = NULL; + + /* Allocate the state structure */ + if (!(istate = (struct __objc_thread_start_state *) + objc_malloc(sizeof(*istate)))) + return NULL; + + /* Initialize the state structure */ + istate->selector = selector; + istate->object = object; + istate->argument = argument; + + /* lock access */ + objc_mutex_lock(__objc_runtime_mutex); + + /* Call the backend to spawn the thread */ + if ((thread_id = __objc_thread_detach((void *)__objc_thread_detach_function, + istate)) == NULL) + { + /* failed! */ + objc_mutex_unlock(__objc_runtime_mutex); + objc_free(istate); + return NULL; + } + + /* Increment our thread counter */ + __objc_runtime_threads_alive++; + objc_mutex_unlock(__objc_runtime_mutex); + + return thread_id; +} + +/* Set the current thread's priority. */ +int +objc_thread_set_priority(int priority) +{ + /* Call the backend */ + return __objc_thread_set_priority(priority); +} + +/* Return the current thread's priority. */ +int +objc_thread_get_priority(void) +{ + /* Call the backend */ + return __objc_thread_get_priority(); +} + +/* + Yield our process time to another thread. Any BUSY waiting that is done + by a thread should use this function to make sure that other threads can + make progress even on a lazy uniprocessor system. + */ +void +objc_thread_yield(void) +{ + /* Call the backend */ + __objc_thread_yield(); +} + +/* + Terminate the current tread. Doesn't return. + Actually, if it failed returns -1. + */ +int +objc_thread_exit(void) +{ + /* Decrement our counter of the number of threads alive */ + objc_mutex_lock(__objc_runtime_mutex); + __objc_runtime_threads_alive--; + objc_mutex_unlock(__objc_runtime_mutex); + + /* Call the backend to terminate the thread */ + return __objc_thread_exit(); +} + +/* + Returns an integer value which uniquely describes a thread. Must not be + NULL which is reserved as a marker for "no thread". + */ +objc_thread_t +objc_thread_id(void) +{ + /* Call the backend */ + return __objc_thread_id(); +} + +/* + Sets the thread's local storage pointer. + Returns 0 if successful or -1 if failed. + */ +int +objc_thread_set_data(void *value) +{ + /* Call the backend */ + return __objc_thread_set_data(value); +} + +/* + Returns the thread's local storage pointer. Returns NULL on failure. + */ +void * +objc_thread_get_data(void) +{ + /* Call the backend */ + return __objc_thread_get_data(); +} + +/* Frontend mutex functions */ + +/* + Allocate a mutex. Return the mutex pointer if successful or NULL if the + allocation failed for any reason. + */ +objc_mutex_t +objc_mutex_allocate(void) +{ + objc_mutex_t mutex; + + /* Allocate the mutex structure */ + if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex)))) + return NULL; + + /* Call backend to create the mutex */ + if (__objc_mutex_allocate(mutex)) + { + /* failed! */ + objc_free(mutex); + return NULL; + } + + /* Initialize mutex */ + mutex->owner = NULL; + mutex->depth = 0; + return mutex; +} + +/* + Deallocate a mutex. Note that this includes an implicit mutex_lock to + insure that no one else is using the lock. It is legal to deallocate + a lock if we have a lock on it, but illegal to deallocate a lock held + by anyone else. + Returns the number of locks on the thread. (1 for deallocate). + */ +int +objc_mutex_deallocate(objc_mutex_t mutex) +{ + int depth; + + /* Valid mutex? */ + if (!mutex) + return -1; + + /* Acquire lock on mutex */ + depth = objc_mutex_lock(mutex); + + /* Call backend to destroy mutex */ + if (__objc_mutex_deallocate(mutex)) + return -1; + + /* Free the mutex structure */ + objc_free(mutex); + + /* Return last depth */ + return depth; +} + +/* + Grab a lock on a mutex. If this thread already has a lock on this mutex + then we increment the lock count. If another thread has a lock on the + mutex we block and wait for the thread to release the lock. + Returns the lock count on the mutex held by this thread. + */ +int +objc_mutex_lock(objc_mutex_t mutex) +{ + objc_thread_t thread_id; + int status; + + /* Valid mutex? */ + if (!mutex) + return -1; + + /* If we already own the lock then increment depth */ + thread_id = objc_thread_id(); + if (mutex->owner == thread_id) + return ++mutex->depth; + + /* Call the backend to lock the mutex */ + status = __objc_mutex_lock(mutex); + + /* Failed? */ + if (status) + return status; + + /* Successfully locked the thread */ + mutex->owner = thread_id; + return mutex->depth = 1; +} + +/* + Try to grab a lock on a mutex. If this thread already has a lock on + this mutex then we increment the lock count and return it. If another + thread has a lock on the mutex returns -1. + */ +int +objc_mutex_trylock(objc_mutex_t mutex) +{ + objc_thread_t thread_id; + int status; + + /* Valid mutex? */ + if (!mutex) + return -1; + + /* If we already own the lock then increment depth */ + thread_id = objc_thread_id(); + if (mutex->owner == thread_id) + return ++mutex->depth; + + /* Call the backend to try to lock the mutex */ + status = __objc_mutex_trylock(mutex); + + /* Failed? */ + if (status) + return status; + + /* Successfully locked the thread */ + mutex->owner = thread_id; + return mutex->depth = 1; +} + +/* + Unlocks the mutex by one level. + Decrements the lock count on this mutex by one. + If the lock count reaches zero, release the lock on the mutex. + Returns the lock count on the mutex. + It is an error to attempt to unlock a mutex which this thread + doesn't hold in which case return -1 and the mutex is unaffected. + */ +int +objc_mutex_unlock(objc_mutex_t mutex) +{ + objc_thread_t thread_id; + int status; + + /* Valid mutex? */ + if (!mutex) + return -1; + + /* If another thread owns the lock then abort */ + thread_id = objc_thread_id(); + if (mutex->owner != thread_id) + return -1; + + /* Decrement depth and return */ + if (mutex->depth > 1) + return --mutex->depth; + + /* Depth down to zero so we are no longer the owner */ + mutex->depth = 0; + mutex->owner = NULL; + + /* Have the backend unlock the mutex */ + status = __objc_mutex_unlock(mutex); + + /* Failed? */ + if (status) + return status; + + return 0; +} + +/* Frontend condition mutex functions */ + +/* + Allocate a condition. Return the condition pointer if successful or NULL + if the allocation failed for any reason. + */ +objc_condition_t +objc_condition_allocate(void) +{ + objc_condition_t condition; + + /* Allocate the condition mutex structure */ + if (!(condition = + (objc_condition_t)objc_malloc(sizeof(struct objc_condition)))) + return NULL; + + /* Call the backend to create the condition mutex */ + if (__objc_condition_allocate(condition)) + { + /* failed! */ + objc_free(condition); + return NULL; + } + + /* Success! */ + return condition; +} + +/* + Deallocate a condition. Note that this includes an implicit + condition_broadcast to insure that waiting threads have the opportunity + to wake. It is legal to dealloc a condition only if no other + thread is/will be using it. Here we do NOT check for other threads + waiting but just wake them up. + */ +int +objc_condition_deallocate(objc_condition_t condition) +{ + /* Broadcast the condition */ + if (objc_condition_broadcast(condition)) + return -1; + + /* Call the backend to destroy */ + if (__objc_condition_deallocate(condition)) + return -1; + + /* Free the condition mutex structure */ + objc_free(condition); + + return 0; +} + +/* + Wait on the condition unlocking the mutex until objc_condition_signal() + or objc_condition_broadcast() are called for the same condition. The + given mutex *must* have the depth set to 1 so that it can be unlocked + here, so that someone else can lock it and signal/broadcast the condition. + The mutex is used to lock access to the shared data that make up the + "condition" predicate. + */ +int +objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex) +{ + objc_thread_t thread_id; + + /* Valid arguments? */ + if (!mutex || !condition) + return -1; + + /* Make sure we are owner of mutex */ + thread_id = objc_thread_id(); + if (mutex->owner != thread_id) + return -1; + + /* Cannot be locked more than once */ + if (mutex->depth > 1) + return -1; + + /* Virtually unlock the mutex */ + mutex->depth = 0; + mutex->owner = (objc_thread_t)NULL; + + /* Call the backend to wait */ + __objc_condition_wait(condition, mutex); + + /* Make ourselves owner of the mutex */ + mutex->owner = thread_id; + mutex->depth = 1; + + return 0; +} + +/* + Wake up all threads waiting on this condition. It is recommended that + the called would lock the same mutex as the threads in objc_condition_wait + before changing the "condition predicate" and make this call and unlock it + right away after this call. + */ +int +objc_condition_broadcast(objc_condition_t condition) +{ + /* Valid condition mutex? */ + if (!condition) + return -1; + + return __objc_condition_broadcast(condition); +} + +/* + Wake up one thread waiting on this condition. It is recommended that + the called would lock the same mutex as the threads in objc_condition_wait + before changing the "condition predicate" and make this call and unlock it + right away after this call. + */ +int +objc_condition_signal(objc_condition_t condition) +{ + /* Valid condition mutex? */ + if (!condition) + return -1; + + return __objc_condition_signal(condition); +} + +/* End of File */ diff --git a/gnu/usr.bin/gcc/objc/thr.h b/gnu/usr.bin/gcc/objc/thr.h new file mode 100644 index 00000000000..f904733695a --- /dev/null +++ b/gnu/usr.bin/gcc/objc/thr.h @@ -0,0 +1,143 @@ +/* Thread and mutex controls for Objective C. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Galen C. Hunt (gchunt@cs.rochester.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. + +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. */ + + +#ifndef __thread_INCLUDE_GNU +#define __thread_INCLUDE_GNU + +#include "objc/objc.h" + +/************************************************************************* + * Universal static variables: + */ +extern int __objc_thread_exit_status; /* Global exit status. */ + +/******** + * Thread safe implementation types and functions. + */ + +/* Thread priorities */ +#define OBJC_THREAD_INTERACTIVE_PRIORITY 2 +#define OBJC_THREAD_BACKGROUND_PRIORITY 1 +#define OBJC_THREAD_LOW_PRIORITY 0 + +/* A thread */ +typedef void * objc_thread_t; + +/* This structure represents a single mutual exclusion lock. */ +struct objc_mutex +{ + volatile objc_thread_t owner; /* Id of thread that owns. */ + volatile int depth; /* # of acquires. */ + void * backend; /* Specific to backend */ +}; +typedef struct objc_mutex *objc_mutex_t; + +/* This structure represents a single condition mutex */ +struct objc_condition +{ + void * backend; /* Specific to backend */ +}; +typedef struct objc_condition *objc_condition_t; + +/* Frontend mutex functions */ +objc_mutex_t objc_mutex_allocate(void); +int objc_mutex_deallocate(objc_mutex_t mutex); +int objc_mutex_lock(objc_mutex_t mutex); +int objc_mutex_unlock(objc_mutex_t mutex); +int objc_mutex_trylock(objc_mutex_t mutex); + +/* Frontend condition mutex functions */ +objc_condition_t objc_condition_allocate(void); +int objc_condition_deallocate(objc_condition_t condition); +int objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex); +int objc_condition_signal(objc_condition_t condition); +int objc_condition_broadcast(objc_condition_t condition); + +/* Frontend thread functions */ +objc_thread_t objc_thread_detach(SEL selector, id object, id argument); +void objc_thread_yield(void); +int objc_thread_exit(void); +int objc_thread_set_priority(int priority); +int objc_thread_get_priority(void); +void * objc_thread_get_data(void); +int objc_thread_set_data(void *value); +objc_thread_t objc_thread_id(void); + +/* + Use this to set the hook function that will be called when the + runtime initially becomes multi threaded. + The hook function is only called once, meaning only when the + 2nd thread is spawned, not for each and every thread. + + It returns the previous hook function or NULL if there is none. + + A program outside of the runtime could set this to some function so + it can be informed; for example, the GNUstep Base Library sets it + so it can implement the NSBecomingMultiThreaded notification. + */ +typedef void (*objc_thread_callback)(); +objc_thread_callback objc_set_thread_callback(objc_thread_callback func); + +/* Backend initialization functions */ +int __objc_init_thread_system(void); +int __objc_fini_thread_system(void); + +/* Backend mutex functions */ +int __objc_mutex_allocate(objc_mutex_t mutex); +int __objc_mutex_deallocate(objc_mutex_t mutex); +int __objc_mutex_lock(objc_mutex_t mutex); +int __objc_mutex_trylock(objc_mutex_t mutex); +int __objc_mutex_unlock(objc_mutex_t mutex); + +/* Backend condition mutex functions */ +int __objc_condition_allocate(objc_condition_t condition); +int __objc_condition_deallocate(objc_condition_t condition); +int __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex); +int __objc_condition_broadcast(objc_condition_t condition); +int __objc_condition_signal(objc_condition_t condition); + +/* Backend thread functions */ +objc_thread_t __objc_thread_detach(void (*func)(void *arg), void *arg); +int __objc_thread_set_priority(int priority); +int __objc_thread_get_priority(void); +void __objc_thread_yield(void); +int __objc_thread_exit(void); +objc_thread_t __objc_thread_id(void); +int __objc_thread_set_data(void *value); +void * __objc_thread_get_data(void); + +#endif /* not __thread_INCLUDE_GNU */ |