Changes for GCC version 2.3.1, from version 2.2.2. This does not include changes in files you can reconstruct with etags, makeinfo, TeX, or Bison. Before applying the diffs below, execute the following commands. rm proto-man mv ChangeLog ChangeLog.5 mv config-gcc.com vmsconfig.com mv global-alloc.c global.c mv limits.h glimits.h mv va-hp800.h va-pa.h rm config/i386vgas.h rm config/i486v4.h rm config/x-dpx2200 config/x-dpx2300 rm config/x-i386v4 rm config/x-m88kv3 rm config/xm-mipsbsdn.h mv config/vms.h config/vax-vms.h mv config/xm-vms.h config/xm-vax-vms.h diff -rc2N gcc-2.2.2/ChangeLog gcc-2.3.1/ChangeLog *** gcc-2.2.2/ChangeLog --- gcc-2.3.1/ChangeLog Sun Nov 1 03:26:25 1992 *************** *** 0 **** --- 1,8182 ---- + Sun Nov 1 03:19:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Version 2.3.1 released. + + * x-i386s4: Renamed from x-i386sco4. + * configure (i[34]86-*-sco*): Use new name. + + * sol2-c1.asm, sol2-ci.asm, sol2-cn.asm: Renamed from sol2-crt... + * t-sol2: User new names. + + Sat Oct 31 15:19:54 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Version 2.3 released. + + * Makefile.in (install-libobjc): New target. + ($(srcdir)/gcc.dvi, $(srcdir)/cpp.dvi): New targets. + (extraclean): rm *diff, *lose, config/*lose. + (mostlyclean): rm config/core. + + * objc-actions.c (OBJC_SELECTORS_WITHOUT_LABELS): Define by default. + + Fri Oct 30 20:11:52 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * i386.c (output_move_double): Undo 10/25 change. Handle case + where part of a dest reg is used in a src mem rtx, without using + stack. + + Fri Oct 30 18:52:57 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Bump meissner version number to 28. + + * mips.md (addsi3, subsi3): Don't allow -32768 as the second + operand, the assembler complains if the instruction fills a delay + slot. + + Fri Oct 30 16:11:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * combine.c (simplify_shift_const): + For a subreg, require subreg_lowpart_p and not paradoxical. + + * Makefile.in (install-fixincludes): Ignore dirs that don't exist. + + Thu Oct 29 20:15:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gvarargs.h, gstdarg.h [4.3 net 2]: If _VA_LIST_, is undefined + then va_list is already declared. + + * i386gas.h (ASM_GENERATE_INTERNAL_LABEL, ASM_OUTPUT_INTERNAL_LABEL): + Override, if NO_UNDERSCORES. + + Thu Oct 29 17:30:52 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * flow.c (life_analysis): Mark FP live at end of function. + * reload1.c (reload): If FP was eliminated, remove it from + being live in any basic block. + + * varasm.c (output_constant_pool): Labels can be deleted by being + turned into NOTEs, not just have INSN_DELETED_P. + + Thu Oct 29 16:15:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h: Use _ANSI_STDARG_H_, not _ANSI_STDARG_H. + + * gstddef.h [4.3 net 2]: If _SIZE_T_, etc. are undefined + then type is already declared. + + * m68k.c (print_operand_address) [MOTOROLA !SGS]: + Don't subtract 2 in the address displacement. + + Thu Oct 29 14:36:23 1992 Michael Meissner (meissner@osf.org) + + * libgcc2.c (__builtin_vec_new): #undef NULL before including + stdio.h to prevent redeclaration message. + (pyramid __enable_execute_stack): Ditto. + + * i386rose.h (YES_UNDERSCORES): Define. + (ASM_OUTPUT_LABELREF): Don't redefine. + + * mips.h (ASM_FINAL_SPEC): If cross compiling, don't invoke + mips-tfile by default. + + * decrose.h (ASM_FINAL_SPEC): If cross compiling, don't invoke + mips-tfile by default. + + * mips-tdump.c, mips-tfile.c: Handle the case where CROSS_COMPILE + is defined more gracefully. + + Thu Oct 29 12:10:16 1992 Tim Moore (moore at defmacro.cs.utah.edu) + + * combine.c (make_extraction): Fix paren error in if for INNER is reg. + + Thu Oct 29 13:49:03 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * xm-mipsbsd.h: Really delete file. + + Thu Oct 29 02:48:28 1992 Tom Wood (wood@dg-rtp.dg.com) + + * dwarfout.c, arm.c, m88k.c: Include "assert.h" instead of . + + Thu Oct 29 00:43:00 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstddef.h [4.3 net 2]: Force inclusion of ansi.h. + Undef _SIZE_T_, _PTRDIFF_T_, _WCHAR_T_ at end. + + * Makefile.in (libgcc2.a, libgcc1.a): Use || to exit if cp fails. + (install-float-h-cross): Use fi, not done. + Write float.h in $(tmpdir), not in `.'. + (tmpdir): New variable. + + * i386gas.h (NO_UNDERSCORES): Test was backwards. + (SDB_DEBUGGING_OUTPUT): Defined. + + Wed Oct 28 16:33:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h, gvarargs.h: + On Net 2 system, don't test, define or undef _VA_LIST_. + Use _ANSI_H_, __BSD_NET2__ and ____386BSD____ to test for this. + + * i386bsd.h (CPP_PREDEFINES): Add ____386BSD____. + + * c-decl.c (pushdecl): Allow redeclaring builtin as any sort of static. + + * Makefile.in (install-cross-tools): Fix typo. + (all.build): Dep on xgcc instead of $(GCC_PASSES). + + Wed Oct 28 15:25:42 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.c (print_operand): When AS_BUG_FLDCR is defined, use alternate + fldcr form. + * m88kdgux.h (AS_BUG_FLDCR): Define to accomodate 4.30 assembler bug. + + * m88kv3.h (CPP_PREDEFINES): Add -Dunix. + + * m88kdolph.h (SDB_ALLOW_FORWARD_REFERENCES): Don't override. + + Wed Oct 28 05:34:11 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * reload1.c (gen_input_reload): In PLUS, if OP0 and OP1 are the + same, use RELOADREG when generating the addition. + + * reload.c (find_reloads_address): When copying memref after we've + made recursive calls on it, copy any replacements we made. + + * combine.c (can_combine_p): Don't substitute an expression + containing a register that will be clobbered in I3. + + * objc/core.c, objc/hash.c: Include tconfig.h, not config.h. + Include gstdarg.h. + * objc/object.m: Include tconfig.h, not config.h. + Include gstdarg.h before stdio.h. + * objc/objc.h: Don't include gstdarg.h here. + * objc/objc-proto.h (CLASS_LOCATION_SHIFT): Use HOST_BITS_PER_LONG, + not BITS_PER_WORD. + (setClassNumber, getClassNumber): `info' field is long, not int. + + Wed Oct 28 10:54:50 1992 Michael Meissner (meissner@osf.org) + + * libgcc2.c (L_caps_new): Properly close comment. + + Wed Oct 28 05:50:10 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * pa.md (mulsi): Input predicates back to srcsi_operands. + Don't handle constants specifically for TARGET_SNAKE, but call + force_reg to put them in registers. + (indexed addressing mode patterns): Remove the patterns with + unscaled index. Switch off patterns that never match. + + * longlong.h (file header): Add comment describing sdiv_qrnnd. + (__hppa sub_ddmmss): Swap input operands. + + * gcc.c (process_command): Check that we have enough arguments. + + Wed Oct 28 00:40:18 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure (i[34]86-*-sysv*): Take note of $stabs. + * i386gas.h (SDB_DEBUGGING_INFO): #undef deleted. + (DBX_DEBUGGING_INFO): Definition deleted. + * i386gstabs.h: New file. + + * Makefile.in (mostlyclean): Don't delete tmp-limits.h. + + * i386vgas.h: File deleted. + + Tue Oct 27 15:35:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * libgcc2.c: Include stdio.h. + [__GNU_LIBRARY__] (write): Defined. + + * Makefile.in (install-cross-tools): When handling $(tooldir)/include, + do all cd's starting from build directory. + + * i386gas.h (NO_UNDERSCORES): Don't define, if YES_UNDERSCORES. + * i386linux.h (YES_UNDERSCORES): Defined. + + Tue Oct 27 14:17:43 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * configure (i[34]86-*-linux): Set broken_install. + * x-linux (INSTALL): Delete. + * x-iris (INSTALL): Delete. + + Tue Oct 27 13:39:22 1992 Tim Moore (moore@hal.gnu.ai.mit.edu) + + * pa.h (ASM_GLOBALIZE_LABEL): Give function symbols CODE type, + others DATA type. + + Mon Oct 26 16:40:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (build_c_cast): Don't warn about size change between + pointer and integer if the value is constant. + + * Makefile.in (libobjc.a): If ln fails, copy libobjc.a. + + Mon Oct 26 16:21:11 1992 Tim Moore (moore@defmacro.cs.utah.edu) + + * pa.h (EXPORT_PARMS, ASM_DECLARE_FUNCTION): Blow away usage of + EXPORT_PARMS. BUGGY_GAS isn't a problem any more. + (TEXT_SPACE_P, FUNCTION_NAME_P): New macros. + (ENCODE_SECTION_INFO): Use TEXT_SPACE_P. + (STRIP_NAME_ENCODING): Strip a '*' which might preceed a '@'. + (ASM_OUTPUT_EXTERNAL): Give only function labels a CODE type. + (ASM_OUTPUT_LABELREF): Use FUNCTION_NAME_P. + * pa.c (hppa_encode_label): Change function name encoding to + preserve leading '*' if there is one. + (function_label_operand): Use FUNCTION_NAME_P macro. + + Mon Oct 26 14:39:46 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + From Tim Moore: + * function.c (locate_and_pad_parm): In ARGS_GROW_DOWNWARD case, + don't pad to argument alignment if where_pad is downward. + + Mon Oct 26 11:21:36 1992 Chris Smith (csmith@convex.com) + + * convex.h (SHIFT_COUNT_TRUNCATED): Undefine. + + Mon Oct 26 07:48:35 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * alpha.c (print_operand, new 'L'): New case. + * alpha.md (movhi/movqi patterns): For long constants, use 'i' + constraint instead of 'K'; use "%L1" in template. + + * configure (alpha): Set use_collect2. + + Mon Oct 26 04:19:24 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * xm-alpha.h: Declare calloc. + + Sun Oct 25 17:19:52 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * function.c (fixup_var_refs_insns): Don't call delete_insn if not -O. + Make a NOTE_INSN_DELETED instead. + + Sun Oct 25 11:57:04 1992 Chris Smith (csmith@convex.com) + + * convex.h (target_flags): prevent -mnoc2 from clearing + TARGET_INDIRECTS. + (TARGET_INDIRECTS): Always on. + + Sun Oct 25 16:56:18 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * calls.c (expand_call): Don't call convert_to_mode if we obtained + VALUE in the proper mode; VALUE might be a CONST_INT. + + Sun Oct 25 03:18:03 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * expr.c (gen_push_operand): No longer static. + + * i386.c (output_move_double): Divert first word via the stack + if it's a register used in the input operand. + * i386.md (movdi): Delete the `&' from constraint. + + Sat Oct 24 21:41:00 1992 Chris Smith (csmith@convex.com) + + * convex.md (movstrictsi): Correct output constraint is + not =. + + Sat Oct 24 14:10:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * news.h (FUNCTION_EPILOGUE): Fix typos. + + * cccp.c (get_lintcmd): Length of `LINTLIBRARY' is 11. + + Sat Oct 24 13:22:09 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * arm.md (DImode patterns): Add `&' to target operand constraints. + + * Makefile.in (setting version variable): Prepend $(srcdir) to + version.c. + + From Wilson: + * longlong.h (sparclite): Use machine independent USItype instead + of explicit types. + + Sat Oct 24 10:35:18 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * rs6000.md (movdi): Tests were in wrong order. + + * rs6000.h (LEGITIMIZE_ADDRESS): Indexed addresses are not valid + for DImode and TImode; GO_IF_LEGITIMATE_ADDRESS knows this. + + * Makefile.in (mostlyclean): Add missing semicolon. + + * a29k.c (a29k_set_memflags, a29k_set_memflags_1): New functions. + * a29k.md (movqi, movhi, reload_{in,out}{qi,hi}): Use them. + + * alpha.c (get_aligned_mem): Copy memory flags to new MEM. + (alpha_set_memflags, alpha_set_memflags_1): New functions. + * alpha.md (movqi, movhi, reload_{in,out}{qi,hi}): Use new + functions. + + * alpha.h (ASM_FILE_START): Stop at blank in version string. + + Sat Oct 24 04:35:16 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * reload1.c (emit_reload_insns): If not -O, Don't try find_equiv_reg. + (choose_reload_regs): If not -O, don't inherit reloads. + + Fri Oct 23 18:07:10 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * news.h (FUNCTION_EPILOGUE): + If no frame ptr, increment stack ptr to free up the local space. + + * gcc.c (process_command): Discard after first space in spec_version. + + * print-tree.c (print_node): Always output `>' to match `<'. + + * Makefile.in (version): Use sed to extract. + Ignore excess after space. + (install-fixincludes): Fix typo in last change. + + * configure (i386-ibm-aix*): Use aix386ng.h if not --with-gas. + * aix386ng.h: New file. + + Fri Oct 23 15:14:49 1992 Brendan Kehoe (brendan@lisa.cygnus.com) + + * sdbout.c (sdbout_symbol): Return if a symbol's DECL_NAME is + empty, since we won't be able to make a symtab of it. + + * convex.h (P_tmpdir): Remove definition. + * xm-convex.h: Put it here. + + Fri Oct 23 10:27:34 1992 Michael Meissner (meissner@osf.org) + + * i386rose.h (ASM_OUTPUT_LABELREF): Define so that external + identifiers have leading underscores in front of them. + + * mips-tfile.c (parse_stabs_common): Allow stabs with line numbers + of 0. These come from g++ for compiler generated functions that + take arguments. + + Fri Oct 23 07:49:12 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * romp.c (output_fpops): Add SYMBOL_REF and LABEL_REF cases to + constants handled. + + Fri Oct 23 01:58:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * flow.c (find_basic_blocks): Check for LABEL_REF_NONLOCAL_P + in label_value_list. + * jump.c (mark_jump_label): Copy LABEL_REF_NONLOCAL_P from + LABEL_REF into REG_LABEL note. + + * toplev.c (push_float_handler): Declare arg old_handler. + + * t-next (OTHER_FIXINCLUDES_DIRS): Defined. + + * Makefile.in (OTHER_FIXINCLUDES_DIRS): New variable, normally empty. + (install-fixincludes): Run fixincludes on those dirs. + * fixincludes: Convert //-style comments to /*...*/ style. + + * loop.c (record_biv): Clear total_benefit field of new iv_class. + (get_condition): + Verify op 2 of source is label_ref before looking within. + + Thu Oct 22 21:17:53 1992 Tim Moore (moore at defmacro.cs.utah.edu) + + * varasm.c (STRIP_NAME_ENCODING): New macro to decode a symbol name + munged by ENCODE_SECTION_INFO. + (assemble_start_function, assemble_variable): Use STRIP_NAME_ENCODING. + * pa.h (STRIP_NAME_ENCODING): New definition. + + Thu Oct 22 17:53:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (mostlyclean): Clean objc subdir only if it exists. + + * news.h (FUNCTION_PROLOGUE): Do allocate local stack space + when no frame pointer. + + Thu Oct 22 15:21:27 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * i960.h (FUNCTION_VALUE): Simplify, just return reg 0. + * i960.c (i960_function_value): Delete. + + Thu Oct 22 09:42:50 1992 Michael Meissner (meissner@osf.org) + + * mips-tfile.c (parse_stabs_common): Ignore stab line numbers + of 0, since the G++ front end generates them. Check whether + line numbers can fit within the index field, and if not report + an error. + + * mips.c (function_arg): Align passed structures to double word + boundary if structure has double word alignment. + + * mips.h (STACK_DYNAMIC_OFFSET): Do not define this macro in order + to work around a bug. + + Thu Oct 22 08:00:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h, gvarargs.h: Treat _AIX and _M_UNIX like __svr4__. + + * i386gas.h (NO_UNDERSCORES): Defined. + + * next.h (INCLUDE_DEFAULTS): Put in GPLUSPLUS_INCLUDE_DIR, + GCC_INCLUDE_DIR, LOCAL_INCLUDE_DIR, STANDARD_INCLUDE_DIR. + Don't define at all if cross-compiling. + + * tree.c (copy_node): Copy the excess bytes--don't clear them. + + Thu Oct 22 06:40:55 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * a29k.h (TARGET_SWITCHES): Add missing complementary switches: + -mno-stack-check and -mstorem-bug. + + * a29k.md (long constant split): Use gen_lowpart instead of making + a SUBREG directly. + + * arm.h (STORE_FLAG_VALUE): Remove bogus definition. + + Thu Oct 22 03:04:28 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.c (prologue_marked): New variable. + (m88k_end_prologue): Output the epilogue mark here if the start of + the epilogue passed the end of the prologue. + (m88k_begin_epilogue): Don't output the epilogue mark if the end + of the prologue hasn't been processed yet. + + Thu Oct 22 03:20:40 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * function.c (put_var_into_stack): When we operate on a pseudo + that holds the address, use proper modes. + + * combine.c (make_extraction): Use is_mode, not inner_mode, + for BYTES_BIG_ENDIAN adjustment to offset for non-bitfield case. + Update is_mode when stripping subreg from around a mem. + + * m68k.h (GO_IF_INDEXABLE_BASE): Allow LABEL_REF only if jump table. + + Wed Oct 21 18:55:24 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h: Check and define _ANSI_STDARG_H along with _STDARG_H. + + Wed Oct 21 11:41:39 1992 Tom Wood (wood at gen-rtx) + + * toplev.c (push_float_handler, pop_float_handler): New functions. + * fold-const.c (real_value_truncate): + Use them, in case another handler is already in effect. + + Wed Oct 21 22:08:31 1992 H.J. Lu (hlu@yardbird.eecs.wsu.edu) + + * Makefile (all.build): Add target $(GCC_PASSES) for xgcc. + * build-make (CC): Defined. + (CROSS_GCC_FLAGS): Deleted. + (HOST_CC): Delete -V option; CC supplies that. + + Wed Oct 21 12:34:39 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + From Wilson: + * longlong.h (sparclite udiv_qrnnd): Remove comma before + __AND_CLOBBER_CC. + + Wed Oct 21 12:24:24 1992 Michael Meissner (meissner@osf.org) + + * decrose.h (WORD_SWITCH_TAKES_ARG): Add -pic-names. + (CC1_SPEC): If -pic-names, pass -mhalf-pic to cc1. + + * i386rose.h (WORD_SWITCH_TAKES_ARG): Add -pic-names. + (CC1_SPEC): If -pic-names, pass -mhalf-pic to cc1. + + Wed Oct 21 07:34:16 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * configure (alpha): Only accept OSF/1. + + * alpha.h (ASM_FILE_START): Change .verstamp ident for BL9. + * alpha.md (div/mod): Change calling sequence to agree with BL9. + + * expr.c (do_store_flag): Ensure we don't get confused when + emit_store_flag fails and an operand has a QUEUED. + + Wed Oct 21 02:53:58 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * cexp.y (integer_overflow): Do nothing unless pedantic. + + Tue Oct 20 17:02:15 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * README, sparc.h, flow.c, regs.h: Change global-alloc.c to global.c. + + * i960.md (call, call_value): Use 'd' not 'r' constraint for scratch. + + * gcc.c (WORD_SWITCH_TAKES_ARG): Handle -Ttext and -Tbss in + addition to -Tdata. + * i960.h (WORD_SWITCH_TAKES_ARG): Delete, now unnecessary. + * next.h (WORD_SWITCH_TAKES_ARG): Add -Tbss. + * sparc.h, sun2.h, sun3.h (WORD_SWITCH_TAKES_ARG): Add -Ttext and + -Tbss. + + Tue Oct 20 16:49:57 1992 Ron Guilmette (rfg at netcom.com) + + * dwarfout.c (dwarfout_file_scope_decl): Generate DIEs for + built-in non-fundamental types. + + Tue Oct 20 14:58:18 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * objc-actions.c (handle_impent, handle_class_ref): Use __ + to start the generated names, not period. + + Tue Oct 20 14:38:30 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * cp-method.c (fndecl_as_string): Undo change of Sep 14th for + emitting a space after the return type of a fn. + + Wed Oct 7 16:01:55 1992 Chip Salzenberg (chip@tct.com) + + * cp-lex.c (readescape): No warning if digits in \x are all 0's. + + Tue Oct 20 06:50:28 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * expr.c (force_operand): Clarify comment to say what it can return. + * integrate.c (copy_rtx_and_substitute): Don't assume force_operand + on an address returns a REG; it might be a SUBREG. Use force_reg. + + Tue Oct 20 04:54:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * tree.c (make_node, copy_node): + Don't assume node length is multiple of int. + + Mon Oct 19 18:14:56 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * genrecog.c (write_tree): For type SPLIT, check subroutine return + values for non-zero value not positive value. + + Mon Oct 19 16:11:04 1992 Michael Meissner (meissner@osf.org) + + * c-typeck.c (print_table, scan_table): Add support for XPG4's %S + and %C formats for printing/reading wide characters. %lc and %ls too. + + Mon Oct 19 17:58:18 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * arm.c (output_epilogue): Restore sp's value if no frame pointer. + + From Wilson: + * pa.h (WORD_SWITCH_TAKES_ARG): Delete sparc related cruft. + + Mon Oct 19 14:49:03 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-parse.y (primary): Don't try building a CALL_EXPR or + converting types if $$ is an error_mark. + + Mon Oct 19 14:01:02 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.h (SECONDARY_INPUT_RELOAD_CLASS): Require a temporary for a + pic address with a large constant term. + * m88k.md (reload_insi): New pattern. + (addsi3 pattern for large constants): Delete. Causes reload trouble. + * m88k.c (emit_move_sequence): Add scratch register. All callers + changed. + (legitimize_address): Add scratch register. All callers changed + to pass zero instead of gen_reg_rtx result. Allocate another temp + register for -fPIC case. Use scratch register for pic cases with + a large constant term. + + * m88k.h (FUNCTION_PROFILER_LENGTH, FUNCTION_BLOCK_PROFILER_LENGTH, + BLOCK_PROFILER_LENGTH, REG_PUSH_LENGTH, REG_POP_LENGTH): Added. + (ADJUST_INSN_LENGTH): Account for profiling code. + + Mon Oct 19 16:46:52 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (libobjc.a): Don't mkdir objc if dir exists. + + * expr.c (store_field): If trying to sign-extend a constant, + use value_mode as the mode. + + Mon Oct 19 10:59:20 1992 Michael Meissner (meissner@osf.org) + + * xm-umips.h (index): Define to be strchr. + (rindex): Define to be strrchr. + + * mips-tdump.c (index, rindex): Undefine these, since the MIPS + include files have a field spelled index. + + Mon Oct 19 03:34:04 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (mostlyclean): Delete libobjc.a. + (libobjc.a): Create the objc subdir. + + Sun Oct 18 17:52:05 1992 Arne H. Juul (arnej@lise.unit.no) + + * objc/Makefile: Add .SUFFIXES .m and .m.o rule to keep non-GNU + make happy. + + * Makefile.in (libobjc.a): Remove libobjc.a in current directory + before attempting to hardlink it or make will fail in later stages. + (sublibobcj.a): Don't use $(MAKEFLAGS) for objc subdir stuff. + + Sun Oct 18 06:00:27 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * cse.c (canon_reg): Don't call validate_change if INSN is zero. + + Sun Oct 18 01:09:02 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * i860.h (PRINT_OPERAND): For `h', always use OPERAND_HIGH_ADJ_PART + even for integer constant addresses. + + * final.c (output_addr_const): Always use FILE, not asm_out_file. + + * cccp.c (collect_expansion): Don't add whitespace at end + if inside a string and not traditional. + (rescan): At end of string, if inside macro, always keep scanning. + + * expr.c (store_field): If signed bitfield and want value, sign extend. + + Sat Oct 17 21:11:09 1992 H.J. Lu (hlu@yardbird.eecs.wsu.edu) + + * Makefile.in (all.build): New rule for making gcc with a + cross-compiler. + (install.build): New target. + (line 271): Add `####build overrides'. + (gen*.o): Depend on hconfig.h, not config.h. + ($(HOST_PREFIX_1)rtl.o, $(HOST_PREFIX_1)print-rtl.o, + $(HOST_PREFIX_1)rtlanal.o, $(HOST_PREFIX_1)obstack.o, + $(HOST_PREFIX_1)malloc.o): Add final `h' to the regexp to replace. + + * configure: If $host == $taget, but $host != $build, merge + `build-make' and emit `build = $build'. + * build-make: New file for making gcc with a cross-compiler. + + Sat Oct 17 19:24:31 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (process_init_constructor): When initializing a union, + handle the case of an empty init list. + + * reload.c (find_reloads_address): Redo last change: copy the mem + in the same way it's usually done. + + * Makefile.in (gcc.xtar): Fix typo in last change. + (mostlyclean): Don't use $(MAKEFLAGS) for objc subdir stuff. + + Sat Oct 17 19:15:16 1992 John Wroclawski (jtw@pmws.lcs.mit.edu) + + * decstatn.h (SIZE_TYPE): Fix typo. + + Sat Oct 17 17:46:08 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * cp-method.c: Don't try to include string.h or strings.h. + * cp-decl.c: Ditto. + + Sat Oct 17 13:50:49 1992 Fred Fish (fnf@fishpond.cygnus.com) + + * fixinc.svr4 (string.h): + Remove #defines for other compiler's builtin functions. + + Sat Oct 17 00:39:30 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * protoize.c: Add #undef getopt after getopt.h. + + * gstdarg.h, gvarargs.h (va_list) [__SVR4_2__]: + Don't set or test _VA_LIST. + + * gstddef.h: Do nothing if _ANSI_STDDEF_H already defined. + + Fri Oct 16 11:39:06 1992 H.J. Lu (hlu@yardbird.eecs.wsu.edu) + + * emit-rtl.c (gen_lowpart_common): Fix typo in last change. + + Fri Oct 16 22:35:15 1992 Eric Youngdale (youngdale@v6550d.nrl.navy.mil) + + * make-cc1.com: Correct previous patch. + + Fri Oct 16 20:07:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * objc-actions.c (start_class): + For an INTERFACE_TYPE, push to permanent obstack. + (build_message_expr): Use TYPE_MAIN_VARIANT when comparing types. + + * Makefile.in (libobjc.a): Don't use $(MAKEFLAGS). + Add braces around shell variable references. + (collect2): Delete file before linking it. + * objc/Makefile (all): Don't use $(MAKEFLAGS). + (VPATH): Get rid of ../ since srcdir now absolute. + + Fri Oct 16 14:23:25 1992 Michael Meissner (meissner@osf.org) + + * decstatn.h (all defines): Protect all defines with an #ifndef, + to allow dec-osf1.h to selectively override macros. + + Fri Oct 16 10:44:47 1992 Tom Wood (wood@dg-rtp.dg.com) + + * Makefile.in (libobjc.a): Compute srcdir1 without changing + directories. Use srcdir1 to locate objc/Makefile. Put quotes + around all potential multi-word values. Recompute GCC_FOR_TARGET. + (sublibobjc.a): Use same text as libobjc.a. + (mostlyclean): Use $(MAKE) and srcdir1 for objc action. + * objc/Makefile (SUBDIR_INCLUDES): Don't use ../$(srcdir). + (all): Use $(MAKE). + + Fri Oct 16 04:16:36 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * function.c (find_fixup_replacement): Renamed from find_replacement. + + * varasm.c (output_addressed_constants): Handle NON_LVALUE_EXPR. + + Fri Oct 16 02:25:17 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.md (call define_expands): If TARGET_LONG_CALLS, then force + the address of the function into a register. + * pa.h (TARGET_SWITCHES): New switch "-mlong-calls". + * pa.c (call_operand_address): Only allow registers if + TARGET_LONG_CALLS. + + Fri Oct 16 00:21:57 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (libobjc.a): Get directories right, using shell vars + thisdir1, srcdir1. Put quotes around $(GCC_CFLAGS). Use $(MAKE). + + Thu Oct 15 17:07:18 1992 Mike Stump (mrs@hal.gnu.ai.mit.edu) + + * configure, config.sub, config/elxsi.{c,h,md}, config/xm-elxsi.h, + config/x-elxsi: Add support for new 64 bit CPU, called Elxsi. + + Thu Oct 15 16:55:22 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * alpha.c (alpha_builtin_saveregs): Fix bug in last change. + + * fold-const.c (distribute_bit_expr): Test for BIT_{AND,IOR}_EXPR. + + * cse.c (cse_insn): Add missing call to apply_change_group. + + Thu Oct 15 15:09:45 1992 Michael Meissner (meissner@osf.org) + + * t-mips (CCLIBFLAGS, LIBGCC2_CFLAGS): Delete, so that libgcc.a is + built with the -G 8 option, instead of -G 0, so that the linker + doesn't complain when linking in libg++.a. + * t-decstatn (CCLIBFLAGS, LIBGCC2_CFLAGS): Ditto. + + Thu Oct 15 14:30:25 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * mips-tfile.c (parse_def): Allow spaces in arguments for C++. + Correct test for null when searching for end of name. + + Thu Oct 15 11:55:51 1992 Tim Moore (moore@defmacro.cs.utah.edu) + + * pa.c (compute_frame_size): Take an fregs_live parameter instead + of setting the static variable save_fregs. + (output_function_prologue): Initialize save_fregs to 0 and pass to + compute_frame_size. + * pa.h (INITIAL_FRAME_POINTER_OFFSET): Pass extra null parameter + to compute_frame_size. + + Thu Oct 15 08:40:07 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * alpha.h (TARGET_FPREGS): New flag. + (TARGET_SWITCHES): Remove temporary -mfp and add -msoft-float and + -mfp-regs. + (TARGET_DEFAULT): Set to -mfp-regs -mno-soft-float. + (CONDITIONAL_REGISTER_USAGE): Use TARGET_FPREGS. + (FUNCTION_VALUE, FUNCTION_ARG, LIBCALL_VALUE): Use integer registers + for FP items if -mno-fp-regs. + * alpha.c (alpha_builtin_saveregs): Store integer regs twice instead + of storing the FP regs if -mno-fp-regs. + + * fold-const.c (fold): Add missing test in case when we + distribute a NOP_EXPR into a COND_EXPR and try to pull it back + out again. + + Thu Oct 15 08:11:00 1992 Tom Wood (wood@dg-rtp.dg.com) + + * fold-const.c (simple_operand_p): Don't regard global or static + variables as simple. + (fold_truthop): Only require the RHS to be simple. + + * m88k.h (CPP_SPEC): Add -D__m88110__ when -m88110 is in effect, + similarly for -m88100. + * m88kdgux.h (CPP_SPEC): Ditto. + * m88kluna.h (CPP_PREDEFINES): Drop -Dmc88100. + (CPP_SPEC): Reproduce the predefine -Dmc88100 when -m88100 is in + effect. Otherwise, supply -D__mc881x0__ when -m881x0 is in effect. + + Thu Oct 15 02:09:49 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * expr.c (get_inner_reference): + If flag_volatile, treat every INDIRECT_REF as volatile. + + * collect2.c (main): If COLLECT_GCC is a relative name, use it anyway. + + * x-next: New file. + * configure (m68k-next-*): Use that. + + * Changes from NeXT: + + * libgcc2.c [L_ctors] (__CTOR_LIST__, __DTOR_LIST__): + Initialize these default definitions if __NeXT__. + + * gvarargs.h [__NeXT__]: Define _VA_LIST_ if _ANSI_STDARG_H_ was + defined; then define _ANSI_STDARG_H_. + + * gstddef.h (_ANSI_STDDEF_H): Define, along with _STDDEF_H. + + * next.h (INCLUDE_DEFAULTS): New macro. + + * cp-method.c (index, rindex): Delete declarations. + (build_overload_value): Cast result of index. + + * cccp.c (cplusplus_comments): New var. + (main): Set it according to options. + (rescan, handle_directive, skip_if_group, validate_else): + (skip_to_end_of_comment, macarg1, discard_comments): + Use cplusplus_comments to enable C++ comment syntax. + + Wed Oct 14 11:34:58 1992 Chip Salzenberg (chip@tct.com) + + * libgcc2.c (__gcc_bcmp): Don't depend on signedness of `char'. + + Wed Oct 14 18:52:28 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sched.c (sched_note_set): Set subreg_p for anything except a + paradoxical subreg. + + * configure (sparc-*-solaris2): Use xm-spc-sol2.h not xm-spcv4.h. + + * reload.c (find_reloads): Don't let an operand have a numbered + constraint that makes it match itself. + + Wed Oct 14 10:38:31 1992 Tim Moore (moore@defmacro.cs.utah.edu) + + * pa.md (sCC patterns): Comparison operator should have SImode, + not CCmode. + (indexed addressing mode patterns): New patterns to use indexed + addressing if possible. + * pa.c (output_and): Do handle (const_int 0) as an operand; it + seems to occur in unoptimized compilation. + * pa.h (REGNO_OK_FOR_FP_P): Logic bug. + * va-pa.h : When __GNUC__ == 1, don't include the gcc 1 varargs + file (va-hp9k8.h). Instead, the definitions are explicitly defined + here. This avoids multiple typedefs of va_list. + * xm-pa.h (HAVE_VPRINTF) Define in HPUX 8.0. + + * pa.md (mulsi): Use the hardware multiply instruction, xmpyu, if + TARGET_SNAKE. + (umulsidi3): New pattern. + (reload_insi, reload_outsi, reload_indi, reload_outdi): New + patterns. These are needed because SImode and DImode pseudoregs + may be allocated (or reloaded) in floating point registers for + multiplication. That means that their addresses, which were + legitimate for SImode and DImode, aren't valid any more. + (movsi, movhi, movqi, movdf, movdi, movsf): Pass null scratch + operand to emit_move_sequence. + (fp SImode load and store patterns): Move before main movsi + pattern. + (fp DImode load and store patterns) New patterns. + (movhi, movqi patterns): Support moves to/from fp registers. + (movdf pattern): Ensure at least one operand is a register. + * pa.c (emit_move_sequence): Take reload scratch register + argument, deal with reloads of SImode and DImode mems into + floating point registers, handle function_label_operand moves. + (secondary_reload_class): A scratch register is needed if + reloading a function_label_operand address (probably doesn't + happen) or an SImode or DImode value into/out of a floating + point register. + * pa.h (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS, + REG_CLASS_FROM_LETTER): Define a new register class + FP_OR_SNAKE_FP_REGS, used only be reload_{in,out}{si,di}. + (HARD_REGNO_MODE_OK): Allow all integer modes in Snake floating + point registers. QImode and HImode pseudoregs may end up there + when using xmpyu. + + * pa.md (pic symbolic address pattern): New pattern. + (movsi, movdi patterns): Remove some * constraints from fp registers. + (pic label address pattern): Fix typo. + (function_label_operand patterns): New patterns for loading a + label address in HPUX 8.0. + * pa.c (finalize_pic): No real initialization is necessary for pic. + (output_function_prologue): Save r19, the pic offset table + register. If profiling, save and restore the structure value + return register (r28) around the call to mcount. + (hppa_encode_label, function_label_operand): New functions. + Record if a label is a code label so it can be treated specially + in HPUX 8.0. + * pa.h (TARGET_SHARED_LIBS): New flag. Generate code that can be + linked with HPUX 8.0 shared libraries. + (TARGET_SWITCHES): New flags: -mshared-libs and -mno-shared-libs. + (PIC_OFFSET_TABLE_REGNUM): This is really r19. The preliminary + docs from HP were wrong. + (ASM_DECLARE_FUNCTION_NAME): Specify "ENTRY" param in .EXPORT + directive. + (ENCODE_SECTION_INFO): Encode function labels. + (ASM_OUTPUT_LABELREF): Deal with function labels. + (ASM_OUTPUT_REG_PUSH, ASM_OUTPUT_REG_POP): Don't do anything for + now; their only use (saving stuff during profiling) interacts in a + wierd way with required assembler directives at the start of a + function. Instead, do the save and restore in the function + prologue. + (hppa_encode_label): Declare. + * pa-hpux.h, pa-ghpux.h (TARGET_DEFAULT): Link against shared + libraries. + (LINK_SPEC): Don't link against shared libraries if debugging or + profiling. + * pa1-hpux.h, pa1-ghpux,h (TARGET_DEFAULT): Link against shared + libraries. + + Wed Oct 14 10:17:49 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (gcc.xtar): Copy the objc subdir. + (mostlyclean): Run the mostlyclean target in the objc subdir. + (objc-runtime, libobjc.a, sublibobjc.a): New targets. + (objc, objective-c): Dep on objc-runtime. + + * objc/*: New files. + + Wed Oct 14 07:17:19 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * alpha.md (smax, smin): Fix typo in output strings. + + * a29k.c (const_16_operand, const_24_operand): Fix typo in declaration + of MODE. + (gpc_reg_or_immediate_operand, and_operand, add_operand): Likwise. + + Wed Oct 14 00:12:16 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.h (RTX_COST): Fix spacing typo. + + Tue Oct 13 21:51:05 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * a29k.md (call, call_value): Don't use call_operand, since + checking for recursive calls at this point is not safe. + + Tue Oct 13 18:52:17 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-type2.c (my_friendly_abort): Tell them to write to bug-g++. + + Tue Oct 13 18:16:12 1992 Chris Smith (csmith@convex.com) + + * convex.h (P_tmpdir): define to use /tmp. + (RETURN_POPS_ARGS): correct definition to return size. + (ASM_IDENTIFY_GCC): output something between gcc2_compiled and + first function to keep gcc2_compiled out of assembler stabs. + + * convex.md (adddi3, ordi3, xordi3): check sign of CONST_INT + operands before using as immediates; these insns are word only. + (ashrdi3): don't use negative shift counts. + + * convex*.h (CPP_SPEC): define __NO_INLINE_STDLIB + + * xm-convex.h: remove temporary workaround from OS 8.0. + + Tue Oct 13 14:10:15 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * cp-lex.c (check_newline): Verify that main_input_filename is + valid before using it. + + Tue Oct 13 19:08:54 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * a29k.c: Now includes reload.h. + (spec_reg_operand): Validate mode and know that some regs support + MODE_PARTIAL_INT and some MODE_INT. + (call_operand, reload_memory_operand, a29k_get_reloaded_address) + New functions. + (in_operand): Allow constants with MODE_PARTIAL_INT. + (out_operand): Allow special registers with any mode. + Any MEM a word or wider is valid. + (extend_operator): Deleted. + (secondary_reload_class): A pseudo is the same as memory; we need + BP_REGS for multi-word memory or for bytes and halfword if -mndw. + (print_operand): Delete %X; add %m. + (print_operand, case 'F'): Check for SYMBOL_REF. + * a29k.h (PROMOTE_MODE, ADJUST_COST): New macros. + (CALL_USED_REGISTERS): LR0 is call-used. + (HARD_REGNO_MODE_OK): Handle MODE_PARTIAL_INT and the special + registers that can only hold those modes. + (MODES_TIEABLE_P): Clean up and handle MODE_PARTIAL_INT modes. + (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add new + classes LR0_REGS, FC_REGS, and CR_REGS. + (REGNO_REG_CLASS, REG_CLASS_FROM_LETTER): Likewise. + (PREDICATE_CODES): Update for new and deleted predicates. + * a29k.md: Use GEN_INT when appropriate. + (define_attr type): New types for SQRT. + (call patterns): Use SCRATCH for LR0. + Use new predicate call_operand so that some integers can be + used as addresses; fix CALLI so it doesn't accept constant. + (EXBYTE, EXTHW, INBYTE, INHW): Use ZERO_EXTEND instead of AND + when combine will make it. + Use PSImode for BP value and don't reference BP explicitly. + Clean up define_expands for these operations. + (rotlsi3): Use PSImode pseudo for FC. + (sign_extend): Sign extension insns clobber BP. + ({load,store}_multiple): Use PSImode pseudo for CR. + (MTSR): Add pattern for TRUNCATE from SImode to PSImode. + (sqrtsf2, sqrtdf2, movpsi): New patterns. + (load/store bytes/halfword): Clean up to accept temporaries as + input and use PSImode when required. + (movhi, movqi): Allocate temporaries here. + (reload_inqi, reload_outqi, reload_inhi, reload_outhi): New + patterns. + (movdf, movdi, movti): Use SCRATCH for BP register. + (reload_{in,out}{df,di,ti}): New patterns. + + Tue Oct 13 16:52:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fixinc.svr4 (sys/stream.h, sys/strsubr.h): Delete spurious `extern' + in various structure definitions. + + * rtlanal.c (single_set): Fix typo in REG_UNUSED check. + + * cse.c (simplify_binary_operation): Insure that folded >> extends + the sign even if the host bootstrap compiler doesn't. + + * final.c (output_asm_insn): Advance over the = when processing %=. + + * fixincludes (stdio.h): Fix va_list when preceeded by a *. + + Tue Oct 13 14:52:57 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * spc-sol2.h (STARTFILE_SPEC): Add crtbegin.o. + (LIB_SPEC): Add crtend.o for running ctors/dtors. + * t-sol2 (EXTRA_PARTS): Add crtbegin.o and crtend.o for C++. + (FIXINCLUDES): Deleted. + * configure (sparc-*-solaris2*): Set fixincludes here. + + Tue Oct 13 20:15:45 1992 Eric Youngdale (youngdale@v6550d.nrl.navy.mil) + + * make-cc1.com: Simplify extraction of YYEMPTY from cp-parse.c. + Generate c-parse.y, objc-parse.y from c-parse.in if required. + Pat Rankin did some of this. + + Tue Oct 13 14:06:45 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sparc.md (in_branch_delay): Allow fpload and fpstore. + + * collect2.c (main): Only install a signal handler for signals + that already have handlers. + (fork_execute): Don't ignore signals before calling do_wait. + + * i960.md: Change 'f' constraint for dest to '*f' if it is not the + only alternative. Add '*f' dest constraints to all patterns where + it is valid but was previously missing. + + * i960.h (OVERRIDE_OPTIONS): Enable function inlining. + * i960.c (g14_save_reg): Delete variable. + (i960_output_call_insn): Add two new parameters arg_pointer and + scratch_reg. Save/set/restore g14 if necessary. + (i960_expand_call): Delete function. + * i960.md (call, call_value): No longer call i960_expand_call, + instead call call_internal/call_value_internal pattern. + (call_internal, call_value_internal): Rewrite patterns to pass new + args to i960_output_call_insn. + + * sparc.md (movstrsi+1): Add `+' to constraints for clobbered inputs. + + * i960.c (i960_output_call_insn): Emit bx instead of b, callx + instead of callj. + + * sparc.c (sparc_frw_output_function_prologue): Frame pointer base + must be same as for regular sparc code. + + Tue Oct 13 06:02:03 1992 Tom Wood (wood@dg-rtp.dg.com) + + * loop.c (loop_optimize): Verify that max_uid_for_loop is still + larger than the uid of any insn. Increase the number of exit + blocks from 4 to 32 per loop. + (find_and_verify_loops): Stop trying to relocate exit blocks when + allocating a new label would exceed max_uid_for_loop. + + * combine.c (subst): Don't change a conditional branch into a + conditional move. + + * m88k.md (ext shift patterns): No longer needed. + + * m88k.c (mostly_false_jump): Recognize a sequence properly. + + Mon Oct 12 22:31:37 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.h (LEGITIMIZE_ADDRESS): Fix typo. + + Tue Oct 13 00:14:09 1992 H Lu (hlu@eecs.wsu.edu) + + * Makefile.in (install-common): Put - on cmd that handles protoize. + (gcc.o, cccp.o): Define TOOLDIR for the compilation. + (all HOST_PREFIX_1 targets): Fix typos. + + * x-linux (cpp.a, linux.a, cc1.a, cc1plus.a, gcc.a): Targets deleted. + (LD, ALIBS, STANDARD_STARTFILE_PREFIX, GPLUSPLUS_INCLUDE_DIR): + Vars deleted. + + * i386linux.h: Delete NO_JUMPTABLE conditional and contents. + (GPLUSPLUS_INCLUDE_DIR): Defined. + (STARTFILE_SPEC): Changed. + + * gen*.c: Include hconfig.h, not config.h. + + Mon Oct 12 16:25:22 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure.bat, vmsconfig.com: Make hconfig.h. + + * vax.h (PRINT_OPERAND): Detect `double' constants by DFmode, + since VOIDmode means an integer. + + * mips.h (DEBUG_REGISTER_NAMES): New macro definition. + * print-rtl.c (reg_names): + Make it static. Use DEBUG_REGISTER_NAMES if that's defined. + * regclass.c (reg_names): Reinstate the definition here. + + * fixinc.svr4: Delete excess fi in fixing stat.h. + + Mon Oct 12 08:10:37 1992 James Van Artsdalen (jrv@goldman.gnu.ai.mit.edu) + + * Makefile.in (install-fixincludes): Only delete an existing + syslimits.h if we install limits.h over it. + + * i386.h (PRINT_REG): Undo Oct 11 change. + (DEBUG_PRINT_REG): New macro, used from print-rtl.c. + + * conditions.h (CC_NOT_SIGNED): New macro. + * final.c (alter_cond): If CC_NOT_SIGNED, convert signed + conditions to unsigned. + + * i386.md (cmpstrM patterns): Compare strings of unsigned chars, + not strings of signed chars. + + Mon Oct 12 06:31:13 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (try_combine): Save DEST of NI2PAT before calling + recog_for_combine, which might make it a PARALLEL. + + * emit-rtl.c (gen_lowpart_common): Allow MODE_PARTIAL_INT where + MODE_INT is allowed. + + * combine.c (try_combine): Properly call single_set when validating + the result of a define_split. + + Mon Oct 12 00:24:29 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * calls.c (calls_alloca): Don't look within DECL_INITIAL if it's 0. + + * varasm.c (simplify_subtraction): New function. + * rtl.h (simplify_subtraction): Declared. + * final.c (output_addr_const): Call it. + + * print-rtl.c (DEBUG_PRINT_REG): Renamed from PRINT_REG. + (print_rtx): Use DEBUG_PRINT_REG. + + Sun Oct 11 16:27:53 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu.edu) + + * genrecog.c (merge_trees): When splitting, remember to clear DUPNO + in addition to the other things we can test. + + * recog.c (general_operand, immediate_operand, const_double_operand): + Allow CONST_INT with MODE_PARTIAL_INT. + (nonmemory_operand): Likewise. + + Sun Oct 11 07:53:39 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * xm-i38v4.h,xm-aix386.h (USE_C_ALLOCA): New macro. Define if not + using GNU C's builtin alloca. + + * i386.c (notice_update_cc): Only set CC_IN_80387 for float compares. + + * i386.h (PRINT_REG): Make register name arrays static within this + macro. + + Sun Oct 11 01:41:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * jump.c (jump_optimize): Don't optimize jumps to store-flag insns + when BLKmode values are being compared. + + Sat Oct 10 16:51:08 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * print-rtl.c (print_rtx): Print hard reg name as well as number. + (PRINT_REG): New macro with default definition. + (reg_name): Moved here. + * regclass.c (reg_name): Deleted. + + Sat Oct 10 02:27:14 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * i386sco.h (TARGET_DEFAULT): New macro - don't make TARGET_IEEE_FP + default for SCO. + + Sat Oct 10 04:52:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * function.h (struct function): New fields const_rtx_hash_table, + const_rtx_sym_hash_table, first_pool, last_pool, pool_offset. + * function.c (pop_function_context, push_function_context): + Call {save,restore}_varasm_status. + * varasm.c: Include function.h. + (restore_varasm_status, save_varasm_status): New fns. + (init_const_rtx_hash_table): Allocate the hash tables in obstack. + (force_const_mem): Don't use CONST_DOUBLE_MEM for nested fns. + (clear_const_double_mem): Do nothing for nested fns. + * Makefile.in (varasm.o): Dep on function.h. + + Fri Oct 9 18:16:18 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * cp-decl.c (duplicate_decls): Only find out if olddecl is a + friend after we know it's not a TREE_LIST. + + Fri Oct 9 18:10:19 1992 Jim Wilson (wilson@geech.gnu.ai.mit.edu) + + * sparc.c (sparc_type_code): Return reasonable result for COMPLEX_TYPE. + + Fri Oct 9 14:33:26 1992 Tom Wood (wood@dg-rtp.dg.com) + + * reorg.c (start_of_epilogue_needs): New variable. + (mark_target_live_regs): Add in start_of_epilogue_needs when + NOTE_INSN_EPILOGUE_BEG is scanned. + (dbr_schedule): Compute start_of_epilogue_needs and update + end_of_function_needs to include sets by all instructions + following NOTE_INSN_EPILOGUE_BEG. + + * m88k.md (return): Always available once reload has completed. + (epilogue): Use a return insn rather than an indirect jump. + + Fri Oct 9 12:36:54 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * spc-sol2.h (DBX_DEBUGGING_INFO): Defined. + + * function.c (aggregate_value_p): Return 1 if regs we would use + are not all call-clobbered. + + * stmt.c (POPSTACK): Pop discarded elts off all the stacks as we go. + + Fri Oct 9 07:30:14 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * reorg.c (mark_target_live_regs): Fix bug in last change. + + * combine.c (subst, case SUBREG): Don't make a new REG for + stack, frame, or arg pointer. + * emit-rtl.c (gen_lowpart_common, gen_highpart, operand_subword): + Likewise. + + * local-alloc.c (optimize_reg_copy_1): Tighten up code to properly + handle the case when SRC or DEST is a multi-word hard register + and only some parts of the register are set or used. Also, avoid + updating register status for DEST if we can't do the optimization. + + * jump.c (jump_optimize): Only use a REG as a target. + + * alpha.c (alpha_builtin_saveregs): Don't use value of NREGS greater + than 6 when computing ARGSIZE. + + * va-alpha.h (va_arg): Put parens around all uses of __VA arg. + + Thu Oct 8 18:45:00 1992 Arne H. Juul (arnej@lise.unit.no) + + * Makefile.in (install-common-headers): added missing 'then' + + Thu Oct 8 15:52:22 1992 Michael Meissner (meissner@osf.org) + + * mips.h (SELECT_RTX_SECTION): Rename macro from obsolete name + SELECT_SECTION_MODE. + + * i386rose.h (whole file): Remove #ifdef before #undef of macros. + (LEGITIMATE_CONSTANT_P): Define, so that when half-pic is on, + half-pic addresses are not considered legitimate. + (SELECT_RTX_SECTION): If putting a half-pic pointer that is + loaded, put the pointer into the data section, rather than the + readonly_data_section. + (SELECT_SECTION): Define. + (ASM_OUTPUT_DOUBLE): If not cross compiling, emit double as two + longs, otherwise emit .double directive. + (ASM_OUTPUT_FLOAT): If not cross compiling, emit float as long, + otherwise emit .float directive. + (perform_fixdfsi): Copy arg to memory variable. + (SIZE_TYPE): Define to be long unsigned int. + (PTRDIFF_TYPE): Define to be int. + (WCHAR_TYPE)L: Define to be unsigned int. + + * i386.md (movsi): Remove obsolete half-pic code. + (call insns): For half-pic insns, force address into register. + + Thu Oct 8 14:22:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (install-common-headers): Fix dir in chmods for assert.h. + + * va-i860.h (__savereg, va_arg): Put uses of __va in parens. + + * vax.h (PRINT_OPERAND): Define new code, D. + * vax.md (movdi): Use D code for operand 1. + + Thu Oct 8 13:23:25 1992 Jeffrey A. Law (law@mole.gnu.ai.mit.edu) + + * pa.md (fp_alu function unit, case fpcc): Fpcc instructions use + the fpalu unit. In the most common case their result will be used + in a ftest instruction. Minimum distance between the fcmp and + ftest instruction is 4. + + Thu Oct 8 06:41:15 1992 Tom Wood (wood@dg-rtp.dg.com) + + * function.c (assign_parms): Provide a safe value for + DECL_INCOMING_RTL in case of syntax errors. + + * dwarfout.c (dwarfout_init, dwarfout_finish): Don't output labels + or .debug_aranges entries for .data1 and .rodata1 as these + sections aren't currently used. + + Thu Oct 8 04:44:17 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * reorg.c (mark_target_live_regs): Look at USE insns made by + update_block when scanning forward past target. + (mark_target_live_regs, dbr_schedule): Use GET_RTX_CLASS. + + * cse.c (PATHLENGH): Change from 20 to 10 to speed up compilations. + + Thu Oct 8 03:07:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fold-const.c (invert_truthvalue): Never alter ARG. + + * Makefile.in (TAGS): Exclude =*.[chy] from tags table. + + * c-lex.c (yylex): For floats, use REAL_VALUES_LESS to distinguish + underflow from overflow. Delete special case for 0.0. + + Wed Oct 7 16:25:19 1992 Tom Wood (wood@dg-rtp.dg.com) + + * dwarfout.c (dwarfout_{begin,end}_function): New functions. + (body_{begin,end}_attribute): New functions. + (dwarf_attr_name): Print AT_body_begin and AT_body_end. + (output_{local,global}_subroutine_die): Output the new attributes. + * dwarf.h (enum dwarf_attribute): Add At_body_begin and AT_body_end. + * final.c (final_scan_insn): Call dwarfout_begin_function. + (final_end_function): Call dwarfout_end_function. + + * m88k.h (FASTEST_ALIGNMENT): Define as 8 for -m88110 otherwise 4. + (CONSTANT_ALIGNMENT, DATA_ALIGNMENT): Base on FASTEST_ALIGNMENT. + * m88k.md (movstrsi): No predicate is needed for the source or + destination. + * m88k.c (best_from_align): Add a target processor dimension for + -m88000, -m88110, and -m88100. + (expand_block_move): Choose method and limits based on -m88xxx option. + (block_move_no_loop): Extend to allow DImode. + * m88k-move.sh: Add the modules moveDI96x and moveDI41x through + moveDI47x. + * t-m88k, t-m88kluna, t-m88ksvr4: New modules added to MOVE_ASM. + + * m88k.c (output_call): Use different syntax for GAS. + + * m88k.h (READONLY_DATA_SECTION): Don't override svr4.h + (ASM_OUTPUT_CASE_LABEL): For svr4, use .rodata. + + Wed Oct 7 15:47:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure (i486-ncr-sysv4): Use i386v4.h. + (i386-*-sysv4, i386-*-linux, i386-*-sysv): Handle 486 too. + (i486-*-sysv4, i486-*-linux): Deleted. + * i486v4.h, i486linux.h: Files deleted. + + Wed Oct 7 12:40:00 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * populate (progname): Just the basename of $0 please. + (target_dir): Use abs_target_dir and rel_target_dir for clarity. + (source_dir): Use abs_source_dir and rel_source_dir for clarity. + (*): List input and output dirs on startup. + (*): Don't be so verbose; Don't echo names of output dirs/files as + they are created. + + * fixinc.svr4 (): Fix types of SIG_DFL, SIG_ERR, + SIG_IGN, and SIG_HOLD. + (): Turn definitions of stat, lstat, fstat, and mknod + into ANSI syntax and add __ to variables used. + + * c-parse.in (component_decl_list): Do pedwarn for missing semicolon + after last field decl. + + Wed Oct 7 09:49:34 1992 Michael Meissner (meissner@osf.org) + + * decstatn.h (LINK_SPEC): Don't define if it is already defined, + ie dec-osf1.h has included decstatn.h. + + * dec-osf1.h (MACHINE_TYPE): Redefine to say DEC OSF/1 instead of + ultrix. + + Wed Oct 7 03:50:11 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure (target_cpu_default): Var renamed from target_default. + Set it to 2, for a 486. Define TARGET_CPU_DEFAULT macro. + + * i386.h (TARGET_CPU_DEFAULT): Add default definition. + (TARGET_SWITCHES): Include that in the default. + + * toplev.c (main): Recover correctly from invalid -Wid-clash option. + + * cccp.c (finclude): Set fp->buf earlier, so it's freed on error. + + * Makefile.in (install-common-headers): Avoid ! operator, for assert.h. + + Tue Oct 6 20:21:21 1992 Jim Wilson (wilson@geech.gnu.ai.mit.edu) + + * unroll.c (copy_loop_body, JUMP_INSN case): Delete abort in the + code for setting the JUMP_LABEL field. + + Tue Oct 6 19:29:19 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * cp-call.c (build_overload_call_real): If `functions' is an + ADDR_EXPR (as with operator new and delete), give the name of its + argument as the error fn. + + Tue Oct 6 14:15:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure: Correct conditional in setting build_xm_file. + + * function.c (get_first_block_beg): New function. + + * cross-make (assertdir): Override usual definition. + * Makefile.in (install-common-headers): chmod assert.h in proper dir. + Use $(assertdir). + (assertdir): New variable. + (install-dir): Create dir $(includedir). + (includedir): Make this /usr/local/include. + + Tue Oct 6 12:05:35 1992 Jeffrey A. Law (law@mole.gnu.ai.mit.edu) + + * pa.md (memory function unit, load case): Loads take two cycles, + not one. + + Tue Oct 6 07:56:05 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * pa.md (adddi3): Fix typo. + + Tue Oct 6 04:03:40 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * m68k.c (floating_exact_log2, standard_68881_constant_p): + (standard_sun_fpa_constant_p): Use REAL_VALUE_FROM_CONST_DOUBLE. + (print_operand): Likewise. + + Mon Oct 5 18:39:29 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * tree.h (TREE_VIA_PROTECTED): Set protected_flag, not static_flag. + + Mon Oct 5 18:27:08 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in ($(srcdir)/INSTALL): Add -D INSTALLONLY. + + Mon Oct 5 14:46:08 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * cp-parse.y (unary_expr): Use the `new' rule when looking for + something like `new(foo) char[10]'. + + * cp-decl.c (grokparms): Don't call digest_init on default args. + + Mon Oct 5 02:21:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * reload1.c (allocate_reload_reg): Always check for asm + on failure instead of simply aborting. + + * optabs.c (init_optabs): Use cabs as the only libcall for abs. + + Mon Oct 5 03:10:14 1992 Mark Eichin (eichin at tweedledumber.cygnus.com) + + * c++ (numargs): $# was used after set was called; instead, save + $# in $numargs and use that value instead. + + Sun Oct 4 12:34:00 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * dwarfout.c (hard-reg-set.h): Included to get decl of `reg_names'. + (PRINT_REG): Default definition added. + (dwarf_last_decl): Variable declaration added. + (output_reg_number): New function; handle -fverbose-asm reg printing. + (output_mem_loc_descriptor, output_loc_descriptor): Call it. + (output_decl): Set `dwarf_last_decl' each time this fn is called. + * i386.h (hi_reg_name, qi_reg_name, qi_high_reg_name): Declared. + (PRINT_REG): Definition moved from i386.c. + * i386.c (hi_reg_name, qi_reg_name, qi_high_reg_name): Not static. + (PRINT_REG): Definition moved to i386.h. + + Sun Oct 4 00:53:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (shadow_tag_warned): Use pedwarn for useless keyword. + + * c-lex.c (readescape): No warning if digits in \x are all 0's. + + Sat Oct 3 14:37:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * optabs.c (expand_complex_abs): New function. + * expr.h (expand_complex_abs): Add declaration. + + Sat Oct 3 07:29:09 1992 Michael Meissner (meissner@osf.org) + + * configure (mips-dec-osf1): Use x-dec-osf1 instead of x-decstatn. + + * x-dec-osf1 (new file): Like x-decstatn, except that INSTALL is + installbsd -c. + + Sat Oct 3 05:04:43 1992 Tom Wood (wood@dg-rtp.dg.com) + + * toplev.c (rest_of_decl_compilation): Don't call + dwarfout_file_scope_decl as this causes duplicates. + + Sat Oct 3 01:35:23 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * explow.c (allocate_dynamic_stack_space) [MUST_ALIGN]: + Always add to size, always round up to STACK_BOUNDARY, + always round the address. + + * rtl.h (gen_realpart, gen_imagpart): Declared. + + Fri Oct 2 20:03:53 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * emit-rtl.c (gen_realpart, gen_imagpart): New functions. + * optabs.c (expand_unop, expand_binop): Use them. + * expr.c (expand_expr): Use them. + + * cccp.c (main): Handle -U before -D (and -A). + + * assert.h: Add magic comment at beginning. + * Makefile.in (includedir): New variable. + (USER_H): assert.h removed from value. + (install-common-headers): Install assert.h separately, in includedir, + but not if file exists and lacks the magic comment. + + * reload1.c (reload): Move test for failure to find any group + to after the loop over i. Also check that all the regnos fit + below FIRST_PSEUDO_REGISTER. + + * expr.c (expand_expr): + For ABS_EXPR, give expand_unop the operand's mode. + + Fri Oct 2 14:58:06 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * i386v4.h (DBX_REGISTER_NUMBER): Don't abort here on pseudo-regs. + * dwarfout.c (output_mem_loc_descriptor, output_loc_descriptor): + Catch cases of bogus DECL_RTL values involving pseudo-regs (for all + target systems) and print an annoying message if we ever see such a + case. + + Thu Oct 1 17:23:08 1992 Michael Meissner (meissner@osf.org) + + * mips-tfile.c (various): Rename some of the index variables and + fields to indx, so that it doesn't conflict with the BSD + index function, which may be #define'd to strchr. However, the + MIPS symbol table has a field called index, so #undef index and + rindex, and write our own functions local_index and local_rindex. + + * mips-bsd.h (CPP_PREDEFINES): Add single underscore in front of + each of the defines, for RISC-OS 5.0 compatibility. + + * mips-sysv.h (CPP_PREDEFINES): Add single underscore in front of + each of the defines, for RISC-OS 5.0 compatibility. + + * mips-svr4.h (CPP_PREDEFINES): Add single underscore in front of + each of the defines, for RISC-OS 5.0 compatibility. + + * mips.h (CPP_PREDEFINES): Add single underscore in front of each + of the defines, for RISC-OS 5.0 compatibility. + + * mips.c (override_options): Only call setvbuf to make stderr line + buffered for -mstats on Ultrix, and OSF/1. + + Thu Oct 1 15:18:55 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * reload1.c (emit_reload_insns): Add a case to handle + SECONDARY_MEMORY_NEEDED in the SECONDARY_OUTPUT_RELOAD_CLASS code. + * sparc.h (SECONDARY_INPUT_RELOAD_CLASS): Also need a temp reg + when loading HImode and QImode values from memory to FP_REGS. + (SECONDARY_OUTPUT_RELOAD_CLASS): New macro. Define this to handle + HImode and QImode stores from FP_REGS to memory similar to above. + + Thu Oct 1 13:36:52 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * cccp.c (rescan): If traditional, recognize # only at bol. + + * expr.c (expand_expr): Just return the lowpart or highpart. + + * configure (i386-*-linux, i486-*-linux): New alternatives. + * i386linux.h, i486linux.h, xm-linux.h: New files. + + * optabs.c (expand_unop): Handle complex negate and abs val. + (init_optabs): Set up libcalls for complex abs. + (init_complex_libcalls): New function. + + Thu Oct 1 22:58:45 1992 Eric Youngdale (youngdale@v6550d.nrl.navy.mil) + + * make-cc1.com: Extract line containing "#define YYEMPTY" from + cp-parse.c, and append to cp-parse.h (a la Makefile.in). + + * cccp.c (main) [VMS]: Use .obj, not .o, in dependencies output. + + Thu Oct 1 17:15:49 1992 Chip Salzenberg (chip@tct.com) + + * c-common.c (declare_function_name): __FUNC__ variables + are compiler-created, so set DECL_SOURCE_LINE to zero. + * c-decl.c (pushdecl): Internally generated vars can be + detected with DECL_SOURCE_LINE of zero, not DECL_IGNORED_P. + + Thu Oct 1 13:07:21 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.c (emit_move_sequence): When making a reference to the data + space before reload, emit an insn sequence which is much more + likely to create "addil" instructions rather than "ldil; add" + sequences. Doing so greatly reduces the chance of running into a + HPUX linker bug when compiling kernels. + + * pa.h (TARGET_KERNEL): New switch "-mkernel" which forces gcc to + avoid "ldil; add" sequences when %r29 and instead generate "addil" + sequences. This avoids a HPUX linker bug when compiling kernels. + * pa.md (add high part and dp register): Split into two patterns, + one for normal code, one for kernels. Kernel version only allows + "r1" as the destination register. + + * pa.h (LEGITIMIZE_ADDRESS, SYMBOL_REF case): Emit a sequence + which will cause "addil" instructions to be emitted instead of + "ldil; add" sequences. + + Thu Oct 1 01:09:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-parse.in, cond.awk: New files. + * Makefile.in (c-parse.y, objc-parse.y): Construct from c-parse.in. + (gcc.xtar): Depend on c-parse.y, objc-parse.y. + (realclean): Delete c-parse.y, objc-parse.y. + + * explow.c (allocate_dynamic_stack_space): If STACK_DYNAMIC_OFFSET + or STACK_POINTER_OFFSET, always round address up to BIGGEST_ALIGNMENT. + + * gstddef.h: If _ANSI_H_, undef _PTRDIFF_T_, _SIZE_T_, _WCHAR_T. + + * gvarargs.h: In the first part (instead of va-*.h), define + __gnuc_va_list, as in gstdarg.h. Always use __gunc_va_list + as basis for defining va_list. + Move interaction with BSD-NET2 down to where va_list itself is defined. + + * cccp.c (do_include): Delete unreachable goto after '"' case. + + Thu Oct 1 16:57:22 1992 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * dpx2g.h (NO_DOLLAR_IN_LABEL): Undef because gas understands dollars + in labels and gdb expects them if configured for gas. + (STARTFILE_SPEC): Include huge.o to be compatible with native cc. + (ASM_OUTPUT_CONSTRUCTOR, ASM_OUTPUT_DESTRUCTOR): + (CTOR_LISTS_DEFINED_EXTERNALLY, DO_GLOBAL_DTORS_BODY): + (STARTFILE_SPEC): Conditionally redefine for a collectless version + of gcc if USE_COLLECT2 is not defined. + + * dpx2.ifile: New ld command file to support not using collect2. + + Wed Sep 30 17:08:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * libgcc2.c (__eprintf): Do nothing if inhibit_eprintf is defined. + + * pbd.h, spc-sol2.h, tower.h (NO_UNDERSCORES): Deleted. + + * Makefile.in (install-fixincludes): rm syslimits.h before installing. + Install it with cp. Add an else-part to the if that installs it. + + * c-decl.c (start_enum): Push obstacks, switch to permanent if global. + (finish_enum): Pop obstacks. + (store_parm_decls): When clearing ->names, clear out the values + from the identifiers, restore shadowed values, and clear ->shadowed. + + * c-decl.c (grokdeclarator): Don't warn of const or volatile function + in a system header file. + + * sdbout.c: Don't use system syms.h on hpux. + + * cccp.c (do_xifdef): Skip all kinds of whitespace, in bof test. + + Wed Sep 30 15:09:10 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sparc.md (orcc peephole): Don't accept FP reg for operand 0. + + Wed Sep 30 00:47:48 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h, gvarargs.h: Use <...> to include va-*.h. + + * c-decl.c (start_struct): Push the obstacks. + Switch to permanent if at top level. + (finish_struct): Pop them. + + * c-decl.c (store_parm_decls): If we have (erroneously) a prototype + and old-style parm decls, throw away the old-style parm decls. + + * configure: Default $build after $host. Canonicalize all three + config names before the main dispatch and save in $canon_host, etc. + Write these into config.status and on terminal at the end. + + Tue Sep 29 18:41:54 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * unroll.c (find_splittable_givs): recog_memoized failure return + is -1 not 0. + + Tue Sep 29 22:19:48 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) + + * config.sub (os handling): Recognize `linux' as a valid os. + + Tue Sep 29 16:05:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * limitx.h: Use <...> in #include. + + * Makefile.in (ENQUIRE_CFLAGS): Remove -DNO_SC. + + Tue Sep 29 10:14:27 1992 Richard Kenner (kenner@.vlsi1.ultra.nyu.edu) + + * optabs.c (expand_binop): Convert X - C to X + (-C). + + Mon Sep 28 22:44:17 1992 Jim Wilson (wilson@cygnus.com) + + * reload.c (find_reloads_address): If tem != ad, then create a new + mem to hold it and store it back into memrefloc. + + Mon Sep 28 10:44:55 1992 Chip Salzenberg (chip@tct.com) + + * regclass.c: Fix comment syntax after #endif. + + Mon Sep 28 17:15:22 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h (va_arg, va_start): Explicitly cast to __gnuc_va_alist. + + Mon Sep 28 17:12:04 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * unroll.c (copy_loop_body, JUMP_INSN case): When invert jump + insn, must first construct new insn before trying to invert it, + so that validate_change will work properly. + + * unroll.c (find_splittable_givs): Pass mem_mode not mode to + memory_address_p. + + * unroll.c (copy_loop_body, JUMP_INSN case): When setting + JUMP_LABEL field, verify that what we think is a label actually + is. If it isn't then map the old JUMP_LABEL to find the new one. + + * sparc.md (orcc peephole): Don't allow FP regs to match pattern. + + * i960.md (indirect_jump): Use bx instead of b*, and accept any + address_operand instead of just a register operand. + + * i960.c (i960_round_tree): Correct conversion of bits to bytes to + round up to nearest byte. + (i960_round_align): Likewise. + + Mon Sep 28 15:54:18 1992 Michael Meissner (meissner@osf.org) + + * dec-osf1.h (LINK_SPEC): Fix typo. + + Mon Sep 28 08:15:02 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * rs6000.md (subsi3): Remove last change. + (allocate_stack): Go back to calling subsi3. + + Mon Sep 28 02:41:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * optabs.c (expand_binop): Use get_insns, not gen_sequence. + + * c-typeck.c (build_unary_op): Address of nested fcn isn't constant. + + * libgcc2.c (__builtin_new): Avoid passing 0 to malloc. + + * m68k.md (indirect_jump): Use address_operand as predicate. + + * c-decl.c (finish_decl): Do the pop_obstacks sooner, when it's + time to start allocating in the ambient context's obstack. + Don't call permanent_allocation unless got back to permanent obstack. + + Sun Sep 27 13:06:19 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * function.c (assign_parms): If PROMOTE_FUNCTION_ARGS is defined, + see if the incoming register should be used in a wider mode. + (expand_function_start): Likewise for return value if + PROMOTE_FUNCTION_RETURN is defined. + * calls.c (struct arg_data): New field unsignedp. + (expand_call): Handle PROMOTE_FUNCTION_ARGS and + PROMOTE_FUNCTION_RETURN. + + * alpha.h (FUNCTION_VALUE): Promote mode for return value. + + * alpha.h (BYTE_LOADS_SIGN_EXTEND): Define. + + * rs6000.md (subsi3): Don't bother calling negate_rtx for constant; + we shouldn't be called with a constant. + (maskir patterns): Don't mention an operand before it is used; + use operand number 1 for operand with '0' constraint. + (allocate_stack): Use reg_or_short_operand for predicate of + allocation amount; use negate_rtx and always make a PLUS. + + * romp.h (EXTRA_CONSTRAINT, case 'Q'): Check for MEM instead of + calling memory_operand. + (SHIFT_COUNT_TRUNCATED): No longer define this. + + Sat Sep 26 18:14:15 1992 Michael Meissner (meissner@osf.org) + + * config.sub (os handling): Recognize riscos as an operating + system. + + * configure (dec-osf1): Use x-decstatn for xmake_file. + (mips computers): Handle RISC-OS 5 vs. RISC-OS 4 configuration + changes -- RISC-OS 5. passes -non_shared by default. + + * mips-5.h (new file): RISC-OS rev 5 config file. + * mips-5bsd.h (new file): RISC-OS rev 5, bsd 4.3 config file. + * mips-5g4.h (new file): RISC-OS rev 5, svr4 + stabs config file. + * mips-5gbsd.h (new file): RISC-OS rev 5, bsd 4.3 + stabs config file. + * mips-5gdb.h (new file): RISC-OS rev 5 + stabs config file. + * mips-5gsysv.h (new file): RISC-OS rev 5 svr3 + stabs config file. + * mips-5svr4.h (new file): RISC-OS rev 5 svr4 + stabs config file. + * mips-5sysv.h (new file): RISC-OS rev 5 svr3 config file. + + * dec-osf1.h (LINK_SPEC): Pass -non_shared to linker unless + -shared was passed. + (SIZE_TYPE): Define as long unsigned int. + (PTRDIFF_TYPE): Define as int. + (WCHAR_TYPE_SIZE): Define as SHORT_TYPE_SIZE. + + * decrose.h (MACHINE_TYPE): Shorten verbage. + + * i386rose.h (TARGET_VERSION): Print appropriate information. + + * xm-mips.h (HAVE_VFPRINTF, HAVE_PUTENV): Define on DEC OSF/1. + + * mips.c (siginfo): Print just current filename, and function + being compiled. + + * mips-tfile.c (Size_t): Use long unsigned on OSF/1. + (toplevel): Don't define rindex and index on OSF/1. + + Sat Sep 26 17:46:57 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * arm.md (comment before extendhisi2): Remove the lie. + (zero_extendhisi2): Rewrite to work if op0 == op1. Use + gen_lowpart in preparation code. + (extendqisi2, extendhisi2): Likewise. + (extendqihi2): Expand. + + * arm.md (restorehi): Rewrite for correctness, efficiency, and + clarity. Avoid generating insns involving truncate. Generate + needed pseudos in preparation statements. + (storehi): Likewise. + (storeinthi): Likewise. + (movhi): Call gen_storehi, gen_restorehi, gen_storeinthi according + their new definitions. Use force_reg to put address in register. + + * m68k.md (indirect_jump): Use %a0 for output, and p for constraint. + + Sat Sep 26 02:42:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * reload1.c (eliminate_regs_in_insn): Rerecognize if move insn + becomes a non-move. + + * Makefile.in (install-fixincludes): + Use - when making syslimits.h; fix if-statement syntax. + + * jump.c (jump_optimize): When handling dispatch table that always + goes to the same place, verify previous insn exists. + + * c-typeck.c (common_type): Renable code to merge qualifiers + given two pointers to compatible types. + + Sat Sep 26 12:02:38 PDT 1992 Ron Guilmette (rfg at netocm.com) + + * dwarfout.c (location_attribute): If DECL_RTL looks like (MEM pseudo), + treat that variable as optimized away. + + Fri Sep 25 19:48:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (explicit_flag_signed_bitfields): New variable. + (c_decode_option): Set that for -f[un]signed-bitfields. + (grokdeclarator): If that's set, and -fsigned-bitfields, + disregard -traditional when handling bitfield signedness. + + * configure: Handle --build option. Make link hconfig.h. + * Makefile.in: In the targets such as $(HOST_PREFIX_1)rtl.o, + use sed to make them include hconfig.h instead of config.h. + (distclean): Add command to delete hconfig.h. + + Fri Sep 25 19:56:35 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + * cp-search.c (compute_visibility): Don't mess with the context. + + * cp-decl.c (grokdeclarator): Return value from do_friend + properly; this shouldn't have gone in yet. + + Fri Sep 25 02:23:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (initializer_constant_valid_p): Really use endtype. + + * cccp.c (do_include): "Concatenate" multiple "strings" in #include. + + * vmsconfig.com: Renamed from configure.com. + + * next.h (CPP_PREDEFINES): Define __ARCHITECTURE__. + + * dbxout.c (dbxout_symbol): For anonymous enum, output type anyway. + + Fri Sep 25 01:33:36 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * function.h (struct function): Add epilogue_delay_list field. + * function.c (push_function_context): Save epilogue_delay_list. + (pop_function_context): Restore epilogue_delay_list. + + * sparc.md (nonlocal_goto): Force operands[0] to be a register. + + * va-sparc.h (va_arg): Add 3 more (void *) casts to avoid warnings + with -Wcast-align. + + * sparc.c (SF_MODES): Accept all single word or smaller integer + modes not just SImode. These are needed for fix/float conversions. + + * sched.c (sched_analyze_2, PRE_DEC case): Call sched_analyze_2 in + addition to sched_analyze_1. + + * va-i960.h (va_start): Must access anonymous arg as offset from + start of argument block. + + * i960.md (movdi, movti, movdf, movtf): Make store zero to memory + a separate case, only accept offsettable memory addresses, and call + adj_offsettable_operand to calculate subword addresses. + + * i960.c (i960_output_ldconst): Pass missing xoperands argument to + output_asm_insn call. + + * a29k.md (movti): Split CONST_INTs into 4 moves, and force all + other constants to memory. + + Thu Sep 24 21:51:46 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + Complete Cygnus<-->FSF merge. + + Thu Sep 24 17:05:27 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (pushdecl): Use a friendly abort rather than an assert. + (grokparms): Pass whether init is set or not for the initialized + parameter to grokdeclarator. + + Wed Sep 23 22:09:44 1992 Mike Stump (mrs@cygnus.com) + + * cp-class.c (finish_struct), cp-decl2.c (warn_nonvdtor), + cp-tree.c (layout_basetypes), cp-tree.h (warn_nonvdtor): Re-enable + warnings for non-virtual destructors in some situations. + + Wed Sep 23 15:42:33 1992 Mike Stump (mrs@cygnus.com) + + Wed Sep 23 16:31:27 1992 Michael Meissner (meissner@osf.org) + + * cp-decl.c (duplicate_decls): Cast bcopy arguments to char * to + avoid warning on OSF/1. + + Wed Sep 23 11:36:44 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (start_method): Give the name of the class if a method's + being defined again, rather than say "aggregate scope". + * cp-decl2.c (grokfield, grokbitfield, groktypefield): Ditto. + + Tue Sep 1 22:55:59 1992 Paul Eggert (eggert@twinsun.com) + + * cp-cvt.c (convert_to_integer): Prefer unsigned + arithmetic if the output type is unsigned and is no more precise than + the computation type. This avoids unnecessary sign extension. + + Tue Sep 15 20:26:18 1992 John F Carr (jfc at Athena.MIT.EDU) + + * cp-pt.c (tsubst): Don't call layout_type near start of function + with T. const and volatile attributes don't affect the memory + structure of the type, and T may not yet be a valid argument for + layout_type (for example, if it is an uninstantiated template). + Individual switch cases will call layout_type if necessary. + + Mon Sep 21 15:59:22 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (pushdecl): Check if DECL_SOURCE_LINE is non-zero, not + if DECL_IGNORED_P is set, when checking for shadowing. We no longer + need DECL_IGNORED_P on builtin types. + (record_builtin_type): Don't set DECL_IGNORED_P for a builtin type. + + * cp-decl.c (start_decl): When working with virtual functions, + always use the node's DECL_CLASS_CONTEXT. + * cp-method.c (hack_identifier): Ditto. + * cp-search.c (compute_visibility): Ditto. + + * cp-decl.c (grokdeclarator): Don't allow a member to be declared + extern. + + * cp-decl.c (grokdeclarator): Return a void_type_node if we're + looking at a friend (even after calling do_friend). + (pushdecl): Disable some code that's untested and + doesn't necessarily help DWARF right now. + (finish_function): Always emit debugging info for the + return type of a function. + (pushdecl): Don't change the DECL_CONTEXT of virtual + methods. + (finish_enum): Always output debugging info for enums. + (grokdeclarator): It's an error if we're doing an init of an extern + at the top level. If we are at the top level, just warn. + + * cp-typeck.c (comp_target_parms): Check if strict is non-zero, not + just > 0. + (build_function_call_real): Don't return an error-mark node when + they call "main" from within the fn, it's only a pedantic warning. + (pointer_int_sum): Reword warning when using a ptr-to-mem in arith. + + * cp-tree.c (layout_basetypes): Make record_align and const_size + unsigned. + + Mon Sep 21 14:53:43 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-tree.h (flag_no_ident): Add extern decl for cp-lex.c. + + * cp-decl.c (duplicate_decls): Save the DECL_UID and DECL_FRIEND_P + info from olddecl. Otherwise, they'd get clobbered when newdecl's + contents get copied into olddecl. + + * cp-lex.c (check_newline): Delete pedantic error about using #ident, + since cccp.c already gives a warning. In the case that + ASM_OUTPUT_IDENT is defined, only actually spit it out if flag_no_ident + is not set. + + Sat Sep 19 14:53:31 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + Sat Sep 19 11:37:11 1992 John F Carr (jfc at Athena.MIT.EDU) + + * cp-decl.c (finish_decl): Don't call + CLASSTYPE_DECLARED_EXCEPTION if TYPE is error_mark_node, to avoid + referencing a nonexistent field. + + Fri Sep 18 14:06:06 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-parse.y (component_decl): Remove sorry about not implementing + methods in anonymous unions---they're illegal, and we generate an + error elsewhere to that effect. + + * cp-decl.c (start_method): Make the error message about a + duplicated member a little more informative. + + Fri Sep 18 12:28:13 1992 Brendan Kehoe (brendan at rtl.cygnus.com) + + * cp-parse.y: Define YYDEBUG if SPEW_DEBUG is defined. + (debug_yytranslate): YYDEBUG will always be defined, no need to test. + + Fri Sep 18 10:46:19 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-parse.y (unary_expr): When parsing delete, first complain if + it's a non-pointer, then check if it's a pointer with the value zero. + Also be sure not to call build_delete if that's the case. + + Thu Sep 24 18:03:07 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Set Meissner version # to 27. + (STRUCT_VALUE_REGNUM): Delete macro. + (STRUCT_VALUE): Define as 0, so that structure return addresses + are passed as the first argument. This fixes various codegen + problems with functions returning structures. + + * mips.c (init_cumulative_args): Don't advance arg pointer if + function returns a structure. + + Thu Sep 24 12:38:31 1992 Torbjorn Granlund (tege@wombat.gnu.ai.mit.edu) + + * pa.h (REGISTER_MOVE_COST): Fix typo. Use `||' instead of `|'. + (REG_CLASS_FROM_LETTER): Don't handle 'r' constraints here. + * pa.c (clobbered_register): Delete. + (srcsi_operand): Return 1 also for things matching + depi_cint_operand. + (secondary_reload_class): Replace. + * pa.md (ldo/ldil SImode and HImode recognizers): Use + "const_int_operand" for operand 1 and simplify final condition. + Remove `n' constraint. + (depi SImode and HImode recognizers): Remove `n' constraint. + (plus:SI ... high ... splitter): Don't overwrite input, go via + clobber operand instead. + (many patterns): Replace `in' constraint with just `i'. + (movstrsi): Don't do (clobber (match_scratch)), use explicit + pseudos instead, generated in preparation C code. Don't call + force_not_mem for operand 2. + (movstrsi recognizer): Add `&' to operand 3. + (andsi3): Fix typo. + (iorsi3): Fix typo. + (load-shift-16): New optimizer. + (load-shift optimizers): Set "type" attr. + + Thu Sep 24 15:17:38 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * toplev.c (lang_options): Add Objc options. + + * configure.bat: Use xgcc, not gcc. + + Thu Sep 24 06:30:47 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * c-lex.c (yylex, case '"'): Initialize arg pased to readescape. + + * genattrtab.c (length_used): New variable. + (walk_attr_value): Set it when we have (eq_attr "length" ...). + (write_const_num_delay_slots): Value is 1 unless LENGTH_USED is set. + + * reorg.c (mark_set_resources, case CC0): Set RES->CC if IN_SEST. + + * regclass.c (forbidden_inc_dec_class, in_inc_dec): New variables. + (regclass): Don't alloca the costs twice. + Initialize forbidden_inc_dec_class. + For regs that have inc-dec, ignore forbidden classes. + (record_address_regs): Update in_inc_dec. + + Thu Sep 24 02:36:00 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * syslimits.h: New file, includes system's limits.h. + * limitx.h: Include syslimits.h instead of system's limits.h. + * Makefile.in (USER_H): Add syslimits.h. + (install-fixincludes): If we fix system's limits.h, install that + as syslimits.h + + * c-lex.c (readescape): New arg ignore_ptr. + (yylex): Pass new arg, handle result that comes back. + + Wed Sep 23 19:26:42 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * reload.c (find_reloads_address): Properly check for constant address. + + * cse.c (simplify_unary_operation, case SIGN_EXTEND): Use + HOST_BITS_PER_WIDE_INT, not HOST_BITS_PER_INT. + + * fold-const.c (fold_convert): Add missing cast to HOST_WIDE_INT. + + * jump.c (jump_optimize): Tighten up test for when we can't + delete a set of CC0. + Don't insert insns between set and use of CC0. + + * final.c (shorten_branches): Correctly access insn needing delay slot. + + * combine.c (significant_bits, num_sign_bit_copies): Handle SUBREGs + made for promoted variables. + + * reorg.c (fill_simple_delay_slots): Don't make copy of insn that + references CC0. + + * romp.md (define_attr "type"): New type "ibranch". + (define_attr "length"): Set length for "ibranch" type. + (define_attr "in_delay_slot"): Add new type "ibranch"; + for "branch", only has delay slot if length is 4. + (define_attr "cc_type"): Add new type "ibranch". + (indirect branches): Now type "ibranch". + + * alpha.c (alpha_gp_dead_after): Return 0 if not optimizing. + + Wed Sep 23 00:11:35 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gvarargs.h: Finish changing _ANSI_H to _ANSI_H_. + + Tue Sep 22 23:39:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * i386mach.h (perform_fixdfsi): Copy arg to memory variable. + + Tue Sep 22 14:54:38 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * loop.c (basic_induction_var): Inside PLUS, when looking for promoted + var, make sure it's a REG. + + Tue Sep 22 12:21:11 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Bump Meissner version # to 26. + (REG_PARM_STACK_SPACE): Use UNITS_PER_WORD instead of 4, and + substract FIRST_PARM_OFFSET. + (FIRST_PARM_CALLER_OFFSET): Delete unused macro. + + * mips.c (init_cumulative_args): Print types of fntype and the + return type if -mdebuge. + + * decrose.h (CPP_SPEC): Eliminate defining various builtin + functions with -D=__builtin_, if neither -fbuiltin nor + -fno-builtin were passed. + (CC1_SPEC): Eliminate passing -fno-builtin to the compiler if + neither -fbuiltin nor -fno-builtin were passed. Eliminate + %{save-temps: } since gcc no longer gives an unknown switch + message if it is used. + + * i386rose.h (CPP_SPEC): Eliminate defining various builtin + functions with -D=__builtin_, if neither -fbuiltin nor + -fno-builtin were passed. + (CC1_SPEC): Eliminate passing -fno-builtin to the compiler if + neither -fbuiltin nor -fno-builtin were passed. Eliminate + %{save-temps: } since gcc no longer gives an unknown switch + message if it is used. + (MASK_HALF_PIC): Move bit mask to 0x40000000, to allow for i386.h + to define more switches without overlapping our private switch. + (TARGET switches): Add -mdebugb to debug half-pic code. + (OPTIMIZATION_OPTIONS): Only set flag_gnu_linker FALSE always, and + flag_inline_functions if -O3. In particular never set + -fomit-frame-pointer which currently messes up debugging. + (GO_IF_LEGITIMATE_ADDRESS): Define i386-osfrose version that deals + with half-pic. + (OVERRIDE_OPTIONS): Define to initialize half-pic. + (ASM_FILE_END): Define to dump out half-pic variables if needed. + + * t-i386rose (EXTRA_OBJS): Define as halfpic.o. + (CONFIG2_H): Add $(srcdir)/halfpic.h. + (halfpic.o): Add dependencies. + + Tue Sep 22 03:12:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * reload1.c (choose_reload_regs): When setting reg_has_output_reload, + loop over multiple regs only for hard reg. Set reg_is_output_reload + in separate loop. + + Mon Sep 21 12:22:24 1992 Jeffrey A. Law (law@mole.gnu.ai.mit.edu) + + * reorg.c (mark_set_resources, case REG): A register is set iff + "in_dest" is nonzero. + + Mon Sep 21 14:16:10 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * combine.c (make_extraction): Make test whether to use AND or + {SIGN,ZERO}_EXTRACT depend on UNSIGNEDP. + + Mon Sep 21 08:26:55 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * reload1.c (reload): If we can't get a register that we know won't + interfere with groups, get one that might instead of giving up. + + * reload1.c (reload): Print the needs to the dump file. + + Mon Sep 21 02:45:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * function.c (put_var_into_stack): Check REG != 0 before dereference. + + Sun Sep 20 16:58:05 1992 Fred Fish (fnf at fishpond.cygnus.com) + + * x-svr4: New generic SVR4 host makefile fragment. + * x-i386v4: File deleted. + * x-ncr3000: Get alloca using ALLOCA, not libucb.a. + * configure (i386-*-sysv4*): Use x-svr4, not x-i386v4. + * configure (i486-*-sysv4*): Use x-svr4. + + Sun Sep 20 21:18:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * combine.c (subst): Set and compare extend_op with 0, not NULL. + + * cse.c (find_comparison_args): New args PMODE1, PMODE2. + (fold_rtx, record_jump_equiv): Use them to get modes of comparison. + (fold_rtx): Associate MINUS with nested PLUS. + + * seq386.h (LPREFIX): Overridden as `.L'. + (ASM_GENERATE_INTERNAL_LABEL, ASM_OUTPUT_INTERNAL_LABEL): Likewise. + + Sun Sep 20 05:53:20 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (try_combine): Always call set_significant on new + patterns, so don't call just in split case. + + * combine.c (subst): Move sign extension inside arithmetic + when we have a constant computation inside another computation. + + * emit-rtl.c (emit_insn_after_with_line_notes): New function. + * jump.c (jump_optimize): Delete insns that set registers that + are not used elsewhere. + Fix some bugs in "if (...) x = a; else x = b;" code. + Remove uses of reorder_insns. + Add code to make scc insns for "if (...) x = exp;" if EXP is simple + enough. + Optimize "if (...) x = b;" if jumps very expensive; don't use a REG + as the older value of X since it doesn't help and can hurt. + Correctly place generated insns in above case. + + * reload.c (find_reloads, find_reloads_toplev): Treat + BYTE_LOADS_SIGN_EXTEND just like BYTE_LOADS_ZERO_EXTEND. + * combine.c (subst, simplify_and_const_int, significant_bits): + Likewise. + (num_sign_bit_copies, case MEM): New case for BYTE_LOADS_SIGN_EXTEND. + (num_sign_bit_copies, case SUBREG): Handle just like significant_bits. + + Sat Sep 19 15:55:31 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (combine_instructions): Clear significant_valid + at end of combine pass for a function. + (find_split_point, case MEM): See if first operand of the PLUS + that makes up an address is complex. + (subst): Add missing arg to recursive calls when IF_THEN_ELSE + is an arg of an operator. + (subst, case IF_THEN_ELSE): Generalize code to propagate comparison + result into arms by using known_cond. + If an arm is the first operand of the comparison, make it the + true arm. + Remove unneeded comparison when arms are identical. + Try to convert IF_THEN_ELSE to ABS, (neg (abs X)), [US]MIN, [US]MAX. + Convert (if_then_else (ne A 0) (OP X C) X) to (OP X (mult A C)). + (subst, case SET): If we don't have conditional moves, + convert IF_THEN_ELSE into logical operations. + (subst, case AND): Always make conditional moves, even if we + don't support them on the machine. + (known_cond, extended_count): New functions. + (gen_binary): For commutative operations, put constant last. + + * combine.c (try_combine): The insns made by a DEFINE_SPLIT might + contain a PARALLEL and the call to recog_for_combine might add it. + + * combine.c (simplify_comparison, case ASHIFT): Fix typo. + + * combine.c (try_combine): When removing REG_UNUSED note, + update reg_n_deaths. + Likewise, when making new REG_DEAD notes for distribute_notes. + (remove_death, move_deaths): Update reg_n_deaths. + (distribute_notes): When placing second REG_DEAD or REG_UNUSED note or + ignoring such a note, update reg_n_deaths. + + * rtl.h (SUBREG_PROMOTED_{VAR,UNSIGNED}_P): New macros. + * tree.h (DECL_MODE, DECL_RTL): Update comments. + * expr.h (PROMOTE_MODE): Provide default definition. + * expr.c (convert_move, convert_to_mode): Strip off a SUBREG made + for variables with promoted modes. + (store_expr): Store into variables with promoted modes by + doing the appropriate extension operation. + (expand_expr, case VAR_DECL): Generate SUBREGs for promoted objects. + (expand_expr, case SAVE_EXPR): Likewise for SAVE_EXPRs. + (expand_increment): Handle increment of promoted objects. + * function.c (fixup_var_refs{,_insns}): Add new parms for promoted + mode and signedness; all callers changed. + Insert mode conversions when required. + (fixup_var_refs_1): Add new parms for mode and signedness; + handle SUBREGs for promoted values. + (assign_parms): Promote the mode of parameters when useful for + the target machine. + * function.h (struct var_refs_queue): Remove unused field ORIGINAL. + Add new fields PROMOTED_MODE and UNSIGNEDP. + * integrate.c (expand_inline_function): Convert actual to formal's + mode (in case formal was promoted). + * loop.c (basic_induction_var): Add new parameter P. + Check for bivs that are set over multiple insns and also + allow a SIGN_EXTEND to be used; remove check for MINUS since + we don't make MINUS with a constant 2nd operand any more. + * optabs.c (expand_binop, expand_unop): Don't make SUBREG for promoted + variables as operands. + * stmt.c (tail_recursion_args): Use mode of DECL_RTL, not + DECL_MODE. + (expand_decl): Promote modes of scalar variables when useful on + target. + * unroll.c (find_splittable_regs): If any BIV update isn't + simple, don't split it. + (final_giv_value): Look for biv updates by matching insns; don't + try to reparse the insn. + * rs6000.h (PROMOTE_MODE): New macro. + + * rtlanal.c (reg_set_last): Allow old value to be a SUBREG. + + * rs6000.c (print_operand, case 'h', 'H', 'w'): Minor cleanups. + * rs6000.h (BRANCH_COST): Increase from 2 to 3. + * rs6000.md (smax, smin, umax, umin): Add define_splits. + + * alpha.h (PROMOTE_MODE): New macro. + (REG_ALLOC_ORDER): Put $0 in front of $21-$16. + (CONST_OK_FOR_LETTER): Change meanings of N, O, and P. + (BRANCH_COST): Increase from 3 to 4. + (PREDICATE_CODES): Add new predicates reg_or_cint_operand and + sext_add_operand. + * alpha.md (addsi3): subl can be used to sign-extend addition of + small negative constants. + (negsi2): Add pattern for (sign_extend (neg ..)). + (and pattern): Fix typo in constraint. + (ashldi3): Use new definition of constant letters. + (smax, smin, umax, umin): Add define_splits. + (compares): Can compare constant with zero by adding negative of + constant. + (store insns): Can store 0 into memory in both integer and FP. + * alpha.c (sext_add_operand, reg_or_cint_operand): New function.s + (print_operand, case 'r', case 'R'): Clean up code; use CONST0_RTX. + + * rtl.c (note_insn_name): Fix typo: had NOT_INSN_DELETED_LABEL. + + * jump.c (delete_insn): Don't change labels to NOTEs if we would + not really have deleted them. + + * genconfig.c (walk_insn_part, case IF_THEN_ELSE): Refine when + HAVE_CMOVE_FLAG gets set. + + Sat Sep 19 14:52:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * reload.c (find_reloads): Always use >= with FIRST_PSEUDO_REGISTER. + + * i386mach.h (SIZE_TYPE): Defined. + + Sat Sep 19 04:57:06 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * i386.md (sCOND patterns): Don't allow a MEM in the SET_DEST, + because these insns can't have input reloads, and a MEM might need + an input address reload. + + * fold-const.c (fold_convert): Avoid using conversion of unsigned + to floating; offset value by hand to fit in signed type. + + Sat Sep 19 00:50:32 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * integrate.c (subst_constants): Do substitute in address of MEM dest. + + * reload1.c (init_reload): Fix typo. + + Fri Sep 18 21:09:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * libgcc2.c: Declare _exit as volatile. + + * function.c (assign_parms): Set MEM_IN_STRUCT_P right in stack slots. + + Fri Sep 18 15:58:15 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * fixincludes: Don't look for *.h symlinks if the host doesn't + have symlinks. + + Fri Sep 18 17:34:27 1992 Michael Meissner (meissner@osf.org) + + * mips.md (call_internal): If the memory address to call is really + a constant integer, load it up into $at and do the call from + there. + (call_value_internal): Ditto. + + Fri Sep 18 03:48:17 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.c (m88k_volatile_code): New variable. + (print_operand): Track volatile memory references and output a + serializing instruction before a load when necessary. + * m88k.h (TARGET_SWITCHES): Add -m{no,}serialize-volatile. + (OVERRIDE_OPTIONS): -m88110 and -m88000 imply -mserilize-volatile. + (ADJUST_INSN_LENGTH): Volatile memory operantions may be longer. + (CC_STATUS_INIT): Reset m88k_volatile_code to the unknown state. + * m88k.md (load store patterns): Prepend loads and stores with %V + and %v to track the type and address of the access. + + * m88k.c (m88k_version, m88k_version_0300): New variables. + * m88k.h (TARGET_OPTIONS): Generalize to -mversion-STRING. + (OVERRIDE_OPTIONS): Compute m88k_version_0300. + * m88k.md (call_movstrsi_loop): Renamed from call_block_move_loop. + Use call-value for the block move patterns. + + * m88kdgux.h (PERFERRED_DEBUGGING_TYPE): Compute based on + m88k_version. + (CPU_DEFAULT): Make it -m88000. + + * m88k.h: Don't use #elif + + Fri Sep 18 01:08:55 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (install-common-headers): Don't copy byteorder.h. + + Thu Sep 17 20:06:22 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + Complete 13th Cygnus<-->FSF merge. + + Thu Sep 17 13:15:15 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + Do some much-needed housecleaning of the C++ front-end. + * cp-call.c (ideal_candidate): Move `p2' down inside #if 0'd (only) + section that actually uses it. Delete unused variable `buf'. + (build_method_call): Delete unused variable `dtor_specd'. + * cp-class.c (finish_struct): Delete unused variable `basetype'. + * cp-cvt.c (convert_to_aggr): Add missing argument decl for `protect'. + (convert_pointer_to): Delete unused variable `form'. + * cp-decl.c: Include string.h/strings.h for strncpy() decl. + Add decls for init_* fns. Delete unused decl `push_overload_decl_1'. + Don't use `c_function_varargs', C++ doesn't need it. + (push_binding_level): Add missing argument decls for + `tag_transparent' and `keep'. + (lookup_tag): Add missing argument decl for `tags_transparent'. + (lookup_name): Add missing argument decl for `prefer_type'. + (start_decl): Delete unused variables `classname' and `tmpl'. + (grokvardecl): Add missing argument decl for `initialized'. + (grokdeclarator): Delete unused variable `t'. + * cp-decl2.c (get_temp_name): Delete unused variable `temp'. + (finish_table): Delete unused variable `publicp'. + (finish_builtin_type): Add missing argument decl for `len'. + (finish_file): Delete unused variables `asm_out_file' and + `init_function_name'. + * cp-except.c (ansi_exception_object_lookup): Add missing + argument decl for `type'. + (cplus_expand_throw): Delete unused variables `cname', `name', + and `raise_id'. + * cp-init.c: Delete unneeded forward decl of `init_init_processing'. + (build_new): Delete unused variable `alignment'. + (expand_vec_init): Add missing argument decl for `from_array'. + (build_vec_delete): Delete unused variable `rval'. + * cp-input.c (feed_input): Add missing argument decl for `len'. + * cp-lex.c: Delete unused variable `nextlastiddecl'. + (check_newline): Delete unused variable `tmp'. Place `asm_out_file' + inside a conditional for ASM_OUTPUT_IDENT. + (real_yylex): Delete unused variable `typename_scope_in_progress' + and unused labels `relex' and `reswitch'. + * cp-method.c: Include string.h/strings.h for strncpy() decl. + (new_text_len): Deleted. + (dump_type_prefix): Delete unused variables `print_struct' and `name'. + (dump_tyupe): Delete unused variable `print_struct'. + (type_as_string): Delete unused variable `spaces'. + (do_inline_function_hair): Delete unused variable `cname'. + (flush_repeats): Delete unused variable `rval'. + (build_t_desc_overload): Delete unused variable `i'. + (build_opfncall): Add missing argument decl for `flags'. + (hack_identifier): Add missing argument decl for `yychar'. + * cp-parse.y (template_instantiate_once): Delete unused + variables `id' and `members'. + * cp-search.c (lookup_field): Add missing argument decl for `want_type'. + (tree_needs_constructor_p): Add missing argument decl for `i'. + (dfs_debug_mark): Delete unused variable `pending_vtables'. + (dfs_get_vbase_types): Delete unused variable `basetype'. + * cp-spew.c (init_spew): Delete unused variables `pc' and + `chars_following_typename'. + (yylex): Delete unused variables `dk' and `tmp'. Move decl of `t2' down + to the block that actually uses it. + * cp-tree.c (build_cplus_staticfn_type): Delete unused variable `ptype'. + (propagate_binfo_offsets): Delete unused variables `t' and `basetype'. + (layout_basetypes): Delete unused variable `binfo'. + (array_type_nelts_total): Delete unused variable `index_type'. + * cp-tree.h: Add many decls. + * cp-typeck.c (comp_array_types): Add missing argument decl + for `strict'. + (build_compound_expr): Delete unused variable `tmp'. + (convert_for_initialization): Delete unused label `converted'. + + Wed Sep 16 12:51:10 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (init_decl_processing): Enable code to add sin and cos + as built-in functions. + + * cp-decl.c (duplicate_decls): Enable code to preserve the DECL_UID + of olddecl. + + * cp-search.c (lookup_nested_fields): Make sure we're climbing along + a chain of nested types, and nothing else. + + Tue Sep 15 17:38:34 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-search.c (lookup_nested_fields): New function. + * cp-tree.h: Declare it. + * cp-decl.c (lookup_name): Call it if there's no class-local + definition. (It could be nested.) + * cp-lex.c (do_identifier): Call lookup_nested_field() if necessary. + + Tue Sep 15 12:37:16 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + Mon Aug 24 14:58:02 1992 Chip Salzenberg (chip at animal) + + * cp-typeck.c (build_conditional_expr): Determine constness + and volatility with TREE_... tests instead of TYPE_... tests. + + Mon Sep 14 18:00:35 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (grokdeclarator): Remove redundant (and broken) + test for multiple destructors in a class. + + Fri Jul 31 19:09:10 1992 Chip Salzenberg (chip@tct.com) + + * cp-cvt.c (convert_to_integer): Push truncation inside COND_EXPR. + + Mon Sep 14 17:52:45 1992 Chip Salzenberg (chip@tct.com) + + * cp-class.c (finish_struct): Always write all structure types, + even if they're defined in a "#pragma interface" header file. + Otherwise, XCOFF debugging info is messed up. + + Mon Sep 14 17:39:32 1992 Chip Salzenberg (chip@tct.com) + + * cp-class.c (finish_struct): ``Actually, I don't understand + this code. What is it supposed to do?'' --Niklas Hallqvist + + Mon Sep 14 17:27:23 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (finish_decl): Don't dump core if a decl is anonymous. + A decl is at the global binding level if DECL_CONTEXT is null. + (grokdeclarator): Don't globalize a type if its first mention + is in a parameter. It's okay to initialize a function in a + non-global scope. + + Tue Sep 15 12:15:26 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-typeck.c (c_expand_return): Emit a warning when they try to + return the address of a local variable. + + * cp-decl.c (finish_method): Make sure it's indeed nested before + checking for the qualified name. + + Mon Sep 14 18:59:25 1992 Mike Stump (mrs@cygnus.com) + + Wed Sep 2 11:04:24 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (init_decl_processing): Add sin and cos as built-in + functions. Fix type of __builtin_constant_p. + + * cp-lex.c (readescape): For \x, don't include leading 0's in count. + + * cp-typeck.c (build_unary_op): For ADDR_EXPR, just set + TREE_CONSTANT if staticp, but don't clear TREE_CONSTANT. + + Mon Sep 14 18:54:41 1992 Mike Stump (mrs@cygnus.com) + + * cp-parse.y (permanent_obstack): Move to top of file. + + Mon Sep 14 18:50:19 1992 Mike Stump (mrs@cygnus.com) + + Mon Sep 14 16:39:10 1992 Chip Salzenberg (chip@tct.com) + + [ Changes propagated from diffs to c-* in 920911 snapshot. ] + + * cp-decl.c (duplicate_decls): Set DECL_INLINE in newdecl so it + is copied into olddecl. Don't set DECL_EXTERNAL in olddecl. + Preserve DECL_UID and DECL_FRIEND_P of olddecl. + + * cp-typeck.c (build_binary_op_nodefault): Don't assume that a + target integer fits in a HOST_WIDE_INT when checking shift widths. + + Mon Sep 14 18:15:42 1992 Mike Stump (mrs@cygnus.com) + + Mon Aug 24 14:32:03 1992 Chip Salzenberg (chip@tct.com) + + * cp-parse.y (reserved_declspecs): Warn if storage class occurs here. + (declmods): Warn if storage class is not first. + + Mon Sep 14 16:59:53 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-method.c (fndecl_as_string): Don't output an extra space when + printing the return type of a function. + + Mon Sep 14 16:01:53 1992 Mike Stump (mrs@cygnus.com) + + Fri Jun 12 18:07:00 1992 Niklas Hallqvist (niklas@appli.se) + + * cp-parse.y (structsp, named_class_head_sans_basetype): Call + overload_template_name in the case of template specializations so + that something like: + + template struct C { C(); }; + struct C { C(); }; + + works. + + Mon Sep 14 15:51:22 1992 Mike Stump (mrs@cygnus.com) + + Fri Apr 10 13:20:56 1992 Niklas Hallqvist (niklas@appli.se) + + * cp-spew.c (spew_debug): exported this flag for use in cp-decl.c + (template_type_seen_before_scope): new global containing contextual + information for the parser, making the compiler grok nested types in + template classes. + (shift_tokens): Guard bcopy calls against moves of zero size. + (yylex): Handle nested types in template classes. + + * cp-parse.y (scoped_typename): Handle nested types in template + classes. + (template_type): Likewise. + (base_class.1): Likewise. + (member_init): Likewise. + (scoped_baseclass): New rule for handling of nested types in + template classes. + + * cp-decl.c (xref_defn_tag): Conditionalized debug printout on + spew_debug (defined in cp-spew.c). + (binding_levels_sane): void function returned value. + + Mon Sep 14 15:41:28 1992 Mike Stump (mrs@cygnus.com) + + Mon Sep 14 17:26:18 1992 Chip Salzenberg (chip@tct.com) + + * cp-parse.y (unary_expr), cp-call.c (build_scoped_method_call): + NEVER use `maybe_adjust' feature in destructors. It's unsafe. + + Mon Sep 14 15:12:34 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (finish_method): Complain when a qualifier is used as + part of a member declaration. + + Mon Sep 14 11:47:30 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl2.c (groktypefield): Revert Wed Aug 19 14:47:08 1992 + change as it breaks template constructor declarations. Gez, this + code is horribly complex, and the comments are wrong. Note, + template constructor definitions are broken in the same way, as + declarations were with this patch in. + + Fri Sep 11 14:09:01 1992 Mike Stump (mrs@cygnus.com) + + Fri Sep 11 10:34:45 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * cp-decl.c (duplicate_decls): For file-scope redefinitions, note + that the variable was previously *defined* at some specific (earlier) + point. + + Fri Sep 11 13:49:55 1992 Mike Stump (mrs@cygnus.com) + + Tue Sep 8 21:39:35 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * cp-decl2.c (finish_file): Don't pass `1's as the `functionbody' + flag to `poplevel' when getting ready to finishing up the per- + compilation-unit constructors and destructors. + + Fri Sep 11 13:28:02 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (grokdeclarator): Upgrade local externs with + initializations to be errors, instead of warnings. + + Fri Sep 11 13:03:52 1992 Mike Stump (mrs@cygnus.com) + + Thu Sep 10 09:40:56 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * cp-decl.c (grokdeclarator): Given an error if *either* a `static' + or an `extern' specifier is attached to a defining declaration of a + static data member. + + Wed Sep 9 19:46:43 1992 Mike Stump (mrs@cygnus.com) + + * c++: Makes sure echo -nostdinc does not eat the -nostdinc. + + Tue Sep 8 13:42:35 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-typeck.c (common_type, case FUNCTION_TYPE): An empty argument + list is represented as a void_type_node; make sure we check for + that, and not just an empty TYPE_ARG_TYPES list on either side. + + Tue Sep 8 02:31:05 1992 Mike Stump (mrs@cygnus.com) + + * cp-tree.c (layout_basetypes, make_binfo): Added support for + debugging information about virtual base class pointers. + + Mon Sep 7 15:34:58 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl2.c (temp_name_p): Deleted function, never used anywhere. + + Sun Sep 6 23:09:29 1992 John F Carr (jfc at Athena.MIT.EDU) + + * cp-typeck.c (convert_arguments): Ignore arguments which are + ERROR_MARK_NODE to avoid crashes trying to reference fields which + are not present. + + Mon Sep 7 12:34:09 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (clear_anon_tags): Do assignment of B after we've seen + if we're to work on an anonymous aggregate. No need to make the + assignment for nearly every aggr we ever declare. + + Sun Sep 6 17:51:47 1992 Mike Stump (mrs@cygnus.com) + + Sun Sep 6 13:12:16 1992 John Carr (jfc@Athena.MIT.EDU) + + * cp-decl.c (pushdecl, finish_decl, store_return_init, + finish_function), cp-decl2.c (constructor_name, finish_file), + cp-except.c (cplus_expand_reraise), cp-init.c (emit_base_init, + expand_aggr_init_1), cp-typeck.c (build_modify_expr, + c_expand_asm_operands, c_expand_return): Include rtl.h and eliminate + unneeded casts. + + * cp-decl2.c (grokbitfield): Use NULL_TREE instead of NULL. + + * cp-decl2.c (finish_file): Don't try and not use stdio.h. + + * cp-except.c (cplus_expand_reraise): emit_move_insn takes 2 + arguments, not three. + + Sat Sep 5 12:04:06 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (finish_function): Undo change of Mon Aug 17 16:28:48 + 1992; it resulted in lots of unnecessary and incorrect warnings. + + * cp-lex.c (do_identifier): For nested classes, check if a variable + being sought is actually in the scope of an enclosing class. If it + is, and the variable's non-static, bail. + + * cp-decl.c (grok_enum_decls): Tighten up some code that was pretty + twisty. + + * cp-class.c (start_struct): Delete; it was #if 0'd out anyway (C++ + doesn't need it), and is an old hold-over from c-decl.c. + + * cp-class.c (minus_one_node): Delete, it's not used. + (init_class_processing): Delete init of minus_one_node. + + * cp-spew.c (yylex): Check return of resolve_scope_to_name to + be NULL_TREE. + (frob_identifier): Likewise. + (hack_more_ids): Likewise. + + * cp-cvt.c (convert_to_real): Use REAL_VALUE_ATOF to make 0. + + Fri Sep 4 19:23:17 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (grok_ctor_properties): When looking for copy + constructors, ignore the first argument since it is the in$chrg + parameter for the object to copy from. + + Fri Sep 4 14:35:31 1992 Mike Stump (mrs@cygnus.com) + + * cp-cvt.c (build_up_reference): Prevent the compiler from dumping + core on semantic errors. + + Thu Sep 17 17:28:13 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (initializer_constant_valid_p): Warn about address + arithmetic destined for a type that's too narrow. + New argument ENDTYPE. + + * limitx.h: Don't include-next if _LIBC_LIMITS_H_ defined. + + Thu Sep 17 20:45:16 1992 Paul Eggert (eggert@twinsun.com) + + * cexp.y (parse_escape): Diagnose '\x' with no digits. + Diagnose integer overflow when parsing \x escapes. + + Thu Sep 17 11:52:53 1992 Michael Meissner (meissner@osf.org) + + * gcc.c (SIGNED_CHAR_SPEC): Use #if rather than ?: in default defn. + + Thu Sep 17 14:53:51 1992 Tim Moore (moore@defmacro.cs.utah.edu) + + * pa.h (FUNCTION_ARG_ADVANCE, FUNCTION_ARG): Fix double integer + argument alignment. + (SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE, WCHAR_SIZE): Define. + * pa-hpux.h, pa-ghpux.h (SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE, + WCHAR_SIZE): Define for hpux. + * x-pa, t-pa : New files. + * configure (hppa cases): add definitions for xmake_file and + tmake_file. + + Wed Sep 16 22:22:15 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * i386.c (print_operand): Don't abort if error: might have been a + user asm. + + * i386.md (addsi3,ashlsi3): Handle the case where the stack + pointer appears as an index reg. + + Wed Sep 16 21:22:23 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * cse.c (fold_rtx): For SUBREG, actually test subreg_lowpart_p in the + code to handle narrowing subregs. And exclude binary ops like DIV + where truncating the args is not valid. + + * libgcc2.c (__CTOR_LIST__, __DTOR_LIST__): Moved to separate member. + * Makefile.in (LIB2FUNCS): Added _ctors. + + Wed Sep 16 23:28:41 1992 Paul Eggert (eggert@twinsun.com) + + * cexp.y (parse_number): Warn about '9' in octal constants. + Commonize overflow detection for various radices. + + Wed Sep 16 19:33:37 1992 Torbjorn Granlund (tege@mole.gnu.ai.mit.edu) + + * pa.md (casesi): Use emit_jump_insn to emit casesi0 pattern. + (xorsi3): Remove `r' from output template. + (movstrsi recognizer): Add `+' to operand 0 & 1 constraints. + + Wed Sep 16 14:53:51 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Set Meissner version # to 25. + + * mips.c (gen_int_relational): Eliminate all vestiages of + figuring out whether the comparison will always be true or false. + Let the optimizer figure it out. + (gen_conditional_branch): Ditto. + (function_epilogue): Print correct number of half-pic pointers + and references. + (prev_half_pic_refs): New static variable. + (prev_half_pic_ptrs): New static variable. + + Tue Sep 15 16:10:47 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * toplev.c (rest_of_decl_compilation): Call `dwarfout_file_scope_decl' + immediately for actual *definitions* of file-scope variables (and + file-scope typedefs too). + + Tue Sep 15 20:56:31 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * fixincludes (EXINIT): Clear it to avoid problems with bad values. + * fixinc.svr4 (EXINIT): Likewise. + + * print-tree.c (print_node): Don't print blank line for null + fields in a TREE_VEC. + + * cccp.c (macroexpand): Don't output another error message if have + already output error message returned from macarg. + + * c-decl.c (grokparms): Copy parm list if it isn't permanent, + instead of copying it if temporary allocation has been turned off. + + * final.c (only_leaf_regs_used): Check for global_regs. + + * c-parse.y (typespec): Don't warn if pedantic when typeof used. + + * c-tree.h (lang_identifier): Add limbo_value field for out of + scope block level extern declarations. + (IDENTIFIER_LIMBO_VALUE): New define, to access that field. + * c-decl.c (print_lang_identifier): Print value of limbo field. + (pushdecl): Check an extern decl against both previous global and + previous limbo declarations. For global declarations, clear limbo + value field. For block level extern declarations, set limbo field + if zero. + (grokdeclarator): If this is a block level extern, then allocate + it on the permanent obstack, not the temporary obstack. + + Tue Sep 15 15:42:24 1992 Paul Eggert (eggert@twinsun.com) + + * tree.c (int_fits_type_p): Negative ints never fit unsigned + types, and unsigned ints with top-bit-set never fit signed types. + * c-lex.c (yylex): Integer constant is unsigned for purposes of + int_fits_type_p so that it compares huge constants properly. + + Tue Sep 15 14:44:51 1992 Michael Meissner (meissner@osf.org) + + * i386.md (string move, string compare): Always issue cld + instruction before doing a rep string move, so that we are + guaranteed that the bytes are moved/compared correctly. + + Tue Sep 15 00:09:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h: (va_arg): Cast ptr to void *, then to TYPE *. + * va-i960.h, va-m88k.h, va-mips.h, va-pa.h, va-pyr.h, va-sparc.h: + Likewise. + + * rtl.c (ftell): Declaration deleted. + + Mon Sep 14 15:17:09 1992 Michael Meissner (meissner@osf.org) + + * configure (arg processing): Add --with-stabs switch. + (all mips configurations, except decrose): If --with-stabs, use + the configuration file that emits stabs as the debug debug + configuration, rather than the native MIPS ECOFF format. + + Mon Sep 14 13:28:29 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * configure (option case statement): Index with `$next_arg' instead + of `next_arg'. Clean up order and indentation for switches. + (several places): Remove space around assignment `='. + (usage printing): Don't use `-n' for echo (SysV lossage). + Print config.status with `tail +2'. + + Mon Sep 14 23:46:19 1992 Paul Eggert (eggert@twinsun.com) + + * c-lex.c (yylex): Warn about integers so large that they are unsigned. + + * cexp.y (parse_number): Diagnose integer constants that are too large. + Diagnose duplicate `l' and `u' suffixes. Diagnose ` 0x ' and ` 0a '. + Warn about integer constants that are so large that they are unsigned. + + Mon Sep 14 10:26:34 1992 Charles Hannum (mycroft@hal.gnu.ai.mit.edu) + + * reload1.c (init_reload): Fix typo in last change. + + Mon Sep 14 01:17:58 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * reload1.c (init_reload): For reg+reg+const, try various regs. + + Sun Sep 13 01:08:06 1992 Paul Eggert (eggert@twinsun.com) + + * cexp.y (exp): Detect signed integer overflow. + Replace `(unsigned)' with `(unsigned long)'. When + evaluating << and >>, compute the correct answer without shifting + by more than HOST_BITS_PER_LONG, or by a negative quantity. + (integer_overflow, left_shift, right_shift): New functions. + + Sun Sep 13 02:00:52 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * arm.md: Clean up indentation. + + * pa.c (output_load_address): Removed. Nothing uses it. + * pa.md (high:DI recognizer): Add return \"\". + * pa.md (sCC, bCC expanders): Remove constraints. + * pa.md (and-with-immediate optimizer): New pattern. + * pa.md (ior-with-immediate optimizer): New pattern. + * pa.c (consec_zeros_p, and_operand, ior_mask_p, ior_operand, + output_and, output_ior): New functions. + * pa.h (output_and, output_ior): Declare. + * pa.h (CONST_OK_FOR_LETTER_P): Add 'O' and 'P'. + * pa.c (compute_xdepi_operands_from_integer): New function. + Some code come from output_zdepi. + (output_zdepi): Removed. + (depi_cint_operand): New name for zdepi_operand. + * pa.md (adddi3): Extend to handle CONST_INT. + * pa.md (movstrsi): Change `!= 4' => `< 4' in test for alignment. + * pa.md (negsi2): Don't use @ for just one output template. + * pa.md (and-not patterns): Make them canonical. Put operands in + the right order. + * pa.md (casesi): Rewrite. Used to be buggy and slow. + * pa.md (several patterns): Make sure # of attribute alternatives + match # of constraint alternatives. + Return assembler output template instead of calling output_asm_insn. + Don't write to operands[n] for n >= max operand number in the + pattern, use xoperands instead. + + Sat Sep 12 15:06:57 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * regclass.c (record_reg_classes): + Ignore leading % when examining constraint. + Don't bypass usual cost computation when a pseudo "matches" + a non-pseudo in matching operands. + + * c-lex.c (yylex): If integer value overflows so highword is negative, + it needs unsigned long long. + + Fri Sep 11 21:09:53 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * sys-types.h (va_alist): Supply `int' as the type to define it as. + + Fri Sep 11 12:39:39 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.md (non-[cf]branch define_delay): Use a single delay description + for the delay slots in "branch", "call", and "milli" insns. + (fbranch define_delay): fbranches have a single delay slot which + may be nullified when the branch is taken (regardless of direction + or distance to the target.) + (in_branch_delay attribute): Disallow fbranch insns explicitly. + (floating point branches): Use "fbranch" attribute for these insns. + Update output template to properly handle nullification. + + Fri Sep 11 10:34:45 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * c-decl.c (duplicate_decls): For file-scope redefinitions, + error message distinguishes previous definitions from mere decls. + + Fri Sep 11 01:07:11 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-convert.c (convert_to_integer): Don't pass truncation thru lshift + if shift count >= width of narrower type. Instead, just use 0. + + * we32k.h (SIZE_TYPE): Defined. + + Fri Sep 11 00:03:45 1992 Paul Eggert (eggert@twinsun.com) + + * c-decl.c (finish_struct): Don't assume that a target integer + fits in a HOST_WIDE_INT when checking bit-field widths. + * c-typeck.c (build_binary_op): Likewise, when checking shift widths. + + Thu Sep 10 22:23:10 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * optabs.c (expand_binop): + Convert op1 of shift libcall to word_mode. + + Thu Sep 10 18:14:36 1992 Tim Moore (moore@defmacro.cs.utah.edu) + + * final.c (shorten_branches): Do shorten branches with delay slots + if the number of delay slots is constant. + * genattrtab.c (write_const_num_delay_slots): New function; + creates const_num_delay_slots (). + (main): Call it. + * genattr.c (main): Write declaration for const_num_delay_slots (). + + Thu Sep 10 17:33:42 1992 Michael Meissner (meissner@osf.org) + + * mips.md (all move patterns): Do not allow memory to memory or + non-zero constant to memory moves to be generated, which causes + reload to generate the load/store using spilled registers, and + does not allow for efficient CSE or scheduling to be done. + + * dec-gosf1.h, iris4g.h: New files. + + Thu Sep 10 12:46:17 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * pa.md (casesi): Add `&' to constraint for clobber operand. + + * optabs.c (expand_binop): Fix typo, `mode' => `methods'. + + Thu Sep 10 00:21:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * optabs.c (expand_binop): Delete #ifdef GPC; complex code now uncond. + + * optabs.c (init_fixtab): Fix typo for fix_truncdfqi2. + + Wed Sep 9 13:25:53 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * c-common.c (declare_function_name): Allow for anonymous function. + + Wed Sep 9 15:56:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (mostlyclean): Delete xlimits.h. + + * final.c (output_addr_const): + If 2nd arg of MINUS is negative integer, put it in parens. + + Wed Sep 9 10:10:30 1992 Michael Meissner (meissner@osf.org) + + * va-mips.h (va_arg): Handle structures larger than 8 bytes. + (all macros): Put __ in front of all macro arguments. + + Wed Sep 9 00:45:02 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * sol2-crt1.asm (.nope): Really store into environ. + + * libgcc2.c (__gcc_bcmp): New function, in cond on L__gcc_bcmp. + * Makefile.in (LIB2FUNCS): Add L__gcc_bcmp. + + * expr.c (expand_expr): Support IN_EXPR. + + Tue Sep 8 20:04:43 1992 Paul Eggert (eggert@twinsun.com) + + * c-convert.c (convert_to_integer): When optimizing LSHIFT_EXPR and + RSHIFT_EXPR, do compares at tree level. + + * tree.c (build_index_type, build_index_2_type): Don't pass + HOST_WIDE_INT to routine expecting an int. Don't pass negative + value even if hash code is INT_MIN. + + Tue Sep 8 17:35:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * dbxout.c (dbxout_type_fields): Handle nameless subrecords for Pascal. + (dbxout_type): Handle CHAR_TYPE, BOOLEAN_TYPE. FILE_TYPE, SET_TYPE. + + * news.h (ASM_OUTPUT_OPCODE): Deleted. + + * c-parse.y (stmt): In for stmt, put proper lineno before increment. + Don't call position_after_white_space. + + Tue Sep 8 06:31:17 1992 Michael Meissner (meissner@osf.org) + + * cp-typeck.c (constant_print_warning): Deleted. + + Tue Sep 8 05:26:19 1992 Mike Stump (mrs@hal) + + Tue Aug 18 23:56:16 1992 Ron Guilmette (rfg at netcom.com) + + * tree.h (BINFO_VPTR_FIELD): Added to support debugging + information about virtual base class pointers. + + Mon Sep 7 19:39:45 1992 Brendan Kehoe (brendan@cygnus.com) + + * c-typeck.c (constant_print_warning): Deleted. + * c-common.c: Moved here. + + Mon Sep 7 17:03:07 1992 Paul Eggert (eggert@twinsun.com) + + * fold-const.c (fold): Check abs for constant integer overflow. + + Mon Sep 7 01:31:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-common.c (check_case_value): Call constant_expression_warning. + + * cse.c (simplify_binary_operation): For DIV by 0, do nothing. + + * c-decl.c (duplicate_decls): Set DECL_INLINE in newdecl + so it is copied into olddecl. + + Sun Sep 6 08:53:46 1992 Fred Fish (fnf at fishpond) + + * m68k.md (fsglmul pattern): If FSGLMUL_USE_S, opcode has .s, not .x. + * amix.h (FSGLMUL_USE_S): Defined. + + Sun Sep 6 17:42:33 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.md (indirect_jump): Annul the next instruction if the delay + slot could not be filled instead of emitting a nop. + + * pa.c (output_function_prologue): Undo Aug. 13 change. + If profiling, then this function makes calls. Reflect this in + CALLINFO. + (output_function_epilogue): If profiling, then be restore "rp" here. + + * pa.md (use_milli_regs attribute): Deleted, not necessary anymore. + All references deleted. + * pa.c (use_milli_regs): Deleted. + + Sun Sep 6 17:11:00 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * arm.h (MOVE_MAX): Define as 4. + + * ns32k.c (hard_regno_mode_ok): Don't abort if unknown mode, + return 0 instead. Declare argument MODE as `enum machine_mode'. + + * i860.h (HARD_REGNO_MODE_OK): Allow BLKmode. + + Sun Sep 6 16:57:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * expr.c (init_expr_once): Don't try HARD_REGNO_MODE_OK on VOIDmode + or BLKmode. + + Sun Sep 6 14:27:57 1992 Michael Meissner (meissner@osf.org) + + * cp-typeck.c (constant_expression_warning): New fn from c-typeck.c. + + Sun Sep 6 09:11:46 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * c-decl.c (duplicate_decls): Don't set DECL_EXTERNAL in olddecl. + Preserve DECL_UID of olddecl. + + Sun Sep 6 03:37:21 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * i386.md (cmpstrsi): Rewrite expander to handle operands correctly. + + Sat Sep 5 22:55:53 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (try_combine): Make change missing from last modification + to splitting code. + + Sat Sep 5 19:21:03 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * stor-layout.c (layout_type): Caller must give size of FILE_TYPE. + + Sat Sep 5 16:34:50 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * arm.c (before functions): Remove xmalloc decl. + (arm_asm_output_label): Cast value from xmalloc. + + * arm.md (storehi): Use match_operand for operand 0. + Use gen_lowpart to change mode of operand 0. + (storeinthi): Use match_operand for operand 0. + Change output code to reassign operand 0. + (truncsihi2, truncsiqi2, trunchiqi2): Remove these patterns. + + Sat Sep 5 02:39:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * news.h (ASM_OUTPUT_OPCODE): Defined. + + Sat Sep 5 18:52:21 1992 Jukka Virtanen (jtv@kampi.hut.fi) + + * stor-layout.c (layout_type): Handle BOOLEAN_TYPE, CHAR_TYPE, + and FILE_TYPE for Pascal. + (fixup_signed_type): New function. + + * optabs.c (init_optabs): Use __gcc_bcmp, not real bcmp. + (expand_unop): Handle NEG for complex modes. + (expand_binop): Likewise. + (expand_complex_binop): New function. + + * expr.c (emit_move_insn): When moving word by word, + mark the whole thing as a libcall block. + (group_insns): New function. + (expand_expr): + Implement COMPLEX_EXPR, REALPART_EXPR, IMAGPART_EXPR, CONJ_EXPR. + + * print-tree.c (print_node): Handle BOOLEAN_TYPE and CHAR_TYPE. + * emit-rtl.c (gen_highpart): New function. + + Fri Sep 4 23:20:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * i860.md (mulsi3_big): Use low half of result. + Use offset 1 in subregs in actual fmlow insn. + (fmlow pattern): Split this into alternatives for big and little end. + + * regclass.c (record_reg_class): For matching operands, handle + case where the earlier one is not a pseudo like the case + where the later one is not a pseudo. + + Fri Sep 4 17:24:11 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * pa.c (output_move_double): Use %R to store at auto-incr/decr + addr. Split incr and decr cases for store. + + Fri Sep 4 03:49:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gcc.c (main): No program should return the error_count! + Return 2 if failure due to signal, 1 if just errors. + (execute): Increment signal_count. + + * move-if-change: Undo previous change. + + * c-decl.c (grokparms): Copy arg type list to savable obstack if nec. + + Fri Sep 4 19:40:32 1992 Paul Eggert (eggert@twinsun.com) + + * c-typeck.c (constant_expression_warning): Now works; + it reports signed integer overflow in constant expressions, + + * fold-const.c (left_shift_overflows, same_sign, overflow_sum_sign): + New macros. + (add_double, div_and_round_double, lshift_double, mul_double, + neg_double, const_binop, fold): Check for signed integer overflow. + Propagate overflow flags from operands to result. + (const_binop, fold_convert): Use pedwarn for overflow warnings. + Say `constant expression', not `constant folding', for user's sake. + + Thu Sep 3 22:28:41 1992 Brendan Kehoe (brendan@mole.gnu.ai.mit.edu) + + Complete 12th Cygnus<-->FSF merge. + + Thu Sep 3 12:29:24 1992 Brendan Kehoe (brendan@cygnus.com) + + These changes are propagated from changes to c-*.c. + + Mon Aug 17 16:28:48 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (finish_function): Test only can_reach_end for the + warning about reaching the end of a non-void function. + (grokdeclarator): When promoting an argument, retain unsignedness + if traditional or if promoted type is not really getting wider. + + * cp-parse.y (datadef): For empty declaration, use pedwarn. + + Mon Aug 17 17:08:11 1992 Chip Salzenberg (chip@tct.com) + + * cp-cvt.c (convert): When converting to variant of same type, fold. + + Wed Aug 19 16:58:41 1992 Chip Salzenberg (chip@tct.com) + + * cp-typeck.c (default_conversion): Convert enumeral types to + appropriate _signed_ type unless -traditional. + + Tue Aug 4 13:11:36 1992 Chip Salzenberg (chip@tct.com) + + * cp-cvt.c (convert): If main variants match, + but the type is not identical, make a NOP_EXPR. + + * cp-decl.c (warn_redundant_decls): Declared. + (duplicate_decls): Optionally warn about redundant declations. + (pushdecl): Never reuse global fcn decl in place of local extern; + just copy some info from it. + (init_decl_processing): __builtin_saveregs returns void *. + (store_parm_decls, finish_function, start_method, finish_method): + Compare TYPE_MAIN_VARIANT against void_type_node. + + * cp-decl2.c (warn_redundant_decls): Defined. + (lang_decode_option): Decode -Wredundant-decls. + + * cp-typeck.c (build_conditional_expr): Don't use type1 as + temporary variable; set result_type directly. + + Tue Aug 4 12:04:17 1992 Chip Salzenberg (chip@tct.com) + + * cp-tree.h (C_PROMOTING_INTEGER_TYPE_P): Defined. + * cp-class.c (finish_struct): Use it. + * cp-decl.c (duplicate_decls, grokdeclarator): Ditto. + (grokparms, start_function): Ditto. + * cp-typeck.c (self_promoting_args_p, default_conversion): Ditto. + * cp-parse.y (primary): Set TREE_CONSTANT in the NOP_EXPR for an enum. + + Tue Aug 4 09:17:32 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (duplicate_decls, grokdeclarator, grokparms): + Use TYPE_MAIN_VARIANT when comparing against specific types. + (build_enumerator): Use STRIP_TYPE_NOPS. + (start_function): Force main() to return "int", not just any + integral type. + + * cp-typeck.c (self_promoting_args_p, default_conversion): + Use TYPE_MAIN_VARIANT when comparing against specific types. + (unsigned_type, signed_type): If type is not known, return it + unchanged instead of returning its TYPE_MAIN_VARIANT. + (build_binary_op_nodefault): Use TYPE_MAIN_VARIANT when + comparing against specific types. Also use STRIP_TYPE_NOPS. + Also copy error messages from equivalent code in c-typeck.c. + + * cp-parse.y (primary): Wrap a NOP_EXPR around an enum value. + + Wed Sep 2 18:06:47 1992 Mike Stump (mrs@cygnus.com) + + Wed Sep 2 17:33:59 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (grokdeclarator): Default friends to being PUBLIC. + + Tue Sep 1 12:33:01 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * cp-init.c (do_friends): Always return `void_type_node'. + + * cp-decl.c (grokparms): Call digest_init on default arguments for + formal parameters. + + * cp-decl.c (xref_tag): The BINFO records describing individual + inheritances aren't shared in the lattice. + + Tue Sep 1 12:27:17 1992 Mike Stump (mrs@cygnus.com) + + * cp-call.c (convert_harshness, compute_conversion_costs): The + READONLY flag for a const object could be down in the type of the + reference. + + * cp-call.c (compute_conversion_costs): Don't ignore the cost of + converting the first argument, if it is not a method. Fixes Mon Aug + 31 22:32:34 change. + + Tue Sep 1 11:58:52 1992 Mike Stump (mrs@cygnus.com) + + * cp-tree.h (THIS_NAME): Use the name ``this'' instead of the more + cryptic name ``$t''. + + Mon Aug 31 22:32:34 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-init.c (build_member_call): When forming method calls that use + a qualified name, convert the instance pointer to the type implied + by the qualification. Base::member_func(); converts this to be a + (Base *). + + * cp-call.c (compute_conversion_costs): Don't penalize conversion + of the instance pointer on method calls, as they could be pointers + to base classes. + + Mon Aug 31 18:34:33 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-decl.c (start_function): When a friend function is being + defined, put it in (lexical) scope of the class in which it appears. + + Mon Aug 31 09:57:27 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * cp-typeck.c (build_modify_expr): For assignments to member + variables like "X::i", call resolve_offset_ref to get the lhs; all + the code and checking was in there, it just wasn't being used. + + * cp-class.c (finish_struct_methods): Give the name of the class + in question when reporting that all its member functions are + private. + + Sun Aug 30 08:34:03 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-decl2.c (setup_vtbl_ptr): Disable the code, until problems can + be worked around. + + Sat Aug 29 10:34:10 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-init.c (emit_base_init): Undo Sat Jan 18 12:06:58 change by + tiemann that incorrectly makes -pedantic initialization of virtual + base classes 1 or more levels deep impossible. + + Sat Aug 29 10:03:07 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-class.c (finish_struct): Allow extern "C" functions to be + friends. + + Sat Aug 29 04:43:22 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-parse.y (used_extern_spec), cp-decl.c (start_decl, + start_function): Make sure extern in extern "C" (fndef | datadef) + applies to only one decl. Fixes problem introduced on Thu Aug 20 + 16:11:58. + + Thu Aug 27 09:33:13 1992 Brendan Kehoe (brendan@cygnus.com) + + * cp-decl.c (grokdeclarator): Name operators properly when + complaining about trying to declare it as a method when not in a + class. + + * cp-decl.c (grok_reference_init): Forbid volatile->const refs, + and vice-versa. Also make the tests apply to all types, not just + aggregates. (Now fully compliant with ANSI C++ June 5 1996 WP + section 8.4.3.5.) + + * cp-decl.c (shadow_tag): Don't allow a function to be a member of + an anonymous union. + + * cp-class.c (finish_struct): For a type that's nested within a + class, use the class value itself when checking a typedef that uses + that new nested type. + + Wed Aug 26 20:24:07 1992 Brendan Kehoe (brendan@cygnus.com) + + * cp-decl.c (decls_match): When converting from a + pseudo-METHOD_TYPE for a static member fn, handle the static + function being both in the new and old declarations. + (revert_static_member_fn): New function. + + * cp-call.c (build_method_call): Put out proper line number for + error with the use of a private constructor. + + * cp-decl.c (grokdeclarator): If a storage class is erroneously + specified for an operator, print the operator's name out properly in + the error message (e.g., print `+' instead of `__pl'). + + * cp-decl.c (grokdeclarator): Allow neither constructors nor + destructors to be declared const or volatile. + + * cp-decl.c (grok_op_properties): New argument VIRTUALP. + Use it to disallow declaring new or delete as virtual. Also + use coerce_new_type() and coerce_delete_type() to + sanity-check overloading of new and delete. + (grokfndecl): Give grok_op_properties if the decl is virtual. + (start_method): Likewise. + + * cp-tree.c (lvalue_p, ADDR_EXPR case): Casts to references are + lvalues. + + Thu Sep 3 02:46:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * caller-save.c (setup_save_areas): Don't look at WORDS_BIG_ENDIAN. + + * fixincludes: If we find a link pointing to ., make a similar + link to ., not a link to an absolute name. + (stdio.h): Change stdio.h to use stdarg.h to get va_list. + + * cexp.y: Comment syntax fix. + + Thu Sep 3 01:48:16 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * we32k.md (casesi): Use match_dup for second mention of operand 4. + + Wed Sep 2 06:58:32 1992 Michael Meissner (meissner@osf.org) + + * gcc.c (default_compilers): Add missing comma between strings, so + that traditional compilers can compile gcc.c. + (main): Don't pass strcpy or strlen a NULL pointer if some of the + spec strings in default_compilers are NULL. + (validate_all_switches): Don't dereference a NULL pointer if some of + the spec strings in defalut_compilers are NULL. + + * gcc.c (main): Use new loop var J to avoid conflict with I. + + Wed Sep 2 19:09:02 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * caller-save.c (init_caller_save): If we were unable to + find a simple insn which meets all its constraints to save + and restore with a single insn in a mode, then set + regno_save_mode to VOIDmode to insure that this mode is never + used to caller-save the current register. + + Wed Sep 2 12:34:39 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * caller-save.c (insert_save_restore): Correct test for + determining whether multiple registers can be saved. + + * sparc.md (SImode ldd peepholes): Add `f' to constraints. + + * sparcv4.h (HANDLE_PRAGMA): Delete. + * sparc.c (handle_pragma_token): Delete. + + * config/spc-sol2.h: Change the location of the Sun bundled C + compiler in MD_STARTFILE_PREFIX (for backup defaults). + + Wed Sep 2 09:11:16 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.h (MOVE_MAX): Express in bytes not bits. + + * m88k.c (output_ascii): Output known escape characters and don't + terminate the constant if an octal escape is used. + + Wed Sep 2 06:38:37 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (make_compound_operation, case ASHIFTRT): Add new + code to handle (ashiftrt (neg (ashift FOO C1) C2)) just like we + currently handle (ashiftrt (OP (ashiftrt FOO C1) C2) C2). + + Wed Sep 2 00:15:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (install): Add semicolon to make an empty command. + + * reload.c (find_reloads): If have any earlyclobbers, don't let any + reloads overlap with them. Make everything RELOAD_OTHER. + + * move-if-change: Give status 1 if file is unchanged. + + * Makefile.in (SYSTEM_HEADER_DIR): New variable. + (xlimits.h): New target, broken out from install-limits-h. + Look in SYSTEM_HEADER_DIR for system's limits.h. + (start.encap): Dep on xlimits.h. + (install-limits-h): Install xlimits.h already made. + * cross-make (SYSTEM_HEADER_DIR): Overridden. + + * x-i386sco (X_CFLAGS): Deleted. + * x-i386sco4: New file, like old x-i386sco. + * configure (i386-*-sco3.2v4*): Use x-i386sco4. + + * t-sol2 (gmon.o): Find gmon-sol2.c in config. + + * c-typeck.c (process_init_constructor): Fix bugs in previous change. + + Tue Sep 1 23:51:19 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * gcc.c (default_compilers, ".C" and ".ii"): Pass `+e*' into cc1plus. + (process_command): Allow +e[012] to be passed down into cc1plus. + * cp-decl.c (lang_decode_option): The options `+e0' thru `+e2' will + be coming in prefixed as `-+e'. + + Tue Sep 1 20:09:29 1992 Paul Eggert (eggert@twinsun.com) + + * print-tree.c (print_node): Avoid 1 << (HOST_BITS_PER_INT - 1), + which overflows. Use unsigned % to compute HASH. + + Tue Sep 1 17:23:28 1992 Tim Moore (moore@hal) + + * pa.h (CPP_SPEC, TARGET_SWITCHES): new flags: -mnosnake, + -mpa-risc-1-0, -mpa-risc-1-1. + (ASM_DECLARE_FUNCTION_NAME): Emit argument descriptors for all + general registers if current_function_varargs. + + Tue Sep 1 11:27:08 1992 Brendan Kehoe (brendan@rtl.cygnus.com) + + * sparc.c (handle_pragma_token): Only use if HANDLE_SYSV_PRAGMA + isn't defined. (We'll be getting the fn from c-pragma.c, then.) + + Sat Aug 29 13:44:21 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * tree.h (current_block): Decl deleted. + (set_block): Declared. + * stmt.c (expand_fixup): Create a BLOCK node (via pushlevel/poplevel) + to represent an artificial scope containing all of the fixup code. + Also emit NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END for that block. + (fixup_gotos): Declaration of NEWBLOCK deleted. + Call `set_block' to use the BLOCK made in expand_fixup. + Deleted code to insert NEWBLOCK into block hierarchy. + * c-decl.c, cp-decl.c (current_block): Function deleted. + (set_block): New function. + (poplevel): If using a previously created block, + don't insert it into the parent level. + * emit-rtl.c (emit_insns_after): Update last_insn if nec. + + Tue Sep 1 10:53:58 1992 Torbjorn Granlund (tege@jupiter.sics.se) + + * pa.c (output_move_double): Use `ldo' for immediate adds (instead + of `addi' with bad syntax). + (output_load_address): Likewise. + + Tue Sep 1 02:41:13 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * tree.h (struct tree_type): Make `align' field an int. + + * c-tree.h (IDENTIFIER_LIMBO_VALUE): New macro. + (struct lang_identifier): New field limbo_value. + + Mon Aug 31 12:59:22 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * tree.c (make_node): Fix typo in July 6 change: + assignment of DECL_IN_SYSTEM_HEADER was inserted in bad place. + + Mon Aug 31 21:28:08 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sched.c (sched_analyze_2): Remove an explicit dependence between + an insn that uses CC0 and the immediately previous insn + (SCHED_GROUP_P represents the dependence). + (schedule_block): Only check sets_cc0_p on an insn. + + Mon Aug 31 15:32:13 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gcc.c (struct compiler): spec field is now array of 4 elements. + (read_specs): Clear the entire new element of compilers. + (lookup_compiler): Copy all of spec array. Check element 0 for @. + (main): Concatenate all elements of compiler spec. + (validate_all_switches): Validate from all elements of compiler spec. + (default_compilers): Split CPP commands into separate strings. + + Mon Aug 31 10:06:16 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * caller-save.c (restore_referenced_regs): When restoring a + referenced hard register, use CEIL instead of a truncating divide + to determine the maximum number of registers to restore. + (insert_save_restore): Document maxrestore parameter. + (CEIL): Define. + + Mon Aug 31 04:02:21 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fold-const.c (const_binop): Delete special case for mult by 3. + + * toplev.c (lang_options): Add terminating zero. + + * configure.bat: Remove version number from initial message. + + Sun Aug 30 17:22:11 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * cccp.c (do_pragma): In prev. change, really use U_CHAR *, not char *. + + * aix386.h, i386gas.h, i386sun.h, i386v.h, i386v4.h, i386vgas.h, + seq386.h (TARGET_DEFAULT,VALUE_REGNO,FUNCTION_VALUE_REGNO): + Move from here, + * unx386.h (TARGET_DEFAULT,VALUE_REGNO,FUNCTION_VALUE_REGNO): + To here. + (TARGET_DEFAULT): Make TARGET_IEEE_FP default on. + (VALUE_REGNO): Test for MODE_FLOAT instead of specific modes. + (VALUE_REGNO,FUNCTION_VALUE_REGNO): MODE_FLOAT return reg depends on + TARGET_FLOAT_RETURNS_IN_80387. + + * i386.h (TARGET_FLOAT_RETURNS_IN_80387): New macro. + (TARGET_SWITCHES): Add "no-80387", "no-soft-float", + "fp-ret-in-387", and "no-fp-ret-in-387". + Change no* switches to no-*. + (CONDITIONAL_REGISTER_USAGE): Make 387 regs fixed if the 387 is not + used at all. + (REG_CLASS_FROM_LETTER): Constraint letters 'f', 't' and 'u' are + NO_REGS if the 387 is not used. + (TRAMPOLINE_TEMPLATE): Use GEN_INT to generate const_int rtx. + + * x-i386v4: New file. + (CLIB): Get alloca from libucb.a. + * configure (i386-*-sysv4*): Use x-i386v4. + + Sun Aug 30 15:32:54 1992 Dennis Glatting (dglattin at trirex.com) + + * objc-actions.c (create_builtin_decl): Set TREE_STATIC. + Don't set DECL_EXTERNAL or TREE_PUBLIC. + + Sun Aug 30 03:08:48 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-parse.y (initlist): Handle ranges of array elements. + * c-typeck.c (process_init_constructor): Handle ranges. + + * fixincludes: When link points to a dir $dirname outside $INPUT, + copy that dir into $LIB/root$dirname. Translate the link itself + into a link to that new dir. Make a file DONE in each treetop dir + so no treetop is scanned twice. Improve progress messages. + + Sat Aug 29 22:41:49 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * alpha.h (ASM_FILE_START): Object file version number now 8.0. + + * alpha.h (ADJUST_COST): New macro. + * alpha.c (alpha_adjust_cost): New function. + * alpha.md: Adjust function unit delays and more precisely + describe function units. + + * alpha.h (CONST_OK_FOR_LETTER_P): Add new letters `O' and `P'. + * alpha.c (print_operand, case 'P'): New case. + * alpha.md (ashldi3): Special-case shifts by 1, 2, and 3 bits to + use arithmetic instructions. + Add pattern for sign-extending shifts by 1, 2, and 3 bits. + + * alpha.h (INITIALIZE_TRAMPOLINE): Use Pmode when appropriate. + (FUNCTION_MODE): Use Pmode. + + * alpha.md (div/mod): Indicate that reg 27 is clobbered too. + + * alpha.md (cmov): Add define_split for if_then_else/plus case. + + * expr.c (emit_library_call): Pass correct number of args to + convert_to_mode. + + * expr.c (emit_block_move): Eliminate unnecessary test against + HOST_BITS_PER_WIDE_INT. + + * optabs.c (expand_{binop,unop}): Don't make invalid + paradoxical SUBREGs. + + * genattrtab.c (RTL_HASH, attr_rtx): Avoid warnings by casting + pointers to HOST_WIDE_INT instead of int. + + + Sat Aug 29 15:35:58 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * toplev.c (lang_options): New table. + (main): Recognize all language-dependent options of any language + and always treat them as language-specific and valid. + + * c-decl.c (c_decode_option): -fnotraditional really undoes + -ftraditional. Handle -fno-traditional also. + + Sat Aug 29 00:34:01 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * reg-stack.c (record_reg_life): Mark an unused reg as such, even + if it appears in SET_SRC. + + Fri Aug 28 17:40:49 1992 John F Carr (jfc at Athena.MIT.EDU) + + * tree.c (chainon): Check for op2 being the last elt of the chain. + + Fri Aug 28 13:26:56 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * cccp.c (do_pragma): Use rindex, not strrchr. + + * tree.h (BLOCK_END_NOTE): Macro definition added. + (struct tree_block): `end_note' field added. + * stmt.c (last_block_end_note): New variable. + (remember_end_note): New function. + (expand_end_bindings): Save NOTE_INSN_BLOCK_END in last_block_end_note. + * c-decl.c, cp-decl.c (poplevel): Call `remember_end_note' for each + newly created BLOCK node. + * integrate.c (adjust_copied_decl_tree): New function. + (save_for_inline_copying): When making copies of NOTE_INSN_BLOCK_END + notes, stash a "forwarding" pointer in the original to point to the + copy. Also, when all BLOCKs & insns for a function have been copied, + call `adjust_copied_decl_tree' to fixup the end_note pointers in the + copied BLOCKs. + + Fri Aug 28 13:25:59 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * cccp.c (do_pragma): In prev. change, use U_CHAR *, not char *. + + Fri Aug 28 09:11:56 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.h (ADJUST_COST): Add definition. + + Thu Aug 27 18:27:02 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * c-decl.c (init_decl_processing): Add sin and cos as built-in + functions. + * expr.c (expand_builtin): Likewise. + + * expr.h (sin_optab,cos_optab): Declare optabs for sin and cos. + * optabs.c (sin_optab,cos_optab): Define them. + (init_optabs): Initialize them. + + * tree.h (BUILT_IN_SIN,BUILT_IN_COS): New builtin codes. + + * reg-stack.c (record_note_if_dead): Delete function. + (record_reg_life_pat): Rewrite to handle any sort of pattern. + (record_reg_life): Change interface to record_reg_life_pat. + + (stack_reg_life_analysis): Don't assume that MODE_FLOAT values are + always returned in a float reg. + + (subst_stack_regs_pat): Add support for sin and cos insns. + + * i386.c (all gen_rtx (CONST_INT) references): Use GEN_INT to + generate const_int rtx. + (legitimize_pic_address): Pass NULL_RTX instead of "0" as pointer. + + * i386.md (all patterns): Use GEN_INT instead of gen_rtx to get + const_ints. + Avoid double-negative "! NON_*" constructs for clarity. + Pass NULL_PTR as null parameter instead of 0. + + (sqrtM2): Patterns are only valid if IEEE FP or -ffast-math. + (sinM2,cosM2): New patterns. + (zero_extract test): New pattern. + (movstrsi): Rewrite expander to handle operands correctly. + + Thu Aug 27 16:58:09 1992 Michael Meissner (meissner@osf.org) + + * genattrtab.c (MAX_DIGITS): New macro to gauge how much space we + need to reserve when printing integers. + (expand_delays): Use sizeof and MAX_DIGITS to properly size the + strings when calling attr_printf. + (expand_units): Ditto. + (encode_units_mask): Ditto. + (make_numeric_value): Ditto. + (oballoc): New macro, to allocate from the hash_obstack. + (convert_const_symbol_ref): Call oballoc instead of xmalloc. + (get_attr_value): Ditto. + (fill_attr): Ditto. + (make_length_attrs): Ditto. + (gen_attr): Ditto. + (gen_insn): Ditto. + (gen_delay): Ditto. + (gen_unit): Ditto. + (find_attr): Ditto. + (main): Ditto. + + Thu Aug 27 14:47:16 1992 Mike Stump (mrs@mole.gnu.ai.mit.edu) + + * cp-decl.c (curent_block, struct binding_level, poplevel): Copy + Tue Aug 25 16:29:47 and Wed Aug 26 01:56:30 changes in c-decl.c by + rms. + + Thu Aug 27 01:32:11 1992 Paul Eggert (eggert@twinsun.com) + + * c-lex.c, cp-lex.c (readescape): DEL isn't printable. + * c-typeck.c (check_format): Likewise. + + Wed Aug 26 20:42:36 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-lex.c (readescape): For \x, don't include leading 0's in count. + + * c-decl.c (init_decl_processing): Fix type of __builtin_constant_p. + + * expr.c (emit_block_move): When trying movstrMM, cvt size to mode MM. + + * c-parse.y (stmt): For computed goto, convert arg to void *. + + * fold-const.c (fold): Do A op C1 ? A : C2 opt only for INTEGER_TYPEs. + + Wed Aug 26 20:19:56 1992 Mike Stump (mrs@wombat.gnu.ai.mit.edu) + + * cp-decl.c (insert_block, delete_block): New functions. + * cp-parse.y (primary, using compstmt): Call delete_block instead + of clearing TREE_USED. + + 11th Cygnus<-->FSF merge. + + Wed Aug 26 12:02:41 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-decl.c (finish_function): Don't core dump when a conversion is + ambiguous. + + Tue Aug 25 16:32:42 1992 Mike Stump (mrs@rtl.cygnus.com) + + * cp-init.c (build_new), cp-typeck.c (build_c_cast): Handle ``new + type ( ... )'' better. Default constructors and better error + checking. + + Tue Aug 25 01:21:48 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl2.c (finish_file): Mark " @%$#@!" as being internal. + + Mon Aug 24 16:40:15 1992 Brendan Kehoe (brendan@cygnus.com) + + * cp-lex.c (check_newline): For `#pragma implementation', use + strcmp to check if it was done at the top level, rather than relying + on the pointers being the same. + + Mon Aug 24 20:48:16 1992 Mike Stump (mrs@cygnus.com) + + Fri Aug 21 14:19:27 1992 Ron Guilmette (rfg at ncd.com) + + * cp-decl2.c (grokclassfn): Mark the artificial `this' parameter as + "artificial". + + Thu Aug 20 22:59:16 1992 Mike Stump (mrs@cygnus.com) + + * cp-spew.c (arbitrate_lookup): Make sure the type name in an + argument list followed by &, or &) is seen as a type name, even when + there is an enumeration constant with the exact same name. + + Thu Aug 20 21:58:30 1992 Mike Stump (mrs@cygnus.com) + + * cp-search.c (get_first_matching_virtual): Don't core dump when a + declaration of a static member is seen with the same name as a base + class virtual function. + + Thu Aug 20 21:20:31 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (finish_function): Don't core dump on parse errors. + + Thu Aug 20 20:52:43 1992 Mike Stump (mrs@cygnus.com) + + * cp-method.c (build_component_type_expr): Don't core dump on parse + errors. + + Thu Aug 20 18:31:58 1992 Mike Stump (mrs@cygnus.com) + + Mon Aug 17 17:08:11 1992 Chip Salzenberg (chip@tct.com) + + Copy some changes from the C front-end: + + * cp-type2.c (process_init_constructor): Warn about partly bracketed + initializers. + * cp-typeck.c (build_component_ref): Don't warn for compound and + conditional expressions when pedantic. These are valid in ANSI C. + + Thu Aug 20 16:11:58 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (start_decl), cp-parse.y (have_extern_spec): extern "C" + int i; is only a declaration, but a definition, make it so. + + Thu Aug 20 14:46:39 1992 Mike Stump (mrs@cygnus.com) + + Thu Aug 20 02:36:39 1992 Ron Guilmette (rfg at ncd.com) + + * cp-lex.c (cons_up_default_function): Use DECL_SOURCE_LINE = 0 for + compiler generated things, not DECL_IGNORED_P. + + Thu Aug 20 13:13:45 1992 Mike Stump (mrs@cygnus.com) + + Wed Aug 19 13:09:45 1992 Ron Guilmette (rfg at ncd.com) + + * cp-decl.c (grokdeclarator): Propagate some changes from the C + front-end to deal with variable sized arrays. + + Wed Aug 19 16:55:43 1992 Mike Stump (mrs@cygnus.com) + + * cp-cvt.c (convert_to_reference): Improve wording on error message. + * cp-method.c (type_as_string), cp-pt.c + (mangle_class_name_for_template), cp-xref.c (GNU_xref_decl): Delete + first argument to type_as_string as it is not needed anymore. + + Wed Aug 19 15:29:02 1992 Mike Stump (mrs@cygnus.com) + + Wed Aug 19 13:09:45 1992 Ron Guilmette (rfg at ncd.com) + + * cp-decl.c (kept_level_p): Update from C frontend. + + Wed Aug 19 14:47:08 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl2.c (groktypefield): Old style conversion operators + are being desupported. Conversion operators much have an + `operator' in front of them. + + Wed Aug 19 01:57:04 1992 Mike Stump (mrs@cygnus.com) + + * cp-call.c (ideal_candidate): Fix bug introduced on Jan 21 + 7:24:21. Warn about ambiguous function calls with multiple + same cost conversions. + + Wed Aug 19 00:08:18 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (grok_enum_decls): Remove invalid error message. + + Mon Aug 17 18:59:18 1992 Mike Stump (mrs@cygnus.com) + + * cp-cvt.c (convert_to_reference, convert, + build_type_conversion_1, build_type_conversion), cp-init.c + (build_dynamic_new), cp-typeck.c (build_modify_expr_1, + convert_for_initialization): Always use constructor_name, and + never TYPE_IDENTIFIER (type) and similar things. + * cp-init.c (expand_aggr_init_1): Try TYPE_HAS_CONSTRUCTOR + before wasting time trying build_method_call. + * cp-xref.c: Don't include memory.h. + + Mon Aug 17 15:10:21 1992 Mike Stump (mrs@cygnus.com) + + * cp-init.c (expand_aggr_init_1): Check for ambiguous + conversion. One through constructor and the other through a + user defined conversion operator. + + Mon Aug 17 11:51:27 1992 Mike Stump (mrs@cygnus.com) + + * cp-call.c (convert_harshness): When an argument is T, a T& + should be choosen over a const T& when selecting overloaded + functions. + + Mon Aug 17 01:37:06 1992 Mike Stump (mrs@cygnus.com) + + * cp-call.c (build_method_call): The second argument to + operator delete is sometimes magically deleted. + * cp-decl.c (init_decl_processing, grokfndecl): Global + operator delete never has two arguments. + + Wed Aug 5 18:54:19 1992 Mike Stump (mrs@cygnus.com) + + * cp-class.c (finish_struct), cp-tree.c (layout_basetypes): + Make sure VFIELD_BASEs are aligned. This fixes a really + annoying problem that causes code that uses complex + inheritance hierarchies that have virtual bases to get a + segmentation fault. + + Wed Aug 5 12:35:07 1992 Mike Stump (mrs@cygnus.com) + + Wed Aug 5 08:10:34 1992 Tom Wood (wood@dg-rtp.dg.com) + + * cp-tree.c (__eprintf): `line' is unsigned. + * cp-lex.c: Include stdlib.h and locale.h if needed. + * cp-typeck.c (mark_addressable): Use DECL_EXTERNAL not + TREE_EXTERNAL. + + Wed Aug 5 03:20:07 1992 Mike Stump (mrs@cygnus.com) + + * cp-class.c (finish_struct_methods): Check to make sure + operator delete is not overloaded. + * cp-decl.c (grokfndecl): Check to make sure operator delete + is declared properly. + + Tue Aug 4 16:52:28 1992 Mike Stump (mrs@cygnus.com) + + Mon Aug 3 22:55:04 1992 Michael Meissner (meissner@osf.org) + + * cp-decl.c (grokdeclarator): Make sure const and volatile get + put on the type built when building reference types. + * cp-parse.y (attrib): tree_cons takes three arguments, not + two. + * cp-tree.h: Add hash_chainon, build_virtual_init, + build_vbase_delete, build_vbase_vtables_init. + * cp-typeck.c (build_modify_expr_1. build_modify_expr): + build_unary_op takes three arguments, not two. + + Tue Aug 4 16:07:57 1992 Mike Stump (mrs@cygnus.com) + + Sat Aug 1 16:52:20 1992 John Carr (jfc@Athena.MIT.EDU) + + * cp-decl.c (): Make sure the base type of an ARRAY_TYPE is + layedout before using it. + + Wed Aug 26 17:04:45 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * tree.h (current_block): Declared. + + Wed Aug 26 15:42:11 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + Major rework to have caller-saves emit load/store double insns when + possible and to avoid useless resaving of registers restored for + source accesses only. + * caller-save.c (toplevel): All arrays are multi-dimensional to + hold information for multiple save/restore insns. New variable + hard_regs_need_restore. + (choose_hard_reg_mode): New argument `nregs' indicating how many + hard registers are desired. All callers changed. + (init_caller_save): Change initialization to handle multiple + register saves. A call-used register can not be live across + if we can not find a single register mode to save it in. + (multiple register saves are optional) + (init_save_areas): Change initialization of regno_save_mem to + handle multiple register saves. + (setup_save_areas): Allocate space for consecutive hard registers + in aligned consecutive memory locations. When allocating space + for consecutive hard registers, also initialize regno_save_mem + for each hard register stored as a single word. + (save_call_clobbered_regs): Initialize hard_regs_need_restore. + Set hard_regs_need_restore to hard_regs_saved after crossing + a call. Also recompute n_regs_saved. At the end of a basic block + we need only restore registers in hard_regs_need_restore. + (set_reg_live, clear_reg_live): Do the right thing for + hard_regs_need_restore and hard_regs_saved. + (restore_referenced_regs): Just return if X is a clobber. + Test hard_regs_need_restore to determine when to restore a hard + register from the save area. + (insert_save_restore): Now returns the number of extra registers + saved/restored. New argument `maxrestore' which constrains how + many hard registers should be restored. All callers changed. + Do stores of consecutive registers with double store insns if + possible. Else do them with single word insns. Likewise for + loads, except constrained by maxrestore. Set hard_regs_saved + and hard_regs_need_restore appropriately to minimize useless + saves into the save area. Test against hard_regs_need_restore + when trying to restore multiple regs and similarly test against + hard_regs_saved when storing multiple regs. + + + Wed Aug 26 14:24:28 1992 Michael Meissner (meissner@osf.org) + + * mips.h (LINK_SPEC): Pass -shared, -non_shared on to linker. + * mips-bsd.h (LINK_SPEC): Ditto. + * mips-n5.h (LINK_SPEC): Ditto. + * mips-svr4.h (LINK_SPEC): Ditto. + * mips-sysv.h (LINK_SPEC): Ditto. + * iris.h (LINK_SPEC): Ditto. + * dec-osf1.h (LINK_SPEC): Ditto. + + * dec-osf1.h (DECSTATION): Don't define, since decstatn.h which is + included defines it. + (OBJECT_FILE_COFF): Undefine, since the DEC OSF/1 ldfcn doesn't + look like the coff version. + + * decstatn.h (LINK_SPEC): Don't define if already defined. + + Wed Aug 26 13:56:08 1992 Tom Wood (wood@dg-rtp.dg.com) + + * reorg.c: Enhance to fill the last delay slot of a call with an + unconditional jump. + (fill_simple_delay_slots): Look for the case of a call/branch + first. If this applies, record the jump as `last_delay_insn'. + Later, don't look for additional delay insns if the last one has + alreay been filled. + (mark_target_live_regs): A sequence may end in an unconditional + branch. + + * m88k.md (define_function_unit): Correct and simplify memory unit + specification. + + Wed Aug 26 01:56:30 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (poplevel): Store into BLOCK iff it is non-null. + + Tue Aug 25 23:24:45 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sched.c: Add #ifdef INSN_SCHEDULING around variables only used + by schedule_insns. + (INSN_QUEUE_SIZE): Delete default definition. + + * optabs.c, expr.c: Partially undo Mar 7 change. Only call + emit_library_call with no_queue == 1 for const functions. + + * sparc.c (SF_MODES): Allow SImode in fp registers. + (output_floatsisf2, output_floatsidf2, output_floatsitf2): Delete. + * sparc.h: Delete declarations of the above 3 functions. + * sparc.md (float*, fix*): Rewrite to match hardware; take/put + integer input/output from/to fp register instead of memory or + general register. Delete 6 now obsolete combiner patterns. + + Tue Aug 25 16:40:15 1992 Brendan Kehoe (brendan@cygnus.com) + + * cccp.c (do_pragma): Warn if `#pragma implementation "foo.h"' is + invoked after "foo.h" has been included. + + Tue Aug 25 16:29:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * stmt.c (struct goto_fixup): New field context. + (fixup_cleanups): Function deleted. + (fixup_gotos): Put the fixup in a block, and put that block + into its proper place. Use sequences, not reorder_insns. + + * c-decl.c (current_block): New function. + (struct binding_level): New field this_block. + (poplevel): Use this_block if nonzero, rather than making new BLOCK. + + * sched.c (INSN_QUEUE_SIZE): Add default definition. + + Tue Aug 25 15:19:26 1992 Tom Wood (wood@dg-rtp.dg.com) + + * sched.c (schedule_block): Add a virtual cycle counter CLOCK. + Pass CLOCK to schedule_insn. + Compute the tail in the scheduling loop, not before it. + Enable the stall code that advances the insn queue. + Select the insn to schedule and block others with schedule_select. + (adjust_priority): Renamed from launch_link. + (schedule_insn): Renamed from launch_links. + + * genattrtab.c (struct attr_desc): Add unsigned_p field. + (struct function_unit_op): Add issue_delay, conflict_exp, and + issue_exp fields. Drop busyexp field. + (struct function_unit): Add needs_blockage_function, + needs_range_function, issue_delay, and max_blockage fields. Drop + costexp, and busy delay fields. + (enum operator): Add POS_MINUS_OP, EQ_OP, MIN_OP, RANGE_OP. + (operate_exp): Implement new ops. + (make_internal_attr): Set unsigned_p based on the value of SPECIAL. + (write_attr_get): Function is unsigned when unsigned_p is true. + (write_attr_valueq): Write hex value of large constants in a comment. + (simplify_by_exploding): Check for EXP having no EQ_ATTR expressions + and for all values as the default. + (find_and_mark_used_attributes): Add TERMS and NTERMS parameters. + (max_attr_value): Allow IF_THEN_ELSE. + (simplify_knowing, write_complex_function, extend_range): New + functions. + (gen_unit): Use local variables to name the fields. Change the + meaning of busy-delay to issue-delay. + (expand_units): Compute issue_exp. Write attributes for computing + `_unit_blockage' and `_unit_blockage_range' functions. + Compute max_blockage, and the needs_*_function values. + (write_function_unit_info): Write blockage function and conflict cost + functions using write_complex_function. Write new function_unit_desc + fields. + * genattr.c (extend_range, init_range): New functions. + (write_units): Add blockage_function, blockage_range_function, + max_blockage and max_issue_delay fields to struct function_unit_desc. + Drop max_busy_cost field. Write #defines for min/max blockage, + issue delay, multiplicity, and simultaneity and for BLOCKAGE_BITS + and INSN_QUEUE_SIZE. + (main): Compute the new values. + * sched.c (insn_queue): Use INSN_QUEUE_SIZE. + * rtl.def (define_function_unit): Update documentation. + + * sched.c (insn_units, insn_blockage, insn_tick, unit_last_insn, + unit_tick, unit_n_insns): New variables. + (schedule_insns): Allocate and initialize insn_tick, insn_units, and + insn_blockage. + (insn_unit, blockage_range, clear_units, prepare_unit, schedule_unit, + actual_hazard_this_instance, actual_hazard, potential_hazard, + schedule_select): New functions. + (schedule_block): Add dependencies to force insns to remain in order + at the end of a block rather than relying on having the scheduler + issue them in priority order. + + * sched.c (insn_cost): Add LINK and USED parameters. All callers + changed. Supply an ADJUST_COST interface. + (insn_cost): Make a dependence from a USE insn free. + (priority): Clear the link cost adjustment bits. + * rtl.h (LINK_COST_ZERO, LINK_COST_FREE): New macros. + + * genattrtab.c (expand_units): Use the normalized values of the + unit's CONDEXP and BUSYEXP. + + * a29k.md (define_function_unit): Change meaning to ISSUE-DELAY. + * i960.md (define_function_unit): Change meaning to ISSUE-DELAY. + * m88k.md (type attribute, movdi movdf insns): Add loadd. + (unit attribute): Delete. + (function units): Correct simultaneity values. Break out + independent units. Add conflict matrix for the 88100 load double. + * mips.md (define_function_unit): Change meaning to ISSUE-DELAY. + * pa.md (define_function_unit): Change meaning to ISSUE-DELAY. + * sparc.md (define_function_unit): Change meaning to ISSUE-DELAY. + Merge FP_MUL, FP_DIV, and FP_SQRT into one function unit. + + * jump.c (delete_computation): Derived from delete_jump. + (delete_jump): Use delete_computation. + + Tue Aug 25 13:42:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * final.c (final_scan_insn): If 2 consec line notes have same line num, + can omit one. + + Tue Aug 25 13:38:19 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Set Meissner version # to 24. + (ASM_FINAL_SPEC): Use %U to get the last file name created with + %u, rather than %u. + (ARG_POINTER_REGNUM): Use the hardwired register $0 as the + argument pointer, instead of the frame pointer, to allow the frame + pointer to be the same as the stack pointer after the initial + stack allocations. This is to allow GCC generated code to be + linked against MIPS shared libraries. The linker rearranges the + code, and needs to have a frame pointer, if used, to be the same + as the stack. The argument pointer is always eliminated in favor + of the stack pointer or frame pointer. + (FRAME_GROWS_DOWNWARD): Don't define this any more. + (STARTING_FRAME_OFFSET): Locals start after the stack area to pass + arguments to called functions. + (STACK_DYNAMIC_OFFSET): If function is a leaf function, but calls + __builtin_alloca, assume a default argument area, so the MIPS + linker doesn't think a second frame pointer is created. + (INITIAL_FRAME_POINTER_OFFSET): Don't define, since we use + elimination instead. + (ELIMINABLE_REGS): Define to eliminate both the stack pointer and + frame pointer, since they are now separate. + (CAN_ELIMINATE): Ditto. + (INITIAL_ELIMINATION_OFFSET): Ditto. + (ELIGIBLE_FOR_EPILOGUE_DELAY): Don't allow variables based off of + the argument pointer, in addition to frame and stack pointers. + (MUST_SAVE_REGISTER): Add in GP_REG_FIRST to 31, in case we ever + change the base of the gp registers. + (MIPS_STACK_ALIGN): Use ~7, instead of 0xfffffff8. + + * mips.c (number_functions_processed): Delete variable, nobody + uses it anymore. + (mips_debugger_offset): Add support for the frame pointer being + the same as the stack pointer, instead of being the same as the + argument pointer. Abort if the address is not based on any of the + stack, frame, or argument pointers. + (print_operand_address): Add checks for the arg pointer not being + eliminated. + (function_prologue): Ditto. + (mips_expand_prologue): Ditto. + (function_epilogue): Ditto. + (mips_expand_epilogue): Ditto. + (function_epilogue): Strip leading '*' if it exists from + current_function_name when printing statistics. Delete increment + of number_functions_processed. + (compute_frame_size): Don't base extra_size on the macro + STARTING_FRAME_OFFSET. If function is a leaf function, but calls + __builtin_alloca, allocate an arg area, so that the MIPS linker + will not complain about creating a second frame pointer. Move the + argument save area beneath local variables. + + * decrose.h (ASM_FINAL_SPEC): Use %U to get the last file name + created with %u, rather than %u. + + * gcc.c (do_spec_1): Add %U to return the last name generated with + %u. This is for use with mips-tfile, to find the generated object + file. + + + Mon Aug 24 18:09:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (build_unary_op): For ADDR_EXPR, just set TREE_CONSTANT + if staticp, but don't clear TREE_CONSTANT. + + Mon Aug 24 13:52:13 1992 Brendan Kehoe (brendan@cygnus.com) + + * gcc.c (process_command): Don't set verbose_flag if they make a + typo (e.g., `-v-E'); only when it's exactly "-v". + + Mon Aug 24 06:49:16 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (subst): When moving operation inside IF_THEN_ELSE, + make a new rtx instead of using SUBST due to sharing. + + * combine.c (simplify_comparison): Correct test for sign extension + when trying to widen comparison. + + Sun Aug 23 18:58:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fold-const.c (fold): Avoid the normal STRIP_NOPS on arg of NOP_EXPR. + + Sun Aug 23 15:32:03 PDT 1992 Ron Guilmette (rfg at netcom.com) + + * stmt.c (expand_end_bindings): Generation of NOTE_INSN_BLOCK_END + moved down so that it occurs after call to `expand_cleanups'. + + Sun Aug 23 16:24:32 1992 Michael Meissner (meissner@osf.org) + + * decrose.h (CPP_SPEC): Don't define strcmp as __builtin_strcmp in + the case neither -fbuiltin nor -fno-builtin were defined. + * i386rose.h (CPP_SPEC): Ditto. + + Sun Aug 23 02:03:41 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * libgcc2.c (__builtin_new): Cast the result of malloc. + + * toplev.c: Fix typo in prev change. + + * c-decl.c (insert_block, delete_block): New functions. + * c-parse.y (primary, using compstmt): Call delete_block + instead of clearing TREE_USED. + * expr.c (expand_expr): For BIND_EXPR, call insert_block on the block. + + Sat Aug 22 14:12:02 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure: Use absolute pathname in value of INSTALL. + + Sat Aug 22 06:42:39 1992 Tom Wood (wood@dg-rtp.dg.com) + + * emit-rtl.c (insn_emit_once): Provide a zero constant for CC modes. + + Fri Aug 21 18:33:30 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * reorg.c (fill_simple_delay_slots): Always try to fill empty + delay slots with insns from beyond the delay insn, even if + optimize_skip was attempted. + (fill_simple_delay_slots): When filling with insns from after the + delay insn, make sure to always account for the sets and + references in the delay insn. + + Fri Aug 21 16:47:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * sparc.c (print_operand): Use output_operand_error for unknown code. + + * c-typeck.c (build_conditional_expr): Use TREE_READONLY and + TREE_THIS_VOLATILE, not TYPE_... + + Fri Aug 21 14:02:20 1992 James Van Artsdalen (james at bigtex.cactus.org) + + * reload.c (find_dummy_reload): Restore original RTX instead of + passed IN rtx. + + Fri Aug 21 07:53:12 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * optabs.c (expand_binop): If, e.g., mulqi3 doesn't exist, try + mulqihi3. + + * rs6000.h (FUNCTION_ARG): Don't make an EXPR_LIST if making a libcall. + + * combine.c (subst): Move up test for too many restarts. + If we restart, clear OP0_MODE since we don't know it. + + Fri Aug 21 02:11:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * emit-rtl.c (emit_insns_after): New function. + + Fri Aug 21 01:53:04 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * pa.md (call_value+1): For non-dynamic calls, use the "call" + attribute, set length to 1, and fix output template to work + properly with delay slots. + + * pa.md (address and use_call_clobbered attributes): Deleted, + these attributes are useless. All references deleted. + (call define delay): Use "in_branch_delay" as the condition since + "call" delay slots and unconditional "branch" delay slots allow the + same type of insns. + (in_call_delay conditional): Deleted. + (branch define delay): Do not define an annul-if-true delay slot. + It is useless for an unconditional branch. + (all delay branch conditionals): Make sure "call", "dyncall", "multi", + and "milli" insns are explicitly disallowed in delay slots. + + * pa.c (output_mul_insn): Delete nop after branch in template, + conditionally emit a nop if the delay slot was not filled. (via %#) + + * pa.c (output_function_prologue): Handle profiling in a function + without a frame pointer. + + Thu Aug 20 16:16:40 1992 Tom Wood (wood@dg-rtp.dg.com) + + * va-m88k.h (__INT_VARARGS_H): Define this to avoid trouble on DG/UX. + + Thu Aug 20 11:07:26 1992 Michael Meissner (meissner@osf.org) + + * final.c: Move include of stdio.h before output.h. + + Thu Aug 20 01:08:55 1992 Pat Rankin (rankin at eql.caltech.edu) + + Support for bootstrapping cpp & cc1 with VAX C under VMS. + + * xm-vax-vms.h (USE_C_ALLOCA,NO_STAB_H): Define for VAXC. + (bcopy,bzero,bcmp,index,rindex): Define as ANSI/SYSV counterparts. + (QSORT_WORKAROUND, qsort): New macros, for avoiding buggy + qsort in VAXCRTL library. + (check_for_full_enumeration_handling,...): Use macros to shorten + several external names which are longer than 31 characters to + avoid warnings about truncation. + (unlink): Remove redundant definition. + * vax.c (not_qsort): New function. + * cccp.c (toplevel: create_definition): Move forward declaration + past the definition of struct macrodef. + (strncat): New function. + (bcopy, bzero, bcmp): Remove #if VMS code--always use inline C loops. + * genrecog.c, reload1.c: Compare enums (preds. codes, mem_mode) + explicitly to 0 in conditionals to work-around a VAXC bug that + disallows enum as arguments to && and || operators. + * getpwd.c (getpwd): Add alternative defn for VMS. + * toplev.c (environ): Make declaration conditional. + (main: -g debugging setup): Get rid of \ in #if condition. + * make-cccp.com,make-cc1.com (CC,CFLAGS,LIBS): Add commented command + variants for bootstrapping gcc-cpp and gcc-cc1 with VAXC. + * make-cccp.com (alloca): Build alloca.obj from alloca.c if LIBS needs it. + + Not yet installed: + + * machmode.h (FILE_TYPE): For VMS, make sure FILE_TYPE is not + defined as a macro, so that VAXC's won't break tree.h. + * genemit.c (gen_exp): #if VAXC, output a newline in front of + gen_rtx calls, to prevent excessively long lines in insn-emit.c. + + Thu Aug 20 11:32:18 1992 Michael Tiemann (tiemann@mole.gnu.ai.mit.edu) + + * cp-tree.h: Fix incorrect comment about "$this" needing to + be lexicographically less than any other identifier. + + Thu Aug 20 05:37:00 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * a29k.md (load_multiple): Operand 2 should be a MATCH_OPERAND. + (store_multiple_{,no_}bug): Likewise. + + * reorg.c (mark_set_resources): Fix two bugs in last change. + + * expr.c (init_expr_once): Set direct_load and direct_store if SOME + hard register can be loaded or stored; not just if the first one + we pick can be. + + Thu Aug 20 01:40:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * combine.c, emit-rtl.c, final.c, gcc.c, genattrtab.c, mips-tfile.c: + Put include of stdio.h after GCC header files + (for i860-stardent-sysv4). + * tree.c: Likewise. + + * fixincludes (stdio.h): Rename va_list to __va_list__ to coexist + with gvarargs.h. + + Wed Aug 19 21:06:49 1992 Jim Wilson (wilson@cygnus.com) + + * cccp.c (finclude): Increment indepth before calling + trigraph_pcp, so that warning uses the correct file name. + + Wed Aug 19 07:07:41 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (force_to_mode): Add missing test of and_optab. + + * genconfig.c (have_cmove_flag): New variable. + (walk_insn_part): Add new parm NON_PC_SET_SRC; all callers change. + Look for IF_THEN_ELSE in a SET_SRC that isn't setting PC and + set have_cmove_flag if so. + (main): Define HAVE_conditional_move if have_cmove_flag is non-zero. + * combine.c (subst, case AND): Only make IF_THEN_ELSE if conditional + moves exist. + + * cse.c (find_comparison_args): Look for comparison operations + if the second arg is 0 in any mode. + (record_jump_cond): Don't make classes equivalent for floating-point + equality comparison. + + * local-alloc.c (alloc_qty_for_scratch, block_alloc): Provide + alternate code in some cases when REGISTER_CONSTRAINTS is not + defined. + (requires_inout_p): Only used when REGISTER_CONSTRAINTS is defined. + + * reorg.c (mark_set_resources): Add new parm IN_DEST; add callers + changed. + Rework to scan an entire insn to look for auto-inc operations. + + * unroll.c (copy_loop_body): Add missing declaration of EXIT_LABEL + parameter. + + * function.c (instantiate_decl): New function. + (instantiate_decls{,_1}): Call it. + + * combine.c (simplify_comparison): Add a few more cases where we can + do the comparison in a wider mode. + + * combine.c (distribute_notes, REG_EQUAL): Don't put back a note + with a non-constant expression since it may no longer be valid. + + Tue Aug 18 23:07:33 1992 Mike Stump (mrs@cygnus.com) + + * expr.c (expand_expr): The first expansion of a TARGET_EXPR + is marked by DECL_RTL (slot) being filled in AND TREE_OPERAND + (exp, 1) being wiped-out with a NULL_TREE, not just the + DECL_RTL (slot) being filled in. + + Tue Aug 18 00:07:23 1992 Dennis P. Glatting (dglattin@trirex.com) + + * objc-actions.c + (build_selector_translation_table): NULL-terminate the + selector list. Mark _OBJC_SELECTOR_REFERENCES_decl as static, + not extern. + + Tue Aug 18 21:38:46 1992 Mike Stump (mrs@hal) + + * xcoffout.c (assign_type_number): Skip decls with no name. + + * expr.c (expand_expr): When expanding TARGET_EXPRs, make sure + that they are only expanded once, after the first expansion, + the rtl can be used without further expansions. + + Tue Aug 18 12:58:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * x-i386sco (X_CFLAGS): Defined. + + * stmt.c (expand_return): Call emit_queue in ignore-the-value case. + (expand_end_bindings): Check DECL_IN_SYSTEM_HEADER for unused warnings. + + * combine.c (simplify_comparison): + Rearrange conditional in SUBREG case. + + Tue Aug 18 06:49:43 1992 Tom Wood (wood@dg-rtp.dg.com) + + * cccp.c (HOST_WIDE_INT): Copy definition from machmode.h. + + * c-typeck.c (parser_build_binary_op): Replace the assignment of CLASS. + + * configure (Makefile edits): Make the edits independent. + * Makefile.in (sed marker): Use the order {target, host, cross-make}. + + Tue Aug 18 00:15:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (parser_build_binary_op): + For Z Cygnus merge. + + Tue Aug 4 12:58:59 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (pushtag): Don't set DECL_IGNORED_P for binding + layer markers, use only DECL_SOURCE_LINE == 0, as otherwise, + it messes up dbxout.c. + + Tue Aug 4 11:59:36 1992 Mike Stump (mrs@cygnus.com) + + Tue Aug 4 13:43:55 1992 Chip Salzenberg (chip@tct.com) + + * cp-method.c (hack_identifier): Remove redundant call of + assemble_external. + + Tue Aug 4 10:23:02 1992 Chip Salzenberg (chip@tct.com) + + * cp-decl.c (pushdecl): Any kind of DECL should be good enough + at global scope, not just a TEMPLATE_DECL. + + Sun Aug 2 21:12:55 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * cp-tree.c: change definition of __eprintf to match libgcc2.c and + assert.h + + Fri Jul 31 16:53:26 1992 Mike Stump (mrs@cygnus.com) + + * cp-tree (break_out_calls): Only make ony copy of a node on + 's' and 'e' nodes. Handle 'r' just like 's' and 'e' because + nodes of type 'r' can be of different sizes (the old code + would do the wrong thing for a COMPONENT_REF). + + Thu Jul 30 11:46:14 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-init.c (emit_base_init): Set transparent basetypes (those w/o + ctors) as marked if we need to walk up the tree to find a ctor. + + Wed Jul 29 03:25:51 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-decl.c (grokdeclarator): In SCOPE_REF case, sort out visibility + declarations from other declarations, since the compiler will + ultimately handle them differently. This is a part of the solution + to p525. + (finish_method): Tentative (and probably wrong) fix for carrying + along inline methods delcared within a class that really belong to + nested classes of the class. This may be more of the solution to + p525. + + * cp-init.c (build_offset_ref): Use IDENTIFIER_TYPE_VALUE of CNAME + when CURRENT_CLASS_DECL is 0. + + * cp-class.c (finish_struct): Don't give errors for TYPE_DECLs in a + struct that are really only meant for FIELD_DECLs. + + Tue Jul 28 23:36:58 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (grok_op_properties): Do not core dump on parse errors. + + Tue Jul 28 22:43:12 1992 Mark Eichin (eichin@cygnus.com) + + * cp-pt.c (end_template_instantiation) YYDEBUG is now defined in + cp-parse.h -- so don't assume that it's -2 (since under byacc it is + -1 anyway.) iomanip.C compiles again. + + Tue Jul 28 22:33:46 1992 Mike Stump (mrs@cygnus.com) + + * cp-typeck.c (build_c_cast): Allow cast to array type in + some situations to be more compatible with Cfront. + + Tue Jul 28 22:05:14 1992 Mark Eichin (eichin@cygnus.com) + + * cp-parse.y (print_parse_statistics): don't reference TOKEN_LENGTH + or REDUCE_LENGTH unless GATHER_STATISTICS is set. (YYDEBUG alone is + not a sufficient condition.) + + Tue Jul 28 19:18:30 1992 Mike Stump (mrs@cygnus.com) + + * cp-tree.c (break_out_calls): Don't do anything special to + SAVE_EXPRs, as they cannot contain calls that would need + breaking out. This fixes a problem introduced on Jul 15, by + Ron Guilmette. + + Mon Jul 27 16:55:52 1992 Mike Stump (mrs@cygnus.com) + + * c++: Fix errors introduced by rms. Bullet-proof handling + of arguments with funny things in them such as newlines, + spaces, tabs, single quotes, double quotes, etc... + + Mon Jul 27 15:03:23 1992 Ken Raeburn (raeburn@cygnus.com) + + * cp-init.c (build_vec_delete): Extract size of type even for + destructorless types, so value can be computed to pass to delete + operator. + + * Bludgeon interface/implementation code into leaving templates + alone, until we've figured out how to handle their interaction + properly: + * cp-parse.y (template_instantiate_once): Temporarily set interface + flags to `unknown' while processing member templates. + * cp-decl.c (grokfndecl): Even if class vtable is getting written + out, regardless of interface setting of class and write_virtuals + flag, don't force virtual destructor of template class to be public. + * cp-tree.h (struct pending_inline): New field `interface'. + * cp-lex.c (do_pending_inlines): Restore interface flags from stored + values, rather than calling extract_interface_info. + (process_next_inline): Likewise, if more pending inlines exist; else + do call extract_interface_info. + (reinit_parse_for_method): Save away interface flags. + (cons_up_default_function): Ditto. + * cp-pt.c (instantiate_template): Set saved interface flag to + `unknown'. + (end_template_instantiation): Set CLASSTYPE_INTERFACE_UNKNOWN. + + * cp-pt.c (instantiate_member_templates): Deleted some unused code. + + * cp-decl.c (grokfndecl): Make class methods public if + `implementation' pragma is set. + + * cp-pt.c (pending_templates): No longer exported. + (add_pending_template): Ditto. + * cp-parse.y (primary): Don't check it; always call + do_pending_templates. + + Fri Jul 24 14:22:39 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (init_decl_processing, finish_function), + cp-method.c (build_decl_overload, build_opfncall), cp-init.c + (build_x_delete, build_delete, build_vec_delete): Add support + for two argument delete to support ARM 12.5. In some cases, + the argument is smaller than it should be. + + Thu Jul 23 08:12:16 1992 Mike Stump (mrs@cygnus.com) + + * cp-lex.c: Update wide character handling from c-lex.c and make + the type of multicharacter constants be int per ANSI C++ WP. + + * cp-decl.c (init_decl_processing, grokdeclarator), cp-lex.h, + gplus.gperf, cp-lex.c (init_lex), cp-decl2.c (groktypefield), + cp-method.c (build_overload_name): Add support for wchar_t as a + distinct type to conform to x3j16 working paper. + * cp-hash.h: Regenerated. + + Wed Jul 22 17:41:08 1992 Mark Eichin (eichin@cygnus.com) + + * cp-parse.y (structsp): note_got_semicolon was called before + finish_struct (which always clears the got_semicolon bit.) However, + note_got_semicolon was only called if yychar==';', without checking + for YYEMPTY. + + Tue Jul 21 22:59:32 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-typeck.c (mark_addressable): If we have a recursive call to an + otherwise inline function, clear TREE_EXTERNAL so the whole function + is written to the asm file. + + Tue Jul 21 05:31:10 1992 Ken Raeburn (raeburn@cygnus.com) + + * cp-tree.h (start_type_method): Deleted unused declaration. + + * cp-pt.c (tsubst): Fix propagation of qualifiers in several cases. + + * cp-pt.c (tsubst, case FUNCTION_DECL): Look for matches that differ + only in return type. + + * cp-pt.c (tsubst, case FUNCTION_DECL): Rewrite name of + type-conversion operators, in case the target type involves a + template parameter. + + Mon Jul 20 03:35:44 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-class.c (add_virtual_function): Don't crash if + CURRENT_CLASS_TYPE is NULL_TREE. + * cp-decl2.c (grokfield): Ditto. + + Tue Aug 4 15:36:07 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (finish_decl): Don't do expand_decl_init for FUNCTION_DECL. + + * c-typeck.c (build_conditional_expr): Merged const and volatile flags + of incoming types. + + Tue Aug 4 11:15:47 1992 Chip Salzenberg (chip@tct.com) + + * c-decl.c (finish_struct): If bit field is of an unsigned + type that promotes to int, promote it unsigned if traditional + or if it is the same size as int. + (start_function): Ditto for function return value. + * c-typeck.c (default_conversion): Ditto -- fix bug that + promotes short to unsigned if sizeof(short) == sizeof(int). + + Tue Aug 4 15:12:51 1992 Tom Wood (wood@dg-rtp.dg.com) + + * svr3.h (USING_SVR3_H): Define. + * svr4.h (USING_SVR4_H): Define. + * aoutos.h (USING_AOUTOS_H): Define. + * m88k.h (EXTRA_SECTIONS): Base on the above defines. + + Tue Aug 4 14:22:44 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * dbxout.c: Include output.h. + + Tue Aug 4 00:21:06 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (install-common): Install protoize and related files + if they were compiled. + (install-proto): Target deleted. + (dbxout.o): Depend on output.h. + + Mon Aug 3 02:04:03 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (finish_function): Test only can_reach_end for the warning + about reaching the end of a non-void function. + (poplevel): If apparently nested inline function has + DECL_ABSTRACT_ORIGIN, don't output it; propagate TREE_ADDRESSABLE. + (pushdecl): When copying inline details into an extern decl, + copy DECL_RESULT, TREE_ASM_WRITTEN. Set DECL_ABSTRACT_ORIGIN. + + * c-parse.y (datadef): For empty declaration, use pedwarn. + * objc-parse.y (datadef, mydecl): Likewise. + + * Makefile.in (install-cross-tools): Install nm from tooldir. + + * varasm.c: Include real.h. + * sparcv4.h: Don't include real.h. + + * flow.c (mark_used_regs): Do recurse in setting of global hard reg. + Do set reg_next_use for global hard reg. + + * objc-parse.y (reserved_declspecs, declmods): Change as in c-parse.y. + + Mon Aug 3 03:24:17 1992 Paul Eggert (eggert@twinsun.com) + + * c-parse.y (reserved_declspecs): Warn if storage class occurs here. + (declmods): Warn if storage class is not first. + + Sun Aug 2 21:44:34 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * emit-rtl.c (gen_rtx, case REG): Don't use frame_pointer_rtx or + arg_pointer_rtx if reload is in progress. + + * jump.c (jump_optimize): When replacing jumps with logical + expressions, use preserve_subexpressions_p. + + * calls.c (expand_call): Use HOST_WIDE_INT instead of int when + comparing a pointer to an integer constant. + * flow.c (find_use_as_address): Likewise; also when returning int. + * integrate.c (expand_inline_function): Cast -1 to (HOST_WIDE_INT) + first. + + * cse.c (canon_hash): Use HOST_WIDE_INT instead of int when casting + pointers to integers. + * print-tree.c (print_node): Likewise. + * tree.c (TYPE_HASH): Likewise. + * varasm.c (const_hash, SYMHASH): Likewise. + + * toplev.c: (main): Don't cast pointers to int unnecessarily. + + * tree.c: Include function.h after tree.h. + + * rtl.h (NOTE_BLOCK_NUMBER): Change definition to simpler form. + (SET_NOTE_BLOCK_NUMBER): Deleted. + (xrealloc, oballoc, permalloc): Declare here as well as in tree.h. + * function.c (identify_blocks, reorder_blocks): Don't use + SET_NOTE_BLOCK_NUMBER. + + * varasm.c (struct addr_const): Use HOST_WIDE_INT for OFFSET. + + * combine.c (reg_sign_bit_copies): New variable. + (combine_instructions): Initialize it. + (set_significant): Set it. + (try_combine): Set subst_low_cuid immediately before calling `subst' + to the INSN_CUID of the lowest insn involved in the call. + Change XOR with out-of-range constant to (not (xor ...)). + Call both split_insns and find_split_point; pass extra parm to + find_split_point. + Record I2DEST's value if I2 now sets it; similarly for I1DEST. + (find_split_point): Add new arg INSN. + If AND'ing with a large single-bit constant and we only care about + equality with zero, replace with bit extraction. + Make two shifts for ZERO_EXTRACTs unless very narrow. + (subst): Move RESTART label earlier. + If we have a simple operation applied to IF_THEN_ELSE, move + the operation inside the two arms. + (subst, case SUBREG): Use force_to_mode. + (subst, case NOT): Change (not (xor X C)) to (xor X ~C). + (subst, case NEG): Remove optimization of (neg (abs X)); redundant. + Convert (neg (xor A 1)) to (plus A -1) if A is known to be 0 or 1. + (subst, case IF_THEN_ELSE): Simplify if an arm contains a register + being tested by substiting the known value. + Put constant integer in last arm is can reverse comparison. + (subst, case SET): Use gen_lowpart_for_combine. + (subst, case AND): Make IF_THEN_ELSE when appropriate. + (subst, case IOR): (ior A C) can sometimes be just C. + (subst, case XOR): Go back and restart when canonicalizing. + (subst, case ABS): Use num_sign_bit_copies. + (make_extraction): Call force_to_mode. + (make_compound_operation): Look at optabs rather that explicitly + checking for operations and assuming we have SImode. + Handle (ashiftrt (OP (ashift foo C1) C3) C2). + (force_to_mode): Only change mode of arithmetic if optab says we + have operation in that mode. + Remove unneeded ASHIFTRT; add handling for IF_THEN_ELSE. + (significant_bits, case NEG): Call num_sign_bit_copies. + (significant_bits, case ABS, case [US]{MIN,MAX}, IF_THEN_ELSE): New. + (num_sign_bit_copies): New function. + (simplify_shift_const): Remove ASHIFTRT if value is known -1 or 0. + Use num_sign_bit_copies to simplify (ashiftrt (ashift ...) ...) + and (ashiftrt (neg ...) ...). + Remove now redundant case when VAROP is a PLUS. + (simplify_comparison): If A is known to be -1 or 0, A != -1 is A == 0. + Simplify unsigned tests that really check the sign bit. + (simplify_comparison, case ASHIFTRT): Convert to LSHIFTRT if + equality comparison with zero. + (get_last_value): Check if the desired register is set in the + insn before the one whose INSN_CUID is subst_low_cuid. + + * expr.c (expand_builtin, case BUILT_IN_CONSTANT_P): Add missing + call to TREE_CODE. + + * reload1.c (reload): Set reload_in_progress earlier. + + * fold-const.c (optimize_bit_field_compare): Correct bogus use of + types in expressions; always do computation in a type wide enough + for the result. + + Sun Aug 2 01:30:22 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * objc-parse.y (attrib): Copied from c-parse.y. + + Sat Aug 1 13:34:49 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-pragma.c (HANDLE_PRAGMA_WEAK): Define only if SET_ASM_OP defined. + + * vax-vms.h: Renamed from vms.h. + * xm-vax-vms.h: Renamed from xm-vms.h. + * configure (vax-*-vms): Change file names. + + Sat Aug 1 16:13:09 1992 Mark Eichin (eichin@cygnus.com) + + * config/spc-sol2.h (ASM_OUTPUT_DWARF_STRING): redefinition was + incorrect, and uneeded; while Solaris as doesn't support .string, it + does support .asciz, and sparcv4.h takes care of including that + definition. + + Fri Jul 31 08:19:41 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu + + * combine.c (try_combine): Correctly handle implicit deaths of + I2DEST and I1DEST. + + * cexp.y: Add declaration for xmalloc. + + * cccp.c: Add declarations for malloc and realloc. + Include stddef.h when __STDC__ is defined. + (PTR_INT_TYPE): New macro. + (pcfinclude): Use it. + + * c-decl.c (init_decl_processing): __builtin_return_address, + __builtin_frame_address, and __builtin_saveregs all return void *. + + * reload.c (find_reloads_address_1): Convert another push_reload + call into a call to find_reloads_address_part. + + * reload1.c (gen_input_reload): Correct order of insns emitted + when using secondary memory. + + * reload1.c (reload_as_needed): Add missing semicolon after macro. + + * combine.c (distribute_notes, case REG_DEAD): If a register used + exactly twice is referenced in both I2 and I3, show it is used 3 times. + + * final.c (output_operand): Abort if X is a pseudo. + + * cse.c (exp_equiv_p, case CONST_INT): Use INTVAL instead of XINT. + + * expr.c (convert_move): Put FROM into a register if it is a SUBREG. + (For extension case.) + + Fri Jul 31 08:19:05 1992 Tom Wood (wood@dg-rtp.dg.com) + + * function.c (reposition_prologue_and_epilogue_notes): Search for + the notes without using basic_block_end[0] or basic_block_head[N-1]. + + Fri Jul 31 08:18:18 1992 Michael Meissner (meissner@osf.org) + + * reorg.c (get_branch_condition): Return 0 if all tests fall through. + + Fri Jul 31 02:28:02 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * glimits.h: Renamed from limits.h. + * Makefile.in (LIMITS_H): Deleted. + (install-limits-h): Use glimits.h, not limits.h. + * libgcc2.c: Include glimits.h. + + Thu Jul 30 09:54:07 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.h (FUNCTION_BOUNDARY, ASM_OUTPUT_ALIGN_CODE): Pack code + more tightly for the m88110. + + * m88k.md (cpu attribute): List m88100 first for more efficient + code in insn-attrtab.c. + + * m88k.md (rotate/and split pattern): Fix typo. + + Thu Jul 30 00:02:45 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * i860mach.h: New file. + * configure (i860-*-mach*): New alternative. + + * svr3.h (BSS_SECTION_FUNCTION): New macro. + (CTORS_SECTION_FUNCTION, DTORS_SECTION_FUNCTION): Enable these. + * tower-as.h (BSS_SECTION_FUNCTION): Deleted. + * dpx2.h (EXTRA_SECTION_FUNCTIONS): Deleted. + * att386.h (BSS_SECTION_FUNCTION): #undef before defining. + + * i860v3.h (USE_CONST_SECTION): #undef before defining. + + Wed Jul 29 20:04:55 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sparc.md (cmpsi): Delete 'J' constraint. + + Wed Jul 29 00:38:45 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-lex.c (yylex): When traditional, convert 0x80000000 to -0x80000000. + + * gcc.c (link_command_spec): Accept -static but do nothing with it. + + * loop.c (move_movables): When testing whether a reg contains + the function address of a call_insn in a libcall block, + use reg_referenced_p, to ignore destinations. + + * stor-layout.c (layout_record): Take account of + maximum_field_alignment when using the field's alignment. + + * c-parse.y (attrib): Fix previous change--the missing arg + was the last arg. + + * fixincludes: Don't repeat the directory-link-chasing loop + more than twice. Combine $prevdirs with $dirs--they had same value. + Properly discard $d itself from the output of find. + Find the links to directories by finding each link + and testing it with test. Add $newdirs into $files. + + Tue Jul 28 12:46:31 1992 Michael Meissner (meissner@osf.org) + + * c-common.c (decl_attributes): Call layout_decl with two arguments. + + * c-parse.y (attribute processing): Correctly call tree_cons with + three arguments, passing NULL_TREE for the purpose argument. + + * emit-rtl.c (make_insn_raw): Eliminate unused argument pat_formals, + and modify all callers. + (make_jump_insn_raw): Ditto. + + * reorg.c (fill_slots_from_thread): Function follow_jumps only takes + one argument. + (relax_delay_slots): Ditto. + + Tue Jul 28 16:04:43 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * dpx2g.h (ASM_OUTPUT_IDENT): #undef it. + + * c-decl.c (duplicate_decls): Handle warn_redundant_decls here. + But don't warn if function definition follows a declaration. + (pushdecl): Don't handle it here. + (grokparms): Don't warn about non-prototype decl in system header. + + * c-convert.c (convert): If main variants match, + but the type is not identical, make a NOP_EXPR. + + Tue Jul 28 10:06:18 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * mips.md: Correct use of `*' in constraints. Put it before each + letter to ignore, not each group to ignore. + + Tue Jul 28 01:23:35 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * dbxout.c (dbxout_parms): Do something for structures + passed by invisible reference, and living in memory. + + * gstddef.h (wchar_t): Alternate typedef for C++. + + * Makefile.in (extraclean): Delete config/ChangeLog. + + * m68k.md (probe): Use %a0 to output the address. + + Mon Jul 27 20:08:21 1992 Mike Stump (mrs@hal) + + * c++: Fix errors introduced by rms. Bullet-proof handling of + arguments with funny things in them such as newlines, spaces, tabs, + single quotes, double quotes, etc... + + Mon Jul 27 17:38:52 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sparc.md: Add DEFINE_SPLITs to optimize logic operation with + certain immediate values. + + * sparc.md: Correct inconsistent operand constraints in peepholes. + + * sparc.h (ASM_LONG, ASM_SHORT, ASM_BYTE_OP): Definitions added. + (ASM_OUTPUT_DOUBLE): Use REAL_VALUE_TO_TARGET_DOUBLE to convert. + (ASM_OUTPUT_FLOAT): Use REAL_VALUE_TO_TARGET_SINGLE to convert. + (ASM_OUTPUT_INT): Use ASM_LONG pseudo-op. + (ASM_OUTPUT_SHORT): Use ASM_SHORT pseudo-op. + (ASM_OUTPUT_CHAR): Use ASM_BYTE_OP pseudo-op. + (ASM_OUTPUT_BYTE): Use ASM_BYTE_OP pseudo-op. + + Mon Jul 27 17:10:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstdarg.h (va_arg): Don't use +=; no need to set AP twice. + + Sun Jul 26 14:21:13 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * final.c (final_scan_insn): Align jump table only if + READONLY_DATA_SECTION. Otherwise, the table is in the text section. + + * collect2.c (dup2): Defined, if NO_DUP2. + + * plexus.h: New file. + * m68k.c (output_function_prologue): Make a probe instruction + if NEED_PROBE if nonzero. + * configure (m68k-plexus-sysv*): New alternative. + + * c-convert.c (convert): Succeed if TYPE is the main variant + of the given type. + * c-typeck.c (build_conditional_expr): Compare using TYPE_MAIN_VARIANT. + + * c-decl.c (duplicate_decls): Copy old RTL *before* make_var_volatile. + + Sat Jul 25 21:45:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (pushdecl): Never reuse global fcn decl in place of + local extern; just copy some info from it. + + Sat Jul 25 06:14:58 1992 Tom Wood (wood@dg-rtp.dg.com) + + * expmed.c (expand_divmod): Eliminate the generation of branches + when possible. + + Sat Jul 25 04:34:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fixincludes (X11/Xmu/Xmu.h): Fix this or X11/Xmu.h, + whichever exists. + + Sat Jul 25 00:41:12 1992 Paul Eggert (eggert@twinsun.com) + + * c-parse.y (datadecl): Diagnose empty declarations in old-style + function headers. + * c-decl.c (shadow_tag_warned): New function. + + * c-lex.c (yylex): Diagnose `1.0fl'. Issue just one + diagnostic for `1e1000000f'. + + Fri Jul 24 19:25:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * dbxout.c (dbxout_symbol): Distinguish implicit C++ typedefs + from explicit C typedefs for structs, using DECL_SOURCE_LINE. + + * c-decl.c (duplicate_decls): Use TYPE_MAIN_VARIANT even for compares + with void_type_node. + (grokdeclarator, get_parm_info, store_parm_decls): Likewise. + + Fri Jul 24 10:07:13 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * dwarfout.c (is_tagged_type): New function added. + (member_attribute): Use it. + (type_ok_for_scope): Rewritten to eliminate serious bugs. + (output_type): Call `output_pending_types_for_scope' at the end of + struct/union types (which are themselves scopes in C++). + + Fri Jul 24 13:36:46 1992 Michael Meissner (meissner@osf.org) + + * dbxout.c (toplevel): Include defaults.h to get the definition of + ASM_STABD_OP. + + * Makefile.in (dbxout.o): Add defaults.h dependent. + + * i386rose.h (CC1_SPEC): Remove MIPS switches accidently left in. + + Thu Jul 23 09:49:43 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * dwarfout.c (is_body_block): Rewritten for greater saftey. + (output_block): Fixed to deal correctly with non-inlined blocks. + + Thu Jul 23 15:37:23 1992 Jeffrey A Law (law at schirf.cs.utah.edu) + + * flow.c (propagate_block): Change "struct foo" to "struct sometimes". + + Thu Jul 23 15:10:51 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.h (ASM_OUTPUT_CASE_LABEL): Change to readonly section if the + table contains addresses. + (JUMP_TABLES_IN_TEXT_SECTION): True by default. + + Thu Jul 23 13:54:27 1992 Michael Meissner (meissner@osf.org) + + * mips.c (large_int): Use HOST_WIDE_INT type to hold INTVAL. + (gen_int_relational): Ditto. + (gen_conditonal_branch): Don't emit any insns if the result is + always false, and emit a normal jump if the result is always true. + + * mips.c (mips_move_1word): Count LABEL_REF's as a memory + reference. Rework half-pic load of symbols, to not expect movsi + to have converted the load address into a load, and for CONST's, + do the addition after the pointer is loaded. + + * mips.md (type attribute, movsi3): Eliminate 'pic' attribute, + just use 'load' instead. + (fix_truncdfsi2): Make this a define_insn, instead of a + define_exapnd and an insn, and use match_scratch to allocate the + two scratch registers. Adjust length costs, so that they match + the current code the assembler produces. + (fix_truncsfsi2): Ditto. + (movsi): Don't convert load of half-pic addresses and CONST's into + the real load. It causes more problems than it solves. Adjust + cost of half-pic addresses to be 2, not 4. + + * mips-tfile.c (parse_def): Allow spaces in names, since C++ + templates produce things like: #.def SMANIP; ... + (parse_stabs_common): Code from Lisa Repka, to handle symbol +/- + offset, and to look up things in the external string table, if the + name is not found in the local string table. + + Wed Jul 22 13:08:33 1992 Jeffrey A. Law (law@schirf.cs.utah.edu) + + * sparc.md (movdf+1): Use new 'T' and 'U' constraints to + determine when an ldd or std will have a length of 1, and + therefore is eligible for use in some delay slots. + (uncond_branch): New attribute used for unconditional branches. + All unconditional branch patterns changed. + (define_delays and delay slot attributes): Do not allow + uncond_branch instructions in delay slots. Do not allow fpload or + fpstore operations in a conditional branch delay slot. Allow + fpload and fpstore in call, unconditional branch, and annuled + conditional branch delay slots. + + * sparc.c (registers_ok_for_ldd_peep, addrs_ok_for_ldd_peep): + Functions renamed from registers_ok_for_ldd and + memory_ok_for_ldd respectively. All callers changed. + (register_ok_for_ldd): New function to determine if a register is + a pseudo or the first register in a hard register pair. + (mem_aligned_8): No longer static. Return 0 instead of aborting + when presented an rtx which is not a MEM. + (eligible_for_epilogue_delay): Use in_uncond_branch_delay since + this in an unconditional branch. + + * sparc.h (EXTRA_CONSTRAINT) Add new 'T' and 'U' constraints + which check for aligned accesses to memory and register pairs. + + Wed Jul 22 11:22:37 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Bump meissner version number to 22. + (extern declarations): Add declarations for asm_file_name, + call_used_regs, langguage_string, save_argv, version_string, + mips_{begin,end,expand}_{pro,epi}logue, simple_epilogue_p, + {address,const_{double,int},general,{,non}immediate}_operand, + memory_address_p, {{,non}memory,register,scratch}_operand, + abort_with_insn, debug_rtx, fatal_io_error, get_frame_size, + offsettable_address_p, output_address, permalloc, + reg_mentioned_p, abort, atoi, getenv, mktemp, and + mips_expand_{epi,pro}logue. + (*_REGNUM): Add in GP_REG_FIRST in case registers are ever + renumbered. + (struct mips_frame_info): Add num_gp, num_fp fields. + (SECONDARY_MEMORY_NEEDED): Define, return 1 unless -mdebugh if + moving between FP <-> GP registers. + + * mips.c (extern declarations): Move most of the declarations to + mips.h, except for those of type 'rtx' or 'tree', since not all + files include rtl.h and tree.h. Add more declarations for gen_xxx + functions that are now used. + (reg_or_0_operand): Add default case for switch on enumeration, to + allow compiling with -Wall. + (simple_memory_operand): Ditto. + (mips_count_memory_refs): Ditto. + (mips_move_1word): Ditto. + (mips_move_2words): Ditto. + (mips_address_cost): Ditto. + (map_test_to_internal_test): Ditto. + (mips_move_1word): Align asm comments in loading negative ints. + (mips_move_1word): Use GEN_INT macro to generate CONST_INT's. + (mips_move_2words): Ditto. + (gen_int_relational): Ditto. + (block_move_load_store): Ditto. + (block_move_loop): Ditto. + (expand_block_move): Ditto. + (block_move_load_store): #if 0, not currently used. + (block_move_sequence): Ditto. + (compute_frame_size): Fill in num_gp and num_fp fields. + (simple_prologue_p): Rename from null_prologue. + (save_restore_insns): New function to emit appropriate save and + restore operations for prologue/epilogue -- only prologue used at + present. + (function_prologue): Move generation of instructions to + mips_expand_prologue. + (mips_expand_prologue): Generate appropriate insns for the + prologue of the function. + (mips_expand_epilogue): Generate appropriate insns for the + epilogue of the function -- not called at present. + + * mips.md (ashldi3_internal): Add `&' constraint to operand 0. + (ashrdi3_internal): Add `&' constraint to operand 0. + (return): Turn this into a define expand that wraps a return and a + USE reg:31 inside of a parallel. + (return_internal): Insn form of return instruction. + (prologue): New define expand to generate the necessary + instructions for the function prologue. + (mov{si,hi,qi}): Split the integer move INSNs into two groups, + those that support -mdebugh and allow ints to be in floating + point registers, and those that don't allow it. + + Tue Jul 21 21:27:43 1992 Mike Stump (mrs@albert.gnu.ai.mit.edu) + + * Complete 9th Cygnus <---> FSF merge. + + Tue Jul 21 03:17:05 1992 Mark Eichin (eichin@cygnus.com) + + * cp-lex.c (process_next_inline): when bailing out on a parse error, + throw away nextchar as well in case it got set. + + Tue Jul 21 05:31:10 1992 Ken Raeburn (raeburn@cygnus.com) + + * cp-pt.c (tsubst, case FUNCTION_DECL): If the context class has a + null method vector, don't look inside it for its size. + + Thu Jul 16 16:02:55 1992 Per Bothner (bothner@rtl.cygnus.com) + + * cp-typeck.c (convert_for_assignment): If assigning (void*) + to a normal pointer, emit a warning, not an error. There is + a lot of existing code (including libg++ and converted C + code) that expects to be able to assign from (void*). + + Tue Jul 14 06:59:38 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-decl.c (finish_function): Call destructors correctly when + baseclasses are replicated in the inheritance hierarchy. + + Mon Jul 13 05:16:10 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-typeck.c (build_modify_expr): If we split a COND_EXPR in order + to perform the assignment in each arm, convert the rhs of each + branch according to RESULT_TYPE. + + * cp-typeck.c (convert_for_assignment): Treat null_pointer_node + specially when converting to non-void pointers. + + * cp-class.c (modify_vtable_entries): In the loop that modifies + vtable entries for each non-virtual baseclass, correctly handle + cases where BASE is an ambiguous baseclass for BASE_CONTEXT. + + Sun Jul 12 01:32:31 1992 Mike Stump (mrs@cygnus.com) + + Wed May 27 01:33:24 1992 Ron Guilmette (rfg at ncd.com) + + * cp-type2.c (store_init_value), cp-typeck.c + (build_modify_expr, convert_arguments, + build_binary_op_nodefault, convert_for_assignment), cp-parse.y + (member_init, template_def, datadef, stmt): changed some + pedantics into !traditionals and reworded error messages. + + Sun Jul 12 01:11:53 1992 Mike Stump (mrs@cygnus.com) + + Jul 1992 Ron Guilmette (rfg at ncd.com) + + * cp-decl.c (finish_function): Set BLOCK_SUPERCONTEXT for the + outermost scopes of functions to point to the associated + FUNCTION_DECL nodes. + + Fri Jul 10 17:52:36 1992 Ken Raeburn (raeburn@cygnus.com) + + * cp-decl.c (struct binding_level): New field pseudo_global + indicates that this binding level should be treated like the global + binding level in some respects. + (declare_pseudo_global_level, pseudo_global_level_p): Set and test + routines. + (push_overloaded_decl): Don't forget overloads in pseudo-global + binding levels. + * cp-pt.c (tsubst, case FUNCTION_DECL): Search for an existing decl + before creating a new one. + (overload_template_name): Make new level pseudo-global. + (type_unification): Indicate failure for unknown_type_node. + (unify): Likewise. + + Wed Jul 8 01:59:03 1992 Mike Stump (mrs@cygnus.com) + + * cp-decl.c (lookup_name, grokvardecl, grokdeclarator), + cp-call.c (build_field_call), cp-seach.c (lookup_field), + cp-typeck.c (build_component_ref), cp-lex.c (do_identifier), + cp-init.c (expand_member_init, build_member_call, + build_offset_ref): lookup_field now has 4 arguments. + + Wed Jul 8 01:14:43 1992 Mike Stump (mrs@cygnus.com) + + * cp-parse.y (primary): Call to lookup_name needs 2 arguments. + + Tue Jul 7 21:14:05 1992 Mike Stump (mrs@cygnus.com) + + * cp-method.c (build_overload_name): Handle INTEGER_TYPEs + cleanly and uniformly. + + Tue Jul 7 09:19:52 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-call.c (build_method_call): If `convert_to_pointer' returns + error_mark_node, return that without doing any more work. + + Thu Jul 2 15:42:28 1992 Mike Stump (mrs@cygnus.com) + + Thu Jul 2 18:08:42 1992 Chip Salzenberg (chip at tct.com) + + * cp-typeck.c (convert_arguments): Don't assume that error + message will be short enough for fixed-length buffer. + + Wed Jul 1 19:52:59 1992 Mike Stump (mrs at cygnus.com) + + Wed Jun 3 12:57:57 1992 Brendan Kehoe (brendan@cs.widener.edu) + + * cp-decl2.c (grokbitfield): Only do width checking on properly + parsed bitfields. + + Wed Jul 1 18:58:17 1992 Mike Stump (mrs at cygnus.com) + + Wed May 27 01:33:24 1992 Ron Guilmette (rfg at ncd.com) + + * cp-lex.c (readescape), cp-parse.y (unary_expr, maybecomma_warn, + component_decl_list, stmt), cp-type2.c (digest_init), cp-typeck.c + (c_sizeof, build_function_call_real, convert_arguments, + build_binary_op_nodefault, pointer_int_sum, pointer_diff, + build_unary_op, c_expand_return): change some warnings to + pedwarns. Put in new pedwarns, change wording of messages so that + they are more readable. Don't issue some warnings when + traditional is given. + + Wed Jul 1 13:56:30 1992 Mike Stump (mrs at cygnus.com) + + Wed Apr 29 23:37:00 1992 Niklas Hallqvist (niklas at appli.se) + + * cp-decl.c (finish_decl): make sure destructors are called for + objects in a file. + + Wed Jul 1 11:12:05 1992 Mike Stump (mrs at cygnus.com) + + * cp-lex.c: extract YYEMPTY out of the parser generated .c + file and put in the parser .h so that cp-lex.c does not have + to define it. + + Mon Jun 29 12:58:59 1992 Mike Stump (mrs at cygnus.com) + + Mon Jun 29 15:20:48 1992 Chip Salzenberg (chip at tct.com) + + * cp-cvt.c (convert_to_integer): Don't add a NOP_EXPR in cases + where we can simply change the type of the entire tree. + + Mon Jun 29 10:56:56 1992 Mike Stump (mrs at cygnus.com) + + * c++: Makes sure -lg++ comes before -lm since libg++ uses + things from libm. + + Mon Jun 22 13:47:42 1992 Mike Stump (mrs at cygnus.com) + + Sun Jun 21 14:06:41 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-typeck.c (convert_for_initialization): Only try to convert a + rhs that was parsed properly. + + Mon Jun 22 13:31:40 1992 Jim Wilson (wilson at sphagnum.cygnus.com) + + * cp-parse.y (primary): Clear the TREE_USED flag of a block tree + put in a BIND_EXPR. + + Sun Jun 21 09:59:58 1992 Michael Tiemann (tiemann at rtl.cygnus.com) + + * cp-type2.c (build_scoped_ref): Use SCRATCH for head of typelist, + rather than calling alloca. + + Fri Jun 19 16:23:02 1992 Mike Stump (mrs at cygnus.com) + + * cp-pt.c (unify): Type unification of things that do not have a + valid IDENTIFIER_TEMPLATE fail instead of core dumping. + + Wed Jun 17 13:36:04 1992 Michael Tiemann (tiemann at rtl.cygnus.com) + + * cp-pt.c (tsubst): Don't try to substitute into error_mark_node. + + * cp-decl.c (grokparms): Convert initializers that have + TREE_READONLY_DECL_P set into their constant equivalents. + + Tue Jun 16 19:09:23 1992 Mike Stump (mrs at cygnus.com) + + Wed Jun 3 12:57:57 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-decl.c (grokdeclarator): Disallow virtual functions in unions. + + Tue Jun 16 18:11:45 1992 Mike Stump (mrs at cygnus.com) + + Wed Jun 3 12:57:57 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-class.c (finish_struct): Forbid local classes to have static + members. + + Mon Jun 15 21:44:08 1992 Mike Stump (mrs at cygnus.com) + + Tue Jun 2 09:26:34 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-init.c (build_new): Don't allow the use of new on a reference. + + Mon Jun 15 20:52:08 1992 Mike Stump (mrs at cygnus.com) + + Tue Jun 2 09:26:34 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-decl.c (grokparms): Don't allow a local variable to be used + in a default argument expression. + + Mon Jun 15 18:54:28 1992 Mike Stump (mrs at cygnus.com) + + * cp-decl.c (finish_decl): Add an error message for uninitialized + const objects like const int a;. + + Mon Jun 15 16:05:22 1992 Mike Stump (mrs at cygnus.com) + + Not sure if it is strictly necessary for the C++ front end, but... + + Sun May 31 15:31:46 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-typeck.c (self_promoting_args_p): Allow the arg type to be + null (copied from Oct 16, 1991 change by Wood). + + Fri Jun 12 16:42:05 1992 Mike Stump (mrs at cygnus.com) + + * cp-typeck.c (build_binary_op_nodefault): Conditionalize code that + deals with the comparison of non-distinct object types, thus avoiding + a core dump. + + Fri Jun 12 10:23:17 1992 Mike Stump (mrs at cygnus.com) + + Wed Jun 10 19:20:29 1992 Brendan Kehoe (brendan at cs.widener.edu) + + * cp-tree.c (break_out_calls): Begin at 1 less than the length of + the length of the tree code, not the length itself, for generic + expressions and those with side-effects. + + Thu Jun 11 17:43:55 1992 Mike Stump (mrs at cygnus.com) + + * cp-init.c (expand_default_init): New function to handle the + details of default copy constructors and other magic in one place. + + * cp-init.c (expand_aggr_init_1): Implement default constructors + more fully. + + Thu Jun 11 17:16:54 1992 Mike Stump (mrs at cygnus.com) + + * cp-call.c (build_method_call): Don't produce an error message if + we are looking up things speculatively. + + Thu Jun 11 10:58:47 1992 Mike Stump (mrs at cygnus.com) + + * cp-call.c (convert_harshness): Penalize const arguments passed + into non-const parameters. + + Thu Jun 11 10:02:52 1992 Mike Stump (mrs at cygnus.com) + + * cp-typeck.c (build_c_cast): Implement more reference casts so + that one can cast a base reference to a derived reference. + + Tue Jul 21 15:28:36 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sparc.h (SECONDARY_MEMORY_NEEDED): Define to force reload to + handle any copy between GENERAL_REGS and FP_REGS. + + * sched.c (schedule_block): Give some insns high priorities, + instead of excluding them from scheduling, to ensure that they end + up at the end of the block after scheduling. + + * i960.c (i960_output_ldconst): Use REAL_VALUE_FROM_CONST_DOUBLE + instead of pointer indirection to extract double from CONST_DOUBLE. + + Tue Jul 21 14:05:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * svr4.h (HANDLE_SYSV_PRAGMA): Defined. + + * sol-crt*.asm: Renamed from sol-crt*.s, and put in config. + * t-sol2 (crt*.o): Changed accordingly. Also use $(AS). + + * gbl-ctors.h (ON_EXIT): Test HAVE_ATEXIT before sun. + + Mon Jul 20 18:56:02 1992 Fred Fish (fnf at fishpond) + + * svr4.h (ASM_OUTPUT_BEFORE_CASE_LABEL): New macro--default definition. + (ASM_OUTPUT_CASE_LABEL): Use that. + * m68ksgs.h (ASM_OUTPUT_BEFORE_CASE_LABEL): Do the swbeg here. + (ASM_OUTPUT_CASE_LABEL): Use that. + + * configure (m68k-*-amix*): Use fixinc.svr4 and install.sh. + + * x-amix (ENQUIRE_CFLAGS): Remove; obsolete. + + * amix.h (TRANSFER_FROM_TRAMPOLINE): Remove #undef. + + Mon Jul 20 17:45:46 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * dbxout.c (dbxout_source_line): New function. + * final.c (output_source_line): Use that. + + * configure (sparc-*-sunos5*): New alias. + (sparc-*-solaris2*): Use t-sol2. + + * i860.md (mulsi3_little, mulsi3_big): New define_expand patterns. + (mulsi3): Just use one of them. + + * Makefile.in (install-fixincludes): Pass second and third args. + + Mon Jul 20 16:07:12 1992 Pat Rankin (rankin@eql.caltech.edu) + + * vms.h (MAYBE_VMS_FUNCTION_PROLOGUE): change _c$main_args to + uppercase instead of relying on gas to make the case translation + + Sun Jul 19 00:04:16 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-tree.h (C_PROMOTING_INTEGER_TYPE_P): New macro. + * c-decl.c (duplicate_decls, grokdeclarator, finish_struct): + Use C_PROMOTING_INTEGER_TYPE_P to decide whether a type promotes. + (start_function): Likewise. + * c-typeck.c (default_conversion): Use C_PROMOTING_INTEGER_TYPE_P + to decide whether a type should promote. + (self_promoting_args_p, self_promoting_type_p): Likewise. + + * c-aux-info.c (gen_type): For array type, state the size. + + * final.c (output_addr_const): Handle ZERO_EXTEND and SIGN_EXTEND. + * expr.c (expand_expr, NOP_EXPR case): If EXPAND_INITIALIZER, + generate ZERO_EXTEND or SIGN_EXTEND; don't emit insns. + + * function.c (assign_parms): Use const0_rtx as DECL_RTL and as + DECL_INCOMING_RTL if tmode of parm is void. + + * jump.c (mark_jump_label): Don't make REG_LABEL for nonlocal label. + * loop.c (add_label_notes): Don't make REG_LABEL for nonlocal label. + (rtx_renumbered_equal_p): Use == to compare nonlocal labels. + + * rtl.h (LABEL_REF_NONLOCAL_P): New macro. + * expr.c (expand_expr): Set LABEL_REF_NONLOCAL_P for nonlocal labels. + * reload1.c (set_label_offsets): Ignore nonlocal labels. + + * c-parse.y (primary): Set TREE_CONSTANT in the NOP_EXPR for an enum. + + * Solaris changes from Cygnus: + + * fixinc.svr4: take a third argument indicating where files to be + copied in should come from (useful when not building in source + directory). + Set TERM to dumb so ex won't hang (by zoo). + * fixincludes: Take the same new argument. + + * gmon-sol2.c: New file. + * t-sol2: New file. + * sol2-crt1.s, sol2-crti.s, sol2-crtn.s: New files. + + * xm-spcv4.h (ONLY_INT_FIELDS): Define, if __GNUC__. + + * sparc.h (FUNCTION_PROFILER): Use ASM_OUTPUT_INTERNAL_LABELREF. + (FUNCTION_BLOCK_PROFILER): Mark with FIXME that it needs work. + (ASM_OUTPUT_INTERNAL_LABELREF): Define. + * spc-sol2.h: Entire file is new except for + defining MD_STARTFILE_PREFIX. + * dbxout.c (dbxout_block): obey DBX_BLOCKS_FUNCTION_RELATIVE + (dbxout_init): Use ASM_IDENTIFY_GCC_AFTER_SOURCE if defined. + + * sparc.h (CONSTANT_ALIGNMENT): Add parens for Sun compiler. + + Sun Jul 19 11:03:56 1992 Fred Fish (fnf at fishpond) + + * i386v4.h (real.h): Remove apparently unnecessary inclusion. + * i386v4.h (HANDLE_SYSV_PRAGMA): Replaces HANDLE_PRAGMA. + + Sat Jul 18 20:37:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (build_binary_op): Don't set shorten for signed division. + + * final.c (end_final): Align the table of addresses. + + Fri Jul 17 23:49:28 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * cexp.y: Include stdio.h. + + Fri Jul 17 06:17:34 1992 Tom Wood (wood@dg-rtp.dg.com) + + * cp-tree.h (DECL_THIS_EXTERN): Renamed from DECL_EXTERNAL. + * cp-pt.c, cp-decl.c: Rename DECL_EXTERNAL -> DECL_THIS_EXTERN and + then rename TREE_EXTERNAL -> DECL_EXTERNAL. + + Fri Jul 17 05:59:26 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * function.c (instantiate_decls{,_1}): Don't do instantiation + here if the address is mode-dependent. + + * libgcc2.c: Include tconfig.h instead of tm.h. + Include machmode.h. + (__do_global_dtors): Cast to widest integer type, then narrow, to + avoid warning if int is narrower than pointer. + * Makefile.in (libgcc2.a): Includes machmode.h. + + * cse.c (cse_insn): Allow paradoxical SUBREGs in the table. + + * reload.c (secondary_memlocs{,_elim}): New variables. + (get_secondary_mem, clear_secondary_mem): New function. + (push_reload): Convert SUBREG of hard reg to new hard reg. + Call get_secondary_mem when needed. + (find_reloads): Clear secondary_memloc_elim for each insn. + * reload1.c (reload): If SECONDARY_MEMORY_NEEDED, check for frame + size changed. + Call clear_secondary_mem. + (emit_reload_insns, gen_input_reload): Use memory when required to + do reload. + * reload.h (get_secondary_mem): Declare. + + * cccp.c (NULL_PTR): Define as void * if STDC. + + * rs6000.md (negdi2): Corrected name; used to be negdi3. + + * combine.c (subst, case SET): Put code to move SUBREG after + code that calls make_compound_operation. + (make_extraction): Don't check for INNER a REG except for in dest. + Fix typo checking for REG. + (make_compound_operation): Get the result in the same mode it + used to be. + + * reload.c (push_reload): If a SUBREG requires a secondary reload + but the inner expression doesn't, reload the inner expression + instead. + + Fri Jul 17 02:20:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gcc.c (process_command): Handle `-Wl,' and `-Wa,'. + (do_spec_1): Handle %Y. + (default_compilers): Use %Y in assembler commands. + + * function.c (assign_parms): In last change, test mode in parm type. + + Thu Jul 16 15:03:25 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * loop.c (find_and_verify_loops): Ignore jumps to missing labels, + when using P. + + * c-typeck.c (build_binary_op): Improve shift warning messages. + + * x-dpx2 (AS): Use $(GAS). + (GAS): New variable. + + * mot3300.h (ASM_OUTPUT_CASE_END): Deleted. + + * function.c (assign_parms): If arg was passed by invisible + reference, copy it to a pseudo if appropriate. + + * dwarfout.c (pure_or_virtual_attribute): + Add #if 0 around use of DECL_ABSTRACT_VIRTUAL_P. + + Wed Jul 15 16:29:05 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * dwarfout.c (BLOCK_INLINE_FUNCTION): Obsolete definition deleted. + (block_ultimate_origin): New function. + (output_block): + Local var `have_significant_locals' renamed to `must_output_die'. + (output_block): Rewritten to handle abstract & concrete instances of + blocks of inline functions. + (output_decls_for_scope): + Don't bump `next_block_number' for abstract blocks. + + * toplev.c (rest_of_compilation): Call `dwarfout_file_scope_decl' for + both types of "abstract" instances of inline functions. + + * tree.def (BLOCK): Use new tree code category letter 'b' for BLOCKs. + * tree.h (struct tree_block): New struct type definition added. + (BLOCK_VARS, BLOCK_TYPE_TAGS, BLOCK_SUBBLOCKS, BLOCK_HANDLER_BLOCK): + Changed to reference fields of the new `struct tree_block' type. + (BLOCK_ABSTRACT_ORIGIN, BLOCK_ABSTRACT): Definitions added. + (union tree_node): Added `struct tree_block' as a new variant. + * tree.c (typedef tree_node_kind): Added new kind, i.e. `b_kind'. + (tree_node_kind_names): Added string name for new kind `b_kind'. + (make_node, copy_node, stabilize_reference_1): + Handle case 'b' (for BLOCK nodes). + (make_node): Don't try to deal with BLOCKs when doing a type 'e' node. + * print-tree.c (print_node): + Handle type 'b'; delete code for BLOCK from 'e' case. + Handle fields BLOCK_ABSTRACT_ORIGIN and BLOCK_ABSTRACT. + * calls.c (calls_alloca): Don't return 0 automatically if the expr + given is headed by a type 'b' node. + * cp-tree.c (break_out_calls): Add case for decl nodes. + Added case to catch BLOCK nodes (and to abort). + * integrate.c (copy_decl_tree): Set BLOCK_ABSTRACT_ORIGIN in new + instance block if not already set. + (expand_inline_function): Set BLOCK_ABSTRACT_ORIGIN for outermost + scope to point to progenitor (abstract inline) FUNCTION_DECL node. + (integrate_decl_tree): Set BLOCK_ABSTRACT_ORIGIN for inlined instance + BLOCKs. + (set_block_origin_self, set_decl_origin_self, set_block_abstract_flags, + set_decl_abstract_flags): New functions. + (output_inline_function): Call `set_decl_origin_self' for each fndecl + which is about to have an out-of-line instance generated for it. + + Wed Jul 15 15:08:00 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-convert.c (convert_to_integer): Push truncation inside COND_EXPR. + + * optabs.c (emit_cmp_insn): Always do protect_from_queue on x, y, size. + (expand_float, expand_fix): Likewise. + * expmed.c (expand_shift, expand_set_flag): + Call protect_from_queue before convert_to_mode. + * expr.c (convert_move): Don't call protect_from_queue. + (emit_block_move): Protect SIZE. + + * explow.c (allocate_dynamic_stack_space) [SETJMP_VIA_SAVE_AREA]: + Always call round_push; we can't rely on alignment of size. + + Wed Jul 15 06:47:11 1992 Richard Kenner (kenner@vlsi1.ultra.nyu) + + * combine.c (try_combine): Verify that I2DEST is a register before + trying to change its mode. + + Tue Jul 14 15:13:28 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * c-decl.c (finish_struct): Handle nested struct redefinitions. + * stor-layout.c (layout_record): Handle NULL dsize. + + Tue Jul 14 21:31:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (duplicate_decls, pushdecl, grokdeclarator): + (store_parm_decls, combine_parm_decls, finish_function): + Use TYPE_MAIN_VARIANT when comparing against specific non-void types. + * c-typeck.c (self_promoting_args_p, self_promoting_type_p): + (signed_type, unsigned_type, default_conversion, check_format): + (build_binary_op, c_expand_start_case): Likewise. + + Mon Jul 13 14:57:34 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (finish_function): Fix braino validating ret type of main. + + * expr.c (expand_builtin): Refer to errno at rtl level only. + * sparc.h (TARGET_EDOM, GEN_ERRNO_RTX): New macros. + + Mon Jul 13 06:35:53 1992 Paul Eggert (eggert@twinsun.com) + + * expr.c (expand_builtin): + For fsqrt, always use the special insn, then test for nan. + + Mon Jul 13 08:45:34 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.md: Constraint fixes from Torbjorn. + + * jump.c (jump_optimize): In `x = a; if (...) x = b;' allow both a + and b to be non-zero if jumps are very expensive. Also allow a + and b to be constants where all the set bits in a are also set in + b when jumps are merely expensive. + + Sun Jul 12 17:43:03 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * genpeep.c (match_rtx): Sometimes use %ld when printing an XWINT. + + * regclass.c (record_reg_classes): If OP is a REG, use it's mode + in case the mode in MATCH_OPERAND is VOIDmode. + + Sun Jul 12 13:03:54 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fixincludes: Replace the code that finds all directories + so that it looks for subdirs of dir reached via symlinks. + + * cp-tree.h (IDENTIFIER_VIRTUAL_P): Macro moved here. + * tree.h (IDENTIFIER_VIRTUAL_P): Deleted from here. + + * rtl.h (NOTE_BLOCK_NUMBER, SET_NOTE_BLOCK_NUMBER): New macros. + (NOTE_DECL_NAME, NOTE_DECL_CODE, ...): #if 0'd. + * function.c (identify_blocks, reorder_blocks): New functions. + (all_blocks, blocks_nreverse): New functions. + + * isi.h: Deleted the #error; file should work now. + (LIB_SPEC): Use -lg only once. + (STRUCTURE_SIZE_BOUNDARY): Defined. + + * protoize.c (process_aux_info_file): Set must_create before jumping to + start_over. Don't clear must_create at start_over. Don't test + source file mod time for SYSCALLS. + + * machmode.h (GET_MODE_NUNITS): Avoid division by zero. + + Sat Jul 11 22:21:47 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * objc-parse.y (primary): Don't test TREE_EXTERNAL; + call assemble_external regardless. + + * tree.h (DECL_INLINE, DECL_NONLOCAL, DECL_REGISTER, DECL_EXTERNAL): + Renamed from TREE_INLINE, TREE_NONLOCAL, TREE_REGDECL, TREE_EXTERNAL. + All uses changed. + + * xm-hp320.h (USG): Define it. + + Sat Jul 11 21:43:56 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Bump meissner version number to 21. + + * mips.md (andsi3, iorsi3, xorsi3): Make predicates match the + actual machine, since combine can now recreate the bitfields, and + doesn't do multiple logical operations when setting more than one + bitfield in a word. + + * objc-actions.c (xmalloc, free): Don't provide extern decls for + these, since tree.h and rtl.h both now provide them. + + * cp-lex.c (real_yylex): Declare a variable i, since a for loop + uses it as an index. Remove an extra '(' from a build_int_2 call. + + Sat Jul 11 13:13:03 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * varasm.c: Get rid of default definitions of ASM_OUTPUT_CONSTRUCTOR + and ASM_OUTPUT_DESTRUCTOR. + + * c-aux-info (affix_data_type): Don't be fooled by names starting + with `const' or `volatile'. + + * c-typeck.c (digest_init): Deal with nested {...} for scalar. + + * loop.c, reload1.c: Include stdio.h before config.h. + + * toplev.c (rest_of_compilation): Save and restore DECL_ARGUMENTS. + + Fri Jul 10 22:42:34 1992 Paul Eggert (eggert@twinsun.com) + + * tree.c (build_real_from_int_cst): Truncate when folding to float. + (real_value_from_int_cst): Do not treat the topmost bit + of an unsigned long long value as a sign bit. + + * cse.c (simplify_binary_operation): Don't optimize 0.0/x to 0.0 + if IEEE floating point is used, because x might be negative or NaN. + + Fri Jul 10 15:37:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * genpeep.c (match_rtx): Handle `w' elts of rtx. + + * Makefile.in (INTERNAL_CFLAGS): Add -DIN_GCC. + + Fri Jul 10 18:56:22 1992 Eric Youngdale (youngdale@v6550d.nrl.navy.mil) + + * cccp.c (finclude): Clean error msf if file_size_and_mode fails. + + Fri Jul 10 13:44:46 1992 Howard Chu (hyc@hanauma.jpl.nasa.gov) + + * fx2800.h (LINK_LIBGCC_SPECIAL): Defined. + (DBX_OUTPUT_STANDARD_TYPES): Check that DECL_NAME(decl) exists + before trying to get its IDENTIFIER_POINTER. + + Thu Jul 9 20:56:01 1992 Per Bothner (bothner@rtl.cygnus.com) + + * dbxout.c (dbxout_type_methods): Fix minimal_debug so + that it skips a redundant class name prefix, as intended. + It now expects the length digits that precede the class name. + + Thu Jul 9 18:23:12 1992 Torbjorn Granlund (tege@wombat.gnu.ai.mit.edu) + + * Makefile.in, libgcc2.c, longlong.h: Rename udiv_using_sdiv to + udiv_w_sdiv. + + Thu Jul 9 18:10:40 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * tree.h (STRIP_TYPE_NOPS): New macro. + * c-decl.c (build_enumerator): Use STRIP_TYPE_NOPS. + * c-typeck.c (default_conversion): Use STRIP_TYPE_NOPS. + (build_binary_op, build_function_call): Likewise. + * c-common.c (check_case_value): Use STRIP_TYPE_NOPS. + + * mot3300.h (ASM_OUTPUT_CASE_END): New macro. + * m68k.c (switch_table_difference_label_flag): New variable. + + * i860.md (QI and HI bte/btne patterns): Deleted. + + Thu Jul 9 06:09:20 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * c-typeck.c (default_conversion): Don't use STRIP_NOPS. + + * print-rtl.c: Missing merge from 64-bit changes. + (print_rtx): Add new case 'w'. + + Wed Jul 8 14:35:39 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fixincludes, fixinc.svr4: Error if no argument. + + * tree.c (integer_zerop, integer_onep, integer_all_onesp): + (integer_pow2p, real_zerop, real_onep, real_twop): Use STRIP_NOPS. + * expr.c (do_store_flag): Likewise. + * varasm.c (output_constructor): Likewise. + * c-decl.c (finish_struct, build_enumerator): Likewise. + * c-typeck.c (default_conversion, build_binary_op): Likewise. + (build_function_call): Likewise. + + * integrate.c (integrate_decl_tree): Get rid of arg functionbody; + it was always 0. + + * mot3300.h: Fix typo. + + * final.c (leaf_renumber_regs_insn): Handle new 'w' format. + + Wed Jul 8 15:18:33 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * tree.h (DECL_ABSTRACT_ORIGIN, DECL_ABSTRACT): Definitions added. + (struct tree_decl): New fields `abstract_origin' & `abstract_flag'. + (struct tree_decl): Field `from_inline_flag' deleted. + (DECL_FROM_INLINE): Definition revised to check DECL_ABSTRACT_ORIGIN. + * integrate.c (copy_decl_list): New function added. + (save_for_inline_copying): Call `copy_decl_list' for formal parameters. + Set DECL_ABSTRACT_ORIGIN for fndecl to point to itself. + (copy_decl_tree): Use `copy_decl_list' rather than just `copy_list'. + (integrate_parm_decls, integrate_decl_tree): Set DECL_ABSTRACT_ORIGIN + to point to the progenitor. + * print-tree.c (print_node): Print the value of DECL_ABSTRACT_ORIGIN + rather than the value of DECL_FROM_INLINE. + + * dwarfout.c (output_inlined_enumeration_type_die): New function. + (output_inlined_structure_type_die, output_inlined_union_type_die): + New functions added. + (output_entry_point_die, output_formal_parameter_die, + output_global_subroutine_die, output_global_variable_die, + output_label_die, output_lexical_block_die, + output_inlined_subroutine_die, output_local_variable_die, + output_local_subroutine_die): + Fixed to handle inline abstract & concrete (i.e. inlined) instances. + (output_inlined_subroutine_die): Deleted. + (output_label_die): Don't permit the rtx associated with a named + user-declared label to be marked as INSN_DELETED_P. + (output_tagged_type_instantiation): New function added. + (output_decl): Call `output_tagged_type_instantiation'. + Don't generate a pubnames label for anything marked as DECL_ABSTRACT. + (output_die): Generate the proper kind fo DIE for each of the four + possible combination of {normal, inlined} {variable, parameter}. + (dwarfout_file_scope_decl): Don't generate pubnames entries if + strictly abstract. + + * dwarfout.c (ordering_attribute): Only def if USE_ORDERING_ATTRIBUTE + is defined. + (output_array_type_die): Only call ordering_attribute if it is defined. + (name_and_src_coords_attributes): Don't make it inline. + Do make it static linkage. + (const_value_attribute): Catch invalid kinds of rtx nodes + by aborting for the default case in switch. + + * dwarfout.c (output_ptr_to_mbr_type_die): Make it static linkage. + (output_formal_types): Make sure that `formal_type' is initialized. + (output_type): Add a default case for switch. + (output_decl): Don't suppress DIEs for the initial (artificial) + arguments for C++ static member functions. + + * dwarfout.c (ceiling, field_type, simple_type_align_in_bits, + simple_type_size_in_bits, field_byte_offset): New functions added. + (data_member_location_attribute): Use new routine `field_byte_offset' + to calculate the offset value for the AT_location attribute. + (byte_size_attribute): Use new routine `field_type' to get the + actual type for any FIELD_DECL. Also, use `simple_type_size_in_bits' + to avoid potential problems with ERROR_MARKs when computing the size + of a FIELD_DECL. + (bit_offset_attribute): Rewritten to use `field_byte_offset' when + determining the start of the "containing object". + + * integrate.c (expand_inline_function): Integrate parameters before + locals to get debugging information in the proper order. + (integrate_decl_tree): Don't do a redundant pushlevel/poplevel for + the outermost scope (i.e. when level==0)... just use the one created + by `expand_inline_function'. + + * calls.c (calls_alloca): For BLOCK, walk subblocks and vars by hand. + + Wed Jul 8 13:31:19 1992 Michael Meissner (meissner@osf.org) + + * cp-decl.c (print_binding_level): Fix typo, where 'lbl' was used + instead of 'lvl'. + + * objc-actions.c (build_shared_structure_initializer): Correct call + to build_int_2 which had only one argument, instead of two. + + Wed Jul 8 06:37:40 1992 Torbjorn Granlund (tege@sics.se) + + * gstdarg.h, gvarargs.h: Test `__hppa__' instead of `__hp9000s800__'. + + * romp.md (zero_extendhisi2): Remove unneeded constraint. + + * rs6000.md (zero_extendhisi2): Remove unneeded constraint. + (lu/stu): Use %0 instead of %1 in assembler insns. + (call_value): Add missing "=" in constraint. + + Wed Jul 8 06:30:20 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * rs6000.md (floatsidf): Correctly handle case when SImode operand + overlaps the first DFmode register. + + * fold-const.c (distribute_bit_expr, range_test, fold_truthop): + Use TRUTH_AND_EXPR instead of BIT_AND_EXPR so invert_truthvalue works. + + * c-decl.c (grokdeclarator): Strip all NOP_EXPRs from SIZE. + + * integrate.c: Do 64-bit changes (this file omitted the last time). + Replace use of NULL and 0 in functions args with NULL_RTX. + (copy_rtx_and_substitute, subst_constants): Handle "w" rtl + operand class. + + * rs6000.h (LINK_SPEC): Support -static. + + * tree.c (make_node, copy_node, make_tree_vec, tree_cons, build1): + Clear or copy tree nodes in a consistent manner, referencing + every byte of the node. + + * regclass.c: Initialize REG_CLASS_CONTENTS into an array of + ints, then copy into a HARD_REG_SET to avoid conditionalization + of REG_CLASS_CONTENTS on 64-bit machines. + + * c-common.c (check_case_value): Strip the NOP_EXPR added by + the grammar. + * stmt.c (pushcase, pushcase_range): Don't do it here. + + * c-lex.c (yylex): Ensure TOTAL_PARTS is wide enough to store a + constant as wide as we can store in an INTEGER_CST. + (LONG_LONG_TYPE_SIZE): Deleted; no longer needed. + + Tue Jul 7 15:50:38 1992 Chip Salzenberg (chip@tct.com) + + * x-i386sco (XCFLAGS): Omit flags specific to "rcc". + (CC, OLDCC): Put them here instead. + + Tue Jul 7 18:57:10 1992 Mike Stump (mrs@wombat.gnu.ai.mit.edu) + + The below entries should make DWARF debugging a little bit easier. + + * cp-decl.c (pushdecl): IDENTIFIER_GLOBAL_VALUE should not be _DECL + nodes but rather TYPE_DECLs. + + * cp-decl.c (pushtag): Mark binding layer markers as internal. + + * cp-class.c (finish_struct): Propagate internal mark on binding + layer markers. + + * cp-decl2.c (finish_file): Don't name things that should not be + named. + + * cp-method.c (decl_as_string): New back-end routine for + substitute_nice_name. + + * cp-decl2.c (substitute_nice_name): New function used to create + reasonable DECL_NAMEs from cyrptic ones. + + * cp-decl2.c (grokclassfn): Use substitute_nice_name. + + Tue Jul 7 14:04:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * expr.c (emit_move_insn): Don't try subwords for a single word. + + * gcc.c (find_a_file, putenv_from_prefix): + Handle value of 2 in require_machine_suffix. + (process_command): Supply 2 for standard_exec_prefix{,_1}. + + * gstdarg.h: Undefine _BSD_VA_LIST if we define va_list. + + * cccp.c (append_include_chain): Fix setting of first_bracket_include. + + * loop.c (init_loop): Use word_mode, not SImode. + + * x-dpx2: New file. + * x-dpx2200, x-dpx2300: Files deleted. + * configure (m68k-bull-sysv*): Fatal error unless --with-gas. + Always use x-dpx2. + + * libgcc2.c (XFtype): Turn off definition; not used. + (TFtype): Define only if needed. + + Tue Jul 7 11:57:44 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * tahoe.md (call_value): Add `=' to output operand constraint. + * arm.md (call_value): Likewise. + * gmicro.md (negsf2, negdf2, abssf2, absdf2): Likewise. + (peephole for moving returned value to fp reg): Likewise. + + * longlong.h (SI_TYPE_SIZE): Renamed from LONG_TYPE_SIZE. + + * longlong.h (machine independent code): #define udiv_qrnnd to call + __udiv_using_sdiv if we have sdiv_qrnnd but not udiv_qrnnd. + * libgcc2.c (__udiv_using_sdiv): New function. + * Makefile.in (LIB2FUNCS): Add __udiv_using_sdiv. + + Mon Jul 6 23:28:29 1992 Mike Stump (mrs@wombat.gnu.ai.mit.edu) + + * cp-dem.c, cp-lex.c, cp-method.c, cp-xref.c: Do not include + string.h or strings.h. + + Mon Jul 6 18:32:31 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * emit-rtl.c (operand_subword): Avoid conditionals in macro arg. + + * Changes to support execution on 64-bit machines. + * machmode.h (HOST_BITS_PER_WIDE_INT, HOST_WIDE_INT, HOST_PTR_PRINTF): + Provide default definitions. + (MAX_SHORT): New macro. + (GET_MODE_BITSIZE): Cast result and shift constant to HOST_WIDE_INT. + * rtl.h (union rtunion_def): Add field rtwint. + (XWINT): New accessor macro. + (INTVAL): Use XWINT, not XINT. + (exact_log2, floor_log2, plus_constant, plus_constant_for_output): + Now macros that cast arg to HOST_WIDE_INT. + (NULL, NULL_PTR): Provide default definitions. + (GEN_INT): New macro. + (get_integer_term): Now returns HOST_WIDE_INT. + * tree.h (NULL, NULL_PTR): Provide default definitions. + (INT_CST_LT, INT_CST_LT_UNSIGNED): Cast to HOST_WIDE_INT. + (struct tree_int_cst): Pieces of constant are HOST_WIDE_INT, not + long. + (exact_log2, floor_log2, build_int_2): Now macros, like rtl.h. + * real.h (REAL_VALUE_TYPE, union real_extract): Use HOST_WIDE_INT, + not long. + (CONST_DOUBLE_LOW, CONST_DOUBLE_HIGH): Use XWINT instead of XINT. + * rtl.def (CONST_INT): Operand type now "w". + (CONST_DOUBLE): Change operands from type "i" to "w". + * basic-block.h (REGSET_ELT_BITS): Always use HOST_BITS_PER_WIDE_INT. + (REGSET_ELT_TYPE): New macro; same as HOST_WIDE_INT. + * expr.h (ARGS_SIZE_RTX): Use NULL_RTX in expand_expr call. + (plus_constant): Remove duplicate declaration. + * hard-reg-set.h (HARD_REG_SET): Only scalar type we use + is HOST_WIDE_INT; array is array of HOST_WIDE_INT. + * loop.h (struct induction): Field CONST_ADJUST is now HOST_WIDE_INT. + (loop_n_iterations): Now unsigned HOST_WIDE_INT. + (loop_iterations): Returns HOST_WIDE_INT. + * c-parse.y, cexp.y, c-decl.c, c-lex.c, c-typeck.c, caller-save.c: + Change 0 or NULL when passed as a parameter that should be a pointer + to NULL_TREE, NULL_RTX, or NULL_PTR, as appropriate. + * calls.c, cccp.c, combine.c, cp-lex.c, cse.c, dbxout.c: Likewise. + * dwarfout.c, emit-rtl.c, explow.c, expmed.c, expr.c: Likewise. + * final.c, flow.c, fold-const.c, function.c, gcc.c: Likewise. + * genattrtab.c, genpeep.c, genrecog.c, global-alloc.c: Likewise. + * jump.c, local-alloc.c, optabs.c, recog.c, reg-stack.c: Likewise. + * regclass.c, reload.c, reload1.c, reorg.c, rtl.c: Likewise. + * rtlanal.c, sched.c, sdbout.c, stmt.c, stor-layout.c: Likewise. + * toplev.c, unroll.c, varasm.c, loop.c, xcoffout.c: Likewise. + * caller-save.c, combine.c, cp-class.c, cp-decl.c, cp-method.c: + Cast and declare objects used to refer to wide values as HOST_WIDE_INT. + Use HOST_BITS_PER_WIDE_INT instead of HOST_BITS_PER_INT. + * cp-pt.c, cp-type2.c, cp-typeck.c, cse.c, dbxout.c: Likewise. + * dwarfout.c, emit-rtl.c, explow.c, expmed.c, expr.c: Likewise. + * final.c, fold-const.c, genattrtab.c, recog.c, reg-stack.c: Likewise. + * regclass.c, reload.c, sched.c, stmt.c, stor-layout.c: Likewise. + * loop.c, toplev.c, unroll.c, varasm.c: Likewise. + * caller-save.c, combine.c, flow.c, global-alloc.c, reorg.c, sched.c: + When refering to regsets, use type REGSET_ELT_TYPE. + * calls.c, combine.c, emit-rtl.c, explow.c, expmed.c, expr.c, final.c: + Use GEN_INT macro when making CONST_INTs. + * function.c, jump.c, loop.c, optabs.c, recog.c, reload1.c: Likewise. + * unroll.c: Likewise. + * cp-decl.c, cp-ptree.c, print-tree.c: Use HOST_PTR_PRINTF when + printing pointer values. + * cccp.c, cexp.y, gcc.c (NULL, NULL_PTR): Provide default definition. + * c-common.c (NULL): Remove definition from here. + * c-decl.c (NULL): Likewise. + (finish_struct): Ensure high-order part of width is zero. + * cp-decl.c (finish_enum): Likewise. + * c-lex.c (yylex): Call build_int_2 in more portable way. + (yyprint): Print constant different ways, depending on host parameters. + * final.c (output_asm_insn, output_addr_cont): Likewise. + * genattrtab.c (write_test_expr): Likewise. + * print-tree.c (print_node_brief, print_node): Likewise. + * cp-decl.c (xref_tag): Remove explicit reference to modes. + * cp-method.c (build_overload_value): Likewise. + * cp-lex.c (real_yylex): Make accumulating bits for constant + more portable. + * cse.c (uid_cuid): Now pointer to int instead of to short. + (exp_equiv_p): Change ifs on GET_RTX_FORMAT to a switch. + Add format code of "w". + * emit-rtl.c (gen_rtx): Add format code of "w". + * jump.c (rtx_renumbered_equal_p, rtx_equal_for_thread_p): Likewise. + * loop.c (rtx_equal_for_loop_p): Likewise. + * reload.c (operands_match_p): Likewise. + * rtl.c (copy_rtx, copy_most_rtx): Likewise. + * rtlanal.c (rtx_equal_p): Likewise. + * sched.c (rtx_equal_for_memref_p): Likewise. + * explow.c (plus_constant_wide): Formerly plus_constant; argument + is HOST_WIDE_INT. + (plus_constant_for_output_wide): Similarly. + * fold-const.c: Use MAX_SHORTS for dimension of array of shorts. + * genattrtab.c (NULL_ATTR): New macro. + (attr_rtx): Use XWINT, not XINT, for CONST_INT. + Add case "w". + (check_attr_test, write_test_expr, main): Use XWINT, not XINT, + for CONST_INT. + * genemit.c (gen_exp): Use "NULL_RTX" instead of "0" when + emitting null. + Use GEN_INT and proper width when emitting a CONST_INT. + Abort if trying to write a CONST_DOUBLE. + * genrecog.c (struct decision): Add new fields TEST_ELT_ZERO_WIDE + and ELT_ZERO_WIDE. + (add_to_sequence, not_both_true, merge_trees, write_tree_1): + Use new fields. + * global-alloc.c (INT_BITS, INT_TYPE): Use HOST_WIDE_INT for type + of conflict matrix. + * loop. (loop_n_iterations): Now HOST_WIDE_INT. + * recog.c: Remove redundant declarations of plus_constant_for_output + and copy_rtx. + * rtl.c: Declare atol if needed. + (rtx_format): Add code for "w". + (read_rtx): Read code "w" field with atol if required. + (init_rtl): Fields of CONST_DOUBLE are now type "w". + * rtlanal.c (get_integer_term): Returns HOST_WIDE_INT. + * cccp.c, toplev.c: Error function args are HOST_WIDE_INT (kludge). + * toplev.c (exact_log2_wide): Renamed from exact_log2 and now has + arg of type HOST_WIDE_INT. + (floor_log2_wide): Similarly. + * tree.c (permalloc): Type of SIZE arg is int, not long. + (build_int_2_wide): Renamed from build_int_2 and has args of + type HOST_WIDE_INT. + * unroll.c (loop_iterations): Now returns HOST_WIDE_INT. + * varasm.c (immed_double_const): Arguments are now HOST_WIDE_INT. + + Mon Jul 6 14:56:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-common.c (decl_attributes): Don't set DECL_PACKED on VAR_DECL. + + * Makefile.in (GCC_CFLAGS): + Use CROSS_GCC_CFLAGS instead of -B for tooldir. + * cross-make (CROSS_GCC_CFLAGS): Define as -B for tooldir. + + * c-decl.c (finish_function): If return type of `main' is not `int', + warn instead of doing DEFAULT_MAIN_RETURN. + + * collect2.c, dwarfout.c, halfpic.c: Don't incude string.h. + + * c-decl.c (duplicate_decls): Let char *foo () match void *foo () + only if one of them came from a system header file. + + * stmt.c (pushcase): Fix typo. + + * Makefile.in (ALLOCA_FINISH): Make default `true'. + + * cccp.c (main): Clear first_bracket_include for -I-. + Set first_system_include for first system header directory. + (is_system_include): Start search at first_system_include. + + Mon Jul 6 12:58:27 1992 Chip Salzenberg (chip@tct.com) + + * cccp.c (INCLUDE_LEN_FUDGE): Defined. + (append_include_chain): New function. Adds directory(ies) + to include chain and updates value of max_include_len. + (main, path_include): Use append_include_chain. + (do_include): Use INCLUDE_LEN_FUDGE. + + * tree.h (DECL_IN_SYSTEM_HEADER): Defined. + (struct tree_decl): Add in_system_header_flag. + * c-common.c (declare_function_name): For __FUNCTION__ + and __PRETTY_FUNCTION__, set DECL_IN_SYSTEM_HEADER instead + of TREE_USED to supress `unused' warnings. + * c-decl.c (duplicate_decls): Merge DECL_IN_SYSTEM_HEADER flag. + * print-tree.c (print_node): Display TREE_RAISES and + DECL_IN_SYSTEM_HEADER flags. + * toplev.c (compile_file): Do not warn if an unused DECL + has DECL_IN_SYSTEM_HEADER set. + (rest_of_compilation): Do not set TREE_USED on static + functions defined in system headers; this will be taken + care of with DECL_IN_SYSTEM_HEADER. + * tree.c (make_node): Set DECL_IN_SYSTEM_HEADER on permanent + decls defined in system headers. + * objc-actions.c (build_module_descriptor,add_objc_decls): + Set DECL_IN_SYSTEM_HEADER instead of TREE_USED on compiler- + created decls. + + Mon Jul 6 10:17:30 1992 Michael Collison (collison at osf.org) + + * i386.h (SUBTARGET_SWITCHES): + Incoporate SUBTARGET_SWITCHES into TARGET_SWITCHES. + (HALF_PIC_P, HALF_PIC_NUMBER_PTRS, HALF_PIC_NUMBER_REFS, + HALF_PIC_ENCODE, HALF_PIC_DECLARE, HALF_PIC_INIT, + HALF_PIC_ADDRESS_P, HALF_PIC_PTR, HALF_PIC_FINISH): + Define these as stubs if not OSF/1 platform. + * i386.md (movsi): Recognize half-pic moves. + + Mon Jul 6 11:16:47 1992 Tim Moore (moore@defmacro.cs.utah.edu) + + * pa.h (ASM_DECLARE_FUNCTION_NAME): Fix typo + + Mon Jul 6 08:48:51 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * m68k.md (swapsi): Add `+' operand constraints. + (insert to memory recognizer): Add `+'. + (peephole for moving returned value to fp reg): Add `='. + + Sun Jul 5 16:34:24 1992 John F Carr (jfc at Achates.mit.edu) + + * vax.md (addsi3): Code generation improvements (whether to use movab). + + * vax.md (andsi3, andhi3, andqi3): If one of the source operands + is a constant, complement that operand instead of a register or + memory operand. + + Sun Jul 5 13:16:15 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (try_combine): When splitting using a DEFINE_SPLIT, + update the number of sets of the destination if it is being set + twice. Also update reg_significant. + + Sun Jul 5 13:14:50 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c++: Fix typo testing $quote for nullness. + + * cse.c (simplify_binary_operation): Don't put sum of two symbolic + addresses into a CONST. + + * m68kv4.h (ASM_OUTPUT_ALIGNED_COMMON): #undef this. + (ASM_OUTPUT_ALIGNED_LOCAL): #undef this. + (ASM_OUTPUT_ASCII): New overriding definition. + (ASM_OUTPUT_CASE_END): New overriding definition. + + * c-typeck.c (convert_arguments): No -Wconversion warning + if the function wants an enumeral type. + + * tek6000.h, tek6100.h, tek6200.h: New files. + * configure (ns32k-tek6100-bsd, ns32k-tek6200-bsd): New alternatives. + * config.sub: utek is synonym for bsd. + + * Makefile.in (alloca.o): Add -c. + + * Makefile.in (start.encap): Use LIBGCC1, not LIBGCC1_TARGET. + (GCC_CFLAGS): Find executables in $(tooldir)/bin, not $(tooldir). + (libgcc1.cross): New target. + (all.cross, cross-test): Depend on libgcc.a. + * cross-make (LIBGCC1): Use libgcc1.cross. + + * Makefile.in (USER_H): va-hp800.h changed to va-pa.h. + (install-common): Fix typo. + + * stmt.c (pushcase, pushcase_range): Use STRIP_NOPS on the values. + + * x-amix, x-i860v4, x-ncr3000, x-sparcv4: Undo last change. + * x-i386v4, x-m68kv4: Files deleted. + * configure (i386-*-sysv4, i486-*-sysv4, m68k-*-sysv4): + Corresponding changes. + + * c-decl.c (duplicate_decls): Don't warn about disagreement in `inline' + except when non-inline fn is made inline after a call or definition. + + Sun Jul 5 10:25:22 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * c-decl.c (grokdeclarator): Make `long long long' an error, not a + warning. Make duplicate qualifiers do pedwarn, not warning. + + * c-decl.c (pushdecl): Always create a new (variant) ..._TYPE node + for each new TYPE_DECL node created. + + * libgcc2.c (UQItype, SItype, USItype, DItype, UDItype, SFtype, DFtype, + XFtype, TFtype): Typedefs added. + (SI_TYPE_SIZE): Renamed globally from LONG_TYPE_SIZE. + Define names for ANSI C types to `bogus_type' over the range of lines + where we must always use the new mode-related types. Undef them again + at the end of that range (so we can used the ANSI types again), and + then define the mode-related type names to `bogus_type' to insure + those are not used from then on. + + * libgcc2.c, longlong.h (DIstruct): Renamed globally from `longlong'. + (DIunion): Renamed globally from `long_long'. + Universally use the new mode-related type names for all functions + and macros which expect, yield, or otherwise rely on operands to be + of certain GCC-defined machine modes. + + Sun Jul 5 11:11:00 1992 Torbjorn Granlund (tege@wombat.gnu.ai.mit.edu) + + * pa.h: (TARGET_VERSION): Print " (hppa)". + * pa.md (zdepi recognizer): Add attribute. + (recognizers for SImode load and store with fpregs): Add `=' to + operand 0. + + Sat Jul 4 15:02:19 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure (mips-*-sysv4): Don't set use_collect2. + + * c-parse.y (primary): Wrap a NOP_EXPR around an enum value. + + * libgcc2.c (__builtin_saveregs for i860): Test __svr4__, not SVR4. + * va-i860.h: Test __svr4__. + + * c-decl.c (finish_function): Set BLOCK_SUPERCONTEXT of outer block. + + * x-m88kv3: File deleted. + + * x-sparcv4 (X_CFLAGS): Add -dn. + + * reorg.c: Move the #ifdef DELAY_SLOTS after the #includes. + + Sat Jul 4 14:16:33 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (SUBST): Ensure we don't call something that can make + a new undo entry in the middle of our making one. + + Sat Jul 4 12:17:55 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (cp-parse.c): Append YYEMPTY to cp-parse.h, not ...y. + + * cse.c (simplify_unary_operation): Add aborts in zero_extend + and sign_extend cases, explaining how they might need to be changed. + + * i960.h (WORD_SWITCH_TAKES_ARG): Fix typo. + + * x-amix, x-sparcv4, x-i860v4, x-i386v4, x-ncr3000: + Add -static to X_CFLAGS. + * x-m68kv4: New file. + * isc.h (HANDLE_SYSV_PRAGMA): Defined. + + Sat Jul 4 15:18:33 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * xm-spc-sol2.h: New file. + + * tree.h (DECL_UID): Definition added. + (struct tree_decl): `uid' field added. + * tree.c (DECL_UID): Initialize this uniquely for each new ..._DECL. + + * rtl.h (NOTE_INSN_DELETED_LABEL): Definition added. + * rtl.c (note_insn_name): Add entry for NOTE_INSN_DELETED_LABEL. + * final.c (final_scan_insn): Call `dwarfout_label' for each + `NOTE_INSN_DELETED_LABEL'. + * jump.c (delete_insn): Don't really delete CODE_LABELs corresponding + to user-declared lables... Turn them into NOTE_INSN_DELETED_LABELs + instead. + + * dwarf.h (AT_abstract_origin): Renamed from AT_specification. + * dwarfout.c (dwarf_attr_name): Likewise. + (dwarf_tag_name, dwarf_attr_name, dwarf_stack_op_name, + dwarf_typemod_name, dwarf_fmt_byte_name): Use normal DWARF prefixes + for string names of unrecognized values. + (is_block_body): New function added. + (DECL_NAME_FMT): Definition added. + (equate_decl_number_to_die_number, abstract_origin_attribute, + pure_or_virtual_attribute): New functions added. + (src_coords_attribute): Only define this is DWARF_DECL_COORDINATES + is defined. + + * populate: New file. + + * function.c (instantiate_decls): Delete #if 1. + + * flags.h, toplev.c, dbxout.c (use_gnu_debug_info_extensions): + Renamed from `use_gdb_dbx_extensions'. + + * toplev.c (main): Added support for -gdwarf+ and for -gxcoff+. + + Sat Jul 4 08:39:47 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.c (m88k_end_prologue): Reset frame_laid_out here. + (m88k_expand_prologue): Not here. + + * m88k.h (IDENT_ASM_OPT, ALIGN_ASM_OPT, ASM_OUTPUT_CASE_LABEL): + Override svr4.h. + + Fri Jul 3 12:40:27 1992 Paul Eggert (eggert@twinsun.com) + + * fold-const.c (fold_convert): When converting a floating point + constant to integer, warn about out-of-range values after truncating + to integer, not before. + + Fri Jul 3 19:34:07 1992 Mike Stump (mrs@hal) + + * Makefile.in ($(srcdir)/cp-parse.c): extract YYEMPTY out of the + parser generated .c file and put in the parser .h so that cp-lex.c + does not have to define it. + + * cp-tree.c (__eprintf): Third argument line is now unsigned, + completes Ron's Jul 2 change. + + Fri Jul 3 15:03:30 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * configure: Set FIXINCLUDES in Makefile based on sysv4 or not. + * x-amix (ENQUIRE_CFLAGS, FIXINCLUDES): Deleted. + + * config.sub: Recognize i486 like i386. + + * defaults.h (ASM_FORMAT_PRIVATE_NAME, ASM_OUTPUT_ADDR_VEC_ELT): + (ASM_OUTPUT_ADDR_DIFF_ELT, ASM_STABD_OP): New default definitions. + * final.c: Include defaults.h. + (ASM_STABD_OP): Deleted. + * Makefile.in (final.o) Depend on defaults.h. + + * Makefile.in (toplev.o): Use MAYBE_TARGET_DEFAULT. + * configure: Set MAYBE_TARGET_DEFAULT for some targets. + Use 3, if target is i486... + Recognize i486 as well as i386 for most targets. + + * x-hp320g (LIBGCC1, AR, RANLIB, RANLIB_TEST, LIBCONVERT): Deleted. + * t-hp320g (LIBGCC1, AR, RANLIB, RANLIB_TEST, LIBCONVERT): Defined. + * t-svr4 (FIXINCLUDES): Deleted. + + * Makefile.in (ENQUIRE_CFLAGS): Add -DNO_LONG_DOUBLE_IO. + + * fold-const.c (BRANCH_COST): Add default definition. + + * cp-tree.h: Declare intQI_type_node, etc. + * cp-decl.c: Declare intQI_type_node, etc. + (init_decl_processing): Initialize those nodes. + + Thu Jul 2 15:18:33 PDT 1992 Ron Guilmette (rfg at ncd.com) + + * amix.h (ASM_OUTPUT_CASE_END, ASM_OUTPUT_ALIGNED_LOCAL): Output + tabs before SET_ASM_OP. + + * Makefile.in (dwarfout.o): Dependency on defaults.h added. + + * sparcv4.h: Include real.h. + (SET_ASM_OP): Undef it. + + * svr4.h (IDENT_ASM_OP): Added generic svr4 definition. + (ASM_FILE_END, ASM_OUTPUT_IDENT): Use IDENT_ASM_OP. + (ALIGN_ASM_OP): Added generic svr4 definition. + (ASM_OUTPUT_CASE_LABEL): Added generic svr4 definition. + + * i860.c (strict_single_insn_op_p, relop): Deleted. + * i860.h (ASM_OUTPUT_CASE_LABEL): Fixed definition to use + ASM_OUTPUT_ALIGN and ASM_OUTPUT_INTERNAL_LABEL. + * i860b.h, i860v3.h (TARGET_VERSION): Definitions added. + * i860v3.h (CPP_PREDEFINES): Predefine __svr3__ rather than SVR3. + + * c-decl.c (named_labels): Change linkage to static. + + * assert.h (__eprintf): Declare 3rd arg as unsigned. + + * cccp.c (do_include): Don't do fprintf's if inhibit_warnings. + Renamed system_header_p to angle_brackets. Use is_system_include. + (is_system_include): New function. + (redundant_include_p) : Renamed from lookup_include. + + * c-common.c (type_for_size): If no ANSI type matches, check for + matches with built-in mode-releated types. + (type_for_mode): Likewise. + * c-decl.c: Added declarations for mode-related internal type nodes. + (init_decl_processing): Initialize the new type nodes. + * c-tree.h: Added declarations for mode-related internal type nodes. + intQI_type_node, etc. + + * c-lex.c (yylex): For integers, rename shorts to parts. + Let the number of them be variable. Simplify overflow testing. + Don't use long long types unless ll was specified. + Don't warn twice. + + Thu Jul 2 20:30:20 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) + + * gstdarg.h: #ifdef _STDARG_H, not __STDARG_H. + + Thu Jul 2 18:18:07 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * global.c: Renamed from global-alloc.c. + + Thu Jul 2 15:36:25 1992 Torbjorn Granlund (tege@wombat.gnu.ai.mit.edu) + + * pa.c (zdepi_operand): New function. + (emit_move_sequence): Use it. + * pa.md: New pattern to recognize cases where zdepi can be used to + load immediate constant. + (insv): Allow obvious immediate values. + (insv + 1): New recognizer for non-obvious immediate values. + + Thu Jul 2 15:13:15 1992 Michael Meissner (meissner@osf.org) + + * halfpic.c (half_pic_encode): Consider variables which are 'common' + variables to need pic fixup. Move the debug code, so that it prints + for all calls, and calls debug_tree also. + (half_pic_address): When doing eliminate_constant_term on a CONST, + do a XEXP (addr, 0) to get to the real address. + + * decrose.h (CPP_SPEC, CC1_SPEC): If neither -fbuiltin nor + -fno-builtin are passed, pass -fno-builtin, and renable the string + and memory builtins via macros. This is to support compiling the + OSF/1 kernel which has a prototyped exit function which takes three + arguments. With no -pic switches, default to using shared libs. + + * i386rose.h (CPP_SPEC, CC1_SPEC): If neither -fbuiltin nor + -fno-builtin are passed, pass -fno-builtin, and renable the string + and memory builtins via macros. This is to support compiling the + OSF/1 kernel which has a prototyped exit function which takes three + arguments. Turn off pic support until the 386 backend supports it. + + * x-i386rose (SHLIB): Use -pic-none instead of -L${BUILD}/usr/ccs/lib. + + * x-decrose (SHLIB): Use -pic-none instead of -L${BUILD}/usr/ccs/lib. + + * mips.md (movsi): Rewrite handling of half-pic code so that load + address of symbol + value is handled. + (branch_zero): Don't allow branch comparing constant to 0. + + Thu Jul 2 06:26:38 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.md (blockage insn): Renamed from profiler. + (epilogue insn): Don't provide this if a return insn will suffice. + (m88k_end_epilogue): If the last insn isn't a barrier, print a return. + * m88k.c (null_prologue): Renamed from null_epilogue. + + * m88k.c (condition_value): New function. + * m88k.md (compare word insns): New insns and define_split + patterns to take advantage of recent fold_truthop change. + + * m88k.h (ADDITIONAL_REGISTER_NAMES): Represent the condition code + register as (reg:CC 0). Give it the names "cc" and "psr". + * m88k.md (superoptimizer sequences): New define_split patterns. + (add/sub with carry): New insns. + (add/sub DImode, ffssi2): Clobber the condition code register. + + Wed Jul 1 13:37:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gstddef.h Don't define macros associated with size_t unless we + actually want to declare size_t. Likewise for ptrdiff_t and wchar_t. + + * Makefile.in (install-common): Depend on xgcc, g++, c++, EXTRA_PARTS. + Don't delete specs from libsubdir unless it exists in build dir. + + * va-pa.h: Renamed from va-hp800.h. + * gstdarg.h, gvarargs.h: Use new name. + + * news3.h, news3gas.h: New files. + * configure (m68k-sony-newsos3*): New alternative. + + * romp.h (SIZE_TYPE): Defined. + + * configure: Support --exec-prefix. Simplify handling + detached arguments of options. + + * isc.h, and other related files: + waiting for entries from karl@cs.umb.edu. + + Wed Jul 1 12:04:53 1992 Ron Guilmette (rfg at ncd.com) + + * c-decl.c (grokdeclarator): Don't mark file-scope register variables + as TREE_PUBLIC. + + Wed Jul 1 12:04:53 1992 Karl Berry (karl@cs.umb.edu) + + * i386iscgas.h (SIZE_TYPE, PTRDIFF_TYPE): Define these, since we + need to override GCC's defaults. + + * configure (i386-*-isc): Use different files if we have gas. + * t-i386iscgas, i386iscgas.h, isc.h: New files + * i386isc.h: Include isc.h. Most of contents moved to isc.h. + * bsd386.h (ASM_OUTPUT_LABELREF) [NO_UNDERSCORES]: do not prepend an + underscore in this case. + * i386gas.h (CPP_SPEC): if -posix, do -D_POSIX_SOURCE. + + Wed Jul 1 09:13:44 1992 Tom Wood (wood@dg-rtp.dg.com) + + * fold-const.c (fold_truthop): Renamed from merge_component_references. + (simple_operand_p): New function. + (range_test): Change JCODE parameter to the unconditional operation. + (fold_truthop): When branches are expensive, try to evaluate the + RHS unconditionally. Compute local variables as late as possible. + + * m88k.h (HANDLE_SYSV_PRAGMA): Replaces HANDLE_PRAGMA. + * m88k.c (m88k_handle_pragma_token): Deleted. + + Tue Jun 30 15:32:51 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (duplicate_decls): If newdecl for builtin function + has same return mode as the builtin, keep the builtin + but use newdecl's return type. + + * i386.md (lshrdi3_const_int): Fix typo in shr insn. + + * Makefile.in (GCC_CFLAGS): Add `-B$(tooldir)/'. + + * i386sun.h, rs6000-mach.h, sparc.h, sun2o4.h, sun3.h (LINK_SPEC): + Inhibit the default -e if -r or -nostdlib. + + * c-decl.c (lookup_label): Call label_rtx. + + * c-parse.y (primary): Rearrange and clean up. In C_DECL_ANTICIPATED + case, always call assemble_external and set TREE_USED. + + Mon Jun 29 22:27:49 1992 Mike Stump (mrs@wombat.gnu.ai.mit.edu) + + * cccp.c, cp-dem.c, dbxout.c, cp-lex.c, cp-xref.c, cp-method.c, + dwarfout.c, c-typeck.c, mips-tfile.c, protoize.c, collect2.c: Make + the compiler more consistent by using index and rindex everywhere + instead of sometimes using strchr and strrchr. + + Mon Jun 29 22:20:13 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * regclass.c (regclass): Restore some accidentally-deleted code. + + Mon Jun 29 12:48:05 1992 Nobuyuki Hikichi (hikichi@sra.co.jp) + + * collect2.c (MY_ISCOFF): New macro. + (scan_prog_file): Use that instead of ISCOFF. + + * mips.c (override_options) [MIPS_NEWS]: Call setlinebuf. + + Mon Jun 29 12:48:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gcc.c (do_spec_1): For %I, pass -iprefix, not -imacros. + + * c-common.c (decl_attributes): For `packed' on VAR_DECL, + set DECL_PACKED and DECL_ALIGN. + + * configure: Update usage message. + (m68k-sony-newsos*, mips-sony-newsos*): New synonyms. + + * fold-const.c (merge_component_references): + Make sure the four fields correspond in the proper order. + + * c-lex.c (check_newline): Support HANDLE_SYSV_PRAGMA. + (handle_sysv_pragma): New function. + * c-pragma.c: New file. + * stor-layout.c (maximum_field_alignment): New variable. + (layout_decl): Use it. + * Makefile.in (C_OBJS, OBJC_OBJS): Add c-pragma.o + (c-pragma.o): New rule. + + * i386.c (handle_pragma_token): Function deleted. + * i386v4.h (HANDLE_PRAGMA): Deleted. + + * g++: Reestablish symlink to c++. + Delete the testing of $TRACE--this could confuse people. + Delete spurious assignment of $version. + + * tree.h (DECL_PACKED): Store this in regdecl_flag. + + * Makefile.in (LIB2FUNCS): Change _builtin_New to _caps_New. + * libgcc2.c: Change L_builtin_New to L_caps_New. + + * dbxout.c (dbxout_symbol): Pass 3 args to eliminate_regs. + Call alter_subreg for subregs. Delete subreg case later on. + Don't bother with reg_renumber--any pseudo reg is clearly + a variable that was not allocated. + * sdbout.c (sdbout_symbol): Call alter_subreg for subregs. + Don't bother with reg_renumber--any pseudo reg is clearly + a variable that was not allocated. + + * sequent.h (SIZE_TYPE): Defined. + (LINK_LIBGCC_SPECIAL): Fix typo. + + Mon Jun 29 12:04:57 1992 Tom Wood (wood@dg-rtp.dg.com) + + * toplev.c (rest_of_compilation): Thread the prologue and epilogue + code immediately after reloading is done. + * sched.c (schedule_insns): Reposition the prologue and epilogue + notes as needed. + * reorg.c (dbr_schedule): Ditto. + * rtl.h (NOTE_INSN_PROLOGUE_END, NOTE_INSN_EPILOGE_BEGIN): New notes. + * rtl.c (note_insn_name): Record them. + * function.c (record_insns, contains, thead_prologue_and_epilogue_insns, + reposition_prologue_and_epilogue_notes): New functions. + * final.c: Include insn-flags.h. + (profile_after_prologue): New function. + (final_start_function): Use profile_after_prologue here when we + don't HAVE_prologue. + (final_scan_insn): Use profile_after_prologue when we scan + NOTE_INSN_PROLOGUE_END. (This happens when we do HAVE_prologue.) + Perform machine specific actions when the prologue-end and + epilogue-begin notes are scanned. + (final_scan_insn, BARRIER): Align only when something follows. + * Makefile.in (final.o): Depends on insn-flags.h. + + * m88k.h (FUNCTION_END_PROLOGUE, FUNCTION_BEGIN_EPILOGUE): Define. + (DELAY_SLOTS_FOR_EPILOGUE, ELIGIBLE_FOR_EPILOGUE_DELAY): Delete. + * m88k.md (prologue, epilogue, profiler, locate1, locate2): New + patterns for representing prologues and epilogues. + * m88k.c (delay_slots_for_epilogue, eligible_for_epilogue_delay, + ok_for_epilogue_p): Delete epilogue delay slot functions. + (m88k_begin_prologue m88k_end_prologue m88k_expand_prologue): New + functions replacing m88k_output_prologue. + (m88k_begin_epilogue m88k_end_epilogue m88k_expand_epilogue): Ditto. + (preserve_registers): Delete epilogue delay slot mechanism and + change to output insns. + (emit_add, emit_ldst): New functions. + + Sun Jun 28 23:06:04 1992 Brendan Kehoe (brendan@cs.widener.edu) + + * Makefile.in (bootstrap, bootstrap2, bootstrap3): In each + passage of CC, use xgcc, not gcc. + * dostage2, dostage3: Likewise. + + Sun Jun 28 09:48:18 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-decl.c (duplicate_decls): If have char *foo () and + void *foo (...), make just a pedwarn. Add locals oldtype, newtype. + * c-typeck.c (self_promoting_args_p): No longer static. + + * flow.c (regno_uninitialized): Return 0 for global reg var. + + * c-typeck.c (initializer_constant_valid_p): + Allow CONVERT_EXPR if its operand is allowable. + (build_c_cast): For cast to union, make a CONSTRUCTOR. + + * sparc.c (SPARC_STACK_ALIGN): Add default definition. + + * c++: Use `set "$@"' to modify arguments. + Use a case to decide how to set $gcc. + $quote is now empty for false and the option name for true. + Error at end if $quote is nonempty. + $speclang is now the -x option itself. + Move the -v case above the -* case. + + * limitx.h: Add #ifndef. + * limity.h: New file. + * Makefile.in (install-limits-h): Append limity.h to the end. + + * c-typeck.c (digest_init): Don't push spellings here (for union case). + (process_init_constructor): Fix errors for field not found. + (build_c_cast): Fold casts to union type. + + * xm-vms.h (XREF_FILE_NAME): Fix typo. + + * i386sun.h (SIZE_TYPE): Defined. + + * Makefile.in (alloca.o): Delete the rm command. + Use -Demacs explicitly in compilation command. + (ALLOCA_FLAGS, ALLOCA_FINISH): Empty by default. + * x-pa-hpux, x-rs6000, x-rs6k-mach, x-dpx2200, x-dpx2300: + (ALLOCA_FLAGS, ALLOCA_FINISH): Deleted. + * x-dpx2200, x-dpx2300 (AS): Deleted. + + * configure: Set broken_install for V.4. + (i386-*-aix, ns32k-*-genix, i386-*-isc, i386-*-sco): + (i386-*-sco3.2v4, m88k-dg-dgux): Set broken_install. + (m88k-*-sysv): Don't use x-m88kv3. + * x-m88kv3: File deleted. + * x-aix386, x-dpx2200, x-dpx2300, x-genix, x-i386isc, x-i386sco: + * x-i386v, x-i386v4, x-i860v3, x-i860v4, x-m88kdgux, x-m88kdolph: + * x-m88kv4, x-ncr3000, x-sparcv4, x-xenix (INSTALL): Deleted. + + Sun Jun 28 08:44:32 1992 Michael Meissner (meissner@osf.org) + + * regclass.c (record_address_regs): Make the function static to + agree with the forward declaration. + + * mips.h (LINK_LIBGCC_SPECIAL): Define. + + Sun Jun 28 06:14:56 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * expr.c (direct_load, direct_store): New variables. + (init_expr_once): New function. + (convert_move, convert_to_mode): Don't let gen_lowpart make a MEM in + a mode that can't be directly copied to or from memory. + (store_field): Don't directly store into memory in a mode that + can't be used in a single insn. + (expand_expr, case COMPONENT_REF): Likewise, for load. + * toplev.c (compile_file): Call init_expr_once. + + * cse.c (fold_rtx, case SUBREG): If we can find nested SUBREGs + with an inner register in the mode we want, get rid of all the + SUBREGs provided they are all within a word. + + * cp-call.c, cp-class.c, cp-decl.c, cp-edsel.c, cp-lex.c: Don't + declare xmalloc and free here. + * cp-methods.c, cp-pt.c, cp-search.c, flow.c, integrate.c: Likewise. + * loop.c, opjc-actions.c, reload1.c, reorg.c, rtl.c: Likewise. + * stmt.c, tree.c, varasm.c: Likewise. + * toplev.c (xmalloc, xrealloc): Declare return types correctly. + * rtl.h, tree.h: Declare xmalloc and free here. + + * expmed.c (emit_store_flag): Keep the last target around if we + should preserve subexpressions. + + Sat Jun 27 07:11:28 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * cse.c (cse_insn): See if we have a CONST_INT that is already in + a register in a wider mode. + + * regclass.c: Major rework of regclass pass to do a better job of + setting up register preferences and replace the "preferred or + nothing" method with a class that should be used if the preferred + class cannot be allocated. + (MEMORY_MOVE_COST): Default value is 4, not 2. + (move_cost, may_move_cost): New arrays. + (init_reg_sets): Initialize them. + (struct costs): Replaces struct savings. + (costs): Replaces savings. + (op_costs): New array. + (altclass): Replaces preferred_or_nothing. + (reg_alternate_class): New function; replaced reg_preferred_or_nothing. + (regclass): Major rework. Use new recording methods; make two + passes if -fexpensive-optimizations; and refine REGNO_POINTER_FLAG + and loop_depth setting. + (record_reg_class): New function; replaces reg_class_record. + (copy_cost): New function. + (record_address_regs): Major changes. New parameters and simplified + and more efficient algorithm for chosing base vs. index regs. + * rtl.h (reg_alternate_class): Declare it. + * Makefile.in (regclass.o): Now includes reload.h and real.h. + * flow.c (dump_flow_info): Call reg_alternate_class instead of + reg_preferred_or_nothing. + * reload.c (find_reloads): Likewise. + (n_occurrences): No longer static. + * local-alloc.c: Use register alternate class instead of + preferred_or_nothing uniformly; change qty_preferred_or_nothing + to qty_alternate_class. + * global-alloc.c (global_alloc, retry_global_alloc): Call + reg_alternate_class instead of reg_preferred_or_nothing. + (find_reg): Change ALL_REGS_P argument to ALT_REGS_P. + Use alternate register class instead of ALL_REGS if can't allocate + in preferred class. + + * cccp.c (install): Accept separate arguments for integer and + pointer hash values; don't assume the sizes are the same. + All callers changed. + + * rtl.c (copy_rtx, copy_most_rtx): Add new case for 'u'. + + * tree.c (make_node): Clear all of common area, in particular, flags. + + * c-tree.h, cp-tree.h: Add declaration of truthvalue_conversion. + + Sat Jun 27 06:21:18 1992 Tom Wood (wood@dg-rtp.dg.com) + + * m88k.md (type attributes): Delete unused mbit and mfp types. + (ffsi2 insn): Define. + (negdf2 and absdf2 insns): Improve. + + * fold-const.c (range_test): Fix the misordered test. Fail if VAR + isn't an integer. + + Sat Jun 27 00:54:44 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * gcc.c (link_command_spec): No %D if LINK_LIBGCC_SPECIAL. + * sequent.h (LINK_LIBGCC_SPECIAL): Defined. + + * vax.h (PRINT_OPERAND): For SFmode, use 0f, not 0d or 0g. + + * ns32k.h (NS32K_DISPLACEMENT_P): Correct the range limits. + * ns32k.c (print_operand_address): REG_OK_FOR_INDEX_P wants an rtx. + + Fri Jun 26 08:55:03 1992 Tom Wood (wood@dg-rtp.dg.com) + + * fold-const.c (range_test): New function. + (merge_component_references): Look for range tests as well. + + * va-m88k.h: Same changes as other va-*.h files below. Make this + work when and others are included on DG/UX. + + Fri Jun 26 08:17:33 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * expr.c (safe_from_p): Handle 0 in TREE_VALUE of a TREE_LIST. + (store_constructor: Ignore empty links in element chain. + + Fri Jun 26 07:06:19 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * c-convert.c (convert_to_integer): Don't add a NOP_EXPR in cases + where we can simply change the type of the entire tree. + + * cse.c (find_best_addr): Look for equivalents of a REG that is + the first operand of an address that is a binary operator whose + second operand is a CONST_INT. + + * stmt.c (expand_end_bindings): Don't save argument pointer if it + will be eliminated in favor of the frame pointer. + + * combine.c (try_combine): When using define_split to split an + insn, first try to put the pseudo-register into the mode of + the destination since it is the most likely to be the correct mode. + + * combine.c (make_compound_operation): Treat PLUS and MINUS + the same when passing down the code to the next level; for + consistency, an ASHIFT inside either gets turned into a MULT. + + * fold-const.c (optimize_bit_field_compare): Delete dead + assignment which can sometimes reference an undefined variable. + + * genoutput.c (gen_split): Initialize n_alternatives. + + * romp.md (movdf): Fix typo in operand_subword call in define_split. + + Fri Jun 26 04:38:37 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Make stdarg mechanism work with libc. + * va-hp800.h, va-i860.h, va-i960.h, va-mips.h, va-pyr.h, va-sparc.h): + Don't define or declare va_list; declare __gnuc_va_list. + But only declare it once. + Define other things only if _STDARG_H or _VARARGS_H. + Declare va_end as well as defining it. + * gstdarg.h: Likewise. + If __need___va_list was defined, then undef it + and don't define _STDARG_H. + For all machines, declare va_list from __gnuc_va_list + but only if _STDARG_H is defined. + + * gvarargs.h: Test _ANSI_H_, not _ANSI_H. + + Thu Jun 25 23:24:02 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * ns32k.c (print_operand): + Change NO_IMMEDIATE_PREFIX_IF_SYMBOLIC conditional to #ifdef. + + * genoutput.c (gen_split): Set d->n_alternatives. + + * Makefile.in (test-protoize-simple): Expect just 400 lines. + (install-common-headers): When comparing srcdir with ., use pwd. + + Tue Jun 16 22:11:12 1992 Jim Wilson (wilson@sphagnum.cygnus.com) + + * Makefile.in (enquire.o): Don't delete/copy enquire.c, just use + the copy in the source directory. + + Tue Jun 25 23:52:27 1992 Howard Chu (hyc@hanauma.jpl.nasa.gov) + + * libgcc2.c (__builtin_saveregs): Use SVR4 code on Alliant FX2800, + but with BSD function-naming convention. + + * va-i860.h: Use SVR4 definitions of __va_saved_regs and va_list + on Alliant FX2800. + + * fx2800.h (I860_REG_PREFIX, ASM_COMMENT_START): Deleted. + (DBX_NO_EXTRA_TAGS, BSS_ASM_OP): Deleted. + (ASM_OUTPUT_DOUBLE, ASM_OUTPUT_FLOAT): Deleted. + (ASM_FILE_START): Just call output_file_directive. + + Thu Jun 25 06:49:15 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-typeck.c (process_init_constructor): Strip NON_LVALUE_EXPR + from specified array index. + + * configure (i386-*-bsd*, i386-*-mach*): Don't set tmake_file. + They used to use t-libc-ok. + + * input.h (struct file_stack): Revert prev. change. + + Thu Jun 25 06:33:52 1992 Tom Wood (wood@dg-rtp.dg.com) + + * stmt.c (expand_end_case): Add CASE_VALUES_THRESHOLD. + * m88k.h (CASE_VALUES_THRESHOLD): Define. + + Thu Jun 25 06:13:39 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * explow.c (plus_constant, case PLUS): Remove obsolete code; + use recursive call in case remaining operand is one we handle. + + Wed Jun 24 19:15:14 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * combine.c (subst, case PLUS): If adding two things with no bits + in common, convert to IOR. + + * expr.c (do_jump, case BIT_AND_EXPR, COMPONENT_REF): Don't narrow + comparison unless byte accesses are not slow and we have a + comparison in the new mode. + + Wed Jun 24 14:29:09 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * c-parse.y (primary): If built-in decl has not had + an official declaration, print warning. + * c-decl.c (builtin_function): Set C_DECL_ANTICIPATED for + user-visible names. + * c-tree.h (C_DECL_ANTICIPATED): New macro. + + * fixincludes: Make some symlinks in the `multimedia' subdir. + + * i386.c: Change #error to just error. + + * protoize.c: Normalize error message syntax. + (process_aux_info_file): Don't delete .X file if it existed before. + (explicity compare modtime with .c file. + + Wed Jun 24 14:10:35 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * sparc.c (sparc_frw_compute_frame_size): New function, for flat + register window model support. + (sparc_frw_save_restore): Likewise. + (sparc_frw_output_function_prologue): Likewise. + (sparc_frw_output_function_epilogue): Likewise. + (sparc_frw_epilogue_delay_slots): Likewise. + (sparc_frw_eligible_for_epilogue_delay): Likewise. + + Tue Jun 23 22:36:12 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * cccp.c (rescan): Recognize # only when reading directly from a file. + + * input.h (struct file_stack): Add member `fd'. + + * regclass.c (regno_first_uid, regno_last_uid): Make elements ints. + (reg_scan): Allocate and clear them as ints. + * regs.h: Fix the declarations. + + * Create driver executable with name xgcc; rename to gcc in installing. + (xgcc): Target renamed. + (GCC_FOR_TARGET, GCC_PASSES, start.encap, specs, gcc-cross): + (install-common, install-collect2): Rename in deps, commands or value. + (install-collect2): Always get driver from xgcc whether cross or not. + + Tue Jun 23 00:00:35 1992 Brendan Kehoe (brendan@cs.widener.edu) + + * toplev.c (strip_off_ending): Also strip off .C and .cxx. + + Tue Jun 23 18:58:43 1992 Jim Wilson (wilson@wookumz.gnu.ai.mit.edu) + + * genrecog.c (add_to_sequence): Don't ignore mode of first operand + of a MATCH_OPERAND or MATCH_DUP_OP rtl. + * sparc.md (scc): Use noov_compare_op instead of normal_compare_op. + + * function.c (expand_function_start): When not optimizing, don't + put static chain pointer in a pseudo register. + + * sparc.c (print_operand): For '*', only annul branch if + optimizing, to avoid dbx bug. Add '(' to handle unoptimized case. + * sparc.h (PRINT_OPERAND_PUNCT_VALID_P): Add '('. + * sparc.md (jump): Add '%(' to pattern. + + * c-decl.c (store_parm_decls): Change type of void parameter to + error_mark_node. + + * configure (m68k-*-sysv4*): Use xm-m68kv.h not xm-m68kv4.h. + + * configure: Add -prefix option. + + * vax.c (split_quadword_operands): Declare paramater n. + + * i960.h (WORD_SWITCH_TAKES_ARG): Add -aux-info. + + * xcoffout.c (xcoffout_declare_function): Cast alloca result to char *. + + * c-convert.c (convert_to_integer): Don't pass truncation past + shift that is larger than the size being truncated to. + + Tue Jun 23 06:15:47 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * optabs.c (expand_binop, expand_unop): Try widening before trying + to make a library call. + + * stmt.c (expand_return): Add missing emit_queue call in tail + recursion case. + + * cse.c (simplify_unary_operation): Add SIGN_EXTEND and + ZERO_EXTEND to the operations we handle for wide results. + + * expr.c (emit_block_move): Convert size operand to mode that will + be passed to emit_library_call. + + Tue Jun 23 00:41:03 1992 Paul Eggert (eggert@shadow) + + * objc-parse.y (stmt): Fix mispelling for "label" in message. + + * cccp.c: (deps_file, pipe_closed): Deleted. + (main): Do not open deps_file until needed. + Check error status of dep_stream and stdout more carefully. + + Tue Jun 23 00:21:05 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (protoize.1, unprotoize.1): Rules deleted. + (install-man, proto, realclean): Don't operate on them. + * proto-man: File deleted. + + * protoize.c (main): Support -v as alias for -V. + + Mon Jun 22 21:50:01 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * Makefile.in (compare, compare3): Discard error output from second + tail. If it fails, don't compare that file. + + * Makefile.in (stamp-proto): Move the touch command last. + + * cccp.c (finclude): Use xmalloc, not alloca, for file contents. + + * stmt.c (check_for_full_enumeration_handling): For a case range, + consider all values in the range as handled. Also, check both ends + for being in the enumeration. + + * ns32k.h (NS32K_DISPLACEMENT_P): Wide displacement range applies to + all models. + + Mon Jun 22 20:29:47 1992 Ron Guilmette (rfg at ncd.com) + + * expr.h (*_libfunc): Added missing extern declarations of libfuncs + to handle operations on/for TFmode and XFmode operands. + * expr.c (convert_move): Added missing code to handle moves (with + conversion) from/to TFmode and XFmode operands. + * optabs.c (*_libfuncs): Added missing definitions of libfuncs + to handle operations on/for TFmode and XFmode operands. + (emit_float_lib_cmp): Added missing code to handle XFmode and TFmode + comparisons. + (init_fixtab): Added missing code to handle fixing (and trunc'ing) + of XFmode and TFmode operands to various sizes of ints. + (init_floattab): Likewise, but for "float" operations from ints to + either XFmode or TFmode. + (expand_float): Likewise. + (expand_fix): Likewise. + (init_libfuncs, init_integral_libfuncs, init_floating_libfuncs): New + functions added to initialize whole hunks of various optabs with + appropriate `libfunc' field values. + (init_optabs): Use `init_integral_libfuncs' or `init_floating_libfuncs' + wherever a group of consecutive optab entries need to all have their + `libfunc' fields initialized. + (init_optabs): added missing code to handle all operations on/of + XFmode and TFmode operands. + + Mon Jun 22 06:40:32 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * rs6000.h (MEMORY_MOVE_COST): Increase to 6, from 4. + (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add new reg + classes SPEC_OR_GEN_REGS and NON_FLOAT_REGS. + + * rs6000.h (EXTRA_CONSTRAINT): Don't use indirect_operand; instead + check explicitly. + + * rs6000.md (divmod): Use "2" constraint instead of using "q" + twice. + (tablejump): Constraint of "r" should be "l". + + * emit-rtl.c (init_emit): Show that all pointers into the frame are + pointer registers. + + Mon Jun 22 04:20:26 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * va-sparc.h (va_arg): Rename local identifiers to start with __. + + Sun Jun 21 14:51:42 1992 Richard Stallman (rms@mole.gnu.ai.mit.edu) + + * fold-const.c (real_value_truncate): New function. + All calls to REAL_VALUE_TRUNCATE changed to use this function. + + * reload1.c (reload): Record which insn attains each maximum need. + If can't find a spill, call spill_failure and return 1. + (spill_failure): New subroutine. + * global-alloc.c (global_alloc): Return 1 if reload returned 1. + * toplev.c (rest_of_compilation): If they return nonzero, give up + compiling this function. + + * c-decl.c (duplicate_decls): Never warn if redeclaring + a predeclared function. Use the new declaration's types + but keep any predeclared volatile flag. + If redeclaring builtin function, use new declaration's type. + If an old decl becomes volatile, fix the DECL_RTL. + * varasm.c (make_var_volatile): New function. + + * configure (mips-sony-bsd): Use xm-mips.h. + * xm-mipsbsdn.h: File deleted. + + * protoize.c (process_aux_info_file): Simplify logic for calling + gen_aux_info_file. Get rid of the label `retry'. + + * m68ksgs.h (ASM_OUTPUT_REG_PUSH, ASM_OUTPUT_REG_POP): + Override for sgs syntax. + + Sun Jun 21 14:06:41 1992 Brendan Kehoe (brendan@cs.widener.edu) + + * va-sparc.h (va_arg): Use a character array of size TYPE for + `d' in the union, and return its dereference as TYPE. + + Sun Jun 21 14:04:36 1992 Wilson Tien (wtien at urbana.mcd.mot.com) + + * m68k.c (print_operand_address) [MOTOROLA]: Use .w and .l, not :w, :l. + + Sat Jun 20 06:32:11 1992 Richard Kenner (kenner at vlsi1.ultra.nyu.edu) + + * stor-layout.c (get_best_mode): If SLOW_BYTE_ACCESS is true, return + widest mode (but no wider than UNITS_PER_WORD) that meets all + the conditions. + + * combine.c (make_extraction): Always ensure we have a SUBREG when + we make a STRICT_LOW_PART. + + * varasm.c (const_hash, compare_constant_1, record_constant_1): + Handle case when TREE_VALUE of a constructor is zero. + (output_constant): Use CONSTRUCTOR_ELTS. + + * cse.c (cse_insn): Memory is not invalidated by a constant + subroutine call. + (delete_dead_from_cse): Correctly check for being within a + libcall block. + + * cse.c (canon_reg): Call validate_change with IN_GROUP equal to 1. + (cse_insn): Call apply_change_group after canon_reg. + When canonicalizing, call validate_change with IN_GROUP equal to + one and also call when canon_reg would. + + * combine.c (subst, shift cases): Use force_to_mode in + SHIFT_COUNT_TRUNCATED case. + + * rs6000.md: Add new pattern to split move of large constant. + + * cse.c (delete_dead_from_cse): Really delete insn instead of + turning it into a NOTE. + + * romp.md (shift patterns): Use QImode for count operand. + + Sat Jun 20 06:31:21 1992 Tom Wood (wood@dg-rtp.dg.com) + + * a29k.md (storehinhww): Use inhw not inbyte. + + Thu Jun 18 16:01:56 1992 Richard Kenner (kenner@vlsi1.ultra.nyu.edu) + + * protoize.c (WIFEXITED, WEXITSTATUS): Delete unused macros. + + * combine.c (subst): If comparison operator has floating-point + result, adjust the value returned by simplify_relational_operation + accordingly. + * integrate.c (subst_constants): Likewise. + * loop.c (get_condition): Likewise. + * cse.c (fold_rtx): Likewise. + When returning TRUE or FALSE, handle comparisons returning + floating-point. + (find_comparison_args): Handle comparisons returning FP values; + only look at STORE_FLAG_VALUE for comparisons returning integers. + + * combine.c (try_combine, subst): Pass both comparison arguments + to SELECT_CC_MODE. + * i386.h, i960.h, i960.c, mips.h, pa.h, pa.c, rs6000.h: + Add second argument to SELECT_CC_MODE. + * sparc.h, sparc.c: Likewise. + + * cse.c (insert_regs): Make a quantity for the register in a + SUBREG if it doesn't have one. + (fold_rtx, case SUBREG): Always try to find a constant equivalent + for a SUBREG; try for CONST_DOUBLE as well. + (cse_insn): Call insert_regs on DEST if it is a SUBREG. + + Thu Jun 18 15:01:29 1992 Mike Stump (mrs@albert.gnu.ai.mit.edu) + + * c++: Allow for better quoting and -v handling. + + Thu Jun 18 14:49:20 1992 Tom Wood (wood@dg-rtp.dg.com) + + For RMS: + * varasm.c: Declare text_section and readonly_data_section. + + * dpx2.h (CPP_SPEC): Define __HAVE_68881__ unless -msoft-float. + DPX/2 machines all have a 68882. + + * x-i386sco (RCCFLAGS): Use -DNULL=0 to avoid suurious warnings + from rcc. + + * seq386.h (SIZE_TYPE): The Sequent running Dynix uses int for size_t. + + Thu Jun 18 14:36:41 1992 Mike Stump (mrs@albert.gnu.ai.mit.edu) + + Merge in Cygnus sources... + + Fri Jun 5 15:00:55 1992 Mike Stump (mrs at cygnus.com) + + * cp-typeck.c (build_c_cast): When casting, propagate const'ness + from cast type. When casting to a reference to T, really just + cast to T. + + * cp-cvt.c (build_up_reference): Make a copy of a node before + changing it. Only propagate the const bit if we are not + subverting it. + + Fri Jun 5 14:36:19 1992 Mike Stump (mrs at cygnus.com) + + * cp-cvt.c (build_up_reference): When casting away const on + references, do not report an error. + + Fri Jun 5 13:26:11 1992 Mike Stump (mrs at cygnus.com) + + * cp-init.c (build_new): Handle new placement with arrays. + + Thu Jun 4 08:26:44 1992 Mike Stump (mrs at cygnus.com) + + * cp-search.c (compute_visibility): DERIVED_FROM_P had its + arguments reversed, switched them to be in the right order. + Fixes visibility on protected members. + + Wed Jun 3 14:45:40 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (unary_expr): Make it illegal to use delete on + a pointer to a const object. With help from Brendan Kehoe. + + Wed Jun 3 13:25:26 1992 Ken Raeburn (Raeburn@Cygnus.COM) + + * cp-parse.y (template_instantiate_once): Set + CLASSTYPE_GOT_SEMICOLON to eliminate messages about missing + semicolons. + + * cp-decl.c (start_function): Don't emit error message for missing + semicolon after class decl; that syntax (declaring both class and + function returning that type) should be legal. Do emit a warning if + it's not an anonymous name. + + Mon Jun 1 18:08:09 1992 Mike Stump (mrs at cygnus.com) + + Sat May 30 15:38:54 1992 Brendan Kehoe (brendan@cs.widener.edu) + + * cp-decl.c (grokdeclarator): Don't allow main to be static. + + Mon Jun 1 17:52:24 1992 Mike Stump (mrs at cygnus.com) + + Sat May 30 15:38:54 1992 Brendan Kehoe (brendan@cs.widener.edu) + + * cp-decl.c (poplevel): Use DECL_INITIAL to detect undef label + instead of DECL_SOURCE_LINE. + + Mon Jun 1 17:22:54 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (unary_expr): Don't allow old placement syntax(with {}) + nor dynamic with new (with ()) new placement syntax. Completes May 27 + fix. + + Mon Jun 1 13:57:28 1992 Mike Stump (mrs at cygnus.com) + + * cp-type2.c (digest_init): Trailing '\0' is never ignored in + initializations using strings in ANSI draft C++ unlike ANSI C. + + Mon Jun 1 07:18:13 1992 Michael Tiemann (tiemann at rtl.cygnus.com) + + * cp-decl.c (pushdecl): Re-fix May 12 change regarding DECL_CONTEXT. + * cp-call.c (build_method_call): Go back to using DECL_CONTEXT + instead of DECL_CLASS_CONTEXT. DECL_CONTEXT says when a function + was first declared virtual in a class, which is needed information + in case the virtual function comes from a virtual baseclass (because + the derived class won't have a vtable entry for that function (if it + has a vtable at all!)). + + Wed May 27 17:05:50 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (unary_expr): Handle new placement syntax, desupport + the old placement syntax with a pedwarn. + + Tue May 26 17:30:28 1992 Mike Stump (mrs at cygnus.com) + + Thu May 21 17:13:38 1992 Michael Tiemann (tiemann at cygnus.com) + + * cp-decl.c (grok_enum_decls): Allow reference to nested enums from + other classes for NICHL. + + Tue May 26 15:31:30 1992 Mike Stump (mrs at cygnus.com) + + * cp-*.[chy]: Always include "assert.h" and not to + be consistent. + + Tue May 26 10:07:02 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (return_init): Fix simple typo that caused '=' + initialized named return values to fail. + + Mon May 25 11:42:18 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (component_decl): Handle anonymous unions as before, + except check to make sure it is really an anonymous union. + + Sat May 23 23:37:38 1992 Mike Stump (mrs at cygnus.com) + + * cp-tree.c (layout_basetypes): Don't core dump on erroneous input. + + Sat May 23 22:04:31 1992 Mike Stump (mrs at cygnus.com) + + * cp-typeck.c (c_expand_start_case): build_type_conversion can + return a NULL_TREE, so don't try and find a code or type of it. + + Wed May 20 09:09:08 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-call.c (build_method_call): Use DECL_CLASS_CONTEXT, not + DECL_CONTEXT to find the class in which FUNCTION was declared (for + non-virtual calls). + + Tue May 19 02:08:39 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (component_decl): Remove some bogus code that + prevents empty nested union definitions from compiling. + + Tue May 19 01:08:23 1992 Mike Stump (mrs at cygnus.com) + + * cp-decl.c (grokfndecl): Propagate volatile from type of + function out to the decl for the function. + + Mon May 18 17:19:39 1992 Mike Stump (mrs at rtl.cygnus.com) + + * cp-search.c (get_binfo): Since unions cannot participate in + inheritance relationships, return 0 instead of aborting. + + Fri May 15 13:37:40 1992 Mike Stump (mrs at cygnus.com) + + * cp-parse.y (template_type_name): Handle + template class task { friend task* preempt(task*); }; + syntax. + + * cp-pt.c (lookup_template_class): Ditto. + + Thu May 14 22:54:17 1992 Mike Stump (mrs at cygnus.com) + + * cp-tree.c (layout_basetypes): Don't warn about non-virtual + destructors unless the user asks with -Wall. + + Thu May 14 22:38:54 1992 Mike Stump (mrs at cygnus.com) + + * cp-type2.c (build_functional_cast): exp may be an error_mark_node, + don't crash when it is. + + Thu May 14 18:56:26 1992 Mike Stump (mrs at cygnus.com) + + * cp-decl.c (hack_incomplete_structures): Test for underflow + before decreamenting n_incomplete in current_binding_level, since + it is unsigned. + + Tue May 12 15:52:49 1992 Mike Stump (mrs at cygnus.com) + + Mon May 11 14:10:50 1992 Ron Guilmette (rfg at ncd.com) + + * cp-decl.c (poplevel): Reconciled with recent changes made to the + `poplevel' routine in c-decl.c. The changes here cause LABEL_DECL + nodes to be attached (as the BLOCK_VARS chain) to the BLOCK node + which represent the outermost scope of the function. + + Mon May 11 12:35:44 1992 Ron Guilmette (rfg at ncd.com) + + * cp-class.c (finish_struct): Check DECL_CONTEXT to see if it is + any sort of a type (e.g. struct *or* union) rather than just + checking it to see if it's a RECORD_TYPE. + * cp-decl.c (pushdecl): Set DECL_CONTEXT of pushed ..._DECL node, + just as is done in c-decl.c. + (pushdecl): Delete useless variable `cntxt'. + (finish_decl): Set TREE_USED rather than DECL_FROM_INLINE in order + to prevent "unused" warnings. + (finish_function): Check DECL_CONTEXT to see if it is a type. + (finish_function): Fixed indentation problem. + * cp-gc.c (build_m_desc): Check DECL_CONTEXT to see if it is a type. + * cp-init.c (build_virtual_init): Fix indentation. + * cp-lex.c (store_pending_inline): Check DECL_CONTEXT to see if it + is a type. + * cp-pt.c (tsubst, do_pending_expansions): Check DECL_CONTEXT to see + if it is a type. + * cp-typeck.c (mark_addressable): Check DECL_CONTEXT to see if it is + any sort of a type (e.g. struct *or* union) rather than just + checking it to see if it's a RECORD_TYPE. + + Tue May 12 08:52:06 1992 Michael Tiemann (tiemann@rtl.cygnus.com) + + * cp-typeck.c (build_component_ref): Call `break_out_cleanups'. + Also clean up indentiation. + + Mon May 11 23:14:04 1992 Mike Stump (mrs at cygnus.com) + + * cp-decl.c (pushtag): Handle structure tags in the same way as the + C front-end. This completes a change that rms put in on 3/12/92 and + I put in the Cygnus tree on 3/13/92 and Mark Eichin took back out on + 3/18/92. + + Sun May 3 00:29:59 1992 Mike Stump (mrs at cygnus.com) + + * cp-lex.c (copy_lang_decl, store_pending_inline): Cast + arguments to bcopy to be char *. + + Fri May 1 12:22:31 1992 Michael Tiemann (tiemann@cygnus.com) + + * cp-init.c (expand_aggr_init, expand_vec_init): When comparing + array types, use `comptypes' instead of ==, since two array types + may be structurally identical but not == if one was defaulted from + an initializer. + + Wed Apr 29 01:25:25 1992 Mike Stump (mrs at cygnus.com) + + * cp-init.c (do_friend): Check that PREVIOUS_DECL is non-NULL. + + Thu Jun 18 14:15:07 1992 Torbjorn Granlund (tege@hal.gnu.ai.mit.edu) + + * pa.md (insv): Use `+' for operand 0 constraint. + + Thu Jun 18 13:39:22 1992 Michael Meissner (meissner@osf.org) + + * mips.h (MIPS_VERSION): Bump Meissner version # to 20. + (final_prescan_insn): Add declaration. + (FINAL_PRESCAN_INSN): Just call final_prescan_insn. + (CONST_OK_FOR_LETTER_P): Rewrite some tests, so that they will + work on host systems with 64 bit integers. + + * mips.c (large_int): Rework, so that we don't get funny boundary + conditions on systems with 64 bit integers. + (mips_move_1word): Just use li to load constants that can be done + with lui, instead of issuing the lui, since the GAS bug that + generated two instructions has been fixed. + (final_prescan_insn): Move the checking for filling the delay + slots here from the FINAL_PRESCAN_INSN macro. + + * mips.md (andsi3, iorsi3, xorsi3): Make the constraints match + the real machine (the predicate still is more general in order + to optimize bitfields at the expense of not CSE'ing large + constants used in logical ops, and making reload load it into + a scratch register). Don't use $1 as a temporary register any + more. + + * varasm.c (decode_reg_name): If `memory' return -4. + + * stmt.c (expand_asm_operands): If `memory' is used as a clobbered + register, emit a (clobber (const_int 0)) to force the compiler not + to cache memory values in registers across the assembly + instruction(s). + + * mips-tfile.c (read_line): Semicolons within strings are not + counted as statement separators. + + * collect2.c (scan_prog_file, OSF/rose case): Cast pointer arguments + to bcopy to generic * to avoid warnings. + + Thu Jun 18 12:04:53 1992 David J. MacKenzie (djm@wookumz.gnu.ai.mit.edu) + + * c++: If given -v with no file args, don't pass the libraries to + gcc. + + Thu Jun 18 10:34:22 1992 Tom Wood (wood@dg-rtp.dg.com) + + * expr.c (expand_builtin, BUILT_IN_FSQRT): Emit queue of increment + instructions before starting a sequence that may get thrown away. + + See ChangeLog.5 for earlier changes. diff -rc2N gcc-2.2.2/ChangeLog.3 gcc-2.3.1/ChangeLog.3 *** gcc-2.2.2/ChangeLog.3 Sat Oct 5 07:02:37 1991 --- gcc-2.3.1/ChangeLog.3 Fri Sep 11 03:06:17 1992 *************** *** 8062,8070 **** See file ChangeLog.2. - - Local Variables: - mode: indented-text - left-margin: 8 - fill-column: 76 - version-control: never - End: --- 8062,8063 ---- diff -rc2N gcc-2.2.2/ChangeLog.5 gcc-2.3.1/ChangeLog.5 *** gcc-2.2.2/ChangeLog.5 Sun Jun 14 18:14:35 1992 --- gcc-2.3.1/ChangeLog.5 Mon Sep 21 03:51:25 1992 *************** *** 807,811 **** * rs6000.h (ASM_DECLARE_FUNCTION_NAME): Use new function ! xcoffout_declare_function(). * rs6000.c (output_epilog): Shorten internal label. (output_toc, output_function_profiler): Likewise. --- 807,811 ---- * rs6000.h (ASM_DECLARE_FUNCTION_NAME): Use new function ! xcoffout_declare_function. * rs6000.c (output_epilog): Shorten internal label. (output_toc, output_function_profiler): Likewise. *************** *** 877,881 **** * ns32k.md (extzv-1): New pattern for extracting from SImode. ! * g++: -M suppresses -lg++. * svr3.h (DO_GLOBAL_CTORS_BODY): Flush spurious #endif. --- 877,881 ---- * ns32k.md (extzv-1): New pattern for extracting from SImode. ! * c++: -M suppresses -lg++. * svr3.h (DO_GLOBAL_CTORS_BODY): Flush spurious #endif. *************** *** 5004,5008 **** (RCCFLAGS): Define it here, along with other SCO symbols. (XCFLAGS): Use that. New variable. ! (CLIB): Use -lPW to get alloca(). Fri Mar 13 14:11:41 1992 Jeffrey A. Law (law@wombat.gnu.ai.mit.edu) --- 5004,5008 ---- (RCCFLAGS): Define it here, along with other SCO symbols. (XCFLAGS): Use that. New variable. ! (CLIB): Use -lPW to get alloca. Fri Mar 13 14:11:41 1992 Jeffrey A. Law (law@wombat.gnu.ai.mit.edu) *************** *** 6220,6224 **** * xm-i386sco.h: New file. ! * optabs.c (ldexp): New function. Used if host ldexp() is broken. * configure (i386-sequent-bsd*): Use seq386gas.h if --gas. --- 6220,6224 ---- * xm-i386sco.h: New file. ! * optabs.c (ldexp): New function. Used if host ldexp is broken. * configure (i386-sequent-bsd*): Use seq386gas.h if --gas. *************** *** 8953,8961 **** See ChangeLog.4 for earlier changes. - - Local Variables: - mode: indented-text - left-margin: 8 - fill-column: 76 - version-control: never - End: --- 8953,8954 ---- diff -rc2N gcc-2.2.2/INSTALL gcc-2.3.1/INSTALL *** gcc-2.2.2/INSTALL Sun Jun 14 17:58:38 1992 --- gcc-2.3.1/INSTALL Sat Oct 31 19:49:58 1992 *************** *** 1,7 **** ! This is Info file INSTALL, produced by Makeinfo-1.47 from the input ! file install1.texi. ! ! This file documents the installation of the GNU compiler. Copyright ! (C) 1988, 1989, 1992 Free Software Foundation, Inc. You may copy, distribute, and modify it freely as long as you preserve this copyright notice and permission notice. --- 1,4 ---- ! This file documents the installation of the GNU compiler. Copyright (C) ! 1988, 1989, 1992 Free Software Foundation, Inc. You may copy, distribute, and modify it freely as long as you preserve this copyright notice and permission notice. *************** *** 15,19 **** 1. If you have built GNU CC previously in the same directory for a different target machine, do `make distclean' to delete all files ! that might be invalid. 2. On a System V release 4 system, make sure `/usr/bin' precedes --- 12,19 ---- 1. If you have built GNU CC previously in the same directory for a different target machine, do `make distclean' to delete all files ! that might be invalid. One of the files this deletes is ! `Makefile'; if `make distclean' complains that `Makefile' does not ! exist, it probably means that the directory is already suitably ! clean. 2. On a System V release 4 system, make sure `/usr/bin' precedes *************** *** 55,67 **** Here are the possible CPU types: ! a29k, arm, cN, hppa1.0, hppa1.1, i386, i860, i960, m68000, ! m68k, m88k, mips, ns32k, romp, rs6000, sparc, vax, we32k. Here are the recognized company names. As you can see, customary abbreviations are used rather than the longer official names. ! alliant, altos, apollo, att, convergent, convex, crds, dec, ! dg, encore, harris, hp, ibm, mips, motorola, ncr, next, ns, ! omron, sequent, sgi, sony, sun, tti, unicom. The company name is meaningful only to disambiguate when the rest --- 55,68 ---- Here are the possible CPU types: ! a29k, alpha, arm, cN, elxsi, hppa1.0, hppa1.1, i386, i860, ! i960, m68000, m68k, m88k, mips, ns32k, pyramid, romp, rs6000, ! sparc, vax, we32k. Here are the recognized company names. As you can see, customary abbreviations are used rather than the longer official names. ! alliant, altos, apollo, att, cbm, convergent, convex, crds, ! dec, dg, encore, harris, hp, ibm, mips, motorola, ncr, next, ! ns, omron, sequent, sgi, sony, sun, tti, unicom. The company name is meaningful only to disambiguate when the rest *************** *** 72,78 **** Here is a list of system types: ! bsd, sysv, mach, minix, genix, ultrix, vms, sco, isc, aix, ! sunos, hpux, unos, luna, dgux, newsos, osfrose, osf, dynix, ! aos, ctix. You can omit the system type; then `configure' guesses the --- 73,79 ---- Here is a list of system types: ! aix, aos, bsd, ctix, dgux, dynix, genix, hpux, isc, linux, ! luna, mach, minix, newsos, osf, osfrose, riscos, sco, sunos, ! sysv, ultrix, unos, vms. You can omit the system type; then `configure' guesses the *************** *** 109,115 **** company name. ! There are three additional options you can specify independently to describe variant hardware and software configurations. These are ! `--with-gnu-as', `--with-gnu-ld', and `--nfp'. `--with-gnu-as' --- 110,116 ---- company name. ! There are four additional options you can specify independently to describe variant hardware and software configurations. These are ! `--with-gnu-as', `--with-gnu-ld', `--with-stabs' and `--nfp'. `--with-gnu-as' *************** *** 120,124 **** tools. (Specify `--with-gnu-ld' as well, since on these systems GAS works only with the GNU linker.) The systems ! were this makes a difference are `i386-ANYTHING-sysv', `i860-ANYTHING-bsd', `m68k-hp-hpux', `m68k-sony-bsd', `m68k-altos-sysv', `m68000-hp-hpux', and `m68000-att-sysv'. --- 121,125 ---- tools. (Specify `--with-gnu-ld' as well, since on these systems GAS works only with the GNU linker.) The systems ! where this makes a difference are `i386-ANYTHING-sysv', `i860-ANYTHING-bsd', `m68k-hp-hpux', `m68k-sony-bsd', `m68k-altos-sysv', `m68000-hp-hpux', and `m68000-att-sysv'. *************** *** 131,134 **** --- 132,152 ---- system's linker on most configurations. + `--with-stabs' + On MIPS based systems, you must specify whether you want GNU + CC to create the normal ECOFF debugging format, or to use + BSD-style stabs passed through the ECOFF symbol table. The + normal ECOFF debug format cannot fully handle languages other + than C. BSD stabs format can handle other languages, but it + only works with the GNU debugger GDB. + + Normally, GNU CC uses the ECOFF debugging format by default; + if you prefer BSD stabs, specify `--with-stabs' when you + configure GNU CC. + + No matter which default you choose when you configure GNU CC, + the user can use the `-gcoff' and `-gstabs+' options to + specify explicitly the debug format for a particular + compilation. + `--nfp' On certain systems, you must specify whether the machine has *************** *** 150,157 **** special things you must know: `i386-*-sco' ! Compilation with RCC is recommended, but it produces lots of ! spurious warnings. They do not necessarily indicate that ! anything is wrong. `i386-sequent' --- 168,226 ---- special things you must know: + `alpha-*-osf1' + Systems using processors that implement the DEC Alpha + architecture and are running the OSF/1 operating system. (VMS + on the Alpha is not currently supported by GNU CC.) As of + this writing, the only Alpha-based product currently + available from DEC is the 21064 (EV4) processor chip; no + system-level products can be ordered. This port is provided + for those developers who might have early Alpha hardware from + DEC or other vendors and run the OSF/1 operating system. It + has not been extensively tested and both the C++ and + Objective-C languages may not work, except in a + cross-compilation environment. + + The `ASSEMBLE_FILE_START' macro writes a `.verstamp' directive + containing the version of the calling sequence. Currently, + we use `9 0', which we believe will work until the official + release by DEC of their system, at which point `3 11' is the + correct value. If you get a mismatch error from the + assembler on a `.verstamp' line, consult the file + `/usr/include/stamp.h' for the present value. GNU C on the + Alpha does not support versions of DEC's OSF/1 earlier than + BL9; if you are running an older version, we suggest you ask + your DEC contact for an update. + + Note that since the Alpha is a 64-bit architecture, + cross-compilers from 32-bit machines will not generate as + efficient code as that generated when the compiler is running + on a 64-bit machine because many optimizations that depend on + being able to represent a word on the target in an integral + value on the host cannot be performed. + + `a29k' + AMD Am29K-family processors. These are normally used in + embedded applications. There are no standard Unix + configurations. This configuration corresponds to AMD's + standard calling sequence and binary interface and is + compatible with other 29K tools. + + You may need to make a variant of the file `a29k.h' for your + particular configuration. + + `a29k-*-bsd' + AMD Am29050 used in a system running a variant of BSD Unix. + + `elxsi-elxsi-bsd' + The Elxsi's C compiler has known limitations that prevent it + from compiling GNU C. Please contact `mrs@cygnus.com' for + more details. + `i386-*-sco' ! Compilation with RCC is recommended. ! ! `i386-ibm-aix' ! You need a version of GAS that you can get from ! `tranle@intellicorp.com'. `i386-sequent' *************** *** 193,197 **** `m88k-svr3' ! Motorola m88k running the AT&T/Unisoft/Motorla V.3 reference port. These systems tend to use the Green Hills C, revision 1.8.5, as the standard C compiler. There are apparently bugs --- 262,266 ---- `m88k-svr3' ! Motorola m88k running the AT&T/Unisoft/Motorola V.3 reference port. These systems tend to use the Green Hills C, revision 1.8.5, as the standard C compiler. There are apparently bugs *************** *** 247,255 **** The only operating systems supported for the IBM RT PC are AOS and MACH. GNU CC does not support AIX running on the RT. `rs6000-*-aix' ! Read the file `README.RS6000' for information on how to get a ! fix for a problem in the IBM assembler that prevents use of ! GNU CC. `vax-dec-ultrix' --- 316,332 ---- The only operating systems supported for the IBM RT PC are AOS and MACH. GNU CC does not support AIX running on the RT. + We recommend you compile GNU CC with an earlier version of + itself; if you compile GNU CC with `hc', the Metaware + compiler, it will work, but you will get mismatches between + the stage 2 and stage 3 compilers in various files. These + errors are minor differences in some floating-point constants + and can be safely ignored; the stage 3 compiler is correct. `rs6000-*-aix' ! *Read the file `README.RS6000' for information on how to get ! a fix for a problem in the IBM assembler that prevents use of ! GNU CC.* You must either obtain the new assembler or avoid ! using the `-g' switch. Note that `Makefile.in' uses `-g' by ! default when compiling `libgcc2.c'. `vax-dec-ultrix' *************** *** 264,272 **** languages that you want to run. - `we32k-att-sysv' - Don't use `-g' when compiling GNU CC. The system's linker - seems to be unable to handle such a large program with - debugging information. - Here we spell out what files will be set up by `configure'. Normally you need not be concerned with these files. --- 341,344 ---- *************** *** 370,374 **** 9. Recompile the compiler with itself, with this command: ! make CC="stage1/gcc -Bstage1/" CFLAGS="-g -O" This is called making the stage 2 compiler. --- 442,446 ---- 9. Recompile the compiler with itself, with this command: ! make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O" This is called making the stage 2 compiler. *************** *** 393,397 **** is no such hardware, do this instead: ! make CC="stage1/gcc -Bstage1/" CFLAGS="-g -O -msoft-float" 10. If you wish to test the compiler by compiling it with itself one --- 465,469 ---- is no such hardware, do this instead: ! make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O -msoft-float" 10. If you wish to test the compiler by compiling it with itself one *************** *** 399,412 **** make stage2 ! make CC="stage2/gcc -Bstage2/" CFLAGS="-g -O" This is called making the stage 3 compiler. Aside from the `-B' ! option, the options should be the same as when you made the stage 2 ! compiler. ! ! The command shown above builds compilers for all the supported ! languages. If you don't want them all, you can specify the ! languages to build by typing the argument `LANGUAGES="LIST"', as ! described above. Then compare the latest object files with the stage 2 object --- 471,483 ---- make stage2 ! make CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" This is called making the stage 3 compiler. Aside from the `-B' ! option, the compiler options should be the same as when you made ! the stage 2 compiler. But the `LANGUAGES' option need not be the ! same. The command shown above builds compilers for all the ! supported languages; if you don't want them all, you can specify ! the languages to build by typing the argument `LANGUAGES="LIST"', ! as described above. Then compare the latest object files with the stage 2 object *************** *** 436,440 **** support. You can use the following command: ! make CC="stage2/gcc -Bstage2/" CFLAGS="-g -O" install LANGUAGES="LIST" (Use the same value for `CC', `CFLAGS' and `LANGUAGES' that you --- 507,511 ---- support. You can use the following command: ! make install CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" LANGUAGES="LIST" (Use the same value for `CC', `CFLAGS' and `LANGUAGES' that you *************** *** 471,493 **** some other compiler.) ! 12. Correct errors in the header files on your machine. Various system header files often contain constructs which are ! incompatible with ANSI C, and they will not work when you compile ! programs with GNU CC. This behavior consists of substituting for ! macro argument names when they appear inside of character ! constants. The most common offender is `ioctl.h'. ! ! You can overcome this problem when you compile by specifying the ! `-traditional' option. ! ! Alternatively, on Sun systems and 4.3BSD at least, you can correct ! the include files by running the shell script `fixincludes'. This ! installs modified, corrected copies of the files `ioctl.h', ! `ttychars.h' and many others, in a special directory where only ! GNU CC will normally look for them. This script will work on ! various systems because it chooses the files by searching all the ! system headers for the problem cases that we know about. Use the following command to do this: --- 542,568 ---- some other compiler.) ! 12. Install the Objective C library (if you have built the Objective C ! compiler). Here is the command to do this: + make install-libobjc CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" + + 13. Correct errors in the header files on your machine. + Various system header files often contain constructs which are ! erroneous, incompatible with ANSI C or otherwise unsuitable, and ! they will not work when you compile programs with GNU CC. + The most common erroneous construct is found in `ioctl.h', where a + macro expects argument values to be substituted for argument names + inside of character constants--something not done in ANSI C. This + particular problem can be prevented by using `-traditional'. Other + problems are not so easy to work around. + + GNU CC comes with shell scripts to fix known header file problems. + They install corrected copies of various header files in a + special directory where only GNU CC will normally look for them. + The scripts adapt to various systems by searching all the system + header files for the problem cases that we know about. + Use the following command to do this: *************** *** 499,504 **** Note that some systems are starting to come with ANSI C system ! header files. On these systems, don't run `fixincludes'; it may ! not work, and is certainly not necessary. If you cannot install the compiler's passes and run-time support in --- 574,586 ---- Note that some systems are starting to come with ANSI C system ! header files. On these systems, don't run `install-fixincludes'; ! it may not work, and is certainly not necessary. One exception: ! there are is a special script for System V release 4, which you ! should run. ! ! It is not the purpose of `install-fixincludes' to add prototypes to ! the system header files. We support headers with ANSI C ! prototypes in the GNU C Library, and we have no time to support ! adding them to other systems' header files. If you cannot install the compiler's passes and run-time support in *************** *** 579,583 **** To build GNU CC as a cross-compiler, you start out by running ! `configure'. You must specify two different configureations, the host and the target. Use the `--host=HOST' option for the host and `--target=TARGET' to specify the target type. For example, here is how --- 661,665 ---- To build GNU CC as a cross-compiler, you start out by running ! `configure'. You must specify two different configurations, the host and the target. Use the `--host=HOST' option for the host and `--target=TARGET' to specify the target type. For example, here is how *************** *** 588,593 **** Next you should install the cross-assembler and cross-linker (and ! `ar' and `ranlib'). Put them in the directory `/usr/local/TARGET'. ! The installation of GNU CC will find them there and copy or link them to the proper place to find them when you run the cross-compiler later. --- 670,675 ---- Next you should install the cross-assembler and cross-linker (and ! `ar' and `ranlib'). Put them in the directory `/usr/local/TARGET/bin'. ! The installation of GNU CC will find them there and copy or link them to the proper place to find them when you run the cross-compiler later. *************** *** 598,617 **** target machine in `/usr/local/TARGET/include'. ! Then you can proceed just as for compiling a single-machine compiler ! through the step of building stage 1. ! ! When you are using a cross-compiler configuration, building stage 1 ! does not compile all of GNU CC. This is because one part of building, ! the compilation of `libgcc2.c', requires use of the cross-compiler. ! ! However, when you type `make install' to install the bulk of the ! cross-compiler, that will also compile `libgcc2.c' and install the ! resulting `libgcc.a'. ! ! You will find it necessary to produce a substitute for `libgcc1.a'. ! Normally this file is compiled with the "native compiler" for the ! target machine; compiling it with GNU CC does not work. But compiling ! it with the host machine's compiler also doesn't work--that produces a ! file that would run on the host, and you need it to run on the target. We can't give you any automatic way to produce this substitute. For --- 680,688 ---- target machine in `/usr/local/TARGET/include'. ! You must now produce a substitute for `libgcc1.a'. Normally this ! file is compiled with the "native compiler" for the target machine; ! compiling it with GNU CC does not work. But compiling it with the host ! machine's compiler also doesn't work--that produces a file that would ! run on the host, and you need it to run on the target. We can't give you any automatic way to produce this substitute. For *************** *** 623,627 **** the subroutines that you need. If these definitions do not use the C arithmetic operators that they are meant to implement, you might be ! able to compile them with the cross-compiler you have just built. Do not try to build stage 2 for a cross-compiler. It doesn't work to --- 694,717 ---- the subroutines that you need. If these definitions do not use the C arithmetic operators that they are meant to implement, you might be ! able to compile them with the cross-compiler you are building. To do ! this, specify `LIBGCC1=libgcc1.a OLDCC=./xgcc' when building the ! compiler. ! ! Now you can proceed just as for compiling a single-machine compiler ! through the step of building stage 1. If you have not provided some ! sort of `libgcc1.a', then compilation will give up at the point where ! it needs that file, printing a suitable error message. If you do ! provide `libgcc1.a', then building the compiler will automatically ! compile and link a test program called `cross-test'; if you get errors ! in the linking, it means that not all of the necessary routines in ! `libgcc1.a' are available. ! ! When you are using a cross-compiler configuration, building stage 1 ! does not compile all of GNU CC. This is because one part of building, ! the compilation of `libgcc2.c', requires use of the cross-compiler. ! ! However, when you type `make install' to install the bulk of the ! cross-compiler, that will also compile `libgcc2.c' and install the ! resulting `libgcc.a'. Do not try to build stage 2 for a cross-compiler. It doesn't work to *************** *** 650,672 **** `-g' does not work on HP-UX, since that system uses a peculiar ! debugging format which GNU CC does not know about. There is a ! preliminary version available of some modified GNU tools including the ! GDB debugger which do work with GNU CC for debugging. You can get them ! by anonymous ftp from `mancos.cs.utah.edu' in the `dist' subdirectory. ! You would need to install GAS in the file /usr/local/lib/gcc-lib/CONFIGURATION/GCCVERSION/as where CONFIGURATION is the configuration name (perhaps `hpNNN-hpux') ! and GCCVERSION is the GNU CC version number. ! ! If you do this, delete the line ! #undef DBX_DEBUGGING_INFO - from `tm.h' before you build GNU CC, to enable generation of debugging - information. - Installing GNU CC on the Sun ============================= --- 740,760 ---- `-g' does not work on HP-UX, since that system uses a peculiar ! debugging format which GNU CC does not know about. There are ! preliminary versions of GAS and GDB for the HP-PA which do work with ! GNU CC for debugging. You can get them by anonymous ftp from ! `jaguar.cs.utah.edu' `dist' subdirectory. You would need to install ! GAS in the file /usr/local/lib/gcc-lib/CONFIGURATION/GCCVERSION/as where CONFIGURATION is the configuration name (perhaps `hpNNN-hpux') ! and GCCVERSION is the GNU CC version number. Note, if you picked up ! GAS before October 6, 1992 it is highly recommended you get a new one ! to avoid several bugs which have been discovered recently. ! To enable debugging, configure GNU CC with the `--gas' option before ! building. Installing GNU CC on the Sun ============================= *************** *** 766,772 **** 1. Define the VMS logical names `GNU_CC' and `GNU_CC_INCLUDE' to ! point to the directories where the GNU CC executables (`gcc-cpp', ! `gcc-cc1', etc.) and the C include files are kept. This should be ! done with the commands: $ assign /system /translation=concealed - --- 854,860 ---- 1. Define the VMS logical names `GNU_CC' and `GNU_CC_INCLUDE' to ! point to the directories where the GNU CC executables ! (`gcc-cpp.exe', `gcc-cc1.exe', etc.) and the C include files are ! kept respectively. This should be done with the commands: $ assign /system /translation=concealed - *************** *** 788,792 **** 3. To install the help file, do the following: ! $ lib/help sys$library:helplib.hlb gcc.hlp Now you can invoke the compiler with a command like `gcc /verbose --- 876,880 ---- 3. To install the help file, do the following: ! $ library/help sys$library:helplib.hlb gcc.hlp Now you can invoke the compiler with a command like `gcc /verbose *************** *** 817,821 **** We try to put corresponding binaries and sources on the VMS distribution tape. But sometimes the binaries will be from an older ! version that the sources, because we don't always have time to update them. (Use the `/version' option to determine the version number of the binaries and compare it with the source file `version.c' to tell --- 905,909 ---- We try to put corresponding binaries and sources on the VMS distribution tape. But sometimes the binaries will be from an older ! version than the sources, because we don't always have time to update them. (Use the `/version' option to determine the version number of the binaries and compare it with the source file `version.c' to tell *************** *** 823,832 **** to recompile the sources. If you must recompile, here is how: ! 1. Copy the file `vms.h' to `tm.h', `xm-vms.h' to `config.h', ! `vax.md' to `md.' and `vax.c' to `aux-output.c'. The files to be ! copied are found in the subdirectory named `config'; they should ! be copied to the main directory of GNU CC. If you wish, you may ! use the command file `config-gcc.com' to perform these steps for ! you. 2. Setup the logical names and command tables as defined above. In --- 911,922 ---- to recompile the sources. If you must recompile, here is how: ! 1. Execute the command procedure `vmsconfig.com' to copy files ! `vax-vms.h', `xm-vax-vms.h', `vax.c' and `vax.md' to `tm.h', ! `config.h', `aux-output.c', and `md.' respectively, and to create ! files `tconfig.h' and `hconfig.h'. This procedure also creates ! several linker option files used by `make-cc1.com' and a data file ! used by `make-l2.com'. ! ! $ @vmsconfig.com 2. Setup the logical names and command tables as defined above. In *************** *** 865,871 **** To install the library, use the following commands: ! $ lib gnu_cc:[000000]gcclib/delete=(new,eprintf) ! $ lib libgcc2/extract=*/output=libgcc2.obj ! $ lib gnu_cc:[000000]gcclib libgcc2.obj The first command simply removes old modules that will be replaced --- 955,961 ---- To install the library, use the following commands: ! $ library gnu_cc:[000000]gcclib/delete=(new,eprintf) ! $ library libgcc2/extract=*/output=libgcc2.obj ! $ library gnu_cc:[000000]gcclib libgcc2.obj The first command simply removes old modules that will be replaced *************** *** 877,881 **** update the library with the above procedure. ! You may wish to build GCC in such a way that no files are written to the directory where the source files reside. An example would be the when the source files are on a read-only disk. In these --- 967,971 ---- update the library with the above procedure. ! 6. You may wish to build GCC in such a way that no files are written to the directory where the source files reside. An example would be the when the source files are on a read-only disk. In these *************** *** 883,892 **** actual path names): ! $ assign dua0:[gcc.build_dir.]tran=conc, - ! dua1:[gcc.source_dir.]/tran=conc gcc_build $ set default gcc_build:[000000] ! where `dua1:[gcc.source_dir.]' contains the source code, and ! `dua0:[gcc.build_dir.]' is meant to contain all of the generated object files and executables. Once you have done this, you can proceed building GCC as described above. (Keep in mind that --- 973,982 ---- actual path names): ! $ assign dua0:[gcc.build_dir.]/translation=concealed, - ! dua1:[gcc.source_dir.]/translation=concealed gcc_build $ set default gcc_build:[000000] ! where `dua1:[gcc.source_dir]' contains the source code, and ! `dua0:[gcc.build_dir]' is meant to contain all of the generated object files and executables. Once you have done this, you can proceed building GCC as described above. (Keep in mind that *************** *** 895,899 **** name rather than another rooted logical name). ! *If you are building GNU CC with a previous version of GNU CC, you also should check to see that you have the newest version of the assembler*. In particular, GNU CC version 2 treats global constant --- 985,989 ---- name rather than another rooted logical name). ! 7. *If you are building GNU CC with a previous version of GNU CC, you also should check to see that you have the newest version of the assembler*. In particular, GNU CC version 2 treats global constant *************** *** 913,940 **** change this file back. Under previous versions of GNU CC, the generated code would ! occasionally give strange results when linked to the sharable `VAXCRTL' ! library. Now this should work. Even with this version, however, GNU CC itself should not be linked ! to the sharable `VAXCRTL'. The `qsort' routine supplied with `VAXCRTL' ! has a bug which can cause a compiler crash. ! ! Similarly, the preprocessor should not be linked to the sharable ! `VAXCRTL'. The `strncat' routine supplied with `VAXCRTL' has a bug ! which can cause the preprocessor to go into an infinite loop. ! ! If you attempt to link to the sharable `VAXCRTL', the VMS linker ! will strongly resist any effort to force it to use the `qsort' and ! `strncat' routines from `gcclib'. Until the bugs in `VAXCRTL' have ! been fixed, linking any of the compiler components to the sharable ! VAXCRTL is not recommended. (These routines can be bypassed by placing ! duplicate copies of `qsort' and `strncat' in `gcclib' under different ! names, and patching the compiler sources to use these routines). Both ! of the bugs in `VAXCRTL' are still present in VMS version 5.4-1, which ! is the most recent version as of this writing. The executables that are generated by `make-cc1.com' and ! `make-cccp.com' use the nonshared version of `VAXCRTL' (and thus use ! the `qsort' and `strncat' routines from `gcclib.olb'). --- 1003,1130 ---- change this file back. + 8. If you want to build GNU CC with the VAX C compiler, you will need + to make minor changes in `make-cccp.com' and `make-cc1.com' to + choose alternate definitions of `CC', `CFLAGS', and `LIBS'. See + comments in those files. However, you must also have a working + version of the GNU assembler (GNU as, aka GAS) as it is used as + the back-end for GNU CC to produce binary object modules and is + not included in the GNU CC sources. GAS is also needed to compile + `libgcc2' in order to build `gcclib' (see above); `make-l2.com' + expects to be able to find it operational in + `gnu_cc:[000000]gnu-as.exe'. + + To use GNU CC on VMS, you need the VMS driver programs `gcc.exe', + `gcc.com', and `gcc.cld'. They are distributed with the VMS + binaries (`gcc-vms') rather than the GNU CC sources. GAS is also + included in `gcc-vms', as is Bison. + + Once you have successfully built GNU CC with VAX C, you should use + the resulting compiler to rebuild itself. Before doing this, be + sure to restore the `CC', `CFLAGS', and `LIBS' definitions in + `make-cccp.com' and `make-cc1.com'. The second generation + compiler will be able to take advantage of many optimizations that + must be suppressed when building with other compilers. + Under previous versions of GNU CC, the generated code would ! occasionally give strange results when linked with the sharable ! `VAXCRTL' library. Now this should work. Even with this version, however, GNU CC itself should not be linked ! with the sharable `VAXCRTL'. The version of `qsort' in `VAXCRTL' has a ! bug (known to be present in VMS versions V4.6 through V5.5) which ! causes the compiler to fail. The executables that are generated by `make-cc1.com' and ! `make-cccp.com' use the object library version of `VAXCRTL' in order to ! make use of the `qsort' routine in `gcclib.olb'. If you wish to link ! the compiler executables with the shareable image version of `VAXCRTL', ! you should edit the file `tm.h' (created by `vmsconfig.com') to define ! the macro `QSORT_WORKAROUND'. ! ! `QSORT_WORKAROUND' is always defined when GNU CC is compiled with ! VAX C, to avoid a problem in case `gcclib.olb' is not yet available. ! ! ! Installing GNU CC on the WE32K ! =============================== ! ! These computers are also known as the 3b2, 3b5, 3b20 and other ! similar names. (However, the 3b1 is actually a 68000; see *Note 3b1 ! Install::.) ! ! Don't use `-g' when compiling with the system's compiler. The ! system's linker seems to be unable to handle such a large program with ! debugging information. ! ! The system's compiler runs out of capacity when compiling `stmt.c' ! in GNU CC. You can work around this by building `cpp' in GNU CC first, ! then use that instead of the system's preprocessor with the system's C ! compiler to compile `stmt.c'. Here is how: ! ! mv /lib/cpp /lib/cpp.att ! cp cpp /lib/cpp.gnu ! echo "/lib/cpp.gnu -traditional $*" > /lib/cpp ! chmod +x /lib/cpp ! ! The system's compiler produces bad code for some of the GNU CC ! optimization files. So you must build the stage 2 compiler without ! optimization. Then build a stage 3 compiler with optimization. That ! executable should work. Here are the necessary commands: ! ! make LANGUAGES=c CC=stage1/xgcc CFLAGS="-Bstage1/ -g" ! make stage2 ! make CC=stage2/xgcc CFLAGS="-Bstage2/ -g -O" ! ! You may need to raise the ULIMIT setting to build a C++ compiler, as ! the file `cc1plus' is larger than one megabyte. ! ! ! Installing GNU CC on the MIPS ! ============================== ! ! See *Note Installation:: about whether to use `--with-stabs' or not. ! ! The MIPS C compiler needs to be told to increase its table size for ! switch statements with the `-Wf,-XNg1500' option in order to compile ! `cp-parse.c'. If you use the `-O2' optimization option, you also need ! to use `-Olimit 3000'. Both of these options are automatically ! generated in the `Makefile' that the shell script `configure' builds. ! If you override the `CC' make variable and use the MIPS compilers, you ! may need to add `-Wf,-XNg1500 -Olimit 3000'. ! ! MIPS computers running RISC-OS can support four different ! personalities: default, BSD 4.3, System V.3, and System V.4 (older ! versions of RISC-OS don't support V.4). To configure GCC for these ! platforms use the following configurations: ! ! `mips-mips-riscos`rev'' ! Default configuration for RISC-OS, revision `rev'. ! ! `mips-mips-riscos`rev'bsd' ! BSD 4.3 configuration for RISC-OS, revision `rev'. ! ! `mips-mips-riscos`rev'sysv4' ! System V.4 configuration for RISC-OS, revision `rev'. ! ! `mips-mips-riscos`rev'sysv' ! System V.3 configuration for RISC-OS, revision `rev'. ! ! The revision `rev' mentioned above is the revision of RISC-OS to ! use. You must reconfigure GCC when going from a RISC-OS revision 4 to ! RISC-OS revision 5. This has the effect of avoiding a linker bug. ! ! DECstations can support three different personalities: Ultrix, DEC ! OSF/1, and OSF/rose. To configure GCC for these platforms use the ! following configurations: ! ! `decstation-ultrix' ! Ultrix configuration. ! ! `decstation-osf1' ! Dec's version of OSF/1. ! ! `decstation-osfrose' ! Open Software Foundation reference port of OSF/1 which uses the ! OSF/rose object file format instead of ECOFF. Normally, you would ! not select this configuration. diff -rc2N gcc-2.2.2/Makefile.in gcc-2.3.1/Makefile.in *** gcc-2.2.2/Makefile.in Sun Jun 14 17:40:34 1992 --- gcc-2.3.1/Makefile.in Sat Oct 31 20:05:30 1992 *************** *** 33,38 **** ALLOCA = ! ALLOCA_FLAGS = -S -Demacs ! ALLOCA_FINISH = as -o alloca.o alloca.s # Various ways of specifying flags for compilations: --- 33,38 ---- ALLOCA = ! ALLOCA_FLAGS = ! ALLOCA_FINISH = true # Various ways of specifying flags for compilations: *************** *** 88,102 **** OLDAR = ar ! # The GCC to use for compiling libgcc2.a. Usually the one we just built. # Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS). ! GCC_FOR_TARGET = ./gcc # This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET. # It omits XCFLAGS, and specifies -B./. ! GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) -B./ # Special flags for compiling enquire. # We disable optimization to make floating point more reliable. ! ENQUIRE_CFLAGS = -DNO_SC -DNO_MEM -DNO_STDDEF -O0 ENQUIRE_LDFLAGS = $(LDFLAGS) --- 88,104 ---- OLDAR = ar ! # The GCC to use for compiling libgcc2.a, enquire, and cross-test. ! # Usually the one we just built. # Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS). ! GCC_FOR_TARGET = ./xgcc -B./ # This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET. # It omits XCFLAGS, and specifies -B./. ! # It also specifies -B$(tooldir)/ to find as and ld for a cross compiler. ! GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(CROSS_GCC_CFLAGS) # Special flags for compiling enquire. # We disable optimization to make floating point more reliable. ! ENQUIRE_CFLAGS = -DNO_MEM -DNO_STDDEF -DNO_LONG_DOUBLE_IO -O0 ENQUIRE_LDFLAGS = $(LDFLAGS) *************** *** 112,115 **** --- 114,120 ---- CROSS_TOOLS = + # Dir to search for system headers. Overridden by cross-make. + SYSTEM_HEADER_DIR = /usr/include + # There may be a premade insn-attrtab.c for this machine. # (You could rebuild it with genattrtab as usual, but it takes a long time.) *************** *** 122,126 **** xmake_file= ... `configure' substitutes actual x- file name here. tmake_file= ... `configure' substitutes actual t- file name here. ! version=`awk '{printf "%s", substr ($$4, 2, length ($$4) - 3); }' $(srcdir)/version.c` # Directory where sources are, from where we are. --- 127,131 ---- xmake_file= ... `configure' substitutes actual x- file name here. tmake_file= ... `configure' substitutes actual t- file name here. ! version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c` # Directory where sources are, from where we are. *************** *** 137,140 **** --- 142,149 ---- # Directory in which the compiler finds executables, libraries, etc. libsubdir = $(libdir)/gcc-lib/$(target)/$(version) + # Directory for header file assert.h. + includedir = $(prefix)/include + # assertdir is overridden in cross-make. + assertdir = $(includedir) # Extension (if any) to put in installed man-page filename. manext = .1 *************** *** 144,147 **** --- 153,158 ---- # Used in install-cross. tooldir = $(prefix)/$(target) + # Dir for temp files. + tmpdir = /tmp # Additional system libraries to link with. *************** *** 210,228 **** FIXINCLUDES=fixincludes ! # List of things which should already be built whenever we try to use gcc # to compile anything (without linking). ! GCC_PASSES=gcc cc1 cpp $(EXTRA_PASSES) ! # List of things which should already be built whenever we try to use gcc # to link anything. GCC_PARTS=$(GCC_PASSES) libgcc.a $(EXTRA_PROGRAMS) $(USE_COLLECT2) $(EXTRA_PARTS) - # Change this to empty to prevent installing limits.h. - # Actually, this currently has no effect, - # and if that causes no problems, it can be deleted. - # Otherwise, it must be replaced so as to control - # the actions of install-limits-h. - LIMITS_H = limits.h - # Directory to link to, when using the target `maketest'. DIR = ../gcc --- 221,236 ---- FIXINCLUDES=fixincludes ! # Additional directories of header files to run fixincludes on. ! # On most systems, this is empty. ! OTHER_FIXINCLUDES_DIRS= ! ! # List of things which should already be built whenever we try to use xgcc # to compile anything (without linking). ! GCC_PASSES=xgcc cc1 cpp $(EXTRA_PASSES) ! # List of things which should already be built whenever we try to use xgcc # to link anything. GCC_PARTS=$(GCC_PASSES) libgcc.a $(EXTRA_PROGRAMS) $(USE_COLLECT2) $(EXTRA_PARTS) # Directory to link to, when using the target `maketest'. DIR = ../gcc *************** *** 264,268 **** # sed inserts variable overrides after the following line. ! #### # Now figure out from those variables how to compile and link. --- 272,279 ---- # sed inserts variable overrides after the following line. ! ####target overrides ! ####host overrides ! ####cross overrides ! ####build overrides # Now figure out from those variables how to compile and link. *************** *** 270,274 **** all.indirect: $(ALL) ! INTERNAL_CFLAGS = $(CROSS) # This is the variable actually used when we compile. --- 281,286 ---- all.indirect: $(ALL) ! # IN_GCC tells obstack.h to use gstddef.h. ! INTERNAL_CFLAGS = $(CROSS) -DIN_GCC # This is the variable actually used when we compile. *************** *** 328,337 **** # Language-specific object files for C. ! C_OBJS = c-parse.o c-lang.o \ ! c-lex.o c-decl.o c-typeck.o c-convert.o c-aux-info.o c-common.o # Language-specific object files for Objectionable C. OBJC_OBJS = objc-parse.o objc-actions.o \ ! c-lex.o c-decl.o c-typeck.o c-convert.o c-aux-info.o c-common.o # Language-specific object files for C++. --- 340,349 ---- # Language-specific object files for C. ! C_OBJS = c-parse.o c-lang.o c-lex.o \ ! c-decl.o c-typeck.o c-convert.o c-aux-info.o c-common.o c-pragma.o # Language-specific object files for Objectionable C. OBJC_OBJS = objc-parse.o objc-actions.o \ ! c-lex.o c-decl.o c-typeck.o c-convert.o c-aux-info.o c-common.o c-pragma.o # Language-specific object files for C++. *************** *** 349,353 **** dbxout.o sdbout.o dwarfout.o xcoffout.o \ integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o \ ! regclass.o local-alloc.o global-alloc.o reload.o reload1.o caller-save.o \ insn-peep.o reorg.o sched.o final.o recog.o reg-stack.o \ insn-recog.o insn-extract.o insn-output.o insn-emit.o \ --- 361,365 ---- dbxout.o sdbout.o dwarfout.o xcoffout.o \ integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o \ ! regclass.o local-alloc.o global.o reload.o reload1.o caller-save.o \ insn-peep.o reorg.o sched.o final.o recog.o reg-stack.o \ insn-recog.o insn-extract.o insn-output.o insn-emit.o \ *************** *** 383,395 **** LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \ _lshrdi3 _lshldi3 _ashldi3 _ashrdi3 \ ! _udivmoddi4 _cmpdi2 _ucmpdi2 _floatdidf _floatdisf \ _fixunsdfsi _fixunssfsi _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi \ ! _varargs _eprintf _builtin_new _builtin_New _builtin_del \ ! _bb _shtab _clear_cache _trampoline __main _exit # Header files that are made available under the same name ! # to programs compiled with gcc. ! USER_H = assert.h va-hp800.h va-i860.h va-mips.h va-pyr.h va-sparc.h \ ! va-spur.h va-m88k.h va-i960.h proto.h $(EXTRA_HEADERS) # All the header files that are installed for users from GCC itself. --- 395,407 ---- LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 \ _lshrdi3 _lshldi3 _ashldi3 _ashrdi3 \ ! _udiv_w_sdiv _udivmoddi4 _cmpdi2 _ucmpdi2 _floatdidf _floatdisf \ _fixunsdfsi _fixunssfsi _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi \ ! __gcc_bcmp _varargs _eprintf _builtin_new _caps_New _builtin_del \ ! _bb _shtab _clear_cache _trampoline __main _exit _ctors # Header files that are made available under the same name ! # to programs compiled with GCC. ! USER_H = va-alpha.h va-i860.h va-i960.h va-mips.h va-m88k.h \ ! va-pa.h va-pyr.h va-sparc.h va-spur.h proto.h syslimits.h $(EXTRA_HEADERS) # All the header files that are installed for users from GCC itself. *************** *** 417,423 **** all.internal: start.encap rest.encap # This is what to compile if making a cross-compiler. ! all.cross: native gcc-cross cross-test $(EXTRA_PARTS) # This is what must be made before installing GCC and converting libraries. ! start.encap: native gcc specs $(LIBGCC1_TARGET) # Use this to make a GCC that will be used only to recompile GCC. for-bootstrap: start.encap libgcc.a --- 429,437 ---- all.internal: start.encap rest.encap # This is what to compile if making a cross-compiler. ! all.cross: native gcc-cross libgcc.a cross-test $(EXTRA_PARTS) ! # This is what to compile if making gcc with a cross-compiler. ! all.build: native xgcc $(EXTRA_PARTS) # This is what must be made before installing GCC and converting libraries. ! start.encap: native xgcc specs $(LIBGCC1) xlimits.h # Use this to make a GCC that will be used only to recompile GCC. for-bootstrap: start.encap libgcc.a *************** *** 431,436 **** C c: cc1 C++ c++: cc1plus ! OBJC objc: cc1obj ! OBJECTIVE-C objective-c: cc1obj PROTO: proto --- 445,450 ---- C c: cc1 C++ c++: cc1plus ! OBJC objc: cc1obj objc-runtime ! OBJECTIVE-C objective-c: cc1obj objc-runtime PROTO: proto *************** *** 452,456 **** # Verify that it works to compile and link cross-test. # If it does, then there are sufficient replacements for libgcc1.a. ! cross-test: cross-test.o native gcc-cross $(GCC_FOR_TARGET) $(GCC_CFLAGS) cross-test.o -o $@ cross-test.o: cross-test.c native gcc-cross --- 466,470 ---- # Verify that it works to compile and link cross-test. # If it does, then there are sufficient replacements for libgcc1.a. ! cross-test: cross-test.o native gcc-cross libgcc.a $(GCC_FOR_TARGET) $(GCC_CFLAGS) cross-test.o -o $@ cross-test.o: cross-test.c native gcc-cross *************** *** 461,478 **** compilations: ${OBJS} ! gcc: gcc.o version.o $(LIBDEPS) ! $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o gccnew gcc.o version.o $(LIBS) ! # Go via `gccnew' to avoid `file busy' if $(CC) is `gcc'. ! mv -f gccnew gcc # Dump a specs file to make -B./ read these specs over installed ones. ! specs: gcc ! ./gcc -dumpspecs > specs ! # We do want to create an executable named `gcc', so we can use it to # compile libgcc2.a. # Also create gcc-cross, so that install-common will install properly. ! gcc-cross: gcc ! cp gcc gcc-cross cc1:$(P) $(C_OBJS) $(OBJS) $(LIBDEPS) --- 475,493 ---- compilations: ${OBJS} ! # We call this executable `xgcc' rather than `gcc' ! # to avoid confusion if the current directory is in the path ! # and CC is `gcc'. It is renamed to `gcc' when it is installed. ! xgcc: gcc.o version.o $(LIBDEPS) ! $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o xgcc gcc.o version.o $(LIBS) # Dump a specs file to make -B./ read these specs over installed ones. ! specs: xgcc ! ./xgcc -dumpspecs > specs ! # We do want to create an executable named `xgcc', so we can use it to # compile libgcc2.a. # Also create gcc-cross, so that install-common will install properly. ! gcc-cross: xgcc ! cp xgcc gcc-cross cc1:$(P) $(C_OBJS) $(OBJS) $(LIBDEPS) *************** *** 494,507 **** $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@ enquire.o: $(srcdir)/enquire.c $(GCC_PASSES) ! -if [ "$(srcdir)" != "." ]; then rm -f ./enquire.c; else true; fi ! -cp $(srcdir)/enquire.c . > /dev/null 2>&1 # Breaking this line caused a problem with one version of GNU make. ! $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(ENQUIRE_CFLAGS) -I. -c enquire.c # Build libgcc.a. # This is done in two parts because some functions, in libgcc1.c, ! # must be compiled with something other than gcc, ! # while the rest, in libgcc2.c, must be compiled with gcc. ! # That means we can't do libgcc2.c until after gcc, cc1, etc. # Use this as value of LIBGCC1 to cause conversion to GNU library format. --- 509,530 ---- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@ enquire.o: $(srcdir)/enquire.c $(GCC_PASSES) ! # -if [ "$(srcdir)" != "." ]; then rm -f ./enquire.c; else true; fi ! # -cp $(srcdir)/enquire.c . > /dev/null 2>&1 # Breaking this line caused a problem with one version of GNU make. ! $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(ENQUIRE_CFLAGS) -I. -c $(srcdir)/enquire.c ! ! # Build the version of limits.h that we will install. ! xlimits.h: glimits.h limitx.h limity.h ! if [ -f $(SYSTEM_HEADER_DIR)/limits.h ] ; then \ ! cat $(srcdir)/limitx.h $(srcdir)/glimits.h $(srcdir)/limity.h > xlimits.h; \ ! else \ ! cat $(srcdir)/glimits.h > xlimits.h; \ ! fi # Build libgcc.a. # This is done in two parts because some functions, in libgcc1.c, ! # must be compiled with something other than GCC, ! # while the rest, in libgcc2.c, must be compiled with xgcc. ! # That means we can't do libgcc2.c until after xgcc, cc1, etc. # Use this as value of LIBGCC1 to cause conversion to GNU library format. *************** *** 518,523 **** rm -f dummy.o dummy.c # Compile the library of arithmetic subroutines with the native compiler. ! # Don't compile it with gcc! # (That would cause most arithmetic functions to call themselves.) libgcc1.a: libgcc1.c $(CONFIG_H) $(LIB1FUNCS_EXTRA) config.status --- 541,554 ---- rm -f dummy.o dummy.c + # This is $(LIBGCC1) for a cross-compiler. + # We have no automatic way of building libgcc1.a, + # so it's up to the installer to find a way to do that. + # This rule deliberately does not depend on libgcc1.a + # so that it will fail if the installer hasn't provided it. + libgcc1.cross: + mv libgcc1.a libgcc1.cross || (echo You must find a way to make libgcc1.a; false) + # Compile the library of arithmetic subroutines with the native compiler. ! # Don't compile it with GCC! # (That would cause most arithmetic functions to call themselves.) libgcc1.a: libgcc1.c $(CONFIG_H) $(LIB1FUNCS_EXTRA) config.status *************** *** 550,555 **** echo $${name}; \ if [ $${name}.asm = $${file} ]; then \ ! cp $${file} $${name}.s; file=$${name}.s; \ ! if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ else true; fi; \ $(OLDCC) $(CCLIBFLAGS) $(INCLUDES) -c $${file}; \ --- 581,585 ---- echo $${name}; \ if [ $${name}.asm = $${file} ]; then \ ! cp $${file} $${name}.s || exit 1; file=$${name}.s; \ else true; fi; \ $(OLDCC) $(CCLIBFLAGS) $(INCLUDES) -c $${file}; \ *************** *** 577,581 **** libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(LIB2FUNCS_EXTRA) \ ! longlong.h gbl-ctors.h config.status # Actually build it in tmplibgcc2.a, then rename at end, # so that libgcc2.a itself remains nonexistent if compilation is aborted. --- 607,611 ---- libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(LIB2FUNCS_EXTRA) \ ! machmode.h longlong.h gbl-ctors.h config.status # Actually build it in tmplibgcc2.a, then rename at end, # so that libgcc2.a itself remains nonexistent if compilation is aborted. *************** *** 605,610 **** echo $${name}; \ if [ $${name}.asm = $${file} ]; then \ ! cp $${file} $${name}.s; file=$${name}.s; \ ! if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ else true; fi; \ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \ --- 635,639 ---- echo $${name}; \ if [ $${name}.asm = $${file} ]; then \ ! cp $${file} $${name}.s || exit 1; file=$${name}.s; \ else true; fi; \ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \ *************** *** 638,641 **** --- 667,695 ---- mv tmplibgcc.a libgcc.a + objc-runtime: libobjc.a + + # Build the Objective C runtime library. + libobjc.a: cc1obj libgcc2.ready + if [ -d objc ]; then true; else mkdir objc; fi + thisdir1=`pwd`; \ + srcdir1=`cd $(srcdir); pwd`; \ + cd objc; \ + $(MAKE) -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)" + -rm -f libobjc.a + ln objc/libobjc.a . >/dev/null 2>&1 || cp objc/libobjc.a . + -if $(RANLIB_TEST) ; then $(RANLIB) libobjc.a; else true; fi + + # This is used by objc/Makefile if the user runs that directly. + sublibobjc.a: cc1obj libgcc2.ready + thisdir1=`pwd`; \ + srcdir1=`cd $(srcdir); pwd`; \ + cd objc; \ + $(MAKE) -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)" # Compile two additional files that are linked with every program *************** *** 664,667 **** --- 718,723 ---- $(srcdir)/c-parse.c $(srcdir)/c-parse.h: $(srcdir)/c-parse.y cd $(srcdir); $(BISON) $(BISONFLAGS) -d c-parse.y -o c-parse.c + $(srcdir)/c-parse.y: $(srcdir)/c-parse.in $(srcdir)/cond.awk + cd $(srcdir); awk -f cond.awk objc=0 c-parse.in > c-parse.y c-decl.o : c-decl.c $(CONFIG_H) $(TREE_H) c-tree.h c-lex.h flags.h *************** *** 672,675 **** --- 728,732 ---- c-aux-info.o : c-aux-info.c $(CONFIG_H) $(TREE_H) c-tree.h flags.h c-convert.o : c-convert.c $(CONFIG_H) $(TREE_H) flags.h + c-pragma.o: c-pragma.c $(CONFIG_H) $(TREE_H) # C++ language specific files. *************** *** 682,685 **** --- 739,743 ---- @echo expect 30 shift/reduce conflicts and 14 reduce/reduce conflicts cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o cp-parse.c cp-parse.y + cd $(srcdir); grep '^#define[ ]*YYEMPTY' cp-parse.c >>cp-parse.h cp-spew.o : cp-spew.c $(CONFIG_H) $(CPLUS_TREE_H) \ *************** *** 717,720 **** --- 775,780 ---- collect2 : collect2.o version.o $(LIBDEPS) + # Don't try modifying collect2 (aka ld) in place--it might be linking this. + -rm -f collect2 $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o collect2 collect2.o version.o $(LIBS) *************** *** 734,737 **** --- 794,799 ---- $(srcdir)/objc-parse.c : $(srcdir)/objc-parse.y cd $(srcdir); $(BISON) $(BISONFLAGS) objc-parse.y -o objc-parse.c + $(srcdir)/objc-parse.y: $(srcdir)/c-parse.in $(srcdir)/cond.awk + cd $(srcdir); awk -f cond.awk objc=1 c-parse.in > objc-parse.y objc-actions.o : objc-actions.c $(CONFIG_H) $(TREE_H) c-tree.h c-lex.h \ *************** *** 749,752 **** --- 811,815 ---- -DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc-lib/\" \ -DDEFAULT_TARGET_MACHINE=\"$(target)\" \ + -DTOOLDIR=\"$(tooldir)/\" \ -c `echo $(srcdir)/gcc.c | sed 's,^\./,,'` *************** *** 763,767 **** insn-attr.h xcoffout.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ ! $(MAYBE_USE_COLLECT2) -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'` rtl.o : rtl.c $(CONFIG_H) $(RTL_H) --- 826,831 ---- insn-attr.h xcoffout.h $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ ! $(MAYBE_TARGET_DEFAULT) $(MAYBE_USE_COLLECT2) \ ! -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'` rtl.o : rtl.c $(CONFIG_H) $(RTL_H) *************** *** 770,775 **** rtlanal.o : rtlanal.c $(CONFIG_H) $(RTL_H) ! varasm.o : varasm.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h defaults.h \ ! insn-codes.h expr.h hard-reg-set.h regs.h xcoffout.h function.o : function.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h function.h \ insn-flags.h insn-codes.h expr.h regs.h hard-reg-set.h insn-config.h \ --- 834,839 ---- rtlanal.o : rtlanal.c $(CONFIG_H) $(RTL_H) ! varasm.o : varasm.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h function.h \ ! defaults.h insn-codes.h expr.h hard-reg-set.h regs.h xcoffout.h function.o : function.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h function.h \ insn-flags.h insn-codes.h expr.h regs.h hard-reg-set.h insn-config.h \ *************** *** 788,796 **** insn-flags.h insn-config.h insn-codes.h expr.h recog.h dbxout.o : dbxout.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h regs.h \ ! insn-config.h reload.h gstab.h xcoffout.h sdbout.o : sdbout.c $(CONFIG_H) $(TREE_H) $(RTL_H) gsyms.h flags.h \ insn-config.h reload.h dwarfout.o : dwarfout.c $(CONFIG_H) $(TREE_H) $(RTL_H) dwarf.h flags.h \ ! insn-config.h reload.h output.h xcoffout.o : xcoffout.c $(CONFIG_H) $(TREE_H) $(RTL_H) xcoffout.h flags.h emit-rtl.o : emit-rtl.c $(CONFIG_H) $(RTL_H) flags.h gvarargs.h function.h \ --- 852,860 ---- insn-flags.h insn-config.h insn-codes.h expr.h recog.h dbxout.o : dbxout.c $(CONFIG_H) $(TREE_H) $(RTL_H) flags.h regs.h \ ! insn-config.h reload.h gstab.h xcoffout.h defaults.h output.h sdbout.o : sdbout.c $(CONFIG_H) $(TREE_H) $(RTL_H) gsyms.h flags.h \ insn-config.h reload.h dwarfout.o : dwarfout.c $(CONFIG_H) $(TREE_H) $(RTL_H) dwarf.h flags.h \ ! insn-config.h reload.h output.h defaults.h xcoffout.o : xcoffout.c $(CONFIG_H) $(TREE_H) $(RTL_H) xcoffout.h flags.h emit-rtl.o : emit-rtl.c $(CONFIG_H) $(RTL_H) flags.h gvarargs.h function.h \ *************** *** 817,824 **** basic-block.h recog.h real.h regclass.o : regclass.c $(CONFIG_H) $(RTL_H) hard-reg-set.h flags.h \ ! basic-block.h regs.h insn-config.h recog.h local-alloc.o : local-alloc.c $(CONFIG_H) $(RTL_H) flags.h basic-block.h \ regs.h hard-reg-set.h insn-config.h recog.h output.h ! global-alloc.o : global-alloc.c $(CONFIG_H) $(RTL_H) flags.h \ basic-block.h regs.h hard-reg-set.h insn-config.h output.h --- 881,888 ---- basic-block.h recog.h real.h regclass.o : regclass.c $(CONFIG_H) $(RTL_H) hard-reg-set.h flags.h \ ! basic-block.h regs.h insn-config.h recog.h reload.h real.h local-alloc.o : local-alloc.c $(CONFIG_H) $(RTL_H) flags.h basic-block.h \ regs.h hard-reg-set.h insn-config.h recog.h output.h ! global.o : global.c $(CONFIG_H) $(RTL_H) flags.h \ basic-block.h regs.h hard-reg-set.h insn-config.h output.h *************** *** 837,841 **** final.o : final.c $(CONFIG_H) $(RTL_H) gvarargs.h flags.h regs.h \ recog.h conditions.h insn-config.h insn-attr.h real.h output.h \ ! hard-reg-set.h insn-codes.h gstab.h xcoffout.h recog.o : recog.c $(CONFIG_H) $(RTL_H) \ regs.h recog.h hard-reg-set.h flags.h insn-config.h insn-attr.h \ --- 901,905 ---- final.o : final.c $(CONFIG_H) $(RTL_H) gvarargs.h flags.h regs.h \ recog.h conditions.h insn-config.h insn-attr.h real.h output.h \ ! hard-reg-set.h insn-flags.h insn-codes.h gstab.h xcoffout.h defaults.h recog.o : recog.c $(CONFIG_H) $(RTL_H) \ regs.h recog.h hard-reg-set.h flags.h insn-config.h insn-attr.h \ *************** *** 851,861 **** # define ALLOCA=alloca.o. In that case, you must get a suitable alloca.c # from the GNU Emacs distribution. - # Note some machines won't allow $(CC) without -S on this source file. alloca.o: alloca.c - # sed is used to strip the comments from the assembler output. $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(ALLOCA_FLAGS) \ ! `echo $(srcdir)/alloca.c | sed 's,^\./,,'` $(ALLOCA_FINISH) - -rm alloca.s # Generate header and source files from the machine description, --- 915,922 ---- # define ALLOCA=alloca.o. In that case, you must get a suitable alloca.c # from the GNU Emacs distribution. alloca.o: alloca.c $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(ALLOCA_FLAGS) \ ! -Demacs -c `echo $(srcdir)/alloca.c | sed 's,^\./,,'` $(ALLOCA_FINISH) # Generate header and source files from the machine description, *************** *** 872,875 **** --- 933,943 ---- # Each of the other insn-* files is handled by a similar pair of rules. + # This causes an anomaly in the results of make -n + # because insn-* is older than stamp-* + # and thus make -n thinks that insn-* will be updated + # and force recompilation of things that depend on it. + # We use move-if-changed precisely to avoid such recompilation. + # But there is no way to teach make -n that it will be avoided. + # Each of the insn-*.[ch] rules has a semicolon at the end, # for otherwise the system Make on SunOS 4.1 never tries *************** *** 979,983 **** genconfig.o $(HOST_RTL) $(HOST_LIBS) ! genconfig.o : genconfig.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c --- 1047,1051 ---- genconfig.o $(HOST_RTL) $(HOST_LIBS) ! genconfig.o : genconfig.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c *************** *** 986,990 **** genflags.o $(HOST_RTL) $(HOST_LIBS) ! genflags.o : genflags.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c --- 1054,1058 ---- genflags.o $(HOST_RTL) $(HOST_LIBS) ! genflags.o : genflags.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c *************** *** 993,997 **** gencodes.o $(HOST_RTL) $(HOST_LIBS) ! gencodes.o : gencodes.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c --- 1061,1065 ---- gencodes.o $(HOST_RTL) $(HOST_LIBS) ! gencodes.o : gencodes.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c *************** *** 1000,1004 **** genemit.o $(HOST_RTL) $(HOST_LIBS) ! genemit.o : genemit.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c --- 1068,1072 ---- genemit.o $(HOST_RTL) $(HOST_LIBS) ! genemit.o : genemit.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c *************** *** 1007,1011 **** genrecog.o $(HOST_RTL) $(HOST_LIBS) ! genrecog.o : genrecog.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c --- 1075,1079 ---- genrecog.o $(HOST_RTL) $(HOST_LIBS) ! genrecog.o : genrecog.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c *************** *** 1014,1018 **** genextract.o $(HOST_RTL) $(HOST_LIBS) ! genextract.o : genextract.c $(RTL_H) config.h insn-config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c --- 1082,1086 ---- genextract.o $(HOST_RTL) $(HOST_LIBS) ! genextract.o : genextract.c $(RTL_H) hconfig.h insn-config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c *************** *** 1021,1025 **** genpeep.o $(HOST_RTL) $(HOST_LIBS) ! genpeep.o : genpeep.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c --- 1089,1093 ---- genpeep.o $(HOST_RTL) $(HOST_LIBS) ! genpeep.o : genpeep.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c *************** *** 1028,1032 **** genattr.o $(HOST_RTL) $(HOST_LIBS) ! genattr.o : genattr.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c --- 1096,1100 ---- genattr.o $(HOST_RTL) $(HOST_LIBS) ! genattr.o : genattr.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c *************** *** 1035,1039 **** genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_RTLANAL) $(HOST_LIBS) ! genattrtab.o : genattrtab.c $(RTL_H) config.h insn-config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c --- 1103,1107 ---- genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_RTLANAL) $(HOST_LIBS) ! genattrtab.o : genattrtab.c $(RTL_H) hconfig.h insn-config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c *************** *** 1042,1046 **** genoutput.o $(HOST_RTL) $(HOST_LIBS) ! genoutput.o : genoutput.c $(RTL_H) config.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genoutput.c --- 1110,1114 ---- genoutput.o $(HOST_RTL) $(HOST_LIBS) ! genoutput.o : genoutput.c $(RTL_H) hconfig.h $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genoutput.c *************** *** 1051,1065 **** $(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)rtl.c ! cp $(srcdir)/rtl.c $(HOST_PREFIX)rtl.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtl.c $(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)print-rtl.c ! cp $(srcdir)/print-rtl.c $(HOST_PREFIX)print-rtl.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)print-rtl.c $(HOST_PREFIX_1)rtlanal.o: $(srcdir)/rtlanal.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)rtlanal.c ! cp $(srcdir)/rtlanal.c $(HOST_PREFIX)rtlanal.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtlanal.c --- 1119,1133 ---- $(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)rtl.c ! sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(HOST_PREFIX)rtl.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtl.c $(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)print-rtl.c ! sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > $(HOST_PREFIX)print-rtl.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)print-rtl.c $(HOST_PREFIX_1)rtlanal.o: $(srcdir)/rtlanal.c $(CONFIG_H) $(RTL_H) rm -f $(HOST_PREFIX)rtlanal.c ! sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtlanal.c > $(HOST_PREFIX)rtlanal.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtlanal.c *************** *** 1071,1080 **** $(HOST_PREFIX_1)obstack.o: obstack.c rm -f $(HOST_PREFIX)obstack.c ! cp $(srcdir)/obstack.c $(HOST_PREFIX)obstack.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)obstack.c $(HOST_PREFIX_1)malloc.o: malloc.c rm -f $(HOST_PREFIX)malloc.c ! cp $(srcdir)/malloc.c $(HOST_PREFIX)malloc.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)malloc.c --- 1139,1148 ---- $(HOST_PREFIX_1)obstack.o: obstack.c rm -f $(HOST_PREFIX)obstack.c ! sed -e 's/config[.]h/hconfig.h/' $(srcdir)/obstack.c > $(HOST_PREFIX)obstack.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)obstack.c $(HOST_PREFIX_1)malloc.o: malloc.c rm -f $(HOST_PREFIX)malloc.c ! sed -e 's/config[.]h/hconfig.h/' $(srcdir)/malloc.c > $(HOST_PREFIX)malloc.c $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)malloc.c *************** *** 1104,1110 **** -DLOCAL_INCLUDE_DIR=\"$(prefix)/include\" \ -DCROSS_INCLUDE_DIR=\"$(libsubdir)/sys-include\" \ -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'` ! proto: config.status protoize unprotoize SYSCALLS.c.X protoize.1 unprotoize.1 protoize: protoize.o getopt.o getopt1.o getpwd.o version.o $(LIBDEPS) --- 1172,1179 ---- -DLOCAL_INCLUDE_DIR=\"$(prefix)/include\" \ -DCROSS_INCLUDE_DIR=\"$(libsubdir)/sys-include\" \ + -DTOOLDIR=\"$(tooldir)/\" \ -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'` ! proto: config.status protoize unprotoize SYSCALLS.c.X protoize: protoize.o getopt.o getopt1.o getpwd.o version.o $(LIBDEPS) *************** *** 1119,1123 **** stamp-proto: $(srcdir)/protoize.c getopt.h $(CONFIG_H) - touch stamp-proto $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \ --- 1188,1191 ---- *************** *** 1135,1138 **** --- 1203,1207 ---- -DSTD_PROTO_DIR=\"$(libsubdir)\" \ $(srcdir)/protoize.c + touch stamp-proto getopt.o: $(srcdir)/getopt.c getopt.h *************** *** 1141,1158 **** $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/getopt1.c - protoize.1: $(srcdir)/proto-man ./cpp - ./cpp -traditional $(srcdir)/proto-man \ - | grep -v '^#' \ - | awk 'NF > 0 {print}' > tmp-proto.1 - -rm -f protoize.1 - mv tmp-proto.1 protoize.1 - - unprotoize.1: $(srcdir)/proto-man ./cpp - ./cpp -traditional -DUNPRO $(srcdir)/proto-man \ - | grep -v '^#' \ - | awk 'NF > 0 {print}' > tmp-unproto.1 - -rm -f unprotoize.1 - mv tmp-unproto.1 unprotoize.1 - # This info describes the target machine, so compile with GCC just built. SYSCALLS.c.X: $(srcdir)/sys-types.h $(srcdir)/sys-protos.h $(GCC_PASSES) --- 1210,1213 ---- *************** *** 1173,1177 **** -DCROSS_INCLUDE_DIR=0 \ -DSTD_PROTO_DIR=0" tmp-proto.c ! @echo '**********' Expect 402 lines of differences. -diff $(srcdir)/protoize.c tmp-proto.c > tmp-proto.diff -wc -l tmp-proto.diff --- 1228,1232 ---- -DCROSS_INCLUDE_DIR=0 \ -DSTD_PROTO_DIR=0" tmp-proto.c ! @echo '**********' Expect 400 lines of differences. -diff $(srcdir)/protoize.c tmp-proto.c > tmp-proto.diff -wc -l tmp-proto.diff *************** *** 1200,1205 **** makeinfo `echo $(srcdir)/gcc.texi | sed 's,^\./,,'` $(srcdir)/INSTALL: install1.texi install.texi ! makeinfo --no-header `echo $(srcdir)/install1.texi | sed 's,^\./,,'` # Deletion of files made during compilation. --- 1255,1267 ---- makeinfo `echo $(srcdir)/gcc.texi | sed 's,^\./,,'` + # This works with GNU Make's default rule. + $(srcdir)/gcc.dvi: gcc.texi extend.texi install.texi invoke.texi \ + md.texi rtl.texi tm.texi + + # This works with GNU Make's default rule. + $(srcdir)/cpp.dvi: cpp.texi + $(srcdir)/INSTALL: install1.texi install.texi ! makeinfo -D INSTALLONLY --no-header `echo $(srcdir)/install1.texi | sed 's,^\./,,'` # Deletion of files made during compilation. *************** *** 1216,1219 **** --- 1278,1287 ---- mostlyclean: -rm -f $(STAGESTUFF) + # Clean the objc subdir if we created one. + if [ -d objc ]; then \ + srcdir1=`cd $(srcdir); pwd`; \ + cd objc; $(MAKE) -f $$srcdir1/objc/Makefile mostlyclean; \ + else true; fi + -rm -f libobjc.a # Delete the temporary source copies for cross compilation. -rm -f $(HOST_PREFIX_1)rtl.c $(HOST_PREFIX_1)rtlanal.c *************** *** 1221,1228 **** -rm -f $(HOST_PREFIX_1)obstack.c # Delete the temp files made in the course of building libgcc.a. ! -rm -f tmplibgcc* tmpcopy for name in $(LIB1FUNCS); do rm -f $${name}.c; done # Delete other temporary files. ! -rm -f tmp-float.h tmp-gcc.xtar.Z tmp-limits.h gccnew -rm -f tmp-foo1 tmp-foo2 tmp-proto.* tmp-unproto.1 tmp-SYSCALLS.s # Delete the stamp files. --- 1289,1296 ---- -rm -f $(HOST_PREFIX_1)obstack.c # Delete the temp files made in the course of building libgcc.a. ! -rm -f tmplibgcc* tmpcopy xlimits.h for name in $(LIB1FUNCS); do rm -f $${name}.c; done # Delete other temporary files. ! -rm -f tmp-float.h tmp-gcc.xtar.Z -rm -f tmp-foo1 tmp-foo2 tmp-proto.* tmp-unproto.1 tmp-SYSCALLS.s # Delete the stamp files. *************** *** 1239,1243 **** -rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns # Delete core dumps. ! -rm -f core # Delete all files made by compilation --- 1307,1311 ---- -rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns # Delete core dumps. ! -rm -f core config/core # Delete all files made by compilation *************** *** 1254,1258 **** # while building and installing GCC. distclean: clean ! -rm -f tm.h aux-output.c config.h md config.status tconfig.h -rm -f Makefile *.oaux -rm -fr stage1 stage2 stage3 stage4 --- 1322,1326 ---- # while building and installing GCC. distclean: clean ! -rm -f tm.h aux-output.c config.h md config.status tconfig.h hconfig.h -rm -f Makefile *.oaux -rm -fr stage1 stage2 stage3 stage4 *************** *** 1263,1275 **** -rm -rf =* #* *~* config/=* config/#* config/*~* -rm -f patch* *.orig *.rej config/patch* config/*.orig config/*.rej ! -rm -f *.dvi *.oaux *.d *.Z *.tar *.xtar ! -rm -f *.s *.s[0-9] *.i install1.texi # Get rid of every file that's generated from some other file. # Most of these files ARE PRESENT in the GCC distribution. realclean: distclean -rm -f cp-parse.c cp-parse.h cp-parse.output -rm -f objc-parse.c objc-parse.output - -rm -f protoize.1 unprotoize.1 -rm -f c-parse.c c-parse.h c-parse.output -rm -f cexp.c cexp.output TAGS --- 1331,1344 ---- -rm -rf =* #* *~* config/=* config/#* config/*~* -rm -f patch* *.orig *.rej config/patch* config/*.orig config/*.rej ! -rm -f *.dvi *.oaux *.d *.Z *.tar *.xtar *diff ! -rm -f *lose config/*lose ! -rm -f *.s *.s[0-9] *.i install1.texi config/ChangeLog # Get rid of every file that's generated from some other file. # Most of these files ARE PRESENT in the GCC distribution. realclean: distclean + -rm -f c-parse.y objc-parse.y -rm -f cp-parse.c cp-parse.h cp-parse.output -rm -f objc-parse.c objc-parse.output -rm -f c-parse.c c-parse.h c-parse.output -rm -f cexp.c cexp.output TAGS *************** *** 1282,1286 **** # Also use `install-collect2' to install collect2 when the config files don't. ! install: $(INSTALL_TARGET) # Copy the files of native compiler into directories where they will be run. --- 1351,1357 ---- # Also use `install-collect2' to install collect2 when the config files don't. ! # The semicolon is to prevent the install.sh -> install default rule ! # from doing anything. ! install: $(INSTALL_TARGET) ; # Copy the files of native compiler into directories where they will be run. *************** *** 1292,1295 **** --- 1363,1372 ---- install-man install-cross-tools install-libgcc + # Do nothing while making gcc with a cross-compiler. The person who + # makes gcc for the target machine has to know how to put a complete + # gcc together by hand. + install-build: force + @echo You have to install gcc on your target machine by hand. + # Install the tools, libraries and header files for the target machine # where cross-compilation will look for them. *************** *** 1306,1310 **** if [ -d $(tooldir)/. ] ; \ then \ ! for file in as ld ar ranlib; do \ if [ -f $(libsubdir)/$$file ] ; \ then true; \ --- 1383,1387 ---- if [ -d $(tooldir)/. ] ; \ then \ ! for file in as ld ar nm ranlib; do \ if [ -f $(libsubdir)/$$file ] ; \ then true; \ *************** *** 1329,1333 **** $(SYMLINK) $(tooldir)/include $(libsubdir)/sys-include \ || (if [ -d $(libsubdir)/sys-include ] ; then true ; else mkdir $(libsubdir)/sys-include ; fi; \ ! cd $(tooldir)/include; tar cf - . | (cd $(libsubdir)/sys-include; tar xpf -)); \ else true; fi; \ else true; \ --- 1406,1410 ---- $(SYMLINK) $(tooldir)/include $(libsubdir)/sys-include \ || (if [ -d $(libsubdir)/sys-include ] ; then true ; else mkdir $(libsubdir)/sys-include ; fi; \ ! (cd $(tooldir)/include; tar cf - .) | (cd $(libsubdir)/sys-include; tar xpf -)); \ else true; fi; \ else true; \ *************** *** 1343,1350 **** # Run this on the target machine! install-float-h-cross: ! if [ -f enquire ] ; then true; else false; done ! -./enquire -f > float.h -rm -f $(libsubdir)/include/float.h ! $(INSTALL_DATA) float.h $(libsubdir)/include/float.h chmod a-x $(libsubdir)/include/float.h --- 1420,1430 ---- # Run this on the target machine! install-float-h-cross: ! # I don't see what this line is for. ! # If you see what good it does, please tell me. -- rms. ! if [ -f enquire ] ; then true; else false; fi ! -./enquire -f > $(tmpdir)/float.h -rm -f $(libsubdir)/include/float.h ! $(INSTALL_DATA) $(tmpdir)/float.h $(libsubdir)/include/float.h ! -rm -f $(tmpdir)/float.h chmod a-x $(libsubdir)/include/float.h *************** *** 1358,1361 **** --- 1438,1442 ---- -if [ -d $(libdir)/gcc-lib/$(target)/$(version)/include ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target)/$(version)/include ; fi -if [ -d $(bindir) ] ; then true ; else mkdir $(bindir) ; fi + -if [ -d $(includedir) ] ; then true ; else mkdir $(includedir) ; fi # We don't use mkdir -p to create the parents of mandir, # because some systems don't support it. *************** *** 1366,1370 **** # Install the compiler executables built during cross compilation. ! install-common: native install-dir for file in $(COMPILERS); do \ if [ -f $$file ] ; then \ --- 1447,1451 ---- # Install the compiler executables built during cross compilation. ! install-common: native install-dir xgcc $(srcdir)/g++ $(srcdir)/c++ $(EXTRA_PARTS) for file in $(COMPILERS); do \ if [ -f $$file ] ; then \ *************** *** 1380,1385 **** else true; fi; \ done ! -rm -f $(libsubdir)/specs ! $(INSTALL_DATA) specs $(libsubdir)/specs # Install the driver program as gcc-$(target) # and also as either gcc (if native) or $(tooldir)/bin/gcc. --- 1461,1471 ---- else true; fi; \ done ! # Don't mess with specs if it doesn't exist yet. ! # We can't make it a dependency because with a cross compiler ! # you have to make specs on the target machine or not at all. ! -if [ -f specs ] ; then \ ! rm -f $(libsubdir)/specs; \ ! $(INSTALL_DATA) specs $(libsubdir)/specs; \ ! fi # Install the driver program as gcc-$(target) # and also as either gcc (if native) or $(tooldir)/bin/gcc. *************** *** 1392,1400 **** else \ rm -f $(bindir)/gcc; \ ! $(INSTALL_PROGRAM) gcc $(bindir)/gcc; \ rm -f $(bindir)/gcc-$(target)-1; \ ln $(bindir)/gcc $(bindir)/gcc-$(target)-1; \ mv $(bindir)/gcc-$(target)-1 $(bindir)/gcc-$(target); \ fi -rm -f $(bindir)/c++ $(INSTALL_PROGRAM) $(srcdir)/c++ $(bindir)/c++ --- 1478,1497 ---- else \ rm -f $(bindir)/gcc; \ ! $(INSTALL_PROGRAM) xgcc $(bindir)/gcc; \ rm -f $(bindir)/gcc-$(target)-1; \ ln $(bindir)/gcc $(bindir)/gcc-$(target)-1; \ mv $(bindir)/gcc-$(target)-1 $(bindir)/gcc-$(target); \ fi + # Install protoize if it was compiled. + -if [ -f protoize ]; \ + then \ + rm -f $(bindir)/protoize; \ + $(INSTALL_PROGRAM) protoize $(bindir)/protoize; \ + rm -f $(bindir)/unprotoize; \ + $(INSTALL_PROGRAM) unprotoize $(bindir)/unprotoize; \ + rm -f $(libsubdir)/SYSCALLS.c.X; \ + $(INSTALL_DATA) SYSCALLS.c.X $(libsubdir)/SYSCALLS.c.X; \ + chmod a-x $(libsubdir)/SYSCALLS.c.X; \ + fi -rm -f $(bindir)/c++ $(INSTALL_PROGRAM) $(srcdir)/c++ $(bindir)/c++ *************** *** 1404,1420 **** $(INSTALL_PROGRAM) cpp $(libsubdir)/cpp - # Install protoize. - install-proto: proto install-dir - -rm -f $(bindir)/protoize - $(INSTALL_PROGRAM) protoize $(bindir)/protoize - -rm -f $(bindir)/unprotoize - $(INSTALL_PROGRAM) unprotoize $(bindir)/unprotoize - -rm -f $(libsubdir)/SYSCALLS.c.X - $(INSTALL_DATA) SYSCALLS.c.X $(libsubdir)/SYSCALLS.c.X - chmod a-x $(libsubdir)/SYSCALLS.c.X - # Install the man pages. ! install-man: install-dir $(srcdir)/gcc.1 $(srcdir)/cccp.1 \ ! protoize.1 unprotoize.1 $(srcdir)/g++.1 -rm -f $(mandir)/gcc$(manext) -$(INSTALL_DATA) $(srcdir)/gcc.1 $(mandir)/gcc$(manext) --- 1501,1506 ---- $(INSTALL_PROGRAM) cpp $(libsubdir)/cpp # Install the man pages. ! install-man: install-dir $(srcdir)/gcc.1 $(srcdir)/cccp.1 $(srcdir)/g++.1 -rm -f $(mandir)/gcc$(manext) -$(INSTALL_DATA) $(srcdir)/gcc.1 $(mandir)/gcc$(manext) *************** *** 1423,1433 **** -$(INSTALL_DATA) $(srcdir)/cccp.1 $(mandir)/cccp$(manext) -chmod a-x $(mandir)/cccp$(manext) - -rm -f $(mandir)/protoize$(manext) - -$(INSTALL_DATA) protoize.1 $(mandir)/protoize$(manext) - -chmod a-x $(mandir)/protoize$(manext) - -rm -f $(mandir)/unprotoize$(manext) - -$(INSTALL_DATA) unprotoize.1 $(mandir)/unprotoize$(manext) - -chmod a-x $(mandir)/unprotoize$(manext) - -rm -f $(mandir)/g++$(manext) -$(INSTALL_DATA) $(srcdir)/g++.1 $(mandir)/g++$(manext) -chmod a-x $(mandir)/g++$(manext) --- 1509,1512 ---- *************** *** 1443,1446 **** --- 1522,1535 ---- else true; fi + # Install the objc run time library. + install-libobjc: libobjc.a install-dir + -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 + # Install all the header files for native compiler. install-headers: install-common-headers install-float-h install-limits-h *************** *** 1452,1466 **** chmod a-x $(libsubdir)/include/float.h ! # Install limits.h, optionally inheriting from the standard system version. ! install-limits-h: limits.h limitx.h install-dir ! -rm -f $(libsubdir)/include/limits.h tmp-limits.h ! if [ -f /usr/include/limits.h ] ; then \ ! cat $(srcdir)/limitx.h $(srcdir)/limits.h > tmp-limits.h; \ ! else \ ! cat $(srcdir)/limits.h > tmp-limits.h; \ ! fi ! $(INSTALL_DATA) tmp-limits.h $(libsubdir)/include/limits.h chmod a-x $(libsubdir)/include/limits.h - rm tmp-limits.h # Install the fixed headers that are the same for all machines. --- 1541,1549 ---- chmod a-x $(libsubdir)/include/float.h ! # Install limits.h. ! install-limits-h: xlimits.h install-dir ! -rm -f $(libsubdir)/include/limits.h ! $(INSTALL_DATA) xlimits.h $(libsubdir)/include/limits.h chmod a-x $(libsubdir)/include/limits.h # Install the fixed headers that are the same for all machines. *************** *** 1476,1479 **** --- 1559,1580 ---- chmod a-x $$shelllibsubdir/include/`basename $$file`; \ done + # Put assert.h in /usr/local/include, so it won't override GNU libc's assert.h. + # Don't replace the assert.h already there if it is not from GCC. + # This code would be simpler if it tested for -f ... && ! grep ... + # but supposedly the ! operator is missing in sh on some systems. + if [ -f $(assertdir)/assert.h ]; \ + then \ + if grep "__eprintf" $(assertdir)/assert.h; \ + then \ + rm -f $(assertdir)/assert.h; \ + $(INSTALL_DATA) $(srcdir)/assert.h $(assertdir)/assert.h; \ + chmod a-x $(assertdir)/assert.h; \ + else true; \ + fi; \ + else \ + rm -f $(assertdir)/assert.h; \ + $(INSTALL_DATA) $(srcdir)/assert.h $(assertdir)/assert.h; \ + chmod a-x $(assertdir)/assert.h; \ + fi -rm -f $(libsubdir)/include/varargs.h $(INSTALL_DATA) $(srcdir)/gvarargs.h $(libsubdir)/include/varargs.h *************** *** 1485,1494 **** $(INSTALL_DATA) $(srcdir)/gstddef.h $(libsubdir)/include/stddef.h chmod a-x $(libsubdir)/include/stddef.h ! # Copy byteorder.h into the object file directory ! # so that fixinc.svr4 can get at it if necessary. ! # If the dirs are the same, this won't do anything. ! # Delete file first in case it is read-only ! -if [ "$(srcdir)" != "." ]; then rm -f byteorder.h; else true; fi ! -cp $(srcdir)/byteorder.h . > /dev/null 2>&1 # $(libsubdir)/include: --- 1586,1596 ---- $(INSTALL_DATA) $(srcdir)/gstddef.h $(libsubdir)/include/stddef.h chmod a-x $(libsubdir)/include/stddef.h ! # This is turned off because fixinc.svr4 can now get it directly from srcdir. ! ## Copy byteorder.h into the object file directory ! ## so that fixinc.svr4 can get at it if necessary. ! ## If the dirs are the same, this won't do anything. ! ## Delete file first in case it is read-only ! # -if [ x`cd $(srcdir);pwd` != x`pwd` ]; then rm -f byteorder.h; else true; fi ! # -cp $(srcdir)/byteorder.h . > /dev/null 2>&1 # $(libsubdir)/include: *************** *** 1517,1521 **** rm -rf * # Install fixed copies of system files. ! $(srcdir)/$(FIXINCLUDES) $(libsubdir)/include # Bring back gcc's header files. cd $(libsubdir)/include; mv ../tmp/* .; rmdir ../tmp --- 1619,1633 ---- rm -rf * # Install fixed copies of system files. ! for dir in /usr/include $(OTHER_FIXINCLUDES_DIRS); do \ ! if [ -d $$dir ]; \ ! then \ ! $(srcdir)/$(FIXINCLUDES) $(libsubdir)/include $$dir $(srcdir); \ ! else true; fi \ ! done ! -cd $(libsubdir)/include; \ ! if [ -f limits.h ]; then \ ! rm -f ../tmp/syslimits.h; \ ! cp limits.h ../tmp/syslimits.h; \ ! else true; fi # Bring back gcc's header files. cd $(libsubdir)/include; mv ../tmp/* .; rmdir ../tmp *************** *** 1528,1536 **** $(INSTALL_PROGRAM) collect2 $(libsubdir)/ld # Install the driver program as $(libsubdir)/gcc for collect2. ! -if [ -f gcc-cross ] ; then \ ! $(INSTALL_PROGRAM) gcc-cross $(libsubdir)/gcc; \ ! else \ ! $(INSTALL_PROGRAM) gcc $(libsubdir)/gcc; \ ! fi # Cancel installation by deleting the installed files. --- 1640,1644 ---- $(INSTALL_PROGRAM) collect2 $(libsubdir)/ld # Install the driver program as $(libsubdir)/gcc for collect2. ! $(INSTALL_PROGRAM) xgcc $(libsubdir)/gcc # Cancel installation by deleting the installed files. *************** *** 1551,1555 **** cd $(srcdir); \ mkdir temp; \ ! mv -f c-parse.c c-parse.h cp-parse.c cp-parse.h objc-parse.c cexp.c temp; \ etags *.y *.h *.c; \ mv temp/* .; \ --- 1659,1663 ---- cd $(srcdir); \ mkdir temp; \ ! mv -f c-parse.[ch] cp-parse.[ch] objc-parse.c cexp.c =*.[chy] temp; \ etags *.y *.h *.c; \ mv temp/* .; \ *************** *** 1568,1572 **** #gcc-$(version).tar: ! gcc.xtar: doc if grep -s "for version ${version}" gcc.texi; \ then true; \ --- 1676,1680 ---- #gcc-$(version).tar: ! gcc.xtar: doc c-parse.y objc-parse.y if grep -s "for version ${version}" gcc.texi; \ then true; \ *************** *** 1584,1587 **** --- 1692,1696 ---- mkdir tmp mkdir tmp/config + mkdir tmp/objc for file in *[0-9a-zA-Z+]; do \ ln $$file tmp > /dev/null 2>&1 || cp $$file tmp; \ *************** *** 1591,1594 **** --- 1700,1707 ---- ln $$file ../tmp/config >/dev/null 2>&1 || cp $$file ../tmp/config; \ done + cd objc; \ + for file in *[0-9a-zA-Z+]; do \ + ln $$file ../tmp/objc >/dev/null 2>&1 || cp $$file ../tmp/objc; \ + done ln .gdbinit tmp mv tmp gcc-$(version) *************** *** 1618,1621 **** --- 1731,1735 ---- make clean # You must then run config to set up for compilation. + bootstrap: force # Only build the C compiler for stage1, because that is the only one that *************** *** 1629,1643 **** # because alloca.o is newer, we permit these recursive makes to compile # alloca.o. Then cc1 is newer, so it won't have to be relinked. ! $(MAKE) CC="stage1/gcc -Bstage1/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" $(MAKE) stage2 ! $(MAKE) CC="stage2/gcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" bootstrap2: force ! $(MAKE) CC="stage1/gcc -Bstage1/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" $(MAKE) stage2 ! $(MAKE) CC="stage2/gcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" bootstrap3: force ! $(MAKE) CC="stage2/gcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" # Compare the object files in the current directory with those in the --- 1743,1757 ---- # because alloca.o is newer, we permit these recursive makes to compile # alloca.o. Then cc1 is newer, so it won't have to be relinked. ! $(MAKE) CC="stage1/xgcc -Bstage1/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" $(MAKE) stage2 ! $(MAKE) CC="stage2/xgcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" bootstrap2: force ! $(MAKE) CC="stage1/xgcc -Bstage1/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" $(MAKE) stage2 ! $(MAKE) CC="stage2/xgcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" bootstrap3: force ! $(MAKE) CC="stage2/xgcc -Bstage2/" CFLAGS="$(BOOT_CFLAGS)" libdir=$(libdir) LANGUAGES="$(LANGUAGES)" # Compare the object files in the current directory with those in the *************** *** 1646,1652 **** compare: force for file in *.o; do \ ! tail +10c $$file > tmp-foo1; \ ! tail +10c stage2/$$file > tmp-foo2; \ ! cmp tmp-foo1 tmp-foo2 || echo $$file differs; \ done -rm -f tmp-foo* --- 1760,1766 ---- compare: force for file in *.o; do \ ! tail +16c $$file > tmp-foo1; \ ! tail +16c stage2/$$file > tmp-foo2 2>/dev/null \ ! && (cmp tmp-foo1 tmp-foo2 || echo $$file differs); \ done -rm -f tmp-foo* *************** *** 1655,1661 **** compare3: force for file in *.o; do \ ! tail +10c $$file > tmp-foo1; \ ! tail +10c stage3/$$file > tmp-foo2; \ ! cmp tmp-foo1 tmp-foo2 || echo $$file differs; \ done -rm -f tmp-foo* --- 1769,1775 ---- compare3: force for file in *.o; do \ ! tail +16c $$file > tmp-foo1; \ ! tail +16c stage3/$$file > tmp-foo2 2>/dev/null \ ! && (cmp tmp-foo1 tmp-foo2 || echo $$file differs); \ done -rm -f tmp-foo* diff -rc2N gcc-2.2.2/PROJECTS gcc-2.3.1/PROJECTS *** gcc-2.2.2/PROJECTS Tue Feb 4 16:18:54 1992 --- gcc-2.3.1/PROJECTS Tue Oct 20 17:12:16 1992 *************** *** 71,74 **** --- 71,125 ---- change is really an improvement. + * Clean up how cse works. + + The scheme is that each value has just one hash entry. The + first_same_value and next_same_value chains are no longer needed. + + For arithmetic, each hash table elt has the following slots: + + * Operation. This is an rtx code. + * Mode. + * Operands 0, 1 and 2. These point to other hash table elements. + + So, if we want to enter (PLUS:SI (REG:SI 30) (CONST_INT 104)), we + first enter (CONST_INT 104) and find the entry that (REG:SI 30) now + points to. Then we put these elts into operands 0 and 1 of a new elt. + We put PLUS and SI into the new elt. + + Registers and mem refs would never be entered into the table as such. + However, the values they contain would be entered. There would be a + table indexed by regno which points at the hash entry for the value in + that reg. + + The hash entry index now plays the role of a qty number. + We still need qty_first_reg, reg_next_eqv, etc. to record which regs + share a particular qty. + + When a reg is used whose contents are unknown, we need to create a + hash table entry whose contents say "unknown", as a place holder for + whatever the reg contains. If that reg is added to something, then + the hash entry for the sum will refer to the "unknown" entry. Use + UNKNOWN for the rtx code in this entry. This replaces make_new_qty. + + For a constant, a unique hash entry would be made based on the + value of the constant. + + What about MEM? Each time a memory address is referenced, we need a + qty (a hash table elt) to represent what is in it. (Just as for a + register.) If this isn't known, create one, just as for a reg whose + contents are unknown. + + We need a way to find all mem refs that still contain a certain value. + Do this with a chain of hash elts (for memory addresses) that point to + locations that hold the value. The hash elt for the value itself should + point to the start of the chain. It would be good for the hash elt + for an address to point to the hash elt for the contents of that address + (but this ptr can be null if the contents have never been entered). + + With this data structure, nothing need ever be invalidated except + the lists of which regs or mems hold a particular value. It is easy + to see if there is a reg or mem that is equiv to a particular value. + If the value is constant, it is always explicitly constant. + * Support more general tail-recursion among different functions. *************** *** 124,128 **** of the time even though the loop needs all the registers.) ! It might not be very hard to do this in global-alloc.c when a variable fails to get a hard register for its entire life span. --- 175,179 ---- of the time even though the loop needs all the registers.) ! It might not be very hard to do this in global.c when a variable fails to get a hard register for its entire life span. diff -rc2N gcc-2.2.2/README gcc-2.3.1/README *** gcc-2.2.2/README Sun Jun 14 18:15:54 1992 --- gcc-2.3.1/README Sun Nov 1 03:43:07 1992 *************** *** 1,5 **** ! This directory contains the version 2.2.2 release of the GNU C compiler. ! This is a beta test release and we expect it to have a number of bugs. See the file gcc.texi (together with other files that it includes) for installation and porting information. The file INSTALL contains a --- 1,12 ---- ! This directory contains the version 2.3.1 release of the GNU C ! compiler. It includes all of the support for compiling C++ and ! Objective C, including a run-time library for Objective C. + This is still a beta test release, but aside from the Objective C + run-time, it ought to be close to reliable. + + The GNU C compiler is free software. See the file COPYING for copying + permission. + See the file gcc.texi (together with other files that it includes) for installation and porting information. The file INSTALL contains a *************** *** 10,16 **** named libgcc.a. It will also create /usr/local/bin/gcc, which is the user-level command to do a compilation. - - The GNU C compiler is free software. See the file COPYING for copying - permission. See the Bugs chapter of the GCC Manual for how to report bugs --- 17,20 ---- diff -rc2N gcc-2.2.2/README.DWARF gcc-2.3.1/README.DWARF *** gcc-2.2.2/README.DWARF Wed Jun 3 15:03:26 1992 --- gcc-2.3.1/README.DWARF Mon Oct 5 04:01:11 1992 *************** *** 1,23 **** Notes on the GNU Implementation of DWARF Debugging Information -------------------------------------------------------------- ! Last Updated: Sun Jun 3 09:56:42 1992 by rfg@ncd.com ----------------------------------------------------- This file describes special and unique aspects of the GNU implementation ! of the DWARF debugging information language, as provided in the GCC Version ! 2 compiler. For general information about the DWARF debugging information language, ! you should obtain the latest DWARF draft specification document developed ! by the UNIX International Programming Languages Special Interest Group. ! A copy of the this document (in PostScript form) may be obtained either ! from me or from UNIX International. (See below.) The file ! you are looking at now only describes known deviations from the current ! UI/PLSIG DWARF specification document (1.0.1) together with those things ! which are allowed by the current DWARF specification but which are known ! to cause interoperability problems (e.g. with svr4 SDB). ! To obtain a copy of the latest DWARF specification document from UNIX ! International, use the following procedure: --------------------------------------------------------------------------- --- 1,24 ---- Notes on the GNU Implementation of DWARF Debugging Information -------------------------------------------------------------- ! Last Updated: Sun Oct 4 10:04:13 PDT 1992 by rfg@netcom.com ----------------------------------------------------- This file describes special and unique aspects of the GNU implementation ! of the DWARF debugging information language, as provided in the GNU version ! 2.x compiler(s). For general information about the DWARF debugging information language, ! you should obtain the DWARF version 1 specification document (and perhaps ! also the DWARF version 2 draft specification document) developed by the ! UNIX International Programming Languages Special Interest Group. A copy ! of the the DWARF version 1 specification (in PostScript form) may be ! obtained either from me or from UNIX International. (See ! below.) The file you are looking at now only describes known deviations ! from the UI/PLSIG DWARF version 1 specification, together with those ! things which are allowed by the DWARF version 1 specification but which ! are known to cause interoperability problems (e.g. with SVR4 SDB). ! To obtain a copy of the DWARF version 1 specification from UNIX International, ! use the following procedure: --------------------------------------------------------------------------- *************** *** 39,59 **** --------------------------------------------------------------------------- ! The generation of DWARF debugging information in GCC v2.x has now been ! tested rather extensively (in conjunction with the C language front end ! only) for m88k, i386, i860, and Sparc targets. GCC's DWARF output (for C) ! appears to interoperate well with the standard svr4 SDB debugger on these ! kinds of target systems (but of course, there are no guarrantees). ! ! The DWARF generation enhancement for GCC was initially donated to the ! Free Software Foundation by Network Computing Devices. (Thanks NCD!) ! Additional development and maintenance of dwarfout.c has been largely ! supported (i.e. funded) by Intel Corporation. (Thanks Intel!) The code ! in dwarfout.c is (of course) covered under the GNU General Public ! License (aka `copyleft') just as the rest of GCC is. ! ! If you have questions or comments about the DWARF generation feature ! of GCC, please send mail to me . I will be happy to ! investigate any bugs reported and I may even provide fixes (but of ! course, I can make no promises). The DWARF debugging information produced by GCC may deviate in a few minor --- 40,79 ---- --------------------------------------------------------------------------- ! The generation of DWARF debugging information by the GNU version 2.x C ! compiler has now been tested rather extensively for m88k, i386, i860, and ! Sparc targets. The DWARF output of the GNU C compiler appears to inter- ! operate well with the standard SVR4 SDB debugger on these kinds of target ! systems (but of course, there are no guarantees). ! ! DWARF generation for the GNU g++ compiler is still not operable. This is ! due primarily to the many remaining cases where the g++ front end does not ! conform to the conventions used in the GNU C front end for representing ! various kinds of declarations in the TREE data structure. It is not clear ! at this time how these problems will be addressed. ! ! Future plans for the dwarfout.c module of the GNU compiler(s) includes the ! addition of full support for GNU FORTRAN. (This should, in theory, be a ! lot simpler to add than adding support for g++... but we'll see.) ! ! Many features from the evolving DWARF version 2 (draft) specification have ! been adapted to, and used in the GNU implementation of DWARF (version 1). ! In most of these cases, a DWARF version 2 (draft) approach is used in place ! of (or in addition to) DWARF version 1 stuff simply because it is apparent ! that DWARF version 1 is not sufficiently expressive to provide the kinds of ! information which may be necessary to support really robust debugging. ! In *all* of these cases however, the use of DWARF version 2 (draft) features ! should not interfere in any way with the interoperability (of GNU compilers) ! with generally available "classic" (pre version 1) DWARF consumer tools ! (e.g. SVR4 SDB). Full support for DWARF version 2 should be available ! sometime after the DWARF version 2 specification has been finalized. ! ! The DWARF generation enhancement for the GNU compiler(s) was initially ! donated to the Free Software Foundation by Network Computing Devices. ! (Thanks NCD!) Additional development and maintenance of dwarfout.c has ! been largely supported (i.e. funded) by Intel Corporation. (Thanks Intel!) ! ! If you have questions or comments about the DWARF generation feature, please ! send mail to me . I will be happy to investigate any bugs ! reported and I may even provide fixes (but of course, I can make no promises). The DWARF debugging information produced by GCC may deviate in a few minor *************** *** 72,78 **** operates an E-mail mailing list and holds regular meeting in various cities. If you don't have time to participate actively, but would like to be kept ! abrest of recent developments, you con join the UI/PLSIG mailing list and just listen in on our lively discussions. (Footnote: Within this file, the term `Debugging Information Entry' will be abbreviated as `DIE'.) --- 92,114 ---- operates an E-mail mailing list and holds regular meeting in various cities. If you don't have time to participate actively, but would like to be kept ! abreast of recent developments, you con join the UI/PLSIG mailing list and just listen in on our lively discussions. + ** IMPORTANT NOTE ** ** IMPORTANT NOTE ** ** IMPORTANT NOTE ** + + Under normal circumstances, the DWARF information generated by the GNU + compilers (in an assembly language file) is essentially impossible for + a human being to read. This fact can make it very difficult to debug + certain DWARF-related problems. In order to overcome this difficulty, + a feature has been added to dwarfout.c (enabled by the -fverbose-asm + option) which causes additional comments to be placed into the assembly + language output file, out to the right-hand side of most bits of DWARF + material. The comments indicate (far more clearly that the obscure + DWARF hex codes do) what is actually being encoded in DWARF. Thus, the + -fverbose-asm option can be highly useful for those who must study the + DWARF output from the GNU compilers in detail. + + --------- + (Footnote: Within this file, the term `Debugging Information Entry' will be abbreviated as `DIE'.) *************** *** 82,99 **** ------------------------------- ! The AT_bit_offset value for bit-fields whose high-order bit lies smack up ! against an "alignment unit" boundary will probably be incorrect. For ! example, compiling: ! ! struct S { ! int foo:9; ! short bar:7; ! int last:16; ! }; ! ! ... for an x86 target yields a situation where `bar' lies smack up against ! the high-order end of the hypothetical type `short' object which contains it. ! In such cases, the AT_bit_offset should be zero, but it may instead be equal ! to the size of the containing object (which, for this example, is 16 bits). -------------------------------- --- 118,158 ---- ------------------------------- ! In one very obscure case involving dynamically sized arrays, the DWARF ! "location information" for such an array may make it appear that the ! array has been totally optimized out of existence, when in fact it ! *must* actually exist. (This only happens when you are using *both* -g ! *and* -O.) This is due to aggressive dead store elimination in the ! compiler, and to the fact that the DECL_RTL expressions associated with ! variables are not always updated to correctly reflect the effects of ! GCC's aggressive dead store elimination. ! ! ------------------------------- ! ! When attempting to set a breakpoint at the "start" of a function compiled ! with -g1, the debugger currently has no way of knowing exactly where the ! end of the prologue code for the function is. Thus, for most targets, ! all the debugger can do is to set the breakpoint at the AT_low_pc address ! for the function. But if you stop there and then try to look at one or ! more of the formal parameter values, they may not have been "homed" yet, ! so you may get inaccurate answers (or perhaps even addressing errors). ! ! Some people may consider this simply a non-feature, but I consider it a ! bug, and I hope to provide some some GNU-specific attributes (on function ! DIEs) which will specify the address of the end of the prologue and the ! address of the beginning of the epilogue in a future release. ! ! ------------------------------- ! ! It is believed at this time that old bugs relating to the AT_bit_offset ! values for bit-fields have been fixed. ! ! There may still be some very obscure bugs relating to the DWARF description ! of type `long long' bit-fields for target machines (e.g. 80x86 machines) ! where the alignment of type `long long' data objects is different from ! (and less than) the size of a type `long long' data object. ! ! Please report any problems with the DWARF description of bit-fields as you ! would any other GCC bug. (Procedures for bug reporting are given in the ! GNU C compiler manual.) -------------------------------- *************** *** 104,117 **** -------------------------------- ! At this time, GCC does not represent inlined instances of inline functions ! as called for by the current DWARF draft specification. Support for inlined ! instances of inline functions is still "under construction". ! ! Recently, a new approach to the representation of inlined functions (within ! DWARF) has been proposed (by me) to the UI/PLSIG. This proposal was well ! received, but has not yet been formally approved. It is hoped that this ! proposal will be approved by the UI/PLSIG sometime in the future. A future ! release of GCC may incorporate the new approach for representing inlined ! functions (which I have already implemented). Contact me for further details. -------------------------------- --- 163,173 ---- -------------------------------- ! The GNU compilers now represent inline functions (and inlined instances ! thereof) in exactly the manner described by the current DWARF version 2 ! (draft) specification. The version 1 specification for handling inline ! functions (and inlined instances) was known to be brain-damaged (by the ! PLSIG) when the version 1 spec was finalized, but it was simply too late ! in the cycle to get it removed before the version 1 spec was formally ! released to the public (by UI). -------------------------------- *************** *** 140,160 **** -------------------------------- - Full DWARF support for the GNU C++ language/front-end (aka g++) is not - implemented at this time. - -------------------------------- - - Known Interoperability Problems ------------------------------- Although the GNU implementation of DWARF conforms (for the most part) with ! the current UI/PLSIG DWARF draft specification, there are a few known cases ! where GCC's DWARF output causes confusion in System V Release 4 SDB debuggers ! anyway. There cases are described in this section. -------------------------------- ! The current DWARF draft specification includes the fundamental type codes FT_ext_prec_float, FT_complex, FT_dbl_prec_complex, and FT_ext_prec_complex. Since GNU C is only a C compiler (and since C doesn't provide any "complex" --- 196,213 ---- -------------------------------- Known Interoperability Problems ------------------------------- Although the GNU implementation of DWARF conforms (for the most part) with ! the current UI/PLSIG DWARF version 1 specification (with many compatible ! version 2 features added in as "vendor specific extensions" just for good ! measure) there are a few known cases where GCC's DWARF output can cause ! some confusion for "classic" (pre version 1) DWARF consumers such as the ! System V Release 4 SDB debugger. These cases are described in this section. -------------------------------- ! The DWARF version 1 specification includes the fundamental type codes FT_ext_prec_float, FT_complex, FT_dbl_prec_complex, and FT_ext_prec_complex. Since GNU C is only a C compiler (and since C doesn't provide any "complex" *************** *** 162,168 **** generates is FT_ext_prec_float. This fundamental type code is generated by GCC for the `long double' data type. Unfortunately, due to an apparent ! bug, SVR4 SDB can become very confused wherever any attempt is made to ! print a variable, parameter, or field whose type was given in terms of ! FT_ext_prec_float. (Actually, SVR4 SDB fails to understand *any* of the four fundamental type --- 215,221 ---- generates is FT_ext_prec_float. This fundamental type code is generated by GCC for the `long double' data type. Unfortunately, due to an apparent ! bug in the SVR4 SDB debugger, SDB can become very confused wherever any ! attempt is made to print a variable, parameter, or field whose type was ! given in terms of FT_ext_prec_float. (Actually, SVR4 SDB fails to understand *any* of the four fundamental type *************** *** 185,196 **** ---------------------------- ! In the current DWARF draft specification, no provision is made for providing ! accurate information about executable lines which came into the current ! compilation unit by way of an include file. ! ! Recently, a scheme for providing accurate information about code in include ! files was proposed (by me) to the UI/PLSIG. This scheme was rejected by the ! UI/PLSIG for inclusion into the DWARF Version 1 specification, but GNU DWARF ! implements this extension anyway. To understand this GNU DWARF extension, imagine that the sequence of entries --- 238,258 ---- ---------------------------- ! In the current DWARF version 1 specification, no mechanism is specified by ! which accurate information about executable code from include files can be ! properly (and fully) described. (The DWARF version 2 specification *does* ! specify such a mechanism, but it is about 10 times more complicated than ! it needs to be so I'm not terribly anxious to try to implement it right ! away.) ! ! In the GNU implementation of DWARF version 1, a fully downward-compatible ! extension has been implemented which permits the GNU compilers to specify ! which executable lines come from which files. This extension places ! additional information (about source file names) in GNU-specific sections ! (which should be totally ignored by all non-GNU DWARF consumers) so that ! this extended information can be provided (to GNU DWARF consumers) in a way ! which is totally transparent (and invisible) to non-GNU DWARF consumers ! (e.g. the SVR4 SDB debugger). The additional information is placed *only* ! in specialized GNU-specific sections, where it should never even be seen ! by non-GNU DWARF consumers. To understand this GNU DWARF extension, imagine that the sequence of entries *************** *** 292,296 **** in this field (in cases where it is desired to have object files created at different times from identical source files ! be byte-for-byte identical). Note that the first string placed into the .debug_sfnames section for each --- 354,364 ---- in this field (in cases where it is desired to have object files created at different times from identical source files ! be byte-for-byte identical). By default, these timestamps ! are *not* generated by dwarfout.c (so that object files ! compiled at different times will be byte-for-byte identical). ! If you wish to enable this "timestamp" feature however, you ! can simply place a #define for the symbol `DWARF_TIMESTAMPS' ! in your target configuration file and then rebuild the GNU ! compiler(s). Note that the first string placed into the .debug_sfnames section for each *************** *** 299,312 **** directory). Thus, the second word of each specialized initial .debug_srcinfo entry for each compilation unit may be used as a pointer to the (string) ! name of the compilation directory, and that string may in trun be used to "absolutize" any relative pathnames which may appear later on in the .debug_sfnames section entries for the same compilation unit. The fifth and last word of each specialized starting entry for a compilation ! unit in the .debug_srcinfo section indicates the date/time of compilation, ! and this may be used (by the debugger) to determine if any of the source ! files which contributed code to this compilation unit are newer than the ! object code for the compilation unit itself. If so, the debugger may wish ! to print an "out-of-date" warning about the compilation unit. The .debug_srcinfo section associated with each compilation will also have --- 367,381 ---- directory). Thus, the second word of each specialized initial .debug_srcinfo entry for each compilation unit may be used as a pointer to the (string) ! name of the compilation directory, and that string may in turn be used to "absolutize" any relative pathnames which may appear later on in the .debug_sfnames section entries for the same compilation unit. The fifth and last word of each specialized starting entry for a compilation ! unit in the .debug_srcinfo section may (depending upon your configuration) ! indicate the date/time of compilation, and this may be used (by a debugger) ! to determine if any of the source files which contributed code to this ! compilation unit are newer than the object code for the compilation unit ! itself. If so, the debugger may wish to print an "out-of-date" warning ! about the compilation unit. The .debug_srcinfo section associated with each compilation will also have *************** *** 321,332 **** -------------------------------- ! In the current DWARF draft specification, no provision is made for recording ! any information about macro definitions and un-definitions. - Recently, a scheme for providing accurate information about macro definitions - an un-definitions was proposed (by me) to the UI/PLSIG. This scheme was - rejected by the UI/PLSIG for inclusion into the DWARF Version 1 specification, - but GNU DWARF implements this extension anyway (when the -g3 option is used). - GCC records information about macro definitions and undefinitions primarily in a section called the .debug_macinfo section. Normal entries in the --- 390,410 ---- -------------------------------- ! In the current DWARF version 1 specification, no mechanism is specified by ! which information about macro definitions and un-definitions may be provided ! to the DWARF consumer. ! ! The DWARF version 2 (draft) specification does specify such a mechanism. ! That specification was based on the GNU ("vendor specific extension") ! which provided some support for macro definitions and un-definitions, ! but the "official" DWARF version 2 (draft) specification mechanism for ! handling macros and the GNU implementation have diverged somewhat. I ! plan to update the GNU implementation to conform to the "official" ! DWARF version 2 (draft) specification as soon as I get time to do that. ! ! Note that in the GNU implementation, additional information about macro ! definitions and un-definitions is *only* provided when the -g3 level of ! debug-info production is selected. (The default level is -g2 and the ! plain old -g option is considered to be identical to -g2.) GCC records information about macro definitions and undefinitions primarily in a section called the .debug_macinfo section. Normal entries in the *************** *** 387,396 **** tracebacks (only) through fully-debugged code (e.g. code in system libraries). ! Recently, a proposal to define such a level was submitted (by me) to the ! UI/PLSIG. This proposal was rejected by the UI/PLSIG for inclusion into ! the DWARF Version 1 specification because it was felt that the issues ! involved in supporting a "traceback only" subset of dwarf were not yet ! well understood. Nonetheless, the GNU implementation of DWARF provides ! this extension anyway (when the -g1 option is used). -------------------------------- --- 465,491 ---- tracebacks (only) through fully-debugged code (e.g. code in system libraries). ! A proposal to define such a level was submitted (by me) to the UI/PLSIG. ! This proposal was rejected by the UI/PLSIG for inclusion into the DWARF ! version 1 specification for two reasons. First, it was felt (by the PLSIG) ! that the issues involved in supporting a "traceback only" subset of DWARF ! were not well understood. Second, and perhaps more importantly, the PLSIG ! is already having enough trouble agreeing on what it means to be "conformant" ! to the DWARF specification, and it was felt that trying to specify multiple ! different *levels* of conformance would only complicate our discussions of ! this already divisive issue. Nonetheless, the GNU implementation of DWARF ! provides an abbreviated "traceback only" level of debug-info production for ! use with fully-debugged "system library" code. This level should only be ! used for fully debugged system library code, and even then, it should only ! be used where there is a very strong need to conserve disk space. This ! abbreviated level of debug-info production can be used by specifying the ! -g1 option on the compilation command line. ! ! -------------------------------- ! ! As mentioned above, the GNU implementation of DWARF currently uses the DWARF ! version 2 (draft) approach for inline functions (and inlined instances ! thereof). This is used in preference to the version 1 approach because ! (quite simply) the version 1 approach is highly brain-damaged and probably ! unworkable. -------------------------------- *************** *** 416,428 **** In the case of inline functions, the DWARF representation is exactly as ! called for (in the current UI/PLSIG DWARF draft specification) for an ! identical function written in C++; i.e. we "reuse" the representation ! of inline functions defined for C++ to support this GNU C extension. In the case of dynamic arrays, we use the most obvious representational mechanism available; i.e. an array type in which the upper bound of some dimension (usually the first and only dimension) is a variable ! rather than a constant. See the UI/PLSIG DWARF draft specification ! for more details. In the case of incomplete enum types, such types are represented simply --- 511,523 ---- In the case of inline functions, the DWARF representation is exactly as ! called for in the DWARF version 2 (draft) specification for an identical ! function written in C++; i.e. we "reuse" the representation of inline ! functions which has been defined for C++ to support this GNU C extension. In the case of dynamic arrays, we use the most obvious representational mechanism available; i.e. an array type in which the upper bound of some dimension (usually the first and only dimension) is a variable ! rather than a constant. (See the DWARF version 1 specification for more ! details.) In the case of incomplete enum types, such types are represented simply *************** *** 437,458 **** The codes, formats, and other paraphernalia necessary to provide proper ! support for symbolic debugging for the C++ language have now been defined ! and accepted by the UI/PLSIG. Support for C++ (i.e. the g++ front-end) ! in dwarfout.c has not been fully implemented yet however. ! ! Likewise, the UI/PLSIG has defined what is believed to be a complete and ! sufficient set of codes and rules for adequately representing all of ! FORTRAN 77, and most of Fortran 90 in DWARF. While some support for ! this has been implemented in dwarfout.c, further implementation and ! testing will have to await the arrival of the GNU Fortran front-end. ! ! DWARF support for other languages (i.e. Pascal and Modula) currently has ! a number of known problems as far as the current UI/PLSIG DWARF draft ! specification is concerned. Hopefully, A more complete form of DWARF ! which can handle *all* of the symbolic debugging requirements for Pascal, ! Modula, and Ada will evolve in the future. Efforts are currently underway ! to develop DWARF more fully for these and other languages under the auspices ! of the UI/PLSIG. Contact the Chairman, Dan Oldman ! for further information. As currently defined, DWARF only describes a (binary) language which can --- 532,570 ---- The codes, formats, and other paraphernalia necessary to provide proper ! support for symbolic debugging for the C++ language are still being worked ! on by the UI/PLSIG. The vast majority of the additions to DWARF which will ! be needed to completely support C++ have already been hashed out and agreed ! upon, but a few small issues (e.g. anonymous unions, access declarations) ! are still being discussed. Also, we in the PLSIG are still discussing ! whether or not we need to do anything special for C++ templates. (At this ! time it is not yet clear whether we even need to do anything special for ! these.) ! ! Unfortunately, as mentioned above, there are quite a few problems in the ! g++ front end itself, and these are currently responsible for severly ! restricting the progress which can be made on adding DWARF support ! specifically for the g++ front-end. Furthermore, Richard Stallman has ! expressed the view that C++ friendships might not be important enough to ! describe (in DWARF). This view directly conflicts with both the DWARF ! version 1 and version 2 (draft) specifications, so until this small ! misunderstanding is cleared up, DWARF support for g++ is unlikely. ! ! With regard to FORTRAN, the UI/PLSIG has defined what is believed to be a ! complete and sufficient set of codes and rules for adequately representing ! all of FORTRAN 77, and most of Fortran 90 in DWARF. While some support for ! this has been implemented in dwarfout.c, further implementation and testing ! will have to await the arrival of the GNU Fortran front-end (which is ! currently in early alpha test as of this writing). ! ! GNU DWARF support for other languages (i.e. Pascal and Modula) is a moot ! issue until there are GNU front-ends for these other languages. ! ! GNU DWARF support for DWARF version 2 will probably not be attempted until ! such time as the version 2 specification is finalized. (More work needs ! to be done on the version 2 specification to make the new "abbreviations" ! feature of version 2 more easily implementable. Until then, it will be ! a royal pain the ass to implement version 2 "abbreviations".) For the ! time being, version 2 features will be added (in a version 1 compatible ! manner) when and where these features seem necessary or extremely desirable. As currently defined, DWARF only describes a (binary) language which can diff -rc2N gcc-2.2.2/README.RS6000 gcc-2.3.1/README.RS6000 *** gcc-2.2.2/README.RS6000 Sat Apr 25 02:10:23 1992 --- gcc-2.3.1/README.RS6000 Fri Jul 31 08:09:07 1992 *************** *** 12,19 **** ACTIVE line for something like 03.01.0005.0012.) Then call IBM Support at 800-237-5511. Ask for emergency shipment of the rs6000 AIX fix for ! APAR IX22829. They may ask you to verify that it's a fix for ".extern ! foo conflicts with defining foo"; say yes. They may also ask you for your customer number. If you do not know it, you will still be able ! to get the fix, but you will have to be persistent. You will receive a tar or tar.Z file containing an assembler plus --- 12,19 ---- ACTIVE line for something like 03.01.0005.0012.) Then call IBM Support at 800-237-5511. Ask for emergency shipment of the rs6000 AIX fix for ! APAR IX26107. They may ask you to verify that it's a fix for "Don't ! allow .csect name[BS] or [UC]"; say yes. They may also ask you for your customer number. If you do not know it, you will still be able ! to getthe fix, but you will have to be persistent. You will receive a tar or tar.Z file containing an assembler plus *************** *** 23,31 **** no fix is available yet. In fact the 3.15 fix works fine on version 3.2. Talk them into shipping it to you anyway. - - A second upgrade is in the works that will replace IX22829 and fix two - more problems with debug information. There's no scheduled - availability yet, but it's probably summer '92. Ask for the fix for - APAR IX26107, "Don't allow .csect name[BS] or [UC]" IBM has corresponding support organizations outside of North America. --- 23,26 ---- diff -rc2N gcc-2.2.2/README.X11 gcc-2.3.1/README.X11 *** gcc-2.2.2/README.X11 Fri May 29 15:15:32 1992 --- gcc-2.3.1/README.X11 Tue Sep 15 23:58:02 1992 *************** *** 39,42 **** --- 39,44 ---- mit/server/os/Imakefile -- Likewise. + mit/clients/twm/Imakefile -- fix bad decls of malloc, realloc in gram.c. + *** mit/config/Imake.tmpl.ORIG Tue Dec 31 11:07:56 1991 --- mit/config/Imake.tmpl Tue Dec 31 12:30:47 1991 *************** *** 160,161 **** --- 162,203 ---- $(RM) $@ cc -c $(DBM_DEFINES) $(CDEBUGFLAGS) $(ALLDEFINES) $*.c + *** 1.1 1992/09/08 19:52:07 + --- mit/server/ddx/sun/Imakefile 1992/09/08 21:10:22 + *************** + *** 43,48 **** + --- 43,53 ---- + LinkFile(sunGX.o,sunGX.o.dist) + #endif + + + #if HasGcc2 + + SpecialObjectRule(sunCG2C.o,sunCG2C.c,-fvolatile) + + SpecialObjectRule(sunCG2M.o,sunCG2M.c,-fvolatile) + + #endif + + + sunInitExtMono.o: $(ICONFIGFILES) + ObjectFromSpecialSource(sunInitExtMono,../mi/miinitext,-UPEXEXT) + ObjectFromSpecialSource(sunInitMono,sunInit,-DMONO_ONLY) + + *** /tmp/RCSAa24446 Tue Sep 15 12:23:32 1992 + --- mit/clients/twm/Imakefile Thu Aug 13 18:18:07 1992 + *************** + *** 32,41 **** + --- 32,48 ---- + ComplexProgramTarget(twm) + InstallNonExecFile(system.twmrc,$(TWMDIR)) + + + #if HasGcc2 && defined (SunArchitecture) + gram.h gram.c: gram.y + yacc $(YFLAGS) gram.y + + sed -e 's/^extern char \*malloc(), \*realloc();//g' y.tab.c >gram.c + + $(MV) y.tab.h gram.h + + #else + + gram.h gram.c: gram.y + + yacc $(YFLAGS) gram.y + $(MV) y.tab.c gram.c + $(MV) y.tab.h gram.h + + #endif + + clean:: + $(RM) y.tab.h y.tab.c lex.yy.c gram.h gram.c lex.c deftwmrc.c + diff -rc2N gcc-2.2.2/SERVICE gcc-2.3.1/SERVICE *** gcc-2.2.2/SERVICE Sun Jun 14 18:16:12 1992 --- gcc-2.3.1/SERVICE Sun Nov 1 03:43:23 1992 *************** *** 29,34 **** promote a specific unrelated business unless the client asks. ! Please include some indication of your rates, because otherwise ! users have nothing to go by. For a current copy of this directory, or to have yourself listed, ask: --- 29,35 ---- promote a specific unrelated business unless the client asks. ! Please include some indication of your rates, because otherwise users ! have nothing to go by. Please put each e-mail address inside "<>". ! Please put nothing else inside "<>". Thanks! For a current copy of this directory, or to have yourself listed, ask: *************** *** 38,53 ****  ! Joseph Arceneaux PO Box 460633 San Francisco, CA 94146-0633 +1 415 285 9088 ! FSF Staff Programmer. Performed X11 implementation of Emacs version 19. ! Currently working on hypertext emacs. Service and development of GNU and X11 software. Handholding, teaching, and installations at lower rates. ! Rates: $150/hour. Free to non-profits. Updated: 11/7/91 --- 39,54 ----  ! Joseph Arceneaux PO Box 460633 San Francisco, CA 94146-0633 +1 415 285 9088 ! Performed X11 implementation of Emacs version 19. ! Worked on Emacs text annotation. Service and development of GNU and X11 software. Handholding, teaching, and installations at lower rates. ! Rates: $150/hour. Free to selected non-profit and activist organizations. Updated: 11/7/91 *************** *** 80,85 **** D-6100 DARMSTADT West-Germany ! Phone 0049-6151-902762 (Work) Bitnet : ! Fax 0049-6151-90-495 Uucp : Your Rate: Free --- 81,86 ---- D-6100 DARMSTADT West-Germany ! Phone 0049-6151-902762 (Work) Bitnet : ! Fax 0049-6151-90-495 Uucp : Your Rate: Free *************** *** 112,120 **** I've written some 30,000 lines of Gnu Lisp code in total. ! Degree: PhD in CS from MIT. ! Other: My real life as a professor takes precedence over consulting. Updated: 11 Sept 91  Michael I. Bushnell NE43-426, 545 Technology Square --- 113,144 ---- I've written some 30,000 lines of Gnu Lisp code in total. ! Degree: PhD in CS from MIT. ! Other: My real life as a professor takes precedence over consulting. Updated: 11 Sept 91  + James Craig Burley + 4 Mountain Gate Rd. + Ashland, MA 01721-2326 + (508) 881-6087, -4745 + Email: (preferred) + + + + Expertise: + Compiler Internals (author of GNU Fortran, for example) + Operating Systems Internals (lately Linux on the ix86) + Tools/Utilities Development and Maintenance + Microcode Development and Maintenance (primarily VLIW machines) + Debugging (often asked to help debug Other People's Code) + Documentation (authored many books and ran a few doc projects) + Extensive experience with a variety of operating systems, hardware, + languages, and so on + + Rate: $75/hour, though somewhat volatile due to commitments regarding + GNU Fortran -- willing to consider flat-fee arrangements + + Entered: 10 Jul 92 +  Michael I. Bushnell NE43-426, 545 Technology Square *************** *** 160,167 **** Background: Bachelor of Science in Computer Science, Washington University ! Master of Science in Computer Science, Washington University ! Over 12 years experience in the computer industry. ! Author of the future GNU uu/xxen/decoder program. ! Skilled in many languages, including C and Unix scripts. Tasks: I can do on-site service in the St. Louis area. --- 184,191 ---- Background: Bachelor of Science in Computer Science, Washington University ! Master of Science in Computer Science, Washington University ! Over 12 years experience in the computer industry. ! Author of the future GNU uu/xxen/decoder program. ! Skilled in many languages, including C and Unix scripts. Tasks: I can do on-site service in the St. Louis area. *************** *** 174,177 **** --- 198,231 ---- Entered: 1/1/91  + Computing Support Team (CSTeam) + 111 College Place, Rm 2-212 + Syracuse, NY, 13244-4100 + + phone: 1-315-443-3929, fax: 1-315-443-4745, email: + + The Computing Support Team offers a wide variety of support services + including system design, installation, software support, contract + programming, network design, integration and migration services, + training, e-mail and telephone support. Experienced with GNU, X, TeX, + and other public domain software. + + Rates: $50-$80/hr, 33% non-profit discount. + + Entered: 10 Jul 92 +  + Contributed Software + Graefestr. 76 + 1000 Berlin 61, Germany + phone: (+49 30) 694 69 07 + modems: (+49 30) 694 {61 82 | 67 49 | 68 09} + email: + internet: scuzzy.contrib.de [192.109.39.1] + + We distribute, install/port, teach and support free software + in general, i.e. X11, GNU, khoros etc. + Rates are DM 150,-- plus tax per hour, educational sites get rebates. + + Entered: 10 Jul 92 +  Cygnus Support 814 University Avenue ...uunet!cygint!info *************** *** 181,185 **** Cygnus Support offers warranty protection (service contracts) for a ! number of free software tools. For a fixed annual fee our customers receive binary and source distributions, mail and phone support, documentation and customization assistance on a variety of popular --- 235,239 ---- Cygnus Support offers warranty protection (service contracts) for a ! number of free software tools. For a fixed annual fee our customers receive binary and source distributions, mail and phone support, documentation and customization assistance on a variety of popular *************** *** 188,192 **** At the time of this writing we offer support for a development package including (among other things) gcc, g++, gdb, and of course, GNU ! Emacs. We also offer support for a network facilities package including many of the Athena tools like Kerberos and Hesiod. However the set of supported tools and platforms increases frequently so --- 242,246 ---- At the time of this writing we offer support for a development package including (among other things) gcc, g++, gdb, and of course, GNU ! Emacs. We also offer support for a network facilities package including many of the Athena tools like Kerberos and Hesiod. However the set of supported tools and platforms increases frequently so *************** *** 205,209 **** (801) 298-6345 ! Will work on most GNU software. Especially GNU Emacs, GCC and a little X11 and G++. Experienced with PCs and 386s. --- 259,263 ---- (801) 298-6345 ! Will work on most GNU software. Especially GNU Emacs, GCC and a little X11 and G++. Experienced with PCs and 386s. *************** *** 215,220 ****  DePalma SoftCraft Contact: Mauro DePalma ! 2923 Cohansey Drive Voice: (408) 259-4789 ! San Jose, CA 95132-1619 Fax: (408) 259-6935 Internet: (or ) --- 269,274 ----  DePalma SoftCraft Contact: Mauro DePalma ! 2923 Cohansey Drive Voice: (408) 259-4789 ! San Jose, CA 95132-1619 Fax: (408) 259-6935 Internet: (or ) *************** *** 223,227 **** This small business provides consulting in every area of a computer ! s/w project life cycle. We specialize in UNIX, GNU Development Tools (gcc, g++, ...), RCS, and XView. --- 277,281 ---- This small business provides consulting in every area of a computer ! s/w project life cycle. We specialize in UNIX, GNU Development Tools (gcc, g++, ...), RCS, and XView. *************** *** 230,240 **** Equivalent Software HB Repslagaregatan 34 or ! 582 22 Linkoping SWEDEN +46 (0)13 13 54 21 Equivalent Software HB is the worlds second(?) company dedicated to ! supporting free UNIX software. The owners have more than 5 years of ! UNIX experience, both as system adminstrators and programmers. We also have extensive experience in maintaining the GNU programs, both administrating it and fixing bugs. --- 284,294 ---- Equivalent Software HB Repslagaregatan 34 or ! 582 22 Linkoping SWEDEN +46 (0)13 13 54 21 Equivalent Software HB is the worlds second(?) company dedicated to ! supporting free UNIX software. The owners have more than 5 years of ! UNIX experience, both as system adminstrators and programmers. We also have extensive experience in maintaining the GNU programs, both administrating it and fixing bugs. *************** *** 250,254 **** - Finding, Recommending and Investigation of free software in any area of the customers choise. ! - Regular consulting. We prefer smaller jobs, but are willing to consider larger ones. We can work through the Internet, but prefer jobs in Sweden. --- 304,308 ---- - Finding, Recommending and Investigation of free software in any area of the customers choise. ! - Regular consulting. We prefer smaller jobs, but are willing to consider larger ones. We can work through the Internet, but prefer jobs in Sweden. *************** *** 320,324 **** Updated: 9 Feb 92  ! Johannes M. Heuft Pfarrweg 2c D-8000 Munich 90 --- 374,378 ---- Updated: 9 Feb 92  ! Johannes M. Heuft Pfarrweg 2c D-8000 Munich 90 *************** *** 326,330 **** Telephone: Germany+89/681773 ! Rate: min. DM 180.- ($ 120.-) per hour interesting tasks for non-profit organisations may be free --- 380,384 ---- Telephone: Germany+89/681773 ! Rate: min. DM 180.- ($ 120.-) per hour interesting tasks for non-profit organisations may be free *************** *** 361,369 **** Hundred Acre is a consulting group providing support and development ! services to organizations of all sizes. We support all kinds of publicly available software, not just GNU; write for the current list. We work on a "service contract" basis for support -- for a yearly fee, we provide email and toll free telephone support, and free updates and bug fixes. Certain ! support levels even have free on-site support. Development is charged on either an hourly or fixed bid basis. --- 415,423 ---- Hundred Acre is a consulting group providing support and development ! services to organizations of all sizes. We support all kinds of publicly available software, not just GNU; write for the current list. We work on a "service contract" basis for support -- for a yearly fee, we provide email and toll free telephone support, and free updates and bug fixes. Certain ! support levels even have free on-site support. Development is charged on either an hourly or fixed bid basis. *************** *** 373,376 **** --- 427,450 ---- Updated: 2 Jul 91  + Jose A. Fernandez + + WORK: Inference Corporation HOME: + 550 N. Continental Blvd. 1025 Hillside Dr. + El Segundo, CA 90245 Chino Hills, CA 91709 + (310) 322-0200 (714) 528-2523 + + RATES: + $50-$200/hour plus expenses (or possibly free), depending on task. + + SERVICES: + GNU software: installation, troubleshooting, and customization. + X11 software: installation and troubleshooting. + SysAdmin: installation, configuration, and trouble-shooting. + NetAdmin: installation, configuration, and trouble-shooting. + Education: teaching how to fish opens the demand for fishing poles. + Advice: free over email. + + Entered: 10 Jul 92 +  Scott D. Kalter 970 Palm Ave. #218 *************** *** 379,383 **** Work: (213)524-1805 ! Emacs: e-lisp and C level customization/extension training for general use and customization user support, installation, troubleshooting --- 453,457 ---- Work: (213)524-1805 ! Emacs: e-lisp and C level customization/extension training for general use and customization user support, installation, troubleshooting *************** *** 398,402 **** Scott J. Kramer P.O. Box 3392 ! San Rafael, CA 94912 +1 415-454-1295 --- 472,476 ---- Scott J. Kramer P.O. Box 3392 ! San Rafael, CA 94912 +1 415-454-1295 *************** *** 425,429 **** Updated: 7/30/91  ! David C Lawrence P.O. Box 61 North Chatham, NY 12132-0061 --- 499,503 ---- Updated: 7/30/91  ! David C Lawrence P.O. Box 61 North Chatham, NY 12132-0061 *************** *** 437,444 **** Support: Emacs (both lisp and C aspects), GCC, GAWK, sed, fileutils, ! binutils, miscellaneous others. Definitely not G++. ! Consulting via email or telephone, or possibly on-site. ! Updated: Sept 11, 91  Marty Leisner --- 511,536 ---- Support: Emacs (both lisp and C aspects), GCC, GAWK, sed, fileutils, ! binutils, miscellaneous others. Definitely not G++. ! Consulting via email or telephone, or possibly on-site. ! ! Updated: 11 Sept 91 !  ! Greg Lehey ! LEMIS ! Schellnhausen 2 ! W-6324 Feldatal ! Germany ! ! Phone: +49-6637-1488 ! Fax: +49-6637-1489 ! Mail ! ! Services: Supply, porting, installation, consultation on all GNU ! products. ! Experience: 20 years OS and compiler experience, portations of most ! GNU products. ! ! Entered: 10 Jul 92  Marty Leisner *************** *** 448,465 **** Experience: 10 years C/Unix, 7 years DOS. ! Extensive experience with GNU binary tools, cross-compilers, embedded/hosted systems. Degree : BS CS, Cornell University ! Rates: $75/hr Updated: 6 Jul 91  ! Roland McGrath 545 Tech Sq rm 426 Cambridge, MA 02139 ! Work:(617)253-8568 ! Co-author and maintainer of GNU Make (with Richard Stallman). ! Author and maintainer of the GNU C Library. FSF employee summer 1989, fall 1990 to the present. --- 540,557 ---- Experience: 10 years C/Unix, 7 years DOS. ! Extensive experience with GNU binary tools, cross-compilers, embedded/hosted systems. Degree : BS CS, Cornell University ! Rates: $75/hr Updated: 6 Jul 91  ! Roland McGrath 545 Tech Sq rm 426 Cambridge, MA 02139 ! Work: (617) 253-8568 ! Co-author of GNU Make (with Richard Stallman); maintainer of GNU Make. ! Author and maintainer of the GNU C Library and parts of the GNU Hurd. FSF employee summer 1989, fall 1990 to the present. *************** *** 469,473 **** anywhere on the Internet. ! Updated: 12/15/90  Lee McLoughlin --- 561,565 ---- anywhere on the Internet. ! Updated: 10/18/92  Lee McLoughlin *************** *** 483,487 **** Ported emacs to two new platforms (WhiteChappel Worstations, ! HLH Orion). Worked on gcc port to Intergraph Clipper. Support various gnu packages as part of a teaching service. --- 575,579 ---- Ported emacs to two new platforms (WhiteChappel Worstations, ! HLH Orion). Worked on gcc port to Intergraph Clipper. Support various gnu packages as part of a teaching service. *************** *** 495,500 **** Updated: 10.10.91  ! T.S.Mohan ! KBCS Group Supercomputer Education and Research Centre Indian Institute of Science --- 587,592 ---- Updated: 10.10.91  ! T.S.Mohan ! KBCS Group Supercomputer Education and Research Centre Indian Institute of Science *************** *** 503,514 **** Telephone (01-91-812)-341811, -341805 ! Rate: NIL. Availability for consultancy depends on ! work load. High preference for academic institutions. Support: emacs, gdb, gcc, g++ and other small public domain utilities Experience: Installed and supported these + other gnu programs in our ! centre for the past three years. General help to sister academic ! departments and other academic institutions. Degrees: Master of Engineering in CS. Currently working towards a PhD ! in Distributed computing and programming languages. Updated: 1 Dec 1991 --- 595,606 ---- Telephone (01-91-812)-341811, -341805 ! Rate: NIL. Availability for consultancy depends on ! work load. High preference for academic institutions. Support: emacs, gdb, gcc, g++ and other small public domain utilities Experience: Installed and supported these + other gnu programs in our ! centre for the past three years. General help to sister academic ! departments and other academic institutions. Degrees: Master of Engineering in CS. Currently working towards a PhD ! in Distributed computing and programming languages. Updated: 1 Dec 1991 *************** *** 525,533 **** Mojave Systems is able to provide these services for a wide variety of ! hosts. We are currently porting GNU make and RCS to non-Unix hosts. Entered: 12 Dec 90  ! Eric Raible (raible@nas.nasa.gov) Nasa Ames Research Center Mail Stop T045-1 --- 617,625 ---- Mojave Systems is able to provide these services for a wide variety of ! hosts. We are currently porting GNU make and RCS to non-Unix hosts. Entered: 12 Dec 90  ! Eric Raible Nasa Ames Research Center Mail Stop T045-1 *************** *** 581,586 ****  John Sechrest ! Jasmic Systems Internet: ! 2140 SW 49th St. UUCP: Corvallis, Oregon 97333 --- 673,678 ----  John Sechrest ! Jasmic Systems Internet: ! 2140 SW 49th St. UUCP: Corvallis, Oregon 97333 *************** *** 621,625 **** Updated: 10 Oct 91  ! Lynn Slater 42075 Lawrence Place Fremont Ca 94538 --- 713,717 ---- Updated: 10 Oct 91  ! Lynn Slater 42075 Lawrence Place Fremont Ca 94538 *************** *** 630,639 **** Experiance: ! Gnu Emacs Ada Mode -- Co-author, principle integrator Gnu Emacs Empire Tool -- Originator, co-author, principle distributor Emacs -- Almost all parts. Authored super-apropos, headers, first GDB ! interface, fancy-lisp, enhanced scribe mode,and lots of small stuff ! g++ -- Have maintained, modified, and used G++ on 300+ user commercial ! OLTP software. gnumake -- Have bug fixed and extended. --- 722,731 ---- Experiance: ! Gnu Emacs Ada Mode -- Co-author, principle integrator Gnu Emacs Empire Tool -- Originator, co-author, principle distributor Emacs -- Almost all parts. Authored super-apropos, headers, first GDB ! interface, fancy-lisp, enhanced scribe mode,and lots of small stuff ! g++ -- Have maintained, modified, and used G++ on 300+ user commercial ! OLTP software. gnumake -- Have bug fixed and extended. *************** *** 653,657 **** Updated: 10 Oct 91  ! Small Business Systems, Inc. postmaster@anomaly.sbs.com Box 17220, Route 104 Esmond, RI 02917 --- 745,749 ---- Updated: 10 Oct 91  ! Small Business Systems, Inc. Box 17220, Route 104 Esmond, RI 02917 *************** *** 681,685 **** full-time for the GNU project on other GNU programs (June 1988 - August 1989). Primary maintainer of GDB and the GNU loader for that ! period. Resume available on request. Entered: 10 Feb 92 --- 773,777 ---- full-time for the GNU project on other GNU programs (June 1988 - August 1989). Primary maintainer of GDB and the GNU loader for that ! period. Resume available on request. Entered: 10 Feb 92 *************** *** 699,703 **** Entered: 5/24/90  ! Jonathan Stone c/o- Institute of Statistics and Operations Research Victoria University of Wellington --- 791,795 ---- Entered: 5/24/90  ! Jonathan Stone c/o- Institute of Statistics and Operations Research Victoria University of Wellington *************** *** 705,709 **** Wellington New Zealand ! Work: +64 4 715-315 Fax: +64 4 712-070 Rate: hourly rate: NZ $ 150/hr. Quick phone questions are free. --- 797,801 ---- Wellington New Zealand ! Work: +64 4 715-315 Fax: +64 4 712-070 Rate: hourly rate: NZ $ 150/hr. Quick phone questions are free. *************** *** 713,717 **** Programs: GNU Emacs, GCC, GDB, GNU binutils, Ghostscript, MIT X11 ! I am the author of the Pyramid ports of gcc and gdb. Experiance: Five years administration of Unix systems and GNU tools --- 805,809 ---- Programs: GNU Emacs, GCC, GDB, GNU binutils, Ghostscript, MIT X11 ! I am the author of the Pyramid ports of gcc and gdb. Experiance: Five years administration of Unix systems and GNU tools *************** *** 741,747 **** Entered: 2/16/92  Leonard H. Tower Jr. 36 Porter Street ! Somerville, MA 02143, USA +1 (617) 623-7739 --- 833,862 ---- Entered: 2/16/92  + Kayvan Sylvan + Sylvan Associates + 879 Lewiston Drive + San Jose, CA 95136 + Phone: 408-978-1407 + + I will help you port, install and customize GNU Emacs, GCC, G++, + bison, and other GNU tools on almost any architechture and operating + system. Questions answered. GNU C and lisp hacking available. I will + also do ongoing support and periodic upgrades if you get on my GNU + software subscription list. + + Rates: $60-$100/hour, depending on type of work. Substantial discounts + for long-term contracts and also for educational or non-profit + institutions. + + Experience: Many different Unix systems (2.9BSD to 4.3BSD, SVR3 and + SVR4, Xenix). Systems programming and system administration on all + brands of Unix. Kernel hacking experience. Lots of porting experience. + I can port anything to anything (within reason). + + Updated: 10 Jul 92 +  Leonard H. Tower Jr. 36 Porter Street ! Somerville, MA 02143, USA +1 (617) 623-7739 *************** *** 757,761 **** Entered: 12 Feb 92  ! Watchmaker Computing P.O.Box 163, Kendall Square Cambridge, MA 02142 --- 872,876 ---- Entered: 12 Feb 92  ! Watchmaker Computing P.O.Box 163, Kendall Square Cambridge, MA 02142 *************** *** 771,775 **** Entered: 1/16/91  ! Chris Welty RPI Computer Science Dept Troy, NY 12180 --- 886,890 ---- Entered: 1/16/91  ! Chris Welty RPI Computer Science Dept Troy, NY 12180 *************** *** 797,801 **** Experience: 12 years working with C, Unix and Lisp Machines including compilation systems, networks, device drivers, demand paging systems, ! boot programs and window systems. Ported GDB to 80386. Designed COFF encapsulation scheme to run GNU linker output on System 5 kernels. Author of Unix "ispell". --- 912,916 ---- Experience: 12 years working with C, Unix and Lisp Machines including compilation systems, networks, device drivers, demand paging systems, ! boot programs and window systems. Ported GDB to 80386. Designed COFF encapsulation scheme to run GNU linker output on System 5 kernels. Author of Unix "ispell". *************** *** 818,836 **** gnulib.c. Modified gcc and binutils to work in byte-swapped environments. ! Other: email consulting only (pipeline!phw@motown.com, ! uunet!motown!pipeline!phw,sun!pipeline!phw, amdcad!pipeline!phw) Updated: 18 Sept 91  ! Name: david d [zoo] zuhn ! Company: armadillo zoo software Fees: $50/hour, discounts for educational institutions and non-profits GNU and X11 installation and maintainance on SGI Iris, Sun [68k & ! SPARC], and Sequent machines. Additional machines a possibility. Any GNU software installed. Most supported. ! Entered: 2/12/92  ** Please keep this file alphabetical ** --- 933,968 ---- gnulib.c. Modified gcc and binutils to work in byte-swapped environments. ! Other: email consulting only , ! uunet!motown!pipeline!phw,sun!pipeline!phw, amdcad!pipeline!phw Updated: 18 Sept 91  ! xprt Computer Consulting, Inc. ! 17200 El Camino Real Suite 110 T ! Houston, TX 77058 ! (713) 480 UNIX ! (713) 486 8575 (Fax) ! ! Programs Supported: ! X11, TeX, and all of GNU. ! ! Experience: ! We have supported and maintained all of GNU, X11 and TeX for over four ! years for a major oil company's research division on several different ! Unix platforms. ! ! Rates: $150/hour ! ! Entered: 10 Jul 92 !  ! Name: david d [zoo] zuhn Company: armadillo zoo software Fees: $50/hour, discounts for educational institutions and non-profits GNU and X11 installation and maintainance on SGI Iris, Sun [68k & ! SPARC], and Sequent machines. Additional machines a possibility. Any GNU software installed. Most supported. ! Updated: 7/11/92  ** Please keep this file alphabetical ** diff -rc2N gcc-2.2.2/assert.h gcc-2.3.1/assert.h *** gcc-2.2.2/assert.h Mon Jun 8 17:12:58 1992 --- gcc-2.3.1/assert.h Tue Oct 6 15:11:05 1992 *************** *** 24,31 **** #ifdef __cplusplus extern "C" { ! extern void __eprintf (const char *, const char *, int, const char *); } #else ! extern void __eprintf (const char *, const char *, int, const char *); #endif --- 24,31 ---- #ifdef __cplusplus extern "C" { ! extern void __eprintf (const char *, const char *, unsigned, const char *); } #else ! extern void __eprintf (const char *, const char *, unsigned, const char *); #endif diff -rc2N gcc-2.2.2/basic-block.h gcc-2.3.1/basic-block.h *** gcc-2.2.2/basic-block.h Fri May 31 16:32:05 1991 --- gcc-2.3.1/basic-block.h Sat Aug 1 22:45:37 1992 *************** *** 19,26 **** /* Define the type for a pointer to a set with a bit for each (hard or pseudo) register. */ ! typedef long *regset; /* Size of a regset for the current function, --- 19,36 ---- + /* Number of bits in each actual element of a regset. */ + + #define REGSET_ELT_BITS HOST_BITS_PER_WIDE_INT + + /* Type to use for a regset element. Note that lots of code assumes + that the initial part of a regset that contains information on the + hard registers is the same format as a HARD_REG_SET. */ + + #define REGSET_ELT_TYPE HOST_WIDE_INT + /* Define the type for a pointer to a set with a bit for each (hard or pseudo) register. */ ! typedef REGSET_ELT_TYPE *regset; /* Size of a regset for the current function, *************** *** 29,36 **** extern int regset_bytes; extern int regset_size; - - /* Number of bits in each actual element of a regset. */ - - #define REGSET_ELT_BITS HOST_BITS_PER_INT /* Number of basic blocks in the current function. */ --- 39,42 ---- diff -rc2N gcc-2.2.2/build-make gcc-2.3.1/build-make *** gcc-2.2.2/build-make --- gcc-2.3.1/build-make Wed Oct 21 18:13:14 1992 *************** *** 0 **** --- 1,28 ---- + # We have to use the cross-compiler we just built to compile it. + CC = gcc -b $(target) -V $(version) + + # Need those to compile binaries running on host machine. + # It is configured by + # + # configure --host=target_cpu-target_os \ + # --target=host=target_cpu-target_os --build=host_cpu-host_os + # + # That HOST stuff has to be taken care of very carefully. + HOST_PREFIX=l- + HOST_PREFIX_1=$(HOST_PREFIX) + HOST_CC=$(CC) -b $(build) + HOST_CFLAGS=$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS) + HOST_CLIB= + HOST_LDFLAGS=$(LDFLAGS) + HOST_CPPFLAGS=$(ALL_CPPFLAGS) + HOST_ALLOCA=$(ALLOCA) + HOST_MALLOC=$(MALLOC) + HOST_OBSTACK=$(OBSTACK) + + + # Cause installation using install-build. We do nothing here. + INSTALL_TARGET = install-build + + # Don't try to compile the things we can't compile or we have made + # while making gcc with the cross-compiler. + ALL = all.build diff -rc2N gcc-2.2.2/c++ gcc-2.3.1/c++ *** gcc-2.2.2/c++ Tue May 26 14:56:14 1992 --- gcc-2.3.1/c++ Mon Oct 5 18:09:12 1992 *************** *** 3,76 **** : || exec /bin/sh -f $0 $argv:q ! newargs= ! quote=no library=-lg++ ! havefiles= ! for arg in $*; ! do ! if [ $quote = yes ] then ! newargs="$newargs $arg" ! quote=no else ! quote=no case $arg in -nostdlib) # Inhibit linking with -lg++. - newargs="$newargs $arg" library= ;; -[bBVDUoeTuIYmLiA] | -Tdata) - newargs="$newargs $arg" # these switches take following word as argument, # so don't treat it as a file name. ! quote=yes ;; -[cSEM] | -MM) # Don't specify libraries if we won't link, # since that would cause a warning. - newargs="$newargs $arg" library= ;; - -xnone) - newargs="$newargs $arg" - speclang= - ;; -x*) ! newargs="$newargs $arg" ! speclang=yes ;; -*) # Pass other options through; they don't need -x and aren't inputs. - newargs="$newargs $arg" ;; *) - havefiles=yes # If file ends in .c or .i, put options around it. # But not if a specified -x option is currently active. ! temp=`expr $arg : '.*\.[ci]$'` ! if [ \( x$temp != x0 \) -a \( x$speclang = x \) ] ! then ! newargs="$newargs -xc++ $arg -xnone" ! else ! newargs="$newargs $arg" ! fi ;; esac fi done ! if [ x$havefiles = x ] then ! echo "$0: no input files specified" exit 1 fi ! progname=`echo $0 |sed -e 's|/[^/]*$|/gcc|'` ! if [ -f ${progname} ] ! then ! exec ${progname} $newargs $library ! else ! exec gcc $newargs $library ! fi --- 3,100 ---- : || exec /bin/sh -f $0 $argv:q ! # The compiler name might be different when doing cross-compilation ! # (this should be configured) ! gcc_name=gcc ! speclang=-xnone ! ! # replace the command name by the name of the new command ! progname=`basename $0` ! case "$0" in ! */*) ! gcc=`echo $0 | sed -e "s;/[^/]*$;;"`/$gcc_name ! ;; ! *) ! gcc=$gcc_name ! ;; ! esac ! ! # $first is yes for first arg, no afterwards. ! first=yes ! # If next arg is the argument of an option, $quote is non-empty. ! # More precisely, it is the option that wants an argument. ! quote= ! # $library is made empty to disable use of libg++. library=-lg++ ! numargs=$# ! for arg do ! if [ $first = yes ] ! then ! # Need some 1st arg to `set' which does not begin with `-'. ! # We get rid of it after the loop ends. ! set gcc ! first=no ! fi ! # If you have to ask what this does, you should not edit this file. :-) ! # The ``S'' at the start is so that echo -nostdinc does not eat the ! # -nostdinc. ! arg=`echo "S$arg" | sed "s/^S//; s/'/'\\\\\\\\''/g"` ! if [ x$quote != x ] then ! quote= else ! quote= case $arg in -nostdlib) # Inhibit linking with -lg++. library= ;; + -lm) + # Because libg++ uses things from the math library, make sure it + # always comes before the math library. + set "$@" $library + library="" + ;; -[bBVDUoeTuIYmLiA] | -Tdata) # these switches take following word as argument, # so don't treat it as a file name. ! quote=$arg ;; -[cSEM] | -MM) # Don't specify libraries if we won't link, # since that would cause a warning. library= ;; -x*) ! speclang=$arg ! ;; ! -v) ! # catch `g++ -v' ! if [ $numargs = 1 ] ; then library="" ; fi ;; -*) # Pass other options through; they don't need -x and aren't inputs. ;; *) # If file ends in .c or .i, put options around it. # But not if a specified -x option is currently active. ! case "$speclang $arg" in -xnone\ *.[ci]) ! set "$@" -xc++ "'$arg'" -xnone ! continue ! esac ;; esac fi + set "$@" "'$arg'" done ! # Get rid of that initial 1st arg ! shift ! ! if [ x$quote != x ] then ! echo "$0: argument to \`$quote' missing" exit 1 fi ! eval $gcc "$@" $library diff -rc2N gcc-2.2.2/c-aux-info.c gcc-2.3.1/c-aux-info.c *** gcc-2.2.2/c-aux-info.c Wed Jun 10 00:15:39 1992 --- gcc-2.3.1/c-aux-info.c Sun Jul 19 21:54:00 1992 *************** *** 1,5 **** /* Generate information regarding function declarations and definitions based on information stored in GCC's tree structure. This code implements the ! -fgen-aux-info option. This code was written by Ron Guilmette (rfg@mcc.com). --- 1,5 ---- /* Generate information regarding function declarations and definitions based on information stored in GCC's tree structure. This code implements the ! -aux-info option. This code was written by Ron Guilmette (rfg@mcc.com). *************** *** 127,136 **** for (;;) { ! if (!strncmp (p, "volatile", 8)) { p += 9; continue; } ! if (!strncmp (p, "const", 5)) { p += 6; --- 127,136 ---- for (;;) { ! if (!strncmp (p, "volatile ", 9)) { p += 9; continue; } ! if (!strncmp (p, "const ", 6)) { p += 6; *************** *** 385,389 **** case ARRAY_TYPE: ! ret_val = gen_type (concat (ret_val, "[]"), TREE_TYPE (t), style); break; --- 385,400 ---- case ARRAY_TYPE: ! if (TYPE_SIZE (t) == 0 || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST) ! ret_val = gen_type (concat (ret_val, "[]"), TREE_TYPE (t), style); ! else if (int_size_in_bytes (t) == 0) ! ret_val = gen_type (concat (ret_val, "[0]"), TREE_TYPE (t), style); ! else ! { ! int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t))); ! char buff[10]; ! sprintf (buff, "[%d]", size); ! ret_val = gen_type (concat (ret_val, buff), ! TREE_TYPE (t), style); ! } break; *************** *** 569,573 **** ret_val = affix_data_type (ret_val); ! if (TREE_REGDECL (decl)) ret_val = concat ("register ", ret_val); if (TREE_PUBLIC (decl)) --- 580,584 ---- ret_val = affix_data_type (ret_val); ! if (DECL_REGISTER (decl)) ret_val = concat ("register ", ret_val); if (TREE_PUBLIC (decl)) *************** *** 602,606 **** { /* The first line tells which directory file names are relative to. ! Currently, -fgen-aux-info works only for files in the working directory, so just use a `.' as a placeholder for now. */ fprintf (aux_info_file, "/* compiled from: . */\n"); --- 613,617 ---- { /* The first line tells which directory file names are relative to. ! Currently, -aux-info works only for files in the working directory, so just use a `.' as a placeholder for now. */ fprintf (aux_info_file, "/* compiled from: . */\n"); diff -rc2N gcc-2.2.2/c-common.c gcc-2.3.1/c-common.c *** gcc-2.2.2/c-common.c Wed Jun 10 00:14:13 1992 --- gcc-2.3.1/c-common.c Thu Oct 1 14:58:42 1992 *************** *** 25,31 **** #include - #undef NULL - #define NULL 0 - /* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ --- 25,28 ---- *************** *** 46,50 **** if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) kind = "method"; ! name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); printable_name = (*decl_printable_name) (current_function_decl, &kind); } --- 43,51 ---- if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) kind = "method"; ! /* Allow functions to be nameless (such as artificial ones). */ ! if (DECL_NAME (current_function_decl)) ! name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); ! else ! name = ""; printable_name = (*decl_printable_name) (current_function_decl, &kind); } *************** *** 55,59 **** TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; ! TREE_USED (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (strlen (name) + 1, name); --- 56,61 ---- TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; ! DECL_SOURCE_LINE (decl) = 0; ! DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (strlen (name) + 1, name); *************** *** 67,71 **** TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; ! TREE_USED (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (strlen (printable_name) + 1, printable_name); --- 69,74 ---- TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; ! DECL_SOURCE_LINE (decl) = 0; ! DECL_IN_SYSTEM_HEADER (decl) = 1; DECL_IGNORED_P (decl) = 1; init = build_string (strlen (printable_name) + 1, printable_name); *************** *** 199,206 **** if (TREE_CODE (decl) == FIELD_DECL) DECL_PACKED (decl) = 1; } else if (TREE_VALUE (a) != 0 ! && TREE_CODE (TREE_VALUE (a)) == TREE_LIST ! && TREE_PURPOSE (TREE_VALUE (a)) == get_identifier ("mode")) { int i; --- 202,211 ---- if (TREE_CODE (decl) == FIELD_DECL) DECL_PACKED (decl) = 1; + /* We can't set DECL_PACKED for a VAR_DECL, because the bit is + used for DECL_REGISTER. It wouldn't mean anything anyway. */ } else if (TREE_VALUE (a) != 0 ! && TREE_CODE (TREE_VALUE (a)) == TREE_LIST ! && TREE_PURPOSE (TREE_VALUE (a)) == get_identifier ("mode")) { int i; *************** *** 218,222 **** TREE_TYPE (decl) = type; DECL_SIZE (decl) = 0; ! layout_decl (decl); } else --- 223,227 ---- TREE_TYPE (decl) = type; DECL_SIZE (decl) = 0; ! layout_decl (decl, 0); } else *************** *** 283,286 **** --- 288,301 ---- } + /* Print a warning if a constant expression had overflow in folding. */ + + void + constant_expression_warning (value) + tree value; + { + if (TREE_CODE (value) == INTEGER_CST && TREE_CONSTANT_OVERFLOW (value)) + pedwarn ("overflow in constant expression"); + } + void c_expand_expr_stmt (expr) *************** *** 311,316 **** /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! if (TREE_CODE (value) == NON_LVALUE_EXPR) ! value = TREE_OPERAND (value, 0); if (TREE_CODE (value) != INTEGER_CST --- 326,330 ---- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! STRIP_TYPE_NOPS (value); if (TREE_CODE (value) != INTEGER_CST *************** *** 324,327 **** --- 338,343 ---- value = default_conversion (value); + constant_expression_warning (value); + return value; } *************** *** 335,354 **** int unsignedp; { ! if (bits <= TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; ! if (bits <= TYPE_PRECISION (short_integer_type_node)) return unsignedp ? short_unsigned_type_node : short_integer_type_node; ! if (bits <= TYPE_PRECISION (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; ! if (bits <= TYPE_PRECISION (long_integer_type_node)) return unsignedp ? long_unsigned_type_node : long_integer_type_node; ! if (bits <= TYPE_PRECISION (long_long_integer_type_node)) return (unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node); return 0; } --- 351,382 ---- int unsignedp; { ! if (bits == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; ! if (bits == TYPE_PRECISION (short_integer_type_node)) return unsignedp ? short_unsigned_type_node : short_integer_type_node; ! if (bits == TYPE_PRECISION (integer_type_node)) return unsignedp ? unsigned_type_node : integer_type_node; ! if (bits == TYPE_PRECISION (long_integer_type_node)) return unsignedp ? long_unsigned_type_node : long_integer_type_node; ! if (bits == TYPE_PRECISION (long_long_integer_type_node)) return (unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node); + if (bits <= TYPE_PRECISION (intQI_type_node)) + return unsignedp ? unsigned_intQI_type_node : intQI_type_node; + + if (bits <= TYPE_PRECISION (intHI_type_node)) + return unsignedp ? unsigned_intHI_type_node : intHI_type_node; + + if (bits <= TYPE_PRECISION (intSI_type_node)) + return unsignedp ? unsigned_intSI_type_node : intSI_type_node; + + if (bits <= TYPE_PRECISION (intDI_type_node)) + return unsignedp ? unsigned_intDI_type_node : intDI_type_node; + return 0; } *************** *** 378,381 **** --- 406,421 ---- return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; + if (mode == TYPE_MODE (intQI_type_node)) + return unsignedp ? unsigned_intQI_type_node : intQI_type_node; + + if (mode == TYPE_MODE (intHI_type_node)) + return unsignedp ? unsigned_intHI_type_node : intHI_type_node; + + if (mode == TYPE_MODE (intSI_type_node)) + return unsignedp ? unsigned_intSI_type_node : intSI_type_node; + + if (mode == TYPE_MODE (intDI_type_node)) + return unsignedp ? unsigned_intDI_type_node : intDI_type_node; + if (mode == TYPE_MODE (float_type_node)) return float_type_node; *************** *** 880,883 **** --- 920,928 ---- TREE_TYPE (TREE_OPERAND (expr, 0)), TREE_OPERAND (expr, 1))), 1); + + case MODIFY_EXPR: + if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR) + warning ("suggest parentheses around assignment used as truth value"); + break; } diff -rc2N gcc-2.2.2/c-convert.c gcc-2.3.1/c-convert.c *** gcc-2.2.2/c-convert.c Wed Jun 10 00:16:47 1992 --- gcc-2.3.1/c-convert.c Fri Sep 11 03:31:23 1992 *************** *** 138,142 **** register enum tree_code ex_form = TREE_CODE (expr); ! if (outprec >= inprec) return build1 (NOP_EXPR, type, expr); --- 138,155 ---- register enum tree_code ex_form = TREE_CODE (expr); ! /* If we are widening the type, put in an explicit conversion. ! Similarly if we are not changing the width. However, if this is ! a logical operation that just returns 0 or 1, we can change the ! type of the expression (see below). */ ! ! if (TREE_CODE_CLASS (ex_form) == '<' ! || ex_form == TRUTH_AND_EXPR || ex_form == TRUTH_ANDIF_EXPR ! || ex_form == TRUTH_OR_EXPR || ex_form == TRUTH_ORIF_EXPR ! || ex_form == TRUTH_NOT_EXPR) ! { ! TREE_TYPE (expr) = type; ! return expr; ! } ! else if (outprec >= inprec) return build1 (NOP_EXPR, type, expr); *************** *** 165,182 **** case RSHIFT_EXPR: /* We can pass truncation down through right shifting ! when the shift count is a negative constant. */ ! if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST ! || TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)) > 0) ! break; ! goto trunc1; case LSHIFT_EXPR: /* We can pass truncation down through left shifting ! when the shift count is a positive constant. */ ! if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST ! || TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)) < 0) ! break; ! /* In this case, shifting is like multiplication. */ ! goto trunc1; case MAX_EXPR: --- 178,207 ---- case RSHIFT_EXPR: /* We can pass truncation down through right shifting ! when the shift count is a nonpositive constant. */ ! if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST ! && tree_int_cst_lt (TREE_OPERAND (expr, 1), integer_one_node)) ! goto trunc1; ! break; case LSHIFT_EXPR: /* We can pass truncation down through left shifting ! when the shift count is a nonnegative constant. */ ! if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST ! && ! tree_int_cst_lt (TREE_OPERAND (expr, 1), integer_zero_node) ! && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST) ! { ! /* If shift count is less than the width of the truncated type, ! really shift. */ ! if (tree_int_cst_lt (TREE_OPERAND (expr, 1), TYPE_SIZE (type))) ! /* In this case, shifting is like multiplication. */ ! goto trunc1; ! else ! /* If it is >= that width, result is zero. ! Handling this with trunc1 would give the wrong result: ! (int) ((long long) a << 32) is well defined (as 0) ! but (int) a << 32 is undefined and would get a warning. */ ! return convert_to_integer (type, integer_zero_node); ! } ! break; case MAX_EXPR: *************** *** 251,270 **** break; - case EQ_EXPR: - case NE_EXPR: - case GT_EXPR: - case GE_EXPR: - case LT_EXPR: - case LE_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_NOT_EXPR: - /* If we want result of comparison converted to a byte, - we can just regard it as a byte, since it is 0 or 1. */ - TREE_TYPE (expr) = type; - return expr; - case NEGATE_EXPR: case BIT_NOT_EXPR: --- 276,279 ---- *************** *** 336,339 **** --- 345,355 ---- convert (typex, arg2)))); } + else + /* It is sometimes worthwhile + to push the narrowing down through the conditional. */ + return fold (build (COND_EXPR, type, + TREE_OPERAND (expr, 0), + convert (type, TREE_OPERAND (expr, 1)), + convert (type, TREE_OPERAND (expr, 2)))); } } *************** *** 368,373 **** register enum tree_code code = TREE_CODE (type); ! if (type == TREE_TYPE (expr) || TREE_CODE (expr) == ERROR_MARK) return expr; if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; --- 384,392 ---- register enum tree_code code = TREE_CODE (type); ! if (type == TREE_TYPE (expr) ! || TREE_CODE (expr) == ERROR_MARK) return expr; + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold (build1 (NOP_EXPR, type, expr)); if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; diff -rc2N gcc-2.2.2/c-decl.c gcc-2.3.1/c-decl.c *** gcc-2.2.2/c-decl.c Wed Jun 10 00:20:56 1992 --- gcc-2.3.1/c-decl.c Wed Oct 28 16:28:28 1992 *************** *** 42,48 **** TYPENAME}; /* Typename (inside cast or sizeof) */ - #undef NULL - #define NULL 0 - #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT --- 42,45 ---- *************** *** 132,135 **** --- 129,142 ---- tree long_double_type_node; + tree intQI_type_node; + tree intHI_type_node; + tree intSI_type_node; + tree intDI_type_node; + + tree unsigned_intQI_type_node; + tree unsigned_intHI_type_node; + tree unsigned_intSI_type_node; + tree unsigned_intDI_type_node; + /* a VOID_TYPE node. */ *************** *** 228,232 **** at the end of the function. */ ! tree named_labels; /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ --- 235,239 ---- at the end of the function. */ ! static tree named_labels; /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ *************** *** 304,307 **** --- 311,318 ---- tree blocks; + /* The BLOCK node for this level, if one has been preallocated. + If 0, the BLOCK is allocated (if needed) when the level is popped. */ + tree this_block; + /* The binding level which this one is contained in (inherits from). */ struct binding_level *level_chain; *************** *** 355,359 **** static struct binding_level clear_binding_level ! = {NULL, NULL, NULL, NULL, NULL, 0, 0, 0}; /* Nonzero means unconditionally make a BLOCK for the next level pushed. */ --- 366,370 ---- static struct binding_level clear_binding_level ! = {NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0}; /* Nonzero means unconditionally make a BLOCK for the next level pushed. */ *************** *** 379,382 **** --- 390,394 ---- tree pushdecl (); tree builtin_function (); + void shadow_tag_warned (); static tree lookup_tag (); *************** *** 417,420 **** --- 429,433 ---- int flag_signed_bitfields = 1; + int explicit_flag_signed_bitfields = 0; /* Nonzero means handle `#ident' directives. 0 means ignore them. */ *************** *** 511,516 **** #endif } ! else if (!strcmp (p, "-fnotraditional")) ! ; else if (!strcmp (p, "-fsigned-char")) flag_signed_char = 1; --- 524,533 ---- #endif } ! else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional")) ! { ! flag_traditional = 0; ! flag_writable_strings = 0; ! dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1; ! } else if (!strcmp (p, "-fsigned-char")) flag_signed_char = 1; *************** *** 521,532 **** else if (!strcmp (p, "-fno-unsigned-char")) flag_signed_char = 1; ! else if (!strcmp (p, "-fsigned-bitfields")) ! flag_signed_bitfields = 1; ! else if (!strcmp (p, "-funsigned-bitfields")) ! flag_signed_bitfields = 0; ! else if (!strcmp (p, "-fno-signed-bitfields")) ! flag_signed_bitfields = 0; ! else if (!strcmp (p, "-fno-unsigned-bitfields")) ! flag_signed_bitfields = 1; else if (!strcmp (p, "-fshort-enums")) flag_short_enums = 1; --- 538,553 ---- else if (!strcmp (p, "-fno-unsigned-char")) flag_signed_char = 1; ! else if (!strcmp (p, "-fsigned-bitfields") ! || !strcmp (p, "-fno-unsigned-bitfields")) ! { ! flag_signed_bitfields = 1; ! explicit_flag_signed_bitfields = 1; ! } ! else if (!strcmp (p, "-funsigned-bitfields") ! || !strcmp (p, "-fno-signed-bitfields")) ! { ! flag_signed_bitfields = 0; ! explicit_flag_signed_bitfields = 1; ! } else if (!strcmp (p, "-fshort-enums")) flag_short_enums = 1; *************** *** 664,667 **** --- 685,689 ---- print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4); print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4); + print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4); } *************** *** 797,800 **** --- 819,823 ---- tree block = 0; tree decl; + int block_previously_created; keep |= current_binding_level->keep; *************** *** 847,851 **** && DECL_INITIAL (decl) != 0 && TREE_ADDRESSABLE (decl)) ! output_inline_function (decl); /* If there were any declarations or structure tags in that level, --- 870,882 ---- && DECL_INITIAL (decl) != 0 && TREE_ADDRESSABLE (decl)) ! { ! /* If this decl was copied from a file-scope decl ! on account of a block-scope extern decl, ! propagate TREE_ADDRESSABLE to the file-scope decl. */ ! if (DECL_ABSTRACT_ORIGIN (decl) != 0) ! TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; ! else ! output_inline_function (decl); ! } /* If there were any declarations or structure tags in that level, *************** *** 853,860 **** create a BLOCK to record them for the life of this function. */ ! if (keep || functionbody ! || (current_binding_level->keep_if_subblocks && subblocks != 0)) ! block = build_block (keep ? decls : 0, keep ? tags : 0, ! subblocks, 0, 0); /* In each subblock, record that this is its superior. */ --- 884,901 ---- create a BLOCK to record them for the life of this function. */ ! block = 0; ! block_previously_created = (current_binding_level->this_block != 0); ! if (block_previously_created) ! block = current_binding_level->this_block; ! else if (keep || functionbody ! || (current_binding_level->keep_if_subblocks && subblocks != 0)) ! block = make_node (BLOCK); ! if (block != 0) ! { ! BLOCK_VARS (block) = decls; ! BLOCK_TYPE_TAGS (block) = tags; ! BLOCK_SUBBLOCKS (block) = subblocks; ! remember_end_note (block); ! } /* In each subblock, record that this is its superior. */ *************** *** 871,875 **** /* If the ident. was used or addressed via a local extern decl, don't forget that fact. */ ! if (TREE_EXTERNAL (link)) { if (TREE_USED (link)) --- 912,916 ---- /* If the ident. was used or addressed via a local extern decl, don't forget that fact. */ ! if (DECL_EXTERNAL (link)) { if (TREE_USED (link)) *************** *** 941,946 **** DECL_INITIAL (current_function_decl) = block; else if (block) ! current_binding_level->blocks ! = chainon (current_binding_level->blocks, block); /* If we did not make a block for the level just exited, any blocks made for inner levels --- 982,990 ---- DECL_INITIAL (current_function_decl) = block; else if (block) ! { ! if (!block_previously_created) ! current_binding_level->blocks ! = chainon (current_binding_level->blocks, block); ! } /* If we did not make a block for the level just exited, any blocks made for inner levels *************** *** 978,981 **** --- 1022,1072 ---- return block; } + + /* Delete the node BLOCK from the current binding level. + This is used for the block inside a stmt expr ({...}) + so that the block can be reinserted where appropriate. */ + + void + delete_block (block) + tree block; + { + tree t; + if (current_binding_level->blocks == block) + current_binding_level->blocks = TREE_CHAIN (block); + for (t = current_binding_level->blocks; t;) + { + if (TREE_CHAIN (t) == block) + TREE_CHAIN (t) = TREE_CHAIN (block); + else + t = TREE_CHAIN (t); + } + TREE_CHAIN (block) = NULL; + /* Clear TREE_USED which is always set by poplevel. + The flag is set again if insert_block is called. */ + TREE_USED (block) = 0; + } + + /* Insert BLOCK at the end of the list of subblocks of the + current binding level. This is used when a BIND_EXPR is expanded, + to handle the BLOCK node inside teh BIND_EXPR. */ + + void + insert_block (block) + tree block; + { + TREE_USED (block) = 1; + current_binding_level->blocks + = chainon (current_binding_level->blocks, block); + } + + /* Set the BLOCK node for the innermost scope + (the one we are currently in). */ + + void + set_block (block) + register tree block; + { + current_binding_level->this_block = block; + } void *************** *** 1095,1103 **** tagged type we just added to the current binding level. This fake NULL-named TYPE_DECL node helps dwarfout.c to know when it needs ! to output a a representation of a tagged type, and it also gives us a convenient place to record the "scope start" address for the tagged type. */ ! TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL, type)); } --- 1186,1194 ---- tagged type we just added to the current binding level. This fake NULL-named TYPE_DECL node helps dwarfout.c to know when it needs ! to output a representation of a tagged type, and it also gives us a convenient place to record the "scope start" address for the tagged type. */ ! TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type)); } *************** *** 1117,1123 **** int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0); ! if (TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK ! || TREE_CODE (TREE_TYPE (olddecl)) == ERROR_MARK) types_match = 0; --- 1208,1216 ---- int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0); + tree oldtype = TREE_TYPE (olddecl); + tree newtype = TREE_TYPE (newdecl); ! if (TREE_CODE (newtype) == ERROR_MARK ! || TREE_CODE (oldtype) == ERROR_MARK) types_match = 0; *************** *** 1191,1194 **** --- 1284,1288 ---- && DECL_BUILT_IN (olddecl)) { + /* A function declaration for a built-in function. */ if (!TREE_PUBLIC (newdecl)) { *************** *** 1202,1222 **** } else if (!types_match) ! warning_with_decl (newdecl, "conflicting types for built-in function `%s'"); } else if (TREE_CODE (olddecl) == FUNCTION_DECL ! && DECL_BUILT_IN_NONANSI (olddecl)) { if (!TREE_PUBLIC (newdecl)) { ! /* If you declare a built-in function name as static, the ! built-in definition is overridden, ! but optionally warn this was a bad choice of name. */ ! if (warn_shadow) ! warning_with_decl (newdecl, "shadowing library function `%s'"); ! /* Discard the old built-in function. */ return 0; } else if (!types_match) ! warning_with_decl (newdecl, "conflicting types for library function `%s'"); } else if (!types_match --- 1296,1361 ---- } else if (!types_match) ! { ! /* Accept the return type of the new declaration if same modes. */ ! tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl)); ! tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl)); ! if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype)) ! { ! TREE_TYPE (TREE_TYPE (olddecl)) = newreturntype; ! types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); ! if (!types_match) ! TREE_TYPE (TREE_TYPE (olddecl)) = oldreturntype; ! } ! } ! if (!types_match) ! { ! /* If types don't match for a built-in, throw away the built-in. */ ! warning_with_decl (newdecl, "conflicting types for built-in function `%s'"); ! return 0; ! } } else if (TREE_CODE (olddecl) == FUNCTION_DECL ! && DECL_SOURCE_LINE (olddecl) == 0) { + /* A function declaration for a predeclared function + that isn't actually built in. */ if (!TREE_PUBLIC (newdecl)) { ! /* If you declare it as static, the ! default definition is overridden. */ return 0; } else if (!types_match) ! { ! /* If the types don't match, preserve volatility indication. ! Later on, we will discard everything else about the ! default declaration. */ ! TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); ! } ! } ! /* Permit char *foo () to match void *foo (...) if not pedantic, ! if one of them came from a system header file. */ ! else if (!types_match ! && TREE_CODE (olddecl) == FUNCTION_DECL ! && TREE_CODE (newdecl) == FUNCTION_DECL ! && TREE_CODE (TREE_TYPE (oldtype)) == POINTER_TYPE ! && TREE_CODE (TREE_TYPE (newtype)) == POINTER_TYPE ! && (DECL_IN_SYSTEM_HEADER (olddecl) ! || DECL_IN_SYSTEM_HEADER (newdecl)) ! && ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (newtype))) == void_type_node ! && TYPE_ARG_TYPES (oldtype) == 0 ! && self_promoting_args_p (TYPE_ARG_TYPES (newtype)) ! && TREE_TYPE (TREE_TYPE (oldtype)) == char_type_node) ! || ! (TREE_TYPE (TREE_TYPE (newtype)) == char_type_node ! && TYPE_ARG_TYPES (newtype) == 0 ! && self_promoting_args_p (TYPE_ARG_TYPES (oldtype)) ! && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node))) ! { ! if (pedantic) ! pedwarn_with_decl (newdecl, "conflicting types for `%s'"); ! /* Make sure we keep void * as ret type, not char *. */ ! if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node) ! TREE_TYPE (newdecl) = newtype = oldtype; } else if (!types_match *************** *** 1226,1232 **** && ! pedantic /* Return types must still match. */ ! && comptypes (TREE_TYPE (TREE_TYPE (olddecl)), ! TREE_TYPE (TREE_TYPE (newdecl))) ! && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) == 0)) { error_with_decl (newdecl, "conflicting types for `%s'"); --- 1365,1371 ---- && ! pedantic /* Return types must still match. */ ! && comptypes (TREE_TYPE (oldtype), ! TREE_TYPE (newtype)) ! && TYPE_ARG_TYPES (newtype) == 0)) { error_with_decl (newdecl, "conflicting types for `%s'"); *************** *** 1234,1254 **** involving an empty arglist vs a nonempty one. */ if (TREE_CODE (olddecl) == FUNCTION_DECL ! && comptypes (TREE_TYPE (TREE_TYPE (olddecl)), ! TREE_TYPE (TREE_TYPE (newdecl))) ! && ((TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == 0 && DECL_INITIAL (olddecl) == 0) || ! (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) == 0 && DECL_INITIAL (newdecl) == 0))) { /* Classify the problem further. */ ! register tree t = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); if (t == 0) ! t = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); for (; t; t = TREE_CHAIN (t)) { register tree type = TREE_VALUE (t); ! if (TREE_CHAIN (t) == 0 && type != void_type_node) { error ("A parameter list with an ellipsis can't match"); --- 1373,1394 ---- involving an empty arglist vs a nonempty one. */ if (TREE_CODE (olddecl) == FUNCTION_DECL ! && comptypes (TREE_TYPE (oldtype), ! TREE_TYPE (newtype)) ! && ((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0) || ! (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0))) { /* Classify the problem further. */ ! register tree t = TYPE_ARG_TYPES (oldtype); if (t == 0) ! t = TYPE_ARG_TYPES (newtype); for (; t; t = TREE_CHAIN (t)) { register tree type = TREE_VALUE (t); ! if (TREE_CHAIN (t) == 0 ! && TYPE_MAIN_VARIANT (type) != void_type_node) { error ("A parameter list with an ellipsis can't match"); *************** *** 1257,1264 **** } ! if (type == float_type_node ! || (TREE_CODE (type) == INTEGER_TYPE ! && (TYPE_PRECISION (type) ! < TYPE_PRECISION (integer_type_node)))) { error ("An argument type that has a default promotion"); --- 1397,1402 ---- } ! if (TYPE_MAIN_VARIANT (type) == float_type_node ! || C_PROMOTING_INTEGER_TYPE_P (type)) { error ("An argument type that has a default promotion"); *************** *** 1277,1286 **** error_with_decl (newdecl, errmsg); error_with_decl (olddecl, ! "`%s' previously declared here"); } else if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl) != 0 ! && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == 0 ! && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0) { register tree type, parm; --- 1415,1427 ---- error_with_decl (newdecl, errmsg); error_with_decl (olddecl, ! ((DECL_INITIAL (olddecl) ! && current_binding_level == global_binding_level) ! ? "`%s' previously defined here" ! : "`%s' previously declared here")); } else if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl) != 0 ! && TYPE_ARG_TYPES (oldtype) == 0 ! && TYPE_ARG_TYPES (newtype) != 0) { register tree type, parm; *************** *** 1288,1300 **** /* Prototype decl follows defn w/o prototype. */ ! for (parm = TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (olddecl)), ! type = TYPE_ARG_TYPES (TREE_TYPE (newdecl)), nargs = 1; ! (TREE_VALUE (parm) != void_type_node ! || TREE_VALUE (type) != void_type_node); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++) { ! if (TREE_VALUE (parm) == void_type_node ! || TREE_VALUE (type) == void_type_node) { errmsg = "prototype for `%s' follows and number of arguments"; --- 1429,1441 ---- /* Prototype decl follows defn w/o prototype. */ ! for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype), ! type = TYPE_ARG_TYPES (newtype), nargs = 1; ! (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) != void_type_node ! || TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++) { ! if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node ! || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) { errmsg = "prototype for `%s' follows and number of arguments"; *************** *** 1307,1312 **** in the prototype. */ && (! (flag_traditional ! && TREE_VALUE (parm) == integer_type_node ! && TREE_VALUE (type) == unsigned_type_node))) { errmsg = "prototype for `%s' follows and argument %d"; --- 1448,1453 ---- in the prototype. */ && (! (flag_traditional ! && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node ! && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))) { errmsg = "prototype for `%s' follows and argument %d"; *************** *** 1332,1344 **** but was previously declared not inline and has been called. */ if (TREE_CODE (olddecl) == FUNCTION_DECL ! && ! TREE_INLINE (olddecl) && TREE_INLINE (newdecl) && TREE_USED (olddecl)) warning_with_decl (newdecl, "`%s' declared inline after being called"); if (TREE_CODE (olddecl) == FUNCTION_DECL ! && TREE_INLINE (olddecl) != TREE_INLINE (newdecl) ! && ! (TREE_EXTERNAL (olddecl) && TREE_EXTERNAL (newdecl))) warning_with_decl (newdecl, ! "`%s' declarations disagree about `inline'"); /* It is nice to warn when a function is declared global first and then static. */ --- 1473,1485 ---- but was previously declared not inline and has been called. */ if (TREE_CODE (olddecl) == FUNCTION_DECL ! && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl) && TREE_USED (olddecl)) warning_with_decl (newdecl, "`%s' declared inline after being called"); if (TREE_CODE (olddecl) == FUNCTION_DECL ! && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl) ! && DECL_INITIAL (olddecl) != 0) warning_with_decl (newdecl, ! "`%s' declared inline after its definition"); /* It is nice to warn when a function is declared global first and then static. */ *************** *** 1358,1372 **** } /* Copy all the DECL_... slots specified in the new decl ! except for any that we copy here from the old type. */ if (types_match) { - tree oldtype = TREE_TYPE (olddecl); /* Merge the data types specified in the two decls. */ if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) TREE_TYPE (newdecl) = TREE_TYPE (olddecl) ! = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); /* Lay the type out, unless already done. */ --- 1499,1526 ---- } + /* Optionally warn about more than one declaration for the same name. */ + if (warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 + /* Dont warn about a function declaration + followed by a definition. */ + && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0 + && DECL_INITIAL (olddecl) == 0)) + { + warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope"); + warning_with_decl (olddecl, "previous declaration of `%s'"); + } + /* Copy all the DECL_... slots specified in the new decl ! except for any that we copy here from the old type. ! ! Past this point, we don't change OLDTYPE and NEWTYPE ! even if we change the types of NEWDECL and OLDDECL. */ if (types_match) { /* Merge the data types specified in the two decls. */ if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) TREE_TYPE (newdecl) = TREE_TYPE (olddecl) ! = common_type (newtype, oldtype); /* Lay the type out, unless already done. */ *************** *** 1389,1392 **** --- 1543,1549 ---- } + /* Keep the old rtl since we can safely use it. */ + DECL_RTL (newdecl) = DECL_RTL (olddecl); + /* Merge the type qualifiers. */ if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) *************** *** 1396,1400 **** TREE_READONLY (olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) ! TREE_THIS_VOLATILE (olddecl) = 1; /* Keep source location of definition rather than declaration. */ --- 1553,1561 ---- TREE_READONLY (olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) ! { ! TREE_THIS_VOLATILE (olddecl) = 1; ! if (TREE_CODE (newdecl) == VAR_DECL) ! make_var_volatile (newdecl); ! } /* Keep source location of definition rather than declaration. */ *************** *** 1405,1413 **** } /* Merge the initialization information. */ if (DECL_INITIAL (newdecl) == 0) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - /* Keep the old rtl since we can safely use it. */ - DECL_RTL (newdecl) = DECL_RTL (olddecl); } /* If cannot merge, then use the new type and qualifiers, --- 1566,1578 ---- } + /* Merge the unused-warning information. */ + if (DECL_IN_SYSTEM_HEADER (olddecl)) + DECL_IN_SYSTEM_HEADER (newdecl) = 1; + else if (DECL_IN_SYSTEM_HEADER (newdecl)) + DECL_IN_SYSTEM_HEADER (olddecl) = 1; + /* Merge the initialization information. */ if (DECL_INITIAL (newdecl) == 0) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); } /* If cannot merge, then use the new type and qualifiers, *************** *** 1433,1440 **** TREE_PUBLIC (DECL_NAME (olddecl)) = 0; } ! if (TREE_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); ! TREE_EXTERNAL (newdecl) = TREE_EXTERNAL (olddecl); /* An extern decl does not override previous storage class. */ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); --- 1598,1605 ---- TREE_PUBLIC (DECL_NAME (olddecl)) = 0; } ! if (DECL_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); ! DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); /* An extern decl does not override previous storage class. */ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); *************** *** 1443,1453 **** { TREE_STATIC (olddecl) = TREE_STATIC (newdecl); - TREE_EXTERNAL (olddecl) = 0; TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); } /* If either decl says `inline', this fn is inline, unless its definition was passed already. */ ! if (TREE_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0) ! TREE_INLINE (olddecl) = 1; /* Get rid of any built-in function if new arg types don't match it --- 1608,1619 ---- { TREE_STATIC (olddecl) = TREE_STATIC (newdecl); TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); } + /* If either decl says `inline', this fn is inline, unless its definition was passed already. */ ! if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0) ! DECL_INLINE (olddecl) = 1; ! DECL_INLINE (newdecl) = DECL_INLINE (olddecl); /* Get rid of any built-in function if new arg types don't match it *************** *** 1480,1486 **** } ! bcopy ((char *) newdecl + sizeof (struct tree_common), ! (char *) olddecl + sizeof (struct tree_common), ! sizeof (struct tree_decl) - sizeof (struct tree_common)); return 1; --- 1646,1659 ---- } ! /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. ! But preserve OLDdECL's DECL_UID. */ ! { ! register unsigned olddecl_uid = DECL_UID (olddecl); ! ! bcopy ((char *) newdecl + sizeof (struct tree_common), ! (char *) olddecl + sizeof (struct tree_common), ! sizeof (struct tree_decl) - sizeof (struct tree_common)); ! DECL_UID (olddecl) = olddecl_uid; ! } return 1; *************** *** 1508,1512 **** DECL_CONTEXT (x) = 0; ! if (warn_nested_externs && TREE_EXTERNAL (x) && b != global_binding_level && x != IDENTIFIER_IMPLICIT_DECL (name)) warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name)); --- 1681,1685 ---- DECL_CONTEXT (x) = 0; ! if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level && x != IDENTIFIER_IMPLICIT_DECL (name)) warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name)); *************** *** 1544,1548 **** since traditional compilers don't complain. */ if (!flag_traditional && TREE_PUBLIC (name) ! && ! TREE_PUBLIC (x) && ! TREE_EXTERNAL (x) /* We used to warn also for explicit extern followed by static, but sometimes you need to do it that way. */ --- 1717,1721 ---- since traditional compilers don't complain. */ if (!flag_traditional && TREE_PUBLIC (name) ! && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) /* We used to warn also for explicit extern followed by static, but sometimes you need to do it that way. */ *************** *** 1555,1566 **** IDENTIFIER_POINTER (name)); } ! if (warn_redundant_decls && line != 0) ! { ! warning ("redundant redeclaration of `%s' in same scope", ! IDENTIFIER_POINTER (name)); ! warning_with_file_and_line (file, line, ! "previous declaration of `%s'", ! IDENTIFIER_POINTER (name)); ! } return t; } --- 1728,1732 ---- IDENTIFIER_POINTER (name)); } ! return t; } *************** *** 1611,1615 **** if (TREE_CODE (x) == TYPE_DECL) { ! if (DECL_SOURCE_LINE (x) == 0 || !flag_gen_aux_info) { if (TYPE_NAME (TREE_TYPE (x)) == 0) --- 1777,1781 ---- if (TREE_CODE (x) == TYPE_DECL) { ! if (DECL_SOURCE_LINE (x) == 0) { if (TYPE_NAME (TREE_TYPE (x)) == 0) *************** *** 1626,1645 **** } ! /* Multiple external decls of the same identifier ought to match. */ ! if (TREE_EXTERNAL (x) && IDENTIFIER_GLOBAL_VALUE (name) != 0 ! && (TREE_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) ! || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))) ! /* We get warnings about inline functions where they are defined. ! Avoid duplicate warnings where they are used. */ ! && !TREE_INLINE (x)) ! { ! if (! comptypes (TREE_TYPE (x), ! TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)))) { pedwarn_with_decl (x, "type mismatch with previous external decl"); ! pedwarn_with_decl (IDENTIFIER_GLOBAL_VALUE (name), ! "previous external decl of `%s'"); } } --- 1792,1820 ---- } ! /* Multiple external decls of the same identifier ought to match. ! Check against both global declarations and out of scope (limbo) block ! level declarations. ! ! We get warnings about inline functions where they are defined. ! Avoid duplicate warnings where they are used. */ ! if (DECL_EXTERNAL (x) && ! DECL_INLINE (x)) ! { ! tree decl; ! ! if (IDENTIFIER_GLOBAL_VALUE (name) != 0 ! && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) ! || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name)))) ! decl = IDENTIFIER_GLOBAL_VALUE (name); ! else if (IDENTIFIER_LIMBO_VALUE (name) != 0) ! /* Decls in limbo are always extern, so no need to check that. */ ! decl = IDENTIFIER_LIMBO_VALUE (name); ! else ! decl = 0; ! if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))) { pedwarn_with_decl (x, "type mismatch with previous external decl"); ! pedwarn_with_decl (decl, "previous external decl of `%s'"); } } *************** *** 1661,1665 **** /* In PCC-compatibility mode, extern decls of vars with no current decl take effect at top level no matter where they are. */ ! if (flag_traditional && TREE_EXTERNAL (x) && lookup_name (name) == 0) { --- 1836,1840 ---- /* In PCC-compatibility mode, extern decls of vars with no current decl take effect at top level no matter where they are. */ ! if (flag_traditional && DECL_EXTERNAL (x) && lookup_name (name) == 0) { *************** *** 1705,1708 **** --- 1880,1886 ---- IDENTIFIER_GLOBAL_VALUE (name) = x; + /* We no longer care about any previous block level declarations. */ + IDENTIFIER_LIMBO_VALUE (name) = 0; + /* Don't forget if the function was used via an implicit decl. */ if (IDENTIFIER_IMPLICIT_DECL (name) *************** *** 1719,1723 **** /* If this real decl matches the implicit, don't complain. */ && ! (TREE_CODE (x) == FUNCTION_DECL ! && TREE_TYPE (TREE_TYPE (x)) == integer_type_node)) pedwarn ("`%s' was previously implicitly declared to return `int'", IDENTIFIER_POINTER (name)); --- 1897,1902 ---- /* If this real decl matches the implicit, don't complain. */ && ! (TREE_CODE (x) == FUNCTION_DECL ! && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x))) ! == integer_type_node))) pedwarn ("`%s' was previously implicitly declared to return `int'", IDENTIFIER_POINTER (name)); *************** *** 1726,1734 **** that is erroneous. */ if (TREE_PUBLIC (name) ! && ! TREE_PUBLIC (x) && ! TREE_EXTERNAL (x)) { ! /* Okay to declare an ANSI built-in as inline static. */ ! if (t != 0 && DECL_BUILT_IN (t) ! && TREE_INLINE (x)) ; /* Okay to declare a non-ANSI built-in as anything. */ --- 1905,1912 ---- that is erroneous. */ if (TREE_PUBLIC (name) ! && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x)) { ! /* Okay to redeclare an ANSI built-in as static. */ ! if (t != 0 && DECL_BUILT_IN (t)) ; /* Okay to declare a non-ANSI built-in as anything. */ *************** *** 1751,1757 **** /* If this is an extern function declaration, see if we ! have a global definition for the function. */ if (oldlocal == 0 ! && TREE_EXTERNAL (x) && !TREE_INLINE (x) && oldglobal != 0 && TREE_CODE (x) == FUNCTION_DECL --- 1929,1935 ---- /* If this is an extern function declaration, see if we ! have a global definition or declaration for the function. */ if (oldlocal == 0 ! && DECL_EXTERNAL (x) && !DECL_INLINE (x) && oldglobal != 0 && TREE_CODE (x) == FUNCTION_DECL *************** *** 1761,1771 **** if (! comptypes (TREE_TYPE (x), TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)))) ! pedwarn_with_decl (x, "local declaration of `%s' doesn't match global one"); ! /* If the global one is inline, make the local one inline. */ ! else if (TREE_INLINE (oldglobal) ! || DECL_BUILT_IN (oldglobal) ! || (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 ! && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0)) ! IDENTIFIER_LOCAL_VALUE (name) = oldglobal; } --- 1939,1969 ---- if (! comptypes (TREE_TYPE (x), TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)))) ! pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one"); ! else ! { ! /* Inner extern decl is inline if global one is. ! Copy enough to really inline it. */ ! if (DECL_INLINE (oldglobal)) ! { ! DECL_INLINE (x) = DECL_INLINE (oldglobal); ! DECL_INITIAL (x) = DECL_INITIAL (oldglobal); ! DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal); ! DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal); ! DECL_RESULT (x) = DECL_RESULT (oldglobal); ! TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal); ! DECL_ABSTRACT_ORIGIN (x) = oldglobal; ! } ! /* Inner extern decl is built-in if global one is. */ ! if (DECL_BUILT_IN (oldglobal)) ! { ! DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal); ! DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal)); ! } ! /* Keep the arg types from a file-scope fcn defn. */ ! if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 ! && DECL_INITIAL (oldglobal) ! && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0) ! TREE_TYPE (x) = TREE_TYPE (oldglobal); ! } } *************** *** 1776,1780 **** if (oldlocal == 0 && oldglobal != 0 && !TREE_PUBLIC (oldglobal) ! && TREE_EXTERNAL (x) && TREE_PUBLIC (x)) warning ("`%s' locally external but globally static", IDENTIFIER_POINTER (name)); --- 1974,1978 ---- if (oldlocal == 0 && oldglobal != 0 && !TREE_PUBLIC (oldglobal) ! && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) warning ("`%s' locally external but globally static", IDENTIFIER_POINTER (name)); *************** *** 1786,1797 **** if (oldlocal == 0 && oldglobal == 0 ! && TREE_EXTERNAL (x) && TREE_PUBLIC (x)) { TREE_PUBLIC (name) = 1; } /* Warn if shadowing an argument at the top level of the body. */ ! if (oldlocal != 0 && !TREE_EXTERNAL (x) /* This warning doesn't apply to the parms of a nested fcn. */ && ! current_binding_level->parm_flag --- 1984,2005 ---- if (oldlocal == 0 && oldglobal == 0 ! && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { TREE_PUBLIC (name) = 1; + + /* Save this decl, so that we can do type checking against + other decls after it falls out of scope. + + Only save it once. This prevents temporary decls created in + expand_inline_function from being used here, since this + will have been set when the inline function was parsed. + It also helps give slightly better warnings. */ + if (IDENTIFIER_LIMBO_VALUE (name) == 0) + IDENTIFIER_LIMBO_VALUE (name) = x; } /* Warn if shadowing an argument at the top level of the body. */ ! if (oldlocal != 0 && !DECL_EXTERNAL (x) /* This warning doesn't apply to the parms of a nested fcn. */ && ! current_binding_level->parm_flag *************** *** 1811,1817 **** /* Maybe warn if shadowing something else. */ ! else if (warn_shadow && !TREE_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ ! && !DECL_IGNORED_P (x) /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) --- 2019,2025 ---- /* Maybe warn if shadowing something else. */ ! else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ ! && DECL_SOURCE_LINE (x) != 0 /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) *************** *** 1901,1905 **** implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0); ! TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; --- 2109,2113 ---- implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0); ! DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; *************** *** 1915,1919 **** maybe_objc_check_decl (decl); ! rest_of_decl_compilation (decl, 0, 0, 0); if (warn_implicit && implicit_warning) --- 2123,2127 ---- maybe_objc_check_decl (decl); ! rest_of_decl_compilation (decl, NULL_PTR, 0, 0); if (warn_implicit && implicit_warning) *************** *** 1959,1964 **** /* However, defining once as extern inline and a second time in another way is ok. */ ! && !(TREE_INLINE (olddecl) && TREE_EXTERNAL (olddecl) ! && !(TREE_INLINE (newdecl) && TREE_EXTERNAL (newdecl)))) return "redefinition of `%s'"; return 0; --- 2167,2172 ---- /* However, defining once as extern inline and a second time in another way is ok. */ ! && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl) ! && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl)))) return "redefinition of `%s'"; return 0; *************** *** 1968,1972 **** /* Objects declared at top level: */ /* If at least one is a reference, it's ok. */ ! if (TREE_EXTERNAL (newdecl) || TREE_EXTERNAL (olddecl)) return 0; /* Reject two definitions. */ --- 2176,2180 ---- /* Objects declared at top level: */ /* If at least one is a reference, it's ok. */ ! if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) return 0; /* Reject two definitions. */ *************** *** 1987,1991 **** /* Reject two definitions, and reject a definition together with an external reference. */ ! if (!(TREE_EXTERNAL (newdecl) && TREE_EXTERNAL (olddecl))) return "redeclaration of `%s'"; return 0; --- 2195,2199 ---- /* Reject two definitions, and reject a definition together with an external reference. */ ! if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))) return "redeclaration of `%s'"; return 0; *************** *** 2015,2018 **** --- 2223,2229 ---- decl = build_decl (LABEL_DECL, id, void_type_node); + /* Make sure every label has an rtx. */ + label_rtx (decl); + /* A label not explicitly declared must be local to where it's ref'd. */ DECL_CONTEXT (decl) = current_function_decl; *************** *** 2281,2288 **** but not the same as either. */ ! char_type_node = ! (flag_signed_char ! ? make_signed_type (CHAR_TYPE_SIZE) ! : make_unsigned_type (CHAR_TYPE_SIZE)); pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), char_type_node)); --- 2492,2499 ---- but not the same as either. */ ! char_type_node ! = (flag_signed_char ! ? make_signed_type (CHAR_TYPE_SIZE) ! : make_unsigned_type (CHAR_TYPE_SIZE)); pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), char_type_node)); *************** *** 2347,2350 **** --- 2558,2585 ---- unsigned_char_type_node)); + intQI_type_node = make_signed_type (8); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node)); + + intHI_type_node = make_signed_type (16); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node)); + + intSI_type_node = make_signed_type (32); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node)); + + intDI_type_node = make_signed_type (64); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); + + unsigned_intQI_type_node = make_unsigned_type (8); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); + + unsigned_intHI_type_node = make_unsigned_type (16); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node)); + + unsigned_intSI_type_node = make_unsigned_type (32); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node)); + + unsigned_intDI_type_node = make_unsigned_type (64); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node)); + float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; *************** *** 2423,2427 **** void_ftype_any ! = build_function_type (void_type_node, 0); double_ftype_double --- 2658,2662 ---- void_ftype_any ! = build_function_type (void_type_node, NULL_TREE); double_ftype_double *************** *** 2499,2519 **** /* ``integer_tpe_node'' misspelling corrected: North-Keys 30 Mar 91 */ ! builtin_function ("__builtin_constant_p", ! build_function_type (integer_type_node, endlink), ! BUILT_IN_CONSTANT_P, 0); builtin_function ("__builtin_return_address", ! build_function_type (integer_type_node, tree_cons (NULL_TREE, unsigned_type_node, endlink)), ! BUILT_IN_RETURN_ADDRESS, 0); builtin_function ("__builtin_frame_address", ! build_function_type (integer_type_node, tree_cons (NULL_TREE, unsigned_type_node, endlink)), ! BUILT_IN_FRAME_ADDRESS, 0); builtin_function ("__builtin_alloca", --- 2734,2753 ---- /* ``integer_tpe_node'' misspelling corrected: North-Keys 30 Mar 91 */ ! builtin_function ("__builtin_constant_p", int_ftype_int, ! BUILT_IN_CONSTANT_P, NULL_PTR); builtin_function ("__builtin_return_address", ! build_function_type (ptr_type_node, tree_cons (NULL_TREE, unsigned_type_node, endlink)), ! BUILT_IN_RETURN_ADDRESS, NULL_PTR); builtin_function ("__builtin_frame_address", ! build_function_type (ptr_type_node, tree_cons (NULL_TREE, unsigned_type_node, endlink)), ! BUILT_IN_FRAME_ADDRESS, NULL_PTR); builtin_function ("__builtin_alloca", *************** *** 2530,2537 **** sizetype, endlink)), ! BUILT_IN_ALLOCA, 0); /* Suppress error if redefined as a non-function. */ DECL_BUILT_IN_NONANSI (temp) = 1; ! temp = builtin_function ("_exit", void_ftype_any, NOT_BUILT_IN, 0); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; --- 2764,2772 ---- sizetype, endlink)), ! BUILT_IN_ALLOCA, NULL_PTR); /* Suppress error if redefined as a non-function. */ DECL_BUILT_IN_NONANSI (temp) = 1; ! temp = builtin_function ("_exit", void_ftype_any, NOT_BUILT_IN, ! NULL_PTR); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; *************** *** 2540,2549 **** } ! builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, 0); ! builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS, 0); ! builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS, 0); ! builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, 0); ! builtin_function ("__builtin_saveregs", default_function_type, ! BUILT_IN_SAVEREGS, 0); /* EXPAND_BUILTIN_VARARGS is obsolete. */ #if 0 --- 2775,2787 ---- } ! builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); ! builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS, ! NULL_PTR); ! builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS, ! NULL_PTR); ! builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); ! builtin_function ("__builtin_saveregs", ! build_function_type (ptr_type_node, NULL_TREE), ! BUILT_IN_SAVEREGS, NULL_PTR); /* EXPAND_BUILTIN_VARARGS is obsolete. */ #if 0 *************** *** 2553,2563 **** integer_type_node, endlink)), ! BUILT_IN_VARARGS, 0); #endif builtin_function ("__builtin_classify_type", default_function_type, ! BUILT_IN_CLASSIFY_TYPE, 0); builtin_function ("__builtin_next_arg", build_function_type (ptr_type_node, endlink), ! BUILT_IN_NEXT_ARG, 0); builtin_function ("__builtin_args_info", build_function_type (integer_type_node, --- 2791,2801 ---- integer_type_node, endlink)), ! BUILT_IN_VARARGS, NULL_PTR); #endif builtin_function ("__builtin_classify_type", default_function_type, ! BUILT_IN_CLASSIFY_TYPE, NULL_PTR); builtin_function ("__builtin_next_arg", build_function_type (ptr_type_node, endlink), ! BUILT_IN_NEXT_ARG, NULL_PTR); builtin_function ("__builtin_args_info", build_function_type (integer_type_node, *************** *** 2565,2569 **** integer_type_node, endlink)), ! BUILT_IN_ARGS_INFO, 0); /* Currently under experimentation. */ --- 2803,2807 ---- integer_type_node, endlink)), ! BUILT_IN_ARGS_INFO, NULL_PTR); /* Currently under experimentation. */ *************** *** 2580,2583 **** --- 2818,2826 ---- builtin_function ("__builtin_fsqrt", double_ftype_double, BUILT_IN_FSQRT, "sqrt"); + builtin_function ("__builtin_sin", double_ftype_double, + BUILT_IN_SIN, "sin"); + builtin_function ("__builtin_cos", double_ftype_double, + BUILT_IN_COS, "cos"); + /* In an ANSI C program, it is okay to supply built-in meanings for these functions, since applications cannot validly use them *************** *** 2586,2598 **** if (!flag_no_builtin) { ! builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, 0); ! builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, 0); ! builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, 0); ! builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, 0); ! builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, 0); ! builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, 0); ! builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, 0); ! builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, 0); ! builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, 0); /* Declare these functions volatile --- 2829,2846 ---- if (!flag_no_builtin) { ! builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); ! builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR); ! builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR); ! builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR); ! builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, ! NULL_PTR); ! builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, ! NULL_PTR); ! builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, ! NULL_PTR); ! builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR); ! builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR); ! builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR); ! builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR); /* Declare these functions volatile *************** *** 2600,2607 **** /* Don't specify the argument types, to avoid errors from certain code which isn't valid in ANSI but which exists. */ ! temp = builtin_function ("abort", void_ftype_any, NOT_BUILT_IN, 0); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; ! temp = builtin_function ("exit", void_ftype_any, NOT_BUILT_IN, 0); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; --- 2848,2856 ---- /* Don't specify the argument types, to avoid errors from certain code which isn't valid in ANSI but which exists. */ ! temp = builtin_function ("abort", void_ftype_any, NOT_BUILT_IN, ! NULL_PTR); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; ! temp = builtin_function ("exit", void_ftype_any, NOT_BUILT_IN, NULL_PTR); TREE_THIS_VOLATILE (temp) = 1; TREE_SIDE_EFFECTS (temp) = 1; *************** *** 2611,2623 **** /* Support for these has not been written in either expand_builtin or build_function_call. */ ! builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, 0); ! builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, 0); ! builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, 0); ! builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, 0); ! builtin_function ("__builtin_fmod", double_ftype_double_double, BUILT_IN_FMOD, 0); ! builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, 0); ! builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, BUILT_IN_MEMSET, 0); ! builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, 0); ! builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, 0); #endif --- 2860,2879 ---- /* Support for these has not been written in either expand_builtin or build_function_call. */ ! builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR); ! builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR); ! builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR, ! NULL_PTR); ! builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL, ! NULL_PTR); ! builtin_function ("__builtin_fmod", double_ftype_double_double, ! BUILT_IN_FMOD, NULL_PTR); ! builtin_function ("__builtin_frem", double_ftype_double_double, ! BUILT_IN_FREM, NULL_PTR); ! builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, ! BUILT_IN_MEMSET, NULL_PTR); ! builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, ! NULL_PTR); ! builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, ! NULL_PTR); #endif *************** *** 2646,2650 **** { tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); ! TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; /* If -traditional, permit redefining a builtin function any way you like. --- 2902,2906 ---- { tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); ! DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; /* If -traditional, permit redefining a builtin function any way you like. *************** *** 2655,2659 **** if (library_name) DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name); ! make_decl_rtl (decl, 0, 1); pushdecl (decl); if (function_code != NOT_BUILT_IN) --- 2911,2915 ---- if (library_name) DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name); ! make_decl_rtl (decl, NULL_PTR, 1); pushdecl (decl); if (function_code != NOT_BUILT_IN) *************** *** 2662,2665 **** --- 2918,2925 ---- DECL_SET_FUNCTION_CODE (decl, function_code); } + /* Warn if a function in the namespace for users + is used without an occasion to consider it declared. */ + if (name[0] != '_' || name[1] != '_') + C_DECL_ANTICIPATED (decl) = 1; return decl; *************** *** 2678,2683 **** tree declspecs; { int found_tag = 0; - int warned = 0; register tree link; --- 2938,2950 ---- tree declspecs; { + shadow_tag_warned (declspecs, 0); + } + + void + shadow_tag_warned (declspecs, warned) + tree declspecs; + int warned; + { int found_tag = 0; register tree link; *************** *** 2700,2704 **** if (name == 0) { ! if (code != ENUMERAL_TYPE) /* Empty unnamed enum OK */ { pedwarn ("unnamed struct/union that defines no instances"); --- 2967,2971 ---- if (name == 0) { ! if (!warned && code != ENUMERAL_TYPE) /* Empty unnamed enum OK */ { pedwarn ("unnamed struct/union that defines no instances"); *************** *** 2720,2724 **** { if (!warned) ! warning ("useless keyword or type name in empty declaration"); warned = 1; } --- 2987,2991 ---- { if (!warned) ! pedwarn ("useless keyword or type name in empty declaration"); warned = 1; } *************** *** 2855,2864 **** #if 0 /* Seems redundant with grokdeclarator. */ if (current_binding_level != global_binding_level ! && TREE_EXTERNAL (decl) && TREE_CODE (decl) != FUNCTION_DECL) warning ("declaration of `%s' has `extern' and is initialized", IDENTIFIER_POINTER (DECL_NAME (decl))); #endif ! TREE_EXTERNAL (decl) = 0; if (current_binding_level == global_binding_level) TREE_STATIC (decl) = 1; --- 3122,3131 ---- #if 0 /* Seems redundant with grokdeclarator. */ if (current_binding_level != global_binding_level ! && DECL_EXTERNAL (decl) && TREE_CODE (decl) != FUNCTION_DECL) warning ("declaration of `%s' has `extern' and is initialized", IDENTIFIER_POINTER (DECL_NAME (decl))); #endif ! DECL_EXTERNAL (decl) = 0; if (current_binding_level == global_binding_level) TREE_STATIC (decl) = 1; *************** *** 2943,2953 **** } ! /* For top-level declaration, the initial value was read in ! the temporary obstack. MAXINDEX, rtl, etc. to be made below ! must go in the permanent obstack; but don't discard the temporary data yet. */ ! if (current_binding_level == global_binding_level && temporary) end_temporary_allocation (); /* Deduce size of array from initialization, if not already known */ --- 3210,3222 ---- } ! /* Pop back to the obstack that is current for this binding level. ! This is because MAXINDEX, rtl, etc. to be made below ! must go in the permanent obstack. But don't discard the temporary data yet. */ ! pop_obstacks (); ! #if 0 /* pop_obstacks was near the end; this is what was here. */ if (current_binding_level == global_binding_level && temporary) end_temporary_allocation (); + #endif /* Deduce size of array from initialization, if not already known */ *************** *** 2962,2966 **** may have incomplete type at first. */ ? pedantic && !TREE_PUBLIC (decl) ! : !TREE_EXTERNAL (decl)); int failure = complete_array_type (type, DECL_INITIAL (decl), do_default); --- 3231,3235 ---- may have incomplete type at first. */ ? pedantic && !TREE_PUBLIC (decl) ! : !DECL_EXTERNAL (decl)); int failure = complete_array_type (type, DECL_INITIAL (decl), do_default); *************** *** 2977,2981 **** error_with_decl (decl, "array size missing in `%s'"); else if (!pedantic && TREE_STATIC (decl)) ! TREE_EXTERNAL (decl) = 1; } --- 3246,3250 ---- error_with_decl (decl, "array size missing in `%s'"); else if (!pedantic && TREE_STATIC (decl)) ! DECL_EXTERNAL (decl) = 1; } *************** *** 2990,3011 **** if (TREE_CODE (decl) == VAR_DECL) { ! if (TREE_STATIC (decl) && DECL_SIZE (decl) == 0) ! { ! /* A static variable with an incomplete type: ! that is an error if it is initialized or `static'. ! Otherwise, let it through, but if it is not `extern' ! then it may cause an error message later. */ ! if (! (TREE_PUBLIC (decl) && DECL_INITIAL (decl) == 0)) ! error_with_decl (decl, "storage size of `%s' isn't known"); ! } ! else if (!TREE_EXTERNAL (decl) && DECL_SIZE (decl) == 0) { - /* An automatic variable with an incomplete type: - that is an error. */ error_with_decl (decl, "storage size of `%s' isn't known"); TREE_TYPE (decl) = error_mark_node; } ! if ((TREE_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) --- 3259,3280 ---- if (TREE_CODE (decl) == VAR_DECL) { ! if (DECL_SIZE (decl) == 0 ! && (TREE_STATIC (decl) ! ? ! /* A static variable with an incomplete type ! is an error if it is initialized or `static'. ! Otherwise, let it through, but if it is not `extern' ! then it may cause an error message later. */ ! !TREE_PUBLIC (decl) || DECL_INITIAL (decl) ! : ! /* An automatic variable with an incomplete type ! is an error. */ ! !DECL_EXTERNAL (decl))) { error_with_decl (decl, "storage size of `%s' isn't known"); TREE_TYPE (decl) = error_mark_node; } ! if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) *************** *** 3043,3047 **** if it used to be an incomplete type. */ if (was_incomplete ! && ! TREE_STATIC (decl) && ! TREE_EXTERNAL (decl)) { /* If we used it already as memory, it must stay in memory. */ --- 3312,3316 ---- if it used to be an incomplete type. */ if (was_incomplete ! && ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)) { /* If we used it already as memory, it must stay in memory. */ *************** *** 3053,3057 **** } /* Compute and store the initial value. */ ! expand_decl_init (decl); } } --- 3322,3327 ---- } /* Compute and store the initial value. */ ! if (TREE_CODE (decl) != FUNCTION_DECL) ! expand_decl_init (decl); } } *************** *** 3061,3065 **** /* This is a no-op in c-lang.c or something real in objc-actions.c. */ maybe_objc_check_decl (decl); ! rest_of_decl_compilation (decl, 0, current_binding_level == global_binding_level, 0); --- 3331,3335 ---- /* This is a no-op in c-lang.c or something real in objc-actions.c. */ maybe_objc_check_decl (decl); ! rest_of_decl_compilation (decl, NULL_PTR, current_binding_level == global_binding_level, 0); *************** *** 3075,3084 **** } /* Resume permanent allocation, if not within a function. */ /* The corresponding push_obstacks_nochange is in start_decl, and in push_parm_decl and in grokfield. */ pop_obstacks (); ! if (current_binding_level == global_binding_level && temporary) ! /* Actually free the temporary space that we no longer need. */ permanent_allocation (); --- 3345,3358 ---- } + #if 0 /* Resume permanent allocation, if not within a function. */ /* The corresponding push_obstacks_nochange is in start_decl, and in push_parm_decl and in grokfield. */ pop_obstacks (); ! #endif ! ! /* If we have gone back from temporary to permanent allocation, ! actually free the temporary space that we no longer need. */ ! if (temporary && !allocation_temporary_p ()) permanent_allocation (); *************** *** 3350,3354 **** pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); else if (longlong) ! warning ("`long long long' is too long for GCC"); else longlong = 1; --- 3624,3628 ---- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); else if (longlong) ! error ("`long long long' is too long for GCC"); else longlong = 1; *************** *** 3411,3415 **** /* Long double is a special combination. */ ! if ((specbits & 1 << (int) RID_LONG) && type == double_type_node) { specbits &= ~ (1 << (int) RID_LONG); --- 3685,3690 ---- /* Long double is a special combination. */ ! if ((specbits & 1 << (int) RID_LONG) ! && TYPE_MAIN_VARIANT (type) == double_type_node) { specbits &= ~ (1 << (int) RID_LONG); *************** *** 3465,3469 **** if (specbits & 1 << (int) RID_UNSIGNED /* Traditionally, all bitfields are unsigned. */ ! || (bitfield && flag_traditional) || (bitfield && ! flag_signed_bitfields && (explicit_int || explicit_char --- 3740,3745 ---- if (specbits & 1 << (int) RID_UNSIGNED /* Traditionally, all bitfields are unsigned. */ ! || (bitfield && flag_traditional ! && (! explicit_flag_signed_bitfields || !flag_signed_bitfields)) || (bitfield && ! flag_signed_bitfields && (explicit_int || explicit_char *************** *** 3612,3616 **** /* Check for some types that there cannot be arrays of. */ ! if (type == void_type_node) { error ("declaration of `%s' as array of voids", name); --- 3888,3892 ---- /* Check for some types that there cannot be arrays of. */ ! if (TYPE_MAIN_VARIANT (type) == void_type_node) { error ("declaration of `%s' as array of voids", name); *************** *** 3637,3642 **** { /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! while (TREE_CODE (size) == NON_LVALUE_EXPR) ! size = TREE_OPERAND (size, 0); if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE --- 3913,3917 ---- { /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! STRIP_TYPE_NOPS (size); if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE *************** *** 3708,3711 **** --- 3983,3988 ---- else if (TREE_CODE (declarator) == CALL_EXPR) { + int extern_ref = (!(specbits & (1 << (int) RID_AUTO)) + || current_binding_level == global_binding_level); tree arg_types; *************** *** 3733,3740 **** /* Traditionally, declaring return type float means double. */ ! if (flag_traditional && type == float_type_node) type = double_type_node; #endif /* TRADITIONAL_RETURN_FLOAT */ /* Construct the function type and go to the next inner layer of declarator. */ --- 4010,4023 ---- /* Traditionally, declaring return type float means double. */ ! if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node) type = double_type_node; #endif /* TRADITIONAL_RETURN_FLOAT */ + /* If this is a block level extern, it must live past the end + of the function so that we can check it against other extern + declarations (IDENTIFIER_LIMBO_VALUE). */ + if (extern_ref && allocation_temporary_p ()) + end_temporary_allocation (); + /* Construct the function type and go to the next inner layer of declarator. */ *************** *** 3753,3757 **** /* Omit the arg types if -traditional, since the arg types and the list links might not be permanent. */ ! type = build_function_type (type, flag_traditional ? 0 : arg_types); #endif type = build_function_type (type, arg_types); --- 4036,4042 ---- /* Omit the arg types if -traditional, since the arg types and the list links might not be permanent. */ ! type = build_function_type (type, ! flag_traditional ! ? NULL_TREE : arg_types); #endif type = build_function_type (type, arg_types); *************** *** 3808,3814 **** } if (constp > 1) ! warning ("duplicate `const'"); if (volatilep > 1) ! warning ("duplicate `volatile'"); } --- 4093,4099 ---- } if (constp > 1) ! pedwarn ("duplicate `const'"); if (volatilep > 1) ! pedwarn ("duplicate `volatile'"); } *************** *** 3878,3882 **** a better error message can be made later. */ ! if (type == void_type_node && decl_context != PARM) { error ("variable or field `%s' declared void", --- 4163,4167 ---- a better error message can be made later. */ ! if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM) { error ("variable or field `%s' declared void", *************** *** 3894,3897 **** --- 4179,4183 ---- { tree type_as_written = type; + tree main_type; /* A parameter declared as an array of T is really a pointer to T. *************** *** 3914,3920 **** } - if (initialized) - error ("parameter `%s' is initialized", name); - decl = build_decl (PARM_DECL, declarator, type); if (size_varies) --- 4200,4203 ---- *************** *** 3927,3939 **** DECL_ARG_TYPE (decl) = type; ! if (type == float_type_node) DECL_ARG_TYPE (decl) = double_type_node; /* Don't use TYPE_PREISION to decide whether to promote, because we should convert short if it's the same size as int, but we should not convert long if it's the same size as int. */ ! else if (type == char_type_node || type == signed_char_type_node ! || type == unsigned_char_type_node ! || type == short_integer_type_node ! || type == short_unsigned_type_node) { if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) --- 4210,4220 ---- DECL_ARG_TYPE (decl) = type; ! main_type = TYPE_MAIN_VARIANT (type); ! if (main_type == float_type_node) DECL_ARG_TYPE (decl) = double_type_node; /* Don't use TYPE_PREISION to decide whether to promote, because we should convert short if it's the same size as int, but we should not convert long if it's the same size as int. */ ! else if (C_PROMOTING_INTEGER_TYPE_P (main_type)) { if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) *************** *** 3978,3981 **** --- 4259,4270 ---- else if (TREE_CODE (type) == FUNCTION_TYPE) { + /* Every function declaration is "external" + except for those which are inside a function body + in which `auto' is used. + That is a case not specified by ANSI C, + and we use it for forward declarations for nested functions. */ + int extern_ref = (!(specbits & (1 << (int) RID_AUTO)) + || current_binding_level == global_binding_level); + if (specbits & (1 << (int) RID_AUTO) && (pedantic || current_binding_level == global_binding_level)) *************** *** 3993,4009 **** pedwarn ("invalid storage class for function `%s'", IDENTIFIER_POINTER (declarator)); decl = build_decl (FUNCTION_DECL, declarator, type); ! if (pedantic && (constp || volatilep)) pedwarn ("ANSI C forbids const or volatile functions"); ! /* Every function declaration is "external" ! except for those which are inside a function body ! in which `auto' is used. ! That is a case not specified by ANSI C, ! and we use it for forward declarations for nested functions. */ ! if (!(specbits & (1 << (int) RID_AUTO)) ! || current_binding_level == global_binding_level) ! TREE_EXTERNAL (decl) = 1; /* Record absence of global scope for `static' or `auto'. */ TREE_PUBLIC (decl) --- 4282,4300 ---- pedwarn ("invalid storage class for function `%s'", IDENTIFIER_POINTER (declarator)); + + /* If this is a block level extern, it must live past the end + of the function so that we can check it against other + extern declarations (IDENTIFIER_LIMBO_VALUE). */ + if (extern_ref && allocation_temporary_p ()) + end_temporary_allocation (); + decl = build_decl (FUNCTION_DECL, declarator, type); ! if (pedantic && (constp || volatilep) ! && ! DECL_IN_SYSTEM_HEADER (decl)) pedwarn ("ANSI C forbids const or volatile functions"); ! if (extern_ref) ! DECL_EXTERNAL (decl) = 1; /* Record absence of global scope for `static' or `auto'. */ TREE_PUBLIC (decl) *************** *** 4016,4024 **** if (! strcmp (IDENTIFIER_POINTER (declarator), "main")) warning ("cannot inline function `main'"); ! else if (last && TREE_VALUE (last) != void_type_node) warning ("inline declaration ignored for function with `...'"); else /* Assume that otherwise the function can be inlined. */ ! TREE_INLINE (decl) = 1; if (specbits & (1 << (int) RID_EXTERN)) --- 4307,4316 ---- if (! strcmp (IDENTIFIER_POINTER (declarator), "main")) warning ("cannot inline function `main'"); ! else if (last && (TYPE_MAIN_VARIANT (TREE_VALUE (last)) ! != void_type_node)) warning ("inline declaration ignored for function with `...'"); else /* Assume that otherwise the function can be inlined. */ ! DECL_INLINE (decl) = 1; if (specbits & (1 << (int) RID_EXTERN)) *************** *** 4029,4032 **** --- 4321,4326 ---- { /* It's a variable. */ + /* An uninitialized decl with `extern' is a reference. */ + int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN)); /* Move type qualifiers down to element of an array. */ *************** *** 4041,4044 **** --- 4335,4344 ---- } + /* If this is a block level extern, it must live past the end + of the function so that we can check it against other + extern declarations (IDENTIFIER_LIMBO_VALUE). */ + if (extern_ref && allocation_temporary_p ()) + end_temporary_allocation (); + decl = build_decl (VAR_DECL, declarator, type); if (size_varies) *************** *** 4048,4060 **** pedwarn_with_decl (decl, "variable `%s' declared `inline'"); ! /* An uninitialized decl with `extern' is a reference. */ ! TREE_EXTERNAL (decl) ! = !initialized && (specbits & (1 << (int) RID_EXTERN)); ! /* At top level, either `static' or no s.c. makes a definition ! (perhaps tentative), and absence of `static' makes it public. */ if (current_binding_level == global_binding_level) { ! TREE_PUBLIC (decl) = !(specbits & (1 << (int) RID_STATIC)); ! TREE_STATIC (decl) = ! TREE_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ --- 4348,4362 ---- pedwarn_with_decl (decl, "variable `%s' declared `inline'"); ! DECL_EXTERNAL (decl) = extern_ref; ! /* At top level, the presence of a `static' or `register' storage ! class specifier, or the absence of all storage class specifiers ! makes this declaration a definition (perhaps tentative). Also, ! the absence of both `static' and `register' makes it public. */ if (current_binding_level == global_binding_level) { ! TREE_PUBLIC (decl) ! = !(specbits ! & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))); ! TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ *************** *** 4062,4066 **** { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; ! TREE_PUBLIC (decl) = TREE_EXTERNAL (decl); } } --- 4364,4368 ---- { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; ! TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); } } *************** *** 4070,4074 **** if (specbits & (1 << (int) RID_REGISTER)) ! TREE_REGDECL (decl) = 1; /* Record constancy and volatility. */ --- 4372,4376 ---- if (specbits & (1 << (int) RID_REGISTER)) ! DECL_REGISTER (decl) = 1; /* Record constancy and volatility. */ *************** *** 4136,4140 **** last_function_parm_tags = TREE_VALUE (parms_info); ! if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag) warning ("function declaration isn't a prototype"); --- 4438,4443 ---- last_function_parm_tags = TREE_VALUE (parms_info); ! if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag ! && !in_system_header) warning ("function declaration isn't a prototype"); *************** *** 4205,4209 **** } ! return first_parm; } } --- 4508,4525 ---- } ! /* Allocate the list of types the way we allocate a type. */ ! if (first_parm && ! TREE_PERMANENT (first_parm)) ! { ! /* Construct a copy of the list of types ! on the saveable obstack. */ ! tree result = NULL; ! for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt)) ! result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt), ! result); ! return nreverse (result); ! } ! else ! /* The list we have is permanent already. */ ! return first_parm; } } *************** *** 4234,4238 **** if (void_at_end && parms != 0 && TREE_CHAIN (parms) == 0 ! && TREE_TYPE (parms) == void_type_node && DECL_NAME (parms) == 0) { --- 4550,4554 ---- if (void_at_end && parms != 0 && TREE_CHAIN (parms) == 0 ! && TYPE_MAIN_VARIANT (TREE_TYPE (parms)) == void_type_node && DECL_NAME (parms) == 0) { *************** *** 4295,4299 **** types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types); ! if (TREE_VALUE (types) == void_type_node && ! erred && DECL_NAME (decl) == 0) { --- 4611,4615 ---- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types); ! if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred && DECL_NAME (decl) == 0) { *************** *** 4403,4407 **** /* Make sure that the tag NAME is defined *in the current binding level* at least as a forward reference. ! CODE says which kind of tag NAME ought to be. */ tree --- 4719,4726 ---- /* Make sure that the tag NAME is defined *in the current binding level* at least as a forward reference. ! CODE says which kind of tag NAME ought to be. ! ! We also do a push_obstacks_nochange ! whose matching pop is in finish_struct. */ tree *************** *** 4415,4418 **** --- 4734,4741 ---- register tree ref = 0; + push_obstacks_nochange (); + if (current_binding_level == global_binding_level) + end_temporary_allocation (); + if (name != 0) ref = lookup_tag (code, name, current_binding_level, 1); *************** *** 4457,4461 **** value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0); ! finish_decl (value, NULL, NULL); DECL_INITIAL (value) = width; --- 4780,4784 ---- value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0); ! finish_decl (value, NULL_TREE, NULL_TREE); DECL_INITIAL (value) = width; *************** *** 4473,4478 **** /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. ! FIELDLIST is a chain of FIELD_DECL nodes for the fields. */ tree finish_struct (t, fieldlist) --- 4796,4803 ---- /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. ! FIELDLIST is a chain of FIELD_DECL nodes for the fields. + We also do a pop_obstacks to match the push in start_struct. */ + tree finish_struct (t, fieldlist) *************** *** 4542,4549 **** C_TYPE_VARIABLE_SIZE (t) = 1; /* Detect invalid bit-field size. */ ! while (DECL_INITIAL (x) ! && TREE_CODE (DECL_INITIAL (x)) == NON_LVALUE_EXPR) ! DECL_INITIAL (x) = TREE_OPERAND (DECL_INITIAL (x), 0); if (DECL_INITIAL (x) && TREE_CODE (DECL_INITIAL (x)) != INTEGER_CST) { --- 4867,4878 ---- C_TYPE_VARIABLE_SIZE (t) = 1; + /* Detect invalid nested redefinition. */ + if (TREE_TYPE (x) == t) + error ("nested redefinition of `%s'", + IDENTIFIER_POINTER (TYPE_NAME (t))); + /* Detect invalid bit-field size. */ ! if (DECL_INITIAL (x)) ! STRIP_NOPS (DECL_INITIAL (x)); if (DECL_INITIAL (x) && TREE_CODE (DECL_INITIAL (x)) != INTEGER_CST) { *************** *** 4568,4587 **** if (DECL_INITIAL (x)) { ! register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); ! if (width < 0) { DECL_INITIAL (x) = NULL; error_with_decl (x, "negative width in bit-field `%s'"); } ! else if (width == 0 && DECL_NAME (x) != 0) { - error_with_decl (x, "zero width for bit-field `%s'"); DECL_INITIAL (x) = NULL; } ! else if (width > TYPE_PRECISION (TREE_TYPE (x))) { DECL_INITIAL (x) = NULL; - pedwarn_with_decl (x, "width of `%s' exceeds its type"); } } --- 4897,4917 ---- if (DECL_INITIAL (x)) { ! unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x)); ! if (tree_int_cst_lt (DECL_INITIAL (x), integer_zero_node)) { DECL_INITIAL (x) = NULL; error_with_decl (x, "negative width in bit-field `%s'"); } ! else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0 ! || width > TYPE_PRECISION (TREE_TYPE (x))) { DECL_INITIAL (x) = NULL; + pedwarn_with_decl (x, "width of `%s' exceeds its type"); } ! else if (width == 0 && DECL_NAME (x) != 0) { + error_with_decl (x, "zero width for bit-field `%s'"); DECL_INITIAL (x) = NULL; } } *************** *** 4716,4723 **** for (x = fieldlist; x; x = TREE_CHAIN (x)) if (DECL_BIT_FIELD (x) ! && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE ! && (TYPE_PRECISION (TREE_TYPE (x)) ! < TYPE_PRECISION (integer_type_node))) ! TREE_TYPE (x) = integer_type_node; /* If this structure or union completes the type of any previous --- 5046,5062 ---- for (x = fieldlist; x; x = TREE_CHAIN (x)) if (DECL_BIT_FIELD (x) ! && C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x))) ! { ! tree type = TREE_TYPE (x); ! ! /* Preserve unsignedness if traditional or if not really any wider. */ ! if (TREE_UNSIGNED (type) ! && (flag_traditional ! || (TYPE_PRECISION (type) ! == TYPE_PRECISION (integer_type_node)))) ! TREE_TYPE (x) = unsigned_type_node; ! else ! TREE_TYPE (x) = integer_type_node; ! } /* If this structure or union completes the type of any previous *************** *** 4735,4739 **** /* This is a no-op in c-lang.c or something real in objc-actions.c. */ maybe_objc_check_decl (decl); ! rest_of_decl_compilation (decl, 0, toplevel, 0); if (! toplevel) expand_decl (decl); --- 5074,5078 ---- /* This is a no-op in c-lang.c or something real in objc-actions.c. */ maybe_objc_check_decl (decl); ! rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); if (! toplevel) expand_decl (decl); *************** *** 4757,4760 **** --- 5096,5102 ---- rest_of_type_compilation (t, toplevel); + /* The matching push is in start_struct. */ + pop_obstacks (); + return t; } *************** *** 4790,4793 **** --- 5132,5141 ---- enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1); + /* The corresponding pop_obstacks is in finish_enum. */ + push_obstacks_nochange (); + /* If these symbols and types are global, make them permanent. */ + if (current_binding_level == global_binding_level) + end_temporary_allocation (); + if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE) { *************** *** 4825,4833 **** register tree pair; tree minnode = 0, maxnode = 0; ! register long maxvalue = 0; ! register long minvalue = 0; register int i; unsigned precision = 0; int toplevel = global_binding_level == current_binding_level; if (in_parm_level_p ()) --- 5173,5182 ---- register tree pair; tree minnode = 0, maxnode = 0; ! register HOST_WIDE_INT maxvalue = 0; ! register HOST_WIDE_INT minvalue = 0; register int i; unsigned precision = 0; int toplevel = global_binding_level == current_binding_level; + int temporary = allocation_temporary_p (); if (in_parm_level_p ()) *************** *** 4862,4867 **** else { ! int maxvalue = TREE_INT_CST_LOW (maxnode); ! int minvalue = TREE_INT_CST_LOW (minnode); if (maxvalue > 0) --- 5211,5216 ---- else { ! maxvalue = TREE_INT_CST_LOW (maxnode); ! minvalue = TREE_INT_CST_LOW (minnode); if (maxvalue > 0) *************** *** 4915,4918 **** --- 5264,5270 ---- rest_of_type_compilation (enumtype, toplevel); + /* This matches a push in start_enum. */ + pop_obstacks (); + return enumtype; } *************** *** 4932,4939 **** /* Remove no-op casts from the value. */ ! while (value != 0 ! && (TREE_CODE (value) == NOP_EXPR ! || TREE_CODE (value) == NON_LVALUE_EXPR)) ! value = TREE_OPERAND (value, 0); if (value != 0 && TREE_CODE (value) != INTEGER_CST) --- 5284,5289 ---- /* Remove no-op casts from the value. */ ! if (value) ! STRIP_TYPE_NOPS (value); if (value != 0 && TREE_CODE (value) != INTEGER_CST) *************** *** 4971,4975 **** pushdecl (decl); ! return saveable_tree_cons (decl, value, NULL); } --- 5321,5325 ---- pushdecl (decl); ! return saveable_tree_cons (decl, value, NULL_TREE); } *************** *** 5062,5069 **** /* This is a definition, not a reference. ! So normally clear TREE_EXTERNAL. However, `extern inline' acts like a declaration ! except for defining how to inline. So set TREE_EXTERNAL in that case. */ ! TREE_EXTERNAL (decl1) = current_extern_inline; /* This function exists in static storage. --- 5412,5419 ---- /* This is a definition, not a reference. ! So normally clear DECL_EXTERNAL. However, `extern inline' acts like a declaration ! except for defining how to inline. So set DECL_EXTERNAL in that case. */ ! DECL_EXTERNAL (decl1) = current_extern_inline; /* This function exists in static storage. *************** *** 5089,5096 **** restype = TREE_TYPE (TREE_TYPE (current_function_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 (current_function_decl) = build_decl (RESULT_DECL, 0, restype); if (!nested) --- 5439,5456 ---- restype = TREE_TYPE (TREE_TYPE (current_function_decl)); /* Promote the value to int before returning it. */ ! if (C_PROMOTING_INTEGER_TYPE_P (restype)) ! { ! /* It retains unsignedness if traditional ! or if not really getting wider. */ ! if (TREE_UNSIGNED (restype) ! && (flag_traditional ! || (TYPE_PRECISION (restype) ! == TYPE_PRECISION (integer_type_node)))) ! restype = unsigned_type_node; ! else ! restype = integer_type_node; ! } ! DECL_RESULT (current_function_decl) ! = build_decl (RESULT_DECL, NULL_TREE, restype); if (!nested) *************** *** 5161,5166 **** if (parmdecls != 0) ! error_with_decl (fndecl, ! "parm types given both in parmlist and separately"); specparms = nreverse (specparms); --- 5521,5541 ---- if (parmdecls != 0) ! { ! tree decl, link; ! ! error_with_decl (fndecl, ! "parm types given both in parmlist and separately"); ! /* Get rid of the erroneous decls; don't keep them on ! the list of parms, since they might not be PARM_DECLs. */ ! for (decl = current_binding_level->names; ! decl; decl = TREE_CHAIN (decl)) ! if (DECL_NAME (decl)) ! IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0; ! for (link = current_binding_level->shadowed; ! link; link = TREE_CHAIN (link)) ! IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); ! current_binding_level->names = 0; ! current_binding_level->shadowed = 0; ! } specparms = nreverse (specparms); *************** *** 5172,5177 **** if (DECL_NAME (parm) == 0) error_with_decl (parm, "parameter name omitted"); ! else if (TREE_TYPE (parm) == void_type_node) ! error_with_decl (parm, "parameter `%s' declared void"); pushdecl (parm); } --- 5547,5557 ---- if (DECL_NAME (parm) == 0) error_with_decl (parm, "parameter name omitted"); ! else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node) ! { ! error_with_decl (parm, "parameter `%s' declared void"); ! /* Change the type to error_mark_node so this parameter ! will be ignored by assign_parms. */ ! TREE_TYPE (parm) = error_mark_node; ! } pushdecl (parm); } *************** *** 5212,5216 **** if (DECL_NAME (parm) == 0) ; ! else if (TREE_TYPE (parm) == void_type_node) ; else if (TREE_CODE (parm) != PARM_DECL) --- 5592,5596 ---- if (DECL_NAME (parm) == 0) ; ! else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node) ; else if (TREE_CODE (parm) != PARM_DECL) *************** *** 5267,5271 **** /* If the declaration says "void", complain and ignore it. */ ! if (found && TREE_TYPE (found) == void_type_node) { error_with_decl (found, "parameter `%s' declared void"); --- 5647,5651 ---- /* If the declaration says "void", complain and ignore it. */ ! if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node) { error_with_decl (found, "parameter `%s' declared void"); *************** *** 5277,5281 **** /* Traditionally, a parm declared float is actually a double. */ if (found && flag_traditional ! && TREE_TYPE (found) == float_type_node) TREE_TYPE (found) = double_type_node; --- 5657,5661 ---- /* Traditionally, a parm declared float is actually a double. */ if (found && flag_traditional ! && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node) TREE_TYPE (found) = double_type_node; *************** *** 5367,5375 **** for (parm = DECL_ARGUMENTS (fndecl), type = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); ! parm || (type && TREE_VALUE (type) != void_type_node); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type)) { if (parm == 0 || type == 0 ! || TREE_VALUE (type) == void_type_node) { error ("number of arguments doesn't match prototype"); --- 5747,5756 ---- for (parm = DECL_ARGUMENTS (fndecl), type = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); ! parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) ! != void_type_node)); parm = TREE_CHAIN (parm), type = TREE_CHAIN (type)) { if (parm == 0 || type == 0 ! || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) { error ("number of arguments doesn't match prototype"); *************** *** 5401,5406 **** `unsigned' prototype. */ else if (! (flag_traditional ! && TREE_TYPE (parm) == integer_type_node ! && TREE_VALUE (type) == unsigned_type_node)) error ("argument `%s' doesn't match prototype", IDENTIFIER_POINTER (DECL_NAME (parm))); --- 5782,5787 ---- `unsigned' prototype. */ else if (! (flag_traditional ! && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node ! && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)) error ("argument `%s' doesn't match prototype", IDENTIFIER_POINTER (DECL_NAME (parm))); *************** *** 5419,5423 **** for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) { ! type = perm_tree_cons (NULL, DECL_ARG_TYPE (parm), NULL); if (last) TREE_CHAIN (last) = type; --- 5800,5805 ---- for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm)) { ! type = perm_tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), ! NULL_TREE); if (last) TREE_CHAIN (last) = type; *************** *** 5426,5430 **** last = type; } ! type = perm_tree_cons (NULL, void_type_node, NULL); if (last) TREE_CHAIN (last) = type; --- 5808,5812 ---- last = type; } ! type = perm_tree_cons (NULL_TREE, void_type_node, NULL_TREE); if (last) TREE_CHAIN (last) = type; *************** *** 5546,5550 **** /* If the declaration says "void", complain and ignore it. */ ! if (found && TREE_TYPE (found) == void_type_node) { error_with_decl (found, "parameter `%s' declared void"); --- 5928,5932 ---- /* If the declaration says "void", complain and ignore it. */ ! if (found && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node) { error_with_decl (found, "parameter `%s' declared void"); *************** *** 5556,5560 **** /* Traditionally, a parm declared float is actually a double. */ if (found && flag_traditional ! && TREE_TYPE (found) == float_type_node) TREE_TYPE (found) = double_type_node; --- 5938,5942 ---- /* Traditionally, a parm declared float is actually a double. */ if (found && flag_traditional ! && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node) TREE_TYPE (found) = double_type_node; *************** *** 5655,5658 **** --- 6037,6041 ---- poplevel (1, 0, 1); + BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; /* Must mark the RESULT_DECL as being in this function. */ *************** *** 5670,5675 **** if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")) { ! /* Make it so that `main' always returns success by default. */ ! DEFAULT_MAIN_RETURN; } #endif --- 6053,6064 ---- if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")) { ! if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) ! != integer_type_node) ! warning_with_decl (fndecl, "return type of `%s' is not `int'"); ! else ! { ! /* Make it so that `main' always returns success by default. */ ! DEFAULT_MAIN_RETURN; ! } } #endif *************** *** 5688,5692 **** if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) warning ("`volatile' function does return"); ! else if (warn_return_type && current_function_returns_null && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node) /* If this function returns non-void and control can drop through, --- 6077,6081 ---- if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null) warning ("`volatile' function does return"); ! else if (warn_return_type && can_reach_end && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node) /* If this function returns non-void and control can drop through, diff -rc2N gcc-2.2.2/c-lex.c gcc-2.3.1/c-lex.c *** gcc-2.2.2/c-lex.c Wed Jun 10 00:22:36 1992 --- gcc-2.3.1/c-lex.c Thu Oct 8 03:07:25 1992 *************** *** 340,345 **** t = yylval.ttype; if (TREE_CODE (t) == INTEGER_CST) ! fprintf (file, " 0x%8x%8x", TREE_INT_CST_HIGH (t), ! TREE_INT_CST_LOW (t)); break; } --- 340,358 ---- t = yylval.ttype; if (TREE_CODE (t) == INTEGER_CST) ! fprintf (file, ! #if HOST_BITS_PER_WIDE_INT == 64 ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%016lx", ! #else ! " 0x%x%016x", ! #endif ! #else ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%08lx", ! #else ! " 0x%x%08x", ! #endif ! #endif ! TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t)); break; } *************** *** 482,485 **** --- 495,501 ---- && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n')) { + #ifdef HANDLE_SYSV_PRAGMA + return handle_sysv_pragma (finput, c); + #endif /* HANDLE_SYSV_PRAGMA */ #ifdef HANDLE_PRAGMA HANDLE_PRAGMA (finput); *************** *** 730,733 **** --- 746,793 ---- } + #ifdef HANDLE_SYSV_PRAGMA + + /* Handle a #pragma directive. INPUT is the current input stream, + and C is a character to reread. Processes the entire input line + and returns a character for the caller to reread: either \n or EOF. */ + + /* This function has to be in this file, in order to get at + the token types. */ + + int + handle_sysv_pragma (input, c) + FILE *input; + int c; + { + for (;;) + { + while (c == ' ' || c == '\t') + c = getc (input); + if (c == '\n' || c == EOF) + { + handle_pragma_token (0, 0); + return c; + } + ungetc (c, input); + switch (yylex ()) + { + case IDENTIFIER: + case TYPENAME: + case STRING: + case CONSTANT: + handle_pragma_token (token_buffer, yylval.ttype); + break; + default: + handle_pragma_token (token_buffer, 0); + } + if (nextchar >= 0) + c = nextchar, nextchar = -1; + else + c = getc (input); + } + } + + #endif /* HANDLE_SYSV_PRAGMA */ + #define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9')) #define isdigit(char) (char >= '0' && char <= '9') *************** *** 735,742 **** /* Read an escape sequence, returning its equivalent as a character, ! or -1 if it is backslash-newline. */ static int ! readescape () { register int c = getc (finput); --- 795,803 ---- /* Read an escape sequence, returning its equivalent as a character, ! or store 1 in *ignore_ptr if it is backslash-newline. */ static int ! readescape (ignore_ptr) ! int *ignore_ptr; { register int c = getc (finput); *************** *** 744,747 **** --- 805,809 ---- register unsigned count; unsigned firstdig; + int nonnull; switch (c) *************** *** 756,759 **** --- 818,822 ---- code = 0; count = 0; + nonnull = 0; while (1) { *************** *** 773,782 **** if (c >= '0' && c <= '9') code += c - '0'; ! if (count == 0) ! firstdig = code; ! count++; } ! if (count == 0) error ("\\x used with no following hex digits"); else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) || (count > 1 --- 836,852 ---- if (c >= '0' && c <= '9') code += c - '0'; ! if (code != 0 || count != 0) ! { ! if (count == 0) ! firstdig = code; ! count++; ! } ! nonnull = 1; } ! if (! nonnull) error ("\\x used with no following hex digits"); + else if (count == 0) + /* Digits are all 0's. Ok. */ + ; else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) || (count > 1 *************** *** 803,807 **** case '\n': lineno++; ! return -1; case 'n': --- 873,878 ---- case '\n': lineno++; ! *ignore_ptr = 1; ! return 0; case 'n': *************** *** 850,854 **** return c; } ! if (c >= 040 && c <= 0177) pedwarn ("unknown escape sequence `\\%c'", c); else --- 921,925 ---- return c; } ! if (c >= 040 && c < 0177) pedwarn ("unknown escape sequence `\\%c'", c); else *************** *** 1105,1111 **** int numdigits = 0; /* for multi-precision arithmetic, ! we store only 8 live bits in each short, ! giving us 64 bits of reliable precision */ ! short shorts[8]; int overflow = 0; --- 1176,1186 ---- int numdigits = 0; /* for multi-precision arithmetic, ! we actually store only HOST_BITS_PER_CHAR bits in each part. ! The number of parts is chosen so as to be sufficient to hold ! the enough bits to fit into the two HOST_WIDE_INTs that contain ! the integer value (this is always at least as many bits as are ! in a target `long long' value, but may be wider). */ ! #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2) ! int parts[TOTAL_PARTS]; int overflow = 0; *************** *** 1113,1118 **** = NOT_FLOAT; ! for (count = 0; count < 8; count++) ! shorts[count] = 0; p = token_buffer; --- 1188,1193 ---- = NOT_FLOAT; ! for (count = 0; count < TOTAL_PARTS; count++) ! parts[count] = 0; p = token_buffer; *************** *** 1213,1230 **** numdigits++; ! for (count = 0; count < 8; count++) { ! shorts[count] *= base; if (count) { ! shorts[count] += (shorts[count-1] >> 8); ! shorts[count-1] &= (1<<8)-1; } ! else shorts[0] += c; } ! if (shorts[7] >= 1<<8 ! || shorts[7] < - (1 << 8)) ! overflow = TRUE; if (p >= token_buffer + maxtoken - 3) --- 1288,1309 ---- numdigits++; ! for (count = 0; count < TOTAL_PARTS; count++) { ! parts[count] *= base; if (count) { ! parts[count] ! += (parts[count-1] >> HOST_BITS_PER_CHAR); ! parts[count-1] ! &= (1 << HOST_BITS_PER_CHAR) - 1; } ! else ! parts[0] += c; } ! /* If the extra highest-order part ever gets anything in it, ! the number is certainly too big. */ ! if (parts[TOTAL_PARTS - 1] != 0) ! overflow = 1; if (p >= token_buffer + maxtoken - 3) *************** *** 1246,1251 **** { tree type = double_type_node; ! char f_seen = 0; ! char l_seen = 0; REAL_VALUE_TYPE value; jmp_buf handler; --- 1325,1329 ---- { tree type = double_type_node; ! int garbage_chars = 0, exceeds_double = 0; REAL_VALUE_TYPE value; jmp_buf handler; *************** *** 1288,1361 **** set_float_handler (handler); value = REAL_VALUE_ATOF (token_buffer); ! set_float_handler (0); } #ifdef ERANGE if (errno == ERANGE && !flag_traditional && pedantic) { ! char *p1 = token_buffer; ! /* Check for "0.0" and variants; ! Sunos 4 spuriously returns ERANGE for them. */ ! while (*p1 == '0') p1++; ! if (*p1 == '.') ! { ! p1++; ! while (*p1 == '0') p1++; ! } ! if (*p1 == 'e' || *p1 == 'E') { ! /* with significand==0, ignore the exponent */ ! p1++; ! while (*p1 != 0) p1++; } - /* ERANGE is also reported for underflow, - so test the value to distinguish overflow from that. */ - if (*p1 != 0 && (value > 1.0 || value < -1.0)) - pedwarn ("floating point number exceeds range of `double'"); } #endif /* Read the suffixes to choose a data type. */ ! while (1) { ! if (c == 'f' || c == 'F') ! { ! if (f_seen) ! error ("two `f's in floating constant"); ! else ! { ! f_seen = 1; ! type = float_type_node; ! value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value); ! if (REAL_VALUE_ISINF (value) && pedantic) ! pedwarn ("floating point number exceeds range of `float'"); ! } ! } ! else if (c == 'l' || c == 'L') ! { ! if (l_seen) ! error ("two `l's in floating constant"); ! l_seen = 1; ! type = long_double_type_node; ! } ! else ! { ! if (isalnum (c)) ! { ! error ("garbage at end of number"); ! while (isalnum (c)) ! { ! if (p >= token_buffer + maxtoken - 3) ! p = extend_token_buffer (p); ! *p++ = c; ! c = getc (finput); ! } ! } ! break; ! } if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } /* Create a node with determined type and value. */ --- 1366,1412 ---- set_float_handler (handler); value = REAL_VALUE_ATOF (token_buffer); ! set_float_handler (NULL_PTR); } #ifdef ERANGE if (errno == ERANGE && !flag_traditional && pedantic) { ! /* ERANGE is also reported for underflow, ! so test the value to distinguish overflow from that. */ ! if (REAL_VALUES_LESS (dconst1, value) ! || REAL_VALUES_LESS (value, dconstm1)) { ! pedwarn ("floating point number exceeds range of `double'"); ! exceeds_double = 1; } } #endif /* Read the suffixes to choose a data type. */ ! switch (c) { ! case 'f': case 'F': ! type = float_type_node; ! value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value); ! if (REAL_VALUE_ISINF (value) && ! exceeds_double && pedantic) ! pedwarn ("floating point number exceeds range of `float'"); ! garbage_chars = -1; ! break; ! ! case 'l': case 'L': ! type = long_double_type_node; ! garbage_chars = -1; ! break; ! } ! /* Note: garbage_chars is -1 if first char is *not* garbage. */ ! while (isalnum (c)) ! { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); + garbage_chars++; } + if (garbage_chars > 0) + error ("garbage at end of number"); /* Create a node with determined type and value. */ *************** *** 1368,1371 **** --- 1419,1423 ---- { tree traditional_type, ansi_type, type; + HOST_WIDE_INT high, low; int spec_unsigned = 0; int spec_long = 0; *************** *** 1431,1535 **** bytes = TYPE_PRECISION (long_integer_type_node) / 8; ! if (bytes <= 8) ! { ! warn = overflow; ! for (i = bytes; i < 8; i++) ! if (shorts[i]) ! { ! /* If LL was not used, then clear any excess precision. ! This is equivalent to the original code, but it is ! not clear why this is being done. Perhaps to prevent ! ANSI programs from creating long long constants ! by accident? */ ! if (! spec_long_long) ! shorts[i] = 0; ! warn = 1; ! } ! if (warn) ! pedwarn ("integer constant out of range"); ! } ! else if (overflow) ! pedwarn ("integer constant larger than compiler can handle"); ! ! /* If it overflowed our internal buffer, then make it unsigned. ! We can't distinguish based on the tree node because ! any integer constant fits any long long type. */ ! if (overflow) ! spec_unsigned = 1; /* This is simplified by the fact that our constant is always positive. */ - /* The casts in the following statement should not be - needed, but they get around bugs in some C compilers. */ - yylval.ttype - = (build_int_2 - ((((long)shorts[3]<<24) + ((long)shorts[2]<<16) - + ((long)shorts[1]<<8) + (long)shorts[0]), - (((long)shorts[7]<<24) + ((long)shorts[6]<<16) - + ((long)shorts[5]<<8) + (long)shorts[4]))); ! #if 0 ! /* Find the first allowable type that the value fits in. */ ! type = 0; ! for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]); ! i++) ! if (!(spec_long && !type_sequence[i].long_flag) ! && !(spec_long_long && !type_sequence[i].long_long_flag) ! && !(spec_unsigned && !type_sequence[i].unsigned_flag) ! /* A decimal constant can't be unsigned int ! unless explicitly specified. */ ! && !(base == 10 && !spec_unsigned ! && *type_sequence[i].node_var == unsigned_type_node)) ! if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var)) ! { ! type = *type_sequence[i].node_var; ! break; ! } ! if (flag_traditional && type == long_unsigned_type_node ! && !spec_unsigned) ! type = long_integer_type_node; ! ! if (type == 0) ! { ! type = long_long_integer_type_node; ! warning ("integer constant out of range"); ! } ! /* Warn about some cases where the type of a given constant ! changes from traditional C to ANSI C. */ ! if (warn_traditional) ! { ! tree other_type = 0; ! ! /* This computation is the same as the previous one ! except that flag_traditional is used backwards. */ ! for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]); ! i++) ! if (!(spec_long && !type_sequence[i].long_flag) ! && !(spec_long_long && !type_sequence[i].long_long_flag) ! && !(spec_unsigned && !type_sequence[i].unsigned_flag) ! /* A decimal constant can't be unsigned int ! unless explicitly specified. */ ! && !(base == 10 && !spec_unsigned ! && *type_sequence[i].node_var == unsigned_type_node)) ! if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var)) ! { ! other_type = *type_sequence[i].node_var; ! break; ! } ! if (!flag_traditional && type == long_unsigned_type_node ! && !spec_unsigned) ! type = long_integer_type_node; ! ! if (other_type != 0 && other_type != type) ! { ! if (flag_traditional) ! warning ("type of integer constant would be different without -traditional"); ! else ! warning ("type of integer constant would be different with -traditional"); ! } } - #else /* 1 */ /* If warn_traditional, calculate both the ANSI type and the traditional type, then see if they disagree. --- 1483,1509 ---- bytes = TYPE_PRECISION (long_integer_type_node) / 8; ! warn = overflow; ! for (i = bytes; i < TOTAL_PARTS; i++) ! if (parts[i]) ! warn = 1; ! if (warn) ! pedwarn ("integer constant out of range"); /* This is simplified by the fact that our constant is always positive. */ ! high = low = 0; ! for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++) ! { ! high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT ! / HOST_BITS_PER_CHAR)] ! << (i * HOST_BITS_PER_CHAR)); ! low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR); } + + yylval.ttype = build_int_2 (low, high); + TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node; /* If warn_traditional, calculate both the ANSI type and the traditional type, then see if they disagree. *************** *** 1554,1560 **** traditional_type = (spec_unsigned ? unsigned_type_node : integer_type_node); ! else if (! spec_long_long ! && int_fits_type_p (yylval.ttype, ! long_unsigned_type_node)) traditional_type = (spec_unsigned ? long_unsigned_type_node : long_integer_type_node); --- 1528,1532 ---- traditional_type = (spec_unsigned ? unsigned_type_node : integer_type_node); ! else if (! spec_long_long) traditional_type = (spec_unsigned ? long_unsigned_type_node : long_integer_type_node); *************** *** 1576,1584 **** && int_fits_type_p (yylval.ttype, long_integer_type_node)) ansi_type = long_integer_type_node; ! else if (! spec_long_long ! && int_fits_type_p (yylval.ttype, ! long_unsigned_type_node)) ansi_type = long_unsigned_type_node; else if (! spec_unsigned && int_fits_type_p (yylval.ttype, long_long_integer_type_node)) --- 1548,1556 ---- && int_fits_type_p (yylval.ttype, long_integer_type_node)) ansi_type = long_integer_type_node; ! else if (! spec_long_long) ansi_type = long_unsigned_type_node; else if (! spec_unsigned + /* Verify value does not overflow into sign bit. */ + && TREE_INT_CST_HIGH (yylval.ttype) >= 0 && int_fits_type_p (yylval.ttype, long_long_integer_type_node)) *************** *** 1601,1610 **** warning ("width of integer constant may change on other systems with -traditional"); } - #endif ! if (!flag_traditional && !int_fits_type_p (yylval.ttype, type)) pedwarn ("integer constant out of range"); ! TREE_TYPE (yylval.ttype) = type; *p = 0; } --- 1573,1595 ---- warning ("width of integer constant may change on other systems with -traditional"); } ! if (!flag_traditional && !int_fits_type_p (yylval.ttype, type) ! && !warn) pedwarn ("integer constant out of range"); ! if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) ! warning ("integer constant is so large that it is unsigned"); ! ! if (flag_traditional && !int_fits_type_p (yylval.ttype, type)) ! /* The traditional constant 0x80000000 is signed ! but doesn't fit in the range of int. ! This will change it to -0x80000000, which does fit. */ ! { ! TREE_TYPE (yylval.ttype) = unsigned_type (type); ! yylval.ttype = convert (type, yylval.ttype); ! } ! else ! TREE_TYPE (yylval.ttype) = type; ! *p = 0; } *************** *** 1617,1621 **** { register int result = 0; ! register num_chars = 0; unsigned width = TYPE_PRECISION (char_type_node); int max_chars; --- 1602,1606 ---- { register int result = 0; ! register int num_chars = 0; unsigned width = TYPE_PRECISION (char_type_node); int max_chars; *************** *** 1644,1649 **** if (c == '\\') { ! c = readescape (); ! if (c < 0) goto tryagain; if (width < HOST_BITS_PER_INT --- 1629,1635 ---- if (c == '\\') { ! int ignore = 0; ! c = readescape (&ignore); ! if (ignore) goto tryagain; if (width < HOST_BITS_PER_INT *************** *** 1696,1706 **** || ((result >> (num_bits - 1)) & 1) == 0) yylval.ttype ! = build_int_2 (result & ((unsigned) ~0 ! >> (HOST_BITS_PER_INT - num_bits)), 0); else yylval.ttype ! = build_int_2 (result | ~((unsigned) ~0 ! >> (HOST_BITS_PER_INT - num_bits)), -1); } --- 1682,1692 ---- || ((result >> (num_bits - 1)) & 1) == 0) yylval.ttype ! = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0 ! >> (HOST_BITS_PER_WIDE_INT - num_bits)), 0); else yylval.ttype ! = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0 ! >> (HOST_BITS_PER_WIDE_INT - num_bits)), -1); } *************** *** 1716,1720 **** { wchar_t wc; ! (void) mbtowc (NULL, NULL, 0); if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars) result = wc; --- 1702,1706 ---- { wchar_t wc; ! (void) mbtowc (NULL_PTR, NULL_PTR, 0); if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars) result = wc; *************** *** 1742,1747 **** if (!ignore_escape_flag && c == '\\') { ! c = readescape (); ! if (c < 0) goto skipnewline; if (!wide_flag --- 1728,1734 ---- if (!ignore_escape_flag && c == '\\') { ! int ignore = 0; ! c = readescape (&ignore); ! if (ignore) goto skipnewline; if (!wide_flag diff -rc2N gcc-2.2.2/c-parse.in gcc-2.3.1/c-parse.in *** gcc-2.2.2/c-parse.in --- gcc-2.3.1/c-parse.in Wed Oct 7 15:41:23 1992 *************** *** 0 **** --- 1,2523 ---- + /* YACC parser for C syntax and for Objective C. -*-c-*- + Copyright (C) 1987, 1988, 1989, 1992 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. */ + + /* 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. + The awk script cond.awk is 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. */ + + ifobjc + %expect 56 + end ifobjc + ifc + %expect 8 + + /* These are the 8 conflicts you should get in parse.output; + the state numbers may vary if minor changes in the grammar are made. + + State 41 contains 1 shift/reduce conflict. (Two ways to recover from error.) + State 92 contains 1 shift/reduce conflict. (Two ways to recover from error.) + State 99 contains 1 shift/reduce conflict. (Two ways to recover from error.) + State 103 contains 1 shift/reduce conflict. (Two ways to recover from error.) + State 119 contains 1 shift/reduce conflict. (See comment at component_decl.) + State 183 contains 1 shift/reduce conflict. (Two ways to recover from error.) + State 193 contains 1 shift/reduce conflict. (Two ways to recover from error.) + State 199 contains 1 shift/reduce conflict. (Two ways to recover from error.) + */ + end ifc + + %{ + #include + #include + #include + + #include "config.h" + #include "tree.h" + #include "input.h" + #include "c-lex.h" + #include "c-tree.h" + #include "flags.h" + + #ifdef MULTIBYTE_CHARS + #include + #include + #endif + + ifobjc + #include "objc-actions.h" + end ifobjc + + #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; } + + /* 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 ALIGN + %token ATTRIBUTE EXTENSION LABEL + + /* 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 ASSIGN '=' + %right '?' ':' + %left OROR + %left ANDAND + %left '|' + %left '^' + %left '&' + %left EQCOMPARE + %left ARITHCOMPARE + %left LSHIFT RSHIFT + %left '+' '-' + %left '*' '/' '%' + %right UNARY PLUSPLUS MINUSMINUS + %left HYPERUNARY + %left 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 + + + %type unop + + %type identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist + %type expr_no_commas cast_expr unary_expr primary string STRING + %type typed_declspecs reserved_declspecs + %type typed_typespecs reserved_typespecquals + %type declmods typespec typespecqual_reserved + %type SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual + %type initdecls notype_initdecls initdcl notype_initdcl + %type init initlist maybeasm + %type asm_operands nonnull_asm_operands asm_operand asm_clobbers + %type maybe_attribute attribute_list attrib + + %type compstmt + + %type declarator + %type notype_declarator after_type_declarator + %type parm_declarator + + %type structsp component_decl_list component_decl_list2 + %type component_decl components component_declarator + %type enumlist enumerator + %type typename absdcl absdcl1 type_quals + %type xexpr parms parm identifiers + + %type parmlist parmlist_1 parmlist_2 + %type parmlist_or_identifiers parmlist_or_identifiers_1 + %type identifiers_or_typenames + + %type setspecs + + %type save_filename + %type save_lineno + + ifobjc + /* the Objective-C nonterminals */ + + %type ivar_decl_list ivar_decls ivar_decl ivars ivar_declarator + %type methoddecl unaryselector keywordselector selector + %type keyworddecl receiver objcmessageexpr messageargs + %type keywordexpr keywordarglist keywordarg + %type myparms myparm optparmlist reservedwords objcselectorexpr + %type selectorarg keywordnamelist keywordname objcencodeexpr + %type CLASSNAME + end ifobjc + + %{ + /* Number of statements (loosely speaking) seen so far. */ + static int stmt_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; + + /* Stack of saved values of current_declspecs. */ + static tree declspec_stack; + + /* 1 if we explained undeclared var errors. */ + static int undeclared_variable_notice; + + ifobjc + /* 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; + + end ifobjc + + /* 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"); + ifobjc + objc_finish (); + end ifobjc + } + | extdefs + { + ifobjc + objc_finish (); + end ifobjc + } + ; + + /* 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: + {$$ = NULL_TREE; } extdef + | extdefs {$$ = NULL_TREE; } extdef + ; + + extdef: + fndef + | datadef + ifobjc + | objcdef + end ifobjc + | 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"); } + ; + + 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"); } + | declmods setspecs notype_initdecls ';' + {} + | typed_declspecs setspecs initdecls ';' + {} + | 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 ($1, $3, 0)) + YYERROR1; + reinit_parse_for_function (); } + xdecls + { store_parm_decls (); } + compstmt_or_error + { finish_function (0); } + | typed_declspecs setspecs declarator error + { } + | declmods setspecs notype_declarator + { if (! start_function ($1, $3, 0)) + YYERROR1; + reinit_parse_for_function (); } + xdecls + { store_parm_decls (); } + compstmt_or_error + { finish_function (0); } + | declmods setspecs notype_declarator error + { } + | setspecs notype_declarator + { if (! start_function (NULL_TREE, $2, 0)) + YYERROR1; + reinit_parse_for_function (); } + xdecls + { store_parm_decls (); } + compstmt_or_error + { finish_function (0); } + | setspecs notype_declarator error + { } + ; + + identifier: + IDENTIFIER + | TYPENAME + ifobjc + | CLASSNAME + { $$ = CLASS_NAME ($1); } + end ifobjc + ; + + 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 + { $1 = pedantic; + pedantic = 0; } + cast_expr %prec UNARY + { $$ = $3; + pedantic = $1; } + | unop cast_expr %prec UNARY + { $$ = build_unary_op ($1, $2, 0); } + /* Refer to the address of a label as a pointer. */ + | ANDAND identifier + { tree label = lookup_label ($2); + 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 + { if (TREE_CODE ($2) == COMPONENT_REF + && DECL_BIT_FIELD (TREE_OPERAND ($2, 1))) + error ("`sizeof' applied to a bit-field"); + $$ = c_sizeof (TREE_TYPE ($2)); } + | SIZEOF '(' typename ')' %prec HYPERUNARY + { $$ = c_sizeof (groktypename ($3)); } + | ALIGNOF unary_expr %prec UNARY + { $$ = c_alignof_expr ($2); } + | ALIGNOF '(' typename ')' %prec HYPERUNARY + { $$ = c_alignof (groktypename ($3)); } + ; + + cast_expr: + unary_expr + | '(' typename ')' cast_expr %prec UNARY + { tree type = groktypename ($2); + $$ = build_c_cast (type, $4); } + | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY + { tree type = groktypename ($2); + char *name; + 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 = ""; + $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), + NULL_PTR, 0, 0, name); + 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 expr_no_commas + { $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); } + | expr_no_commas OROR expr_no_commas + { $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $3); } + | expr_no_commas '?' xexpr ':' expr_no_commas + { $$ = build_conditional_expr ($1, $3, $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); + C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } + ; + + primary: + IDENTIFIER + { + tree context; + + $$ = lastiddecl; + if (!$$ || $$ == error_mark_node) + { + if (yychar == YYEMPTY) + yychar = YYLEX; + if (yychar == '(') + { + ifobjc + 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 + && is_ivar (objc_ivar_chain, $1)) + $$ = build_ivar_reference ($1); + else + end ifobjc + { + /* Ordinary implicit function declaration. */ + $$ = implicitly_declare ($1); + assemble_external ($$); + TREE_USED ($$) = 1; + } + } + else if (current_function_decl == 0) + { + error ("`%s' undeclared, outside of functions", + IDENTIFIER_POINTER ($1)); + $$ = error_mark_node; + } + else + { + ifobjc + if (objc_receiver_context + && ! strcmp (IDENTIFIER_POINTER ($1), "super")) + /* we have a message to super */ + $$ = get_super_receiver (); + else if (objc_method_context + && is_ivar (objc_ivar_chain, $1)) + $$ = build_ivar_reference ($1); + else + end ifobjc + { + 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. */ + ifobjc + if (objc_method_context + && is_ivar (objc_ivar_chain, $1)) + error ("Instance variable `%s' implicitly declared as function", + IDENTIFIER_POINTER (DECL_NAME ($$))); + else + end ifobjc + 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; + ifobjc + /* we have a definition - still check if iVariable */ + + if (!objc_receiver_context + || (objc_receiver_context + && strcmp (IDENTIFIER_POINTER ($1), "super"))) + { + if (objc_method_context + && is_ivar (objc_ivar_chain, $1)) + { + if (IDENTIFIER_LOCAL_VALUE ($1)) + warning ("local declaration of `%s' hides instance variable", + IDENTIFIER_POINTER ($1)); + else + $$ = build_ivar_reference ($1); + } + } + else /* we have a message to super */ + $$ = get_super_receiver (); + end ifobjc + } + + 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_label_level (); + $$ = expand_start_stmt_expr (); } + compstmt ')' + { tree rtl_exp; + if (pedantic) + pedwarn ("ANSI C forbids braced-groups within expressions"); + pop_label_level (); + rtl_exp = expand_end_stmt_expr ($2); + /* The statements have side effects, so the group does. */ + TREE_SIDE_EFFECTS (rtl_exp) = 1; + + /* 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); + } + | primary '(' exprlist ')' %prec '.' + { $$ = build_function_call ($1, $3); } + | primary '[' expr ']' %prec '.' + { $$ = build_array_ref ($1, $3); } + | primary '.' identifier + { + ifobjc + if (doing_objc_thang) + { + if (is_public ($1, $3)) + $$ = build_component_ref ($1, $3); + else + $$ = error_mark_node; + } + else + end ifobjc + $$ = build_component_ref ($1, $3); + } + | primary POINTSAT identifier + { + tree expr = build_indirect_ref ($1, "->"); + + ifobjc + if (doing_objc_thang) + { + if (is_public (expr, $3)) + $$ = build_component_ref (expr, $3); + else + $$ = error_mark_node; + } + else + end ifobjc + $$ = build_component_ref (expr, $3); + } + | primary PLUSPLUS + { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } + | primary MINUSMINUS + { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); } + ifobjc + | objcmessageexpr + { $$ = build_message_expr ($1); } + | objcselectorexpr + { $$ = build_selector_expr ($1); } + | objcencodeexpr + { $$ = build_encode_expr ($1); } + end ifobjc + ; + + /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */ + string: + STRING + | string STRING + { $$ = chainon ($1, $2); } + ; + + xdecls: + /* 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 + ; + + datadecl: + typed_declspecs setspecs initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs ';' + { shadow_tag_warned ($1, 1); + pedwarn ("empty declaration"); } + | declmods ';' + { 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 (NULL_TREE, current_declspecs, + declspec_stack); + current_declspecs = $0; } + ; + + decl: + typed_declspecs setspecs initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs setspecs nested_function + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_nested_function + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs ';' + { shadow_tag ($1); } + | declmods ';' + { pedwarn ("empty declaration"); } + ; + + /* 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. */ + + 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); } + ; + + /* List of just storage classes and type modifiers. + A declaration can start with just this, but then it cannot be used + to redeclare a typedef-name. */ + + declmods: + TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); + TREE_STATIC ($$) = 1; } + | SCSPEC + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } + | declmods TYPE_QUAL + { $$ = tree_cons (NULL_TREE, $2, $1); + TREE_STATIC ($$) = 1; } + | declmods 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); } + ifobjc + | CLASSNAME + { $$ = get_static_reference ($1); } + end ifobjc + | 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 '=' + { $$ = start_decl ($1, current_declspecs, 1); } + init + /* Note how the declaration of the variable is in effect while its init is parsed! */ + { decl_attributes ($5, $3); + finish_decl ($5, $6, $2); } + | declarator maybeasm maybe_attribute + { tree d = start_decl ($1, current_declspecs, 0); + decl_attributes (d, $3); + finish_decl (d, NULL_TREE, $2); } + ; + + notype_initdcl: + notype_declarator maybeasm maybe_attribute '=' + { $$ = start_decl ($1, current_declspecs, 1); } + init + /* Note how the declaration of the variable is in effect while its init is parsed! */ + { decl_attributes ($5, $3); + finish_decl ($5, $6, $2); } + | notype_declarator maybeasm maybe_attribute + { tree d = start_decl ($1, current_declspecs, 0); + decl_attributes (d, $3); + 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; } + | ATTRIBUTE '(' '(' attribute_list ')' ')' + { $$ = $4; } + ; + + attribute_list + : attrib + { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } + | attribute_list ',' attrib + { $$ = tree_cons (NULL_TREE, $3, $1); } + ; + + attrib + : IDENTIFIER + { if (strcmp (IDENTIFIER_POINTER ($1), "packed")) + warning ("`%s' attribute directive ignored", + IDENTIFIER_POINTER ($1)); + $$ = $1; } + | IDENTIFIER '(' IDENTIFIER ')' + { /* If not "mode (m)", then issue warning. */ + if (strcmp (IDENTIFIER_POINTER ($1), "mode") != 0) + { + warning ("`%s' attribute directive ignored", + IDENTIFIER_POINTER ($1)); + $$ = $1; + } + else + $$ = tree_cons ($1, $3, NULL_TREE); } + | IDENTIFIER '(' CONSTANT ')' + { /* if not "aligned(n)", then issue warning */ + if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0 + || TREE_CODE ($3) != INTEGER_CST) + { + warning ("`%s' attribute directive ignored", + IDENTIFIER_POINTER ($1)); + $$ = $1; + } + else + $$ = tree_cons ($1, $3, NULL_TREE); } + | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' + { /* if not "format(...)", then issue warning */ + if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0 + || TREE_CODE ($5) != INTEGER_CST + || TREE_CODE ($7) != INTEGER_CST) + { + warning ("`%s' attribute directive ignored", + IDENTIFIER_POINTER ($1)); + $$ = $1; + } + else + $$ = tree_cons ($1, + tree_cons ($3, + tree_cons ($5, $7, NULL_TREE), + NULL_TREE), + NULL_TREE); } + ; + + init: + expr_no_commas + | '{' '}' + { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); + if (pedantic) + pedwarn ("ANSI C forbids empty initializer braces"); } + | '{' initlist '}' + { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); } + | '{' initlist ',' '}' + { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); } + | error + { $$ = NULL_TREE; } + ; + + /* This chain is built in reverse order, + and put in forward order where initlist is used. */ + initlist: + init + { $$ = build_tree_list (NULL_TREE, $1); } + | initlist ',' init + { $$ = tree_cons (NULL_TREE, $3, $1); } + /* These are for labeled elements. */ + | '[' expr_no_commas ELLIPSIS expr_no_commas ']' init + { $$ = build_tree_list (tree_cons ($2, NULL_TREE, + build_tree_list ($4, NULL_TREE)), + $6); } + | initlist ',' '[' expr_no_commas ELLIPSIS expr_no_commas ']' init + { $$ = tree_cons (tree_cons ($4, NULL_TREE, + build_tree_list ($6, NULL_TREE)), + $8, + $1); } + | '[' expr_no_commas ']' init + { $$ = build_tree_list ($2, $4); } + | initlist ',' '[' expr_no_commas ']' init + { $$ = tree_cons ($4, $6, $1); } + | identifier ':' init + { $$ = build_tree_list ($1, $3); } + | initlist ',' identifier ':' init + { $$ = tree_cons ($3, $5, $1); } + ; + + nested_function: + declarator + { push_c_function_context (); + if (! start_function (current_declspecs, $1, 1)) + { + pop_c_function_context (); + YYERROR1; + } + reinit_parse_for_function (); + 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, 1)) + { + pop_c_function_context (); + YYERROR1; + } + reinit_parse_for_function (); + 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); } + | TYPENAME + ; + + /* 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); } + | 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); } + | IDENTIFIER + ; + + structsp: + STRUCT identifier '{' + { $$ = start_struct (RECORD_TYPE, $2); + /* Start scope of tag before parsing components. */ + } + component_decl_list '}' + { $$ = finish_struct ($4, $5); + /* Really define the structure. */ + } + | STRUCT '{' component_decl_list '}' + { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE), + $3); } + | STRUCT identifier + { $$ = xref_tag (RECORD_TYPE, $2); } + | UNION identifier '{' + { $$ = start_struct (UNION_TYPE, $2); } + component_decl_list '}' + { $$ = finish_struct ($4, $5); } + | UNION '{' component_decl_list '}' + { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE), + $3); } + | UNION identifier + { $$ = xref_tag (UNION_TYPE, $2); } + | ENUM identifier '{' + { $3 = suspend_momentary (); + $$ = start_enum ($2); } + enumlist maybecomma_warn '}' + { $$ = finish_enum ($4, nreverse ($5)); + resume_momentary ($3); } + | ENUM '{' + { $2 = suspend_momentary (); + $$ = start_enum (NULL_TREE); } + enumlist maybecomma_warn '}' + { $$ = finish_enum ($3, nreverse ($4)); + resume_momentary ($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"); } + ifobjc + /* foo(sizeof(struct{ @defs(ClassName)})); */ + | DEFS '(' CLASSNAME ')' + { $$ = get_class_ivars ($3); } + end ifobjc + ; + + /* 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); + 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); + 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; } + ; + + 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); } + | save_filename save_lineno + declarator ':' expr_no_commas maybe_attribute + { $$ = grokfield ($1, $2, $3, current_declspecs, $5); + decl_attributes ($$, $6); } + | save_filename save_lineno ':' expr_no_commas + { $$ = grokfield ($1, $2, NULL_TREE, current_declspecs, $4); } + ; + + /* 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 + { $$ = chainon ($3, $1); } + ; + + + 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); } + ; + + /* 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_label + | stmts lineno_stmt_or_label + | stmts errstmt + ; + + xstmts: + /* empty */ + | stmts + ; + + errstmt: error ';' + ; + + pushlevel: /* empty */ + { emit_line_note (input_filename, lineno); + pushlevel (0); + clear_last_expr (); + push_momentary (); + expand_start_bindings (0); + ifobjc + if (objc_method_context) + add_objc_decls (); + end ifobjc + } + ; + + /* 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: '{' '}' + { $$ = convert (void_type_node, integer_zero_node); } + | '{' pushlevel maybe_label_decls decls xstmts '}' + { emit_line_note (input_filename, lineno); + expand_end_bindings (getdecls (), 1, 0); + $$ = poplevel (1, 1, 0); + pop_momentary (); } + | '{' 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); + pop_momentary (); } + | '{' 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); + pop_momentary (); } + ; + + /* Value is number of statements counted as of the closeparen. */ + simple_if: + if_prefix lineno_labeled_stmt + /* Make sure expand_end_cond is run once + for each call to expand_start_cond. + Otherwise a crash is likely. */ + | if_prefix error + ; + + if_prefix: + IF '(' expr ')' + { emit_line_note ($-1, $0); + expand_start_cond (truthvalue_conversion ($3), 0); + $1 = stmt_count; + if_stmt_file = $-1; + if_stmt_line = $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++; + emit_line_note ($-1, $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 + { } + ; + + stmt_or_label: + stmt + | label + { int next; + position_after_white_space (); + next = getc (finput); + ungetc (next, finput); + if (pedantic && next == '}') + pedwarn ("ANSI C forbids label at end of compound statement"); + } + ; + + /* Parse a single real statement, not including any labels. */ + stmt: + compstmt + { stmt_count++; } + | expr ';' + { stmt_count++; + emit_line_note ($-1, $0); + c_expand_expr_stmt ($1); + clear_momentary (); } + | simple_if ELSE + { expand_start_else (); + $1 = stmt_count; + position_after_white_space (); } + lineno_labeled_stmt + { expand_end_cond (); + if (extra_warnings && stmt_count == $1) + warning ("empty body in an else-statement"); } + | simple_if %prec IF + { expand_end_cond (); + if (extra_warnings && stmt_count == $1) + warning_with_file_and_line (if_stmt_file, if_stmt_line, + "empty body in an if-statement"); } + /* Make sure expand_end_cond is run once + for each call to expand_start_cond. + Otherwise a crash is likely. */ + | simple_if ELSE error + { expand_end_cond (); } + | WHILE + { stmt_count++; + emit_line_note ($-1, $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 ($-1, $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... */ + { $7 = lineno; + $$ = 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 ($8, $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 (); + $7 = lineno; + $8 = input_filename; } + lineno_labeled_stmt + { /* Emit the increment expression, with a line number. */ + emit_line_note ($8, $7); + expand_loop_continue_here (); + if ($9) + c_expand_expr_stmt ($9); + pop_momentary (); + expand_end_loop (); } + | SWITCH '(' expr ')' + { stmt_count++; + emit_line_note ($-1, $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); + pop_momentary (); } + | BREAK ';' + { stmt_count++; + emit_line_note ($-1, $0); + if ( ! expand_exit_something ()) + error ("break statement not within loop or switch"); } + | CONTINUE ';' + { stmt_count++; + emit_line_note ($-1, $0); + if (! expand_continue_loop (NULL_PTR)) + error ("continue statement not within a loop"); } + | RETURN ';' + { stmt_count++; + emit_line_note ($-1, $0); + c_expand_return (NULL_TREE); } + | RETURN expr ';' + { stmt_count++; + emit_line_note ($-1, $0); + c_expand_return ($2); } + | ASM_KEYWORD maybe_type_qual '(' expr ')' ';' + { stmt_count++; + emit_line_note ($-1, $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 ($-1, $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 ($-1, $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 ($-1, $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 ($-1, $0); + decl = lookup_label ($2); + if (decl != 0) + { + TREE_USED (decl) = 1; + expand_goto (decl); + } + } + | GOTO '*' expr ';' + { stmt_count++; + emit_line_note ($-1, $0); + expand_computed_goto (convert (ptr_type_node, $3)); } + | ';' + ; + + /* 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 ':' + { 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, 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 ELLIPSIS expr ':' + { 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); + + stmt_count++; + + if (value1 != error_mark_node && value2 != error_mark_node) + { + tree duplicate; + int success = pushcase_range (value1, value2, 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, 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); } + | 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); + if (pedantic) + pedwarn ("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 parm_declarator + { $$ = build_tree_list ($1, $2) ; } + | typed_declspecs notype_declarator + { $$ = build_tree_list ($1, $2) ; } + | typed_declspecs absdcl + { $$ = build_tree_list ($1, $2); } + | declmods notype_declarator + { $$ = build_tree_list ($1, $2) ; } + | declmods absdcl + { $$ = build_tree_list ($1, $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)); } + ; + + ifobjc + /* Objective-C productions. */ + + objcdef: + classdef + | 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"); + } + ; + + classdef: + INTERFACE identifier '{' + { + objc_interface_context = objc_ivar_context + = start_class (INTERFACE_TYPE, $2, NULL_TREE); + 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 + { + objc_interface_context + = start_class (INTERFACE_TYPE, $2, NULL_TREE); + continue_class (objc_interface_context); + } + methodprotolist + END + { + finish_class (objc_interface_context); + objc_interface_context = NULL_TREE; + } + + | INTERFACE identifier ':' identifier '{' + { + objc_interface_context = objc_ivar_context + = start_class (INTERFACE_TYPE, $2, $4); + 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 + { + objc_interface_context + = start_class (INTERFACE_TYPE, $2, $4); + 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 (IMPLEMENTATION_TYPE, $2, NULL_TREE); + objc_public_flag = 0; + } + ivar_decl_list '}' + { + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | IMPLEMENTATION identifier + { + objc_implementation_context + = start_class (IMPLEMENTATION_TYPE, $2, NULL_TREE); + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | IMPLEMENTATION identifier ':' identifier '{' + { + objc_implementation_context = objc_ivar_context + = start_class (IMPLEMENTATION_TYPE, $2, $4); + objc_public_flag = 0; + } + ivar_decl_list '}' + { + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | IMPLEMENTATION identifier ':' identifier + { + objc_implementation_context + = start_class (IMPLEMENTATION_TYPE, $2, $4); + objc_ivar_chain + = continue_class (objc_implementation_context); + } + + | INTERFACE identifier '(' identifier ')' + { + objc_interface_context + = start_class (PROTOCOL_TYPE, $2, $4); + 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_TYPE, $2, $4); + objc_ivar_chain + = continue_class (objc_implementation_context); + } + ; + + ivar_decl_list: + ivar_decls PUBLIC { objc_public_flag = 1; } ivar_decls + | ivar_decls + ; + + ivar_decls: + /* empty */ + { + $$ = NULL_TREE; + } + | ivar_decls ivar_decl ';' + | ivar_decls ';' + { + if (pedantic) + warning ("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; + resume_momentary ($2); + } + | nonempty_type_quals setspecs ivars + { + $$ = $3; + 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: + '+' + { + if (objc_implementation_context) + objc_inherit_code = CLASS_METHOD_DECL; + else + fatal ("method definition not in class context"); + } + methoddecl + { + 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; + } + + | '-' + { + if (objc_implementation_context) + objc_inherit_code = INSTANCE_METHOD_DECL; + else + fatal ("method definition not in class context"); + } + methoddecl + { + 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 */ + | {$$ = NULL_TREE; } methodprotolist2 + ; + + methodprotolist2: /* eliminates a shift/reduce conflict */ + methodproto + | datadef + | methodprotolist2 methodproto + | methodprotolist2 {$$ = 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 ';' + { 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 + { $$ = build_tree_list (current_declspecs, $1) ; } + | notype_declarator + { $$ = build_tree_list (current_declspecs, $1) ; } + | absdcl + { $$ = build_tree_list (current_declspecs, $1) ; } + ; + + 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 + | 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; + } + ; + + /* extension to support C-structures in the archiver */ + + objcencodeexpr: + ENCODE '(' typename ')' + { + $$ = groktypename ($3); + } + ; + + end ifobjc + %% + ifobjc + + /* If STRING is the name of an Objective C @-keyword + (not including the @), return the token type for that keyword. + Otherwise return 0. */ + + int + recognize_objc_keyword (string) + char *string; + { + switch (string[0]) + { + case 'd': + if (!strcmp (string, "defs")) + return DEFS; + break; + case 'e': + if (!strcmp (string, "end")) + return END; + if (!strcmp (string, "encode")) + return ENCODE; + break; + case 'i': + if (!strcmp (string, "interface")) + return INTERFACE; + if (!strcmp (string, "implementation")) + return IMPLEMENTATION; + break; + case 'p': + if (!strcmp (string, "public")) + return PUBLIC; + break; + case 's': + if (!strcmp (string, "selector")) + return SELECTOR; + break; + } + return 0; + } + + end ifobjc diff -rc2N gcc-2.2.2/c-parse.y gcc-2.3.1/c-parse.y *** gcc-2.2.2/c-parse.y Wed Jun 10 00:25:30 1992 --- gcc-2.3.1/c-parse.y Wed Oct 7 16:19:01 1992 *************** *** 1,3 **** ! /* YACC parser for C syntax. Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. --- 1,3 ---- ! /* YACC parser for C syntax and for Objective C. -*-c-*- Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. *************** *** 18,21 **** --- 18,26 ---- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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. + The awk script cond.awk is 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 *************** *** 54,57 **** --- 59,63 ---- #endif + #ifndef errno extern int errno; *************** *** 134,138 **** %left POINTSAT '.' '(' '[' ! /* The Objective-C keywords, here so our token codes match obj's. */ %token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE %token CLASSNAME PUBLIC --- 140,145 ---- %left 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 *************** *** 173,176 **** --- 180,184 ---- %type save_lineno + %{ /* Number of statements (loosely speaking) seen so far. */ *************** *** 191,194 **** --- 199,203 ---- static int undeclared_variable_notice; + /* Tell yyparse how to print a token's value, if yydebug is set. */ *************** *** 200,205 **** program: /* empty */ { if (pedantic) ! pedwarn ("ANSI C forbids an empty source file"); } | extdefs ; --- 209,217 ---- program: /* empty */ { if (pedantic) ! pedwarn ("ANSI C forbids an empty source file"); ! } | extdefs + { + } ; *************** *** 237,241 **** {} | declmods ';' ! { error ("empty declaration"); } | typed_declspecs ';' { shadow_tag ($1); } --- 249,253 ---- {} | declmods ';' ! { pedwarn ("empty declaration"); } | typed_declspecs ';' { shadow_tag ($1); } *************** *** 269,273 **** { } | setspecs notype_declarator ! { if (! start_function (0, $2, 0)) YYERROR1; reinit_parse_for_function (); } --- 281,285 ---- { } | setspecs notype_declarator ! { if (! start_function (NULL_TREE, $2, 0)) YYERROR1; reinit_parse_for_function (); } *************** *** 385,389 **** name = ""; $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), ! 0, 0, 0, name); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) { --- 397,401 ---- name = ""; $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), ! NULL_PTR, 0, 0, name); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) { *************** *** 428,434 **** { $$ = build_conditional_expr ($1, $3, $5); } | expr_no_commas '=' expr_no_commas ! { $$ = build_modify_expr ($1, NOP_EXPR, $3); } | expr_no_commas ASSIGN expr_no_commas ! { $$ = build_modify_expr ($1, $2, $3); } ; --- 440,448 ---- { $$ = build_conditional_expr ($1, $3, $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); ! C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } ; *************** *** 445,451 **** if (yychar == '(') { ! $$ = implicitly_declare ($1); ! assemble_external ($$); ! TREE_USED ($$) = 1; } else if (current_function_decl == 0) --- 459,468 ---- if (yychar == '(') { ! { ! /* Ordinary implicit function declaration. */ ! $$ = implicitly_declare ($1); ! assemble_external ($$); ! TREE_USED ($$) = 1; ! } } else if (current_function_decl == 0) *************** *** 457,481 **** 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 { --- 474,536 ---- 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 (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 { *************** *** 483,488 **** TREE_USED ($$) = 1; } if (TREE_CODE ($$) == CONST_DECL) ! $$ = DECL_INITIAL ($$); } | CONSTANT --- 538,550 ---- TREE_USED ($$) = 1; } + 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 *************** *** 518,528 **** /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; - /* Clear TREE_USED which is always set by poplevel. This - block will only be used if the BIND_EXPR is used. */ - TREE_USED ($3) = 0; /* Make a BIND_EXPR for the BLOCK already made. */ $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), NULL_TREE, rtl_exp, $3); } | primary '(' exprlist ')' %prec '.' --- 580,591 ---- /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; /* 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); } | primary '(' exprlist ')' %prec '.' *************** *** 531,537 **** { $$ = build_array_ref ($1, $3); } | primary '.' identifier ! { $$ = build_component_ref ($1, $3); } | primary POINTSAT identifier ! { $$ = build_component_ref (build_indirect_ref ($1, "->"), $3); } | primary PLUSPLUS { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } --- 594,606 ---- { $$ = build_array_ref ($1, $3); } | primary '.' identifier ! { ! $$ = build_component_ref ($1, $3); ! } | primary POINTSAT identifier ! { ! tree expr = build_indirect_ref ($1, "->"); ! ! $$ = build_component_ref (expr, $3); ! } | primary PLUSPLUS { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } *************** *** 582,586 **** resume_momentary ($2); } | typed_declspecs ';' ! { shadow_tag ($1); } | declmods ';' { pedwarn ("empty declaration"); } --- 651,656 ---- resume_momentary ($2); } | typed_declspecs ';' ! { shadow_tag_warned ($1, 1); ! pedwarn ("empty declaration"); } | declmods ';' { pedwarn ("empty declaration"); } *************** *** 610,614 **** { $$ = suspend_momentary (); pending_xref_error (); ! declspec_stack = tree_cons (0, current_declspecs, declspec_stack); current_declspecs = $0; } --- 680,684 ---- { $$ = suspend_momentary (); pending_xref_error (); ! declspec_stack = tree_cons (NULL_TREE, current_declspecs, declspec_stack); current_declspecs = $0; } *************** *** 654,658 **** { $$ = tree_cons (NULL_TREE, $2, $1); } | reserved_declspecs SCSPEC ! { $$ = tree_cons (NULL_TREE, $2, $1); } ; --- 724,731 ---- { $$ = 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); } ; *************** *** 663,673 **** declmods: TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | declmods TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $2, $1); } | declmods SCSPEC ! { $$ = tree_cons (NULL_TREE, $2, $1); } ; --- 736,752 ---- declmods: TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); ! TREE_STATIC ($$) = 1; } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | declmods TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $2, $1); ! TREE_STATIC ($$) = 1; } | declmods 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); } ; *************** *** 701,711 **** $$ = lookup_name ($1); } | TYPEOF '(' expr ')' ! { $$ = TREE_TYPE ($3); ! if (pedantic) ! pedwarn ("ANSI C forbids `typeof'"); } | TYPEOF '(' typename ')' ! { $$ = groktypename ($3); ! if (pedantic) ! pedwarn ("ANSI C forbids `typeof'"); } ; --- 780,786 ---- $$ = lookup_name ($1); } | TYPEOF '(' expr ')' ! { $$ = TREE_TYPE ($3); } | TYPEOF '(' typename ')' ! { $$ = groktypename ($3); } ; *************** *** 792,796 **** } else ! $$ = tree_cons ($1, $3); } | IDENTIFIER '(' CONSTANT ')' { /* if not "aligned(n)", then issue warning */ --- 867,871 ---- } else ! $$ = tree_cons ($1, $3, NULL_TREE); } | IDENTIFIER '(' CONSTANT ')' { /* if not "aligned(n)", then issue warning */ *************** *** 803,807 **** } else ! $$ = tree_cons ($1, $3); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ --- 878,882 ---- } else ! $$ = tree_cons ($1, $3, NULL_TREE); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ *************** *** 815,819 **** } else ! $$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7))); } ; --- 890,898 ---- } else ! $$ = tree_cons ($1, ! tree_cons ($3, ! tree_cons ($5, $7, NULL_TREE), ! NULL_TREE), ! NULL_TREE); } ; *************** *** 840,843 **** --- 919,931 ---- { $$ = tree_cons (NULL_TREE, $3, $1); } /* These are for labeled elements. */ + | '[' expr_no_commas ELLIPSIS expr_no_commas ']' init + { $$ = build_tree_list (tree_cons ($2, NULL_TREE, + build_tree_list ($4, NULL_TREE)), + $6); } + | initlist ',' '[' expr_no_commas ELLIPSIS expr_no_commas ']' init + { $$ = tree_cons (tree_cons ($4, NULL_TREE, + build_tree_list ($6, NULL_TREE)), + $8, + $1); } | '[' expr_no_commas ']' init { $$ = build_tree_list ($2, $4); } *************** *** 1014,1018 **** | component_decl_list2 component_decl { $$ = chainon ($1, $2); ! warning ("no semicolon at end of struct or union"); } ; --- 1102,1106 ---- | component_decl_list2 component_decl { $$ = chainon ($1, $2); ! pedwarn ("no semicolon at end of struct or union"); } ; *************** *** 1169,1173 **** clear_last_expr (); push_momentary (); ! expand_start_bindings (0); } ; --- 1257,1262 ---- clear_last_expr (); push_momentary (); ! expand_start_bindings (0); ! } ; *************** *** 1337,1341 **** expand_start_loop (1); emit_line_note (input_filename, lineno); ! expand_exit_loop_if_false (0, truthvalue_conversion ($4)); position_after_white_space (); } lineno_labeled_stmt --- 1426,1431 ---- 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 *************** *** 1344,1348 **** '(' expr ')' ';' { emit_line_note (input_filename, lineno); ! expand_exit_loop_if_false (0, truthvalue_conversion ($3)); expand_end_loop (); clear_momentary (); } --- 1434,1439 ---- '(' expr ')' ';' { emit_line_note (input_filename, lineno); ! expand_exit_loop_if_false (NULL_PTR, ! truthvalue_conversion ($3)); expand_end_loop (); clear_momentary (); } *************** *** 1375,1385 **** emit_line_note ($8, $7); if ($6) ! expand_exit_loop_if_false (0, 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 (); ! position_after_white_space (); } lineno_labeled_stmt ! { emit_line_note ($-1, $0); expand_loop_continue_here (); if ($9) --- 1466,1479 ---- emit_line_note ($8, $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 (); ! $7 = lineno; ! $8 = input_filename; } lineno_labeled_stmt ! { /* Emit the increment expression, with a line number. */ ! emit_line_note ($8, $7); expand_loop_continue_here (); if ($9) *************** *** 1406,1410 **** { stmt_count++; emit_line_note ($-1, $0); ! if (! expand_continue_loop (0)) error ("continue statement not within a loop"); } | RETURN ';' --- 1500,1504 ---- { stmt_count++; emit_line_note ($-1, $0); ! if (! expand_continue_loop (NULL_PTR)) error ("continue statement not within a loop"); } | RETURN ';' *************** *** 1462,1466 **** { stmt_count++; emit_line_note ($-1, $0); ! expand_computed_goto ($3); } | ';' ; --- 1556,1560 ---- { stmt_count++; emit_line_note ($-1, $0); ! expand_computed_goto (convert (ptr_type_node, $3)); } | ';' ; *************** *** 1689,1691 **** --- 1783,1786 ---- { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } ; + %% diff -rc2N gcc-2.2.2/c-pragma.c gcc-2.3.1/c-pragma.c *** gcc-2.2.2/c-pragma.c --- gcc-2.3.1/c-pragma.c Sat Aug 1 14:18:32 1992 *************** *** 0 **** --- 1,198 ---- + /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack. + Copyright (C) 1992 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. */ + + #include + #include "config.h" + #include "tree.h" + + #ifdef HANDLE_SYSV_PRAGMA + + /* Support #pragma weak by default if WEAK_ASM_OP is defined. */ + #if !defined (HANDLE_PRAGMA_WEAK) && defined (WEAK_ASM_OP) && defined (SET_ASM_OP) + #define HANDLE_PRAGMA_WEAK 1 + #endif + + /* When structure field packing is in effect, this variable is the + number of bits to use as the maximum alignment. When packing is not + in effect, this is zero. */ + + extern int maximum_field_alignment; + + /* File used for outputting assembler code. */ + extern FILE *asm_out_file; + + /* Handle one token of a pragma directive. TOKEN is the + current token, and STRING is its printable form. */ + + void + handle_pragma_token (string, token) + char *string; + tree token; + { + static enum pragma_state + { + ps_start, + ps_done, + ps_bad, + ps_weak, + ps_name, + ps_equals, + ps_value, + ps_pack, + ps_left, + ps_align, + ps_right + } state = ps_start, type; + static char *name; + static char *value; + static int align; + + if (string == 0) + { + if (type == ps_pack) + { + if (state == ps_right) + maximum_field_alignment = align * 8; + else + warning ("malformed `#pragma pack'"); + } + else if (type == ps_weak) + { + #ifdef HANDLE_PRAGMA_WEAK + if (HANDLE_PRAGMA_WEAK) + { + if (state == ps_name || state == ps_value) + { + fprintf (asm_out_file, "\t%s\t", WEAK_ASM_OP); + ASM_OUTPUT_LABELREF (asm_out_file, name); + fputc ('\n', asm_out_file); + if (state == ps_value) + { + fprintf (asm_out_file, "\t%s\t", SET_ASM_OP); + ASM_OUTPUT_LABELREF (asm_out_file, name); + fputc (',', asm_out_file); + ASM_OUTPUT_LABELREF (asm_out_file, value); + fputc ('\n', asm_out_file); + } + } + else if (! (state == ps_done || state == ps_start)) + warning ("malformed `#pragma weak'"); + } + #endif /* HANDLE_PRAMA_WEAK */ + } + + type = state = ps_start; + return; + } + + switch (state) + { + case ps_start: + if (token && TREE_CODE (token) == IDENTIFIER_NODE) + { + if (strcmp (IDENTIFIER_POINTER (token), "pack") == 0) + type = state = ps_pack; + else if (strcmp (IDENTIFIER_POINTER (token), "weak") == 0) + type = state = ps_weak; + else + type = state = ps_done; + } + else + type = state = ps_done; + break; + + case ps_weak: + if (token && TREE_CODE (token) == IDENTIFIER_NODE) + { + name = IDENTIFIER_POINTER (token); + state = ps_name; + } + else + state = ps_bad; + break; + + case ps_name: + state = (strcmp (string, "=") ? ps_bad : ps_equals); + break; + + case ps_equals: + if (token && TREE_CODE (token) == IDENTIFIER_NODE) + { + value = IDENTIFIER_POINTER (token); + state = ps_value; + } + else + state = ps_bad; + break; + + case ps_value: + state = ps_bad; + break; + + case ps_pack: + if (strcmp (string, "(") == 0) + state = ps_left; + else + state = ps_bad; + break; + + case ps_left: + if (token && TREE_CODE (token) == INTEGER_CST + && TREE_INT_CST_HIGH (token) == 0) + switch (TREE_INT_CST_LOW (token)) + { + case 1: + case 2: + case 4: + align = TREE_INT_CST_LOW (token); + state = ps_align; + break; + + default: + state = ps_bad; + } + else if (! token && strcmp (string, ")") == 0) + { + align = 0; + state = ps_right; + } + else + state = ps_bad; + break; + + case ps_align: + if (strcmp (string, ")") == 0) + state = ps_right; + else + state = ps_bad; + break; + + case ps_right: + state = ps_bad; + break; + + case ps_bad: + case ps_done: + break; + + default: + abort (); + } + } + #endif /* HANDLE_SYSV_PRAGMA */ diff -rc2N gcc-2.2.2/c-tree.h gcc-2.3.1/c-tree.h *** gcc-2.2.2/c-tree.h Wed Jun 10 00:28:41 1992 --- gcc-2.3.1/c-tree.h Tue Sep 15 20:52:23 1992 *************** *** 20,42 **** /* Language-dependent contents of an identifier. */ struct lang_identifier { struct tree_identifier ignore; tree global_value, local_value, label_value, implicit_decl; ! tree error_locus; }; /* Macros for access to language-specific slots in an identifier. */ #define IDENTIFIER_GLOBAL_VALUE(NODE) \ (((struct lang_identifier *)(NODE))->global_value) #define IDENTIFIER_LOCAL_VALUE(NODE) \ (((struct lang_identifier *)(NODE))->local_value) #define IDENTIFIER_LABEL_VALUE(NODE) \ (((struct lang_identifier *)(NODE))->label_value) #define IDENTIFIER_IMPLICIT_DECL(NODE) \ (((struct lang_identifier *)(NODE))->implicit_decl) #define IDENTIFIER_ERROR_LOCUS(NODE) \ (((struct lang_identifier *)(NODE))->error_locus) /* In identifiers, C uses the following fields in a special way: --- 20,63 ---- /* Language-dependent contents of an identifier. */ + /* The limbo_value is used for block level extern declarations, which need + to be type checked against subsequent extern declarations. They can't + be referenced after they fall out of scope, so they can't be global. */ + struct lang_identifier { struct tree_identifier ignore; tree global_value, local_value, label_value, implicit_decl; ! tree error_locus, limbo_value; }; /* Macros for access to language-specific slots in an identifier. */ + /* Each of these slots contains a DECL node or null. */ + /* This represents the value which the identifier has in the + file-scope namespace. */ #define IDENTIFIER_GLOBAL_VALUE(NODE) \ (((struct lang_identifier *)(NODE))->global_value) + /* This represents the value which the identifier has in the current + scope. */ #define IDENTIFIER_LOCAL_VALUE(NODE) \ (((struct lang_identifier *)(NODE))->local_value) + /* This represents the value which the identifier has as a label in + the current label scope. */ #define IDENTIFIER_LABEL_VALUE(NODE) \ (((struct lang_identifier *)(NODE))->label_value) + /* This records the extern decl of this identifier, if it has had one + at any point in this compilation. */ + #define IDENTIFIER_LIMBO_VALUE(NODE) \ + (((struct lang_identifier *)(NODE))->limbo_value) + /* This records the implicit function decl of this identifier, if it + has had one at any point in this compilation. */ #define IDENTIFIER_IMPLICIT_DECL(NODE) \ (((struct lang_identifier *)(NODE))->implicit_decl) + /* This is the last function in which we printed an "undefined variable" + message for this identifier. Value is a FUNCTION_DECL or null. */ #define IDENTIFIER_ERROR_LOCUS(NODE) \ (((struct lang_identifier *)(NODE))->error_locus) + #define IDENTIFIER_LIMBO_VALUE(NODE) \ + (((struct lang_identifier *)(NODE))->limbo_value) /* In identifiers, C uses the following fields in a special way: *************** *** 92,99 **** --- 113,136 ---- #define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp)) + /* Nonzero for a declaration of a built in function if there has been no + occasion that would declare the function in ordinary C. + Using the function draws a pedantic warning in this case. */ + #define C_DECL_ANTICIPATED(exp) DECL_LANG_FLAG_3 ((exp)) + /* For FUNCTION_TYPE, a hidden list of types of arguments. The same as TYPE_ARG_TYPES for functions with prototypes, but created for functions without prototypes. */ #define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_NONCOPIED_PARTS (NODE) + + /* Nonzero if the type T promotes to itself. + ANSI C states explicitly the list of types that promote; + in particular, short promotes to int even if they have the same width. */ + #define C_PROMOTING_INTEGER_TYPE_P(t) \ + (TREE_CODE ((t)) == INTEGER_TYPE \ + && (TYPE_MAIN_VARIANT (t) == char_type_node \ + || TYPE_MAIN_VARIANT (t) == signed_char_type_node \ + || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \ + || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ + || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) /* in c-typecheck.c */ *************** *** 171,174 **** --- 208,215 ---- extern char *get_directive_line (); + /* Prepare expr to be an argument of a TRUTH_NOT_EXPR, + or validate its data type for an `if' or `while' statement or ?..: exp. */ + extern tree truthvalue_conversion (); + extern int maybe_objc_comptypes (); extern tree maybe_building_objc_message_expr (); *************** *** 184,187 **** --- 225,232 ---- extern tree wchar_type_node, signed_wchar_type_node, unsigned_wchar_type_node; extern tree float_type_node, double_type_node, long_double_type_node; + extern tree intQI_type_node, unsigned_intQI_type_node; + extern tree intHI_type_node, unsigned_intHI_type_node; + extern tree intSI_type_node, unsigned_intSI_type_node; + extern tree intDI_type_node, unsigned_intDI_type_node; extern tree void_type_node, ptr_type_node, const_ptr_type_node; extern tree string_type_node, const_string_type_node; diff -rc2N gcc-2.2.2/c-typeck.c gcc-2.3.1/c-typeck.c *** gcc-2.2.2/c-typeck.c Wed Jun 10 00:24:42 1992 --- gcc-2.3.1/c-typeck.c Mon Oct 26 19:02:20 1992 *************** *** 34,37 **** --- 34,40 ---- #include "flags.h" + extern char *index (); + extern char *rindex (); + int mark_addressable (); static tree convert_for_assignment (); *************** *** 39,43 **** static int function_types_compatible_p (); static int type_lists_compatible_p (); ! static int self_promoting_args_p (); static int self_promoting_type_p (); static int comp_target_types (); --- 42,46 ---- static int function_types_compatible_p (); static int type_lists_compatible_p (); ! int self_promoting_args_p (); static int self_promoting_type_p (); static int comp_target_types (); *************** *** 151,161 **** /* Return the common type of two types. We assume that comptypes has already been done and returned 1; ! if that isn't so, this may crash. This is the type for the result of most arithmetic operations ! if the operands have the given two types. ! ! We do not deal with enumeral types here because they have already been ! converted to integer types. */ tree --- 154,162 ---- /* Return the common type of two types. We assume that comptypes has already been done and returned 1; ! if that isn't so, this may crash. In particular, we assume that qualifiers ! match. This is the type for the result of most arithmetic operations ! if the operands have the given two types. */ tree *************** *** 228,234 **** case POINTER_TYPE: - #if 0 /* For two pointers, do this recursively on the target type, and combine the qualifiers of the two types' targets. */ { tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), --- 229,237 ---- case POINTER_TYPE: /* For two pointers, do this recursively on the target type, and combine the qualifiers of the two types' targets. */ + /* This code was turned off; I don't know why. + But ANSI C specifies doing this with the qualifiers. + So I turned it on again. */ { tree target = common_type (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), *************** *** 240,245 **** return build_pointer_type (c_build_type_variant (target, constp, volatilep)); } ! #endif return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2))); case ARRAY_TYPE: --- 243,249 ---- return build_pointer_type (c_build_type_variant (target, constp, volatilep)); } ! #if 0 return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2))); + #endif case ARRAY_TYPE: *************** *** 285,289 **** for (i = 0; i < len; i++) ! newargs = tree_cons (0, 0, newargs); n = newargs; --- 289,293 ---- for (i = 0; i < len; i++) ! newargs = tree_cons (NULL_TREE, NULL_TREE, newargs); n = newargs; *************** *** 589,593 **** and none of their types is affected by default promotions. */ ! static int self_promoting_args_p (parms) tree parms; --- 593,597 ---- and none of their types is affected by default promotions. */ ! int self_promoting_args_p (parms) tree parms; *************** *** 601,610 **** return 0; ! if (type == float_type_node) return 0; ! if (type ! && TREE_CODE (type) == INTEGER_TYPE ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) return 0; } --- 605,615 ---- return 0; ! if (type == 0) ! return 0; ! ! if (TYPE_MAIN_VARIANT (type) == float_type_node) return 0; ! if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; } *************** *** 618,626 **** tree type; { ! if (type == float_type_node) return 0; ! if (TREE_CODE (type) == INTEGER_TYPE ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) return 0; --- 623,630 ---- tree type; { ! if (TYPE_MAIN_VARIANT (type) == float_type_node) return 0; ! if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; *************** *** 634,646 **** tree type; { ! if (type == signed_char_type_node || type == char_type_node) return unsigned_char_type_node; ! if (type == integer_type_node) return unsigned_type_node; ! if (type == short_integer_type_node) return short_unsigned_type_node; ! if (type == long_integer_type_node) return long_unsigned_type_node; ! if (type == long_long_integer_type_node) return long_long_unsigned_type_node; return type; --- 638,651 ---- tree type; { ! tree type1 = TYPE_MAIN_VARIANT (type); ! if (type1 == signed_char_type_node || type1 == char_type_node) return unsigned_char_type_node; ! if (type1 == integer_type_node) return unsigned_type_node; ! if (type1 == short_integer_type_node) return short_unsigned_type_node; ! if (type1 == long_integer_type_node) return long_unsigned_type_node; ! if (type1 == long_long_integer_type_node) return long_long_unsigned_type_node; return type; *************** *** 653,665 **** tree type; { ! if (type == unsigned_char_type_node || type == char_type_node) return signed_char_type_node; ! if (type == unsigned_type_node) return integer_type_node; ! if (type == short_unsigned_type_node) return short_integer_type_node; ! if (type == long_unsigned_type_node) return long_integer_type_node; ! if (type == long_long_unsigned_type_node) return long_long_integer_type_node; return type; --- 658,671 ---- tree type; { ! tree type1 = TYPE_MAIN_VARIANT (type); ! if (type1 == unsigned_char_type_node || type1 == char_type_node) return signed_char_type_node; ! if (type1 == unsigned_type_node) return integer_type_node; ! if (type1 == short_unsigned_type_node) return short_integer_type_node; ! if (type1 == long_unsigned_type_node) return long_integer_type_node; ! if (type1 == long_long_unsigned_type_node) return long_long_integer_type_node; return type; *************** *** 783,797 **** return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT); } - - /* Print a warning if a constant expression had overflow in folding. - This doesn't really work--it is waiting for changes in fold. */ - - void - constant_expression_warning (value) - tree value; - { - if (TREE_CODE (value) == NON_LVALUE_EXPR && TREE_CONSTANT_OVERFLOW (value)) - pedwarn ("overflow in constant expression"); - } /* Implement the __alignof keyword: Return the minimum required --- 789,792 ---- *************** *** 799,802 **** --- 794,798 ---- FIELD_DECL's return DECL_ALIGN (which can be set from an "aligned" __attribute__ specification). */ + tree c_alignof_expr (expr) *************** *** 887,892 **** } ! /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! if (TREE_CODE (exp) == NON_LVALUE_EXPR) exp = TREE_OPERAND (exp, 0); --- 883,893 ---- } ! /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as ! an lvalue. */ ! /* Do not use STRIP_NOPS here! It will remove conversions from pointer ! to integer and cause infinite recursion. */ ! while (TREE_CODE (exp) == NON_LVALUE_EXPR ! || (TREE_CODE (exp) == NOP_EXPR ! && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) exp = TREE_OPERAND (exp, 0); *************** *** 901,914 **** } ! if (code == INTEGER_TYPE ! && (TYPE_PRECISION (type) ! < TYPE_PRECISION (integer_type_node))) { ! /* Traditionally, unsignedness is preserved in default promotions. */ ! if (flag_traditional && TREE_UNSIGNED (type)) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } ! if (flag_traditional && type == float_type_node) return convert (double_type_node, exp); if (code == VOID_TYPE) --- 902,916 ---- } ! if (C_PROMOTING_INTEGER_TYPE_P (type)) { ! /* Traditionally, unsignedness is preserved in default promotions. ! Also preserve unsignedness if not really getting any wider. */ ! if (TREE_UNSIGNED (type) ! && (flag_traditional ! || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } ! if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node) return convert (double_type_node, exp); if (code == VOID_TYPE) *************** *** 991,1000 **** { tree value = build_component_ref (TREE_OPERAND (datum, 1), component); - pedantic_lvalue_warning (COMPOUND_EXPR); return build (COMPOUND_EXPR, TREE_TYPE (value), TREE_OPERAND (datum, 0), value); } case COND_EXPR: - pedantic_lvalue_warning (COND_EXPR); return build_conditional_expr (TREE_OPERAND (datum, 0), --- 993,1000 ---- *************** *** 1009,1013 **** if (TYPE_SIZE (type) == 0) { ! incomplete_type_error (0, type); return error_mark_node; } --- 1009,1013 ---- if (TYPE_SIZE (type) == 0) { ! incomplete_type_error (NULL_TREE, type); return error_mark_node; } *************** *** 1193,1197 **** if (pedantic && !lvalue_p (array)) { ! if (TREE_REGDECL (array)) pedwarn ("ANSI C forbids subscripting `register' array"); else --- 1193,1197 ---- if (pedantic && !lvalue_p (array)) { ! if (DECL_REGISTER (array)) pedwarn ("ANSI C forbids subscripting `register' array"); else *************** *** 1204,1208 **** while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); ! if (TREE_CODE (foo) == VAR_DECL && TREE_REGDECL (foo)) pedwarn ("ANSI C forbids subscripting non-lvalue array"); } --- 1204,1208 ---- while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); ! if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) pedwarn ("ANSI C forbids subscripting non-lvalue array"); } *************** *** 1274,1277 **** --- 1274,1278 ---- #define T_C &char_type_node #define T_V &void_type_node + #define T_W &wchar_type_node typedef struct *************** *** 1300,1305 **** { "u", 0, T_UI, T_UI, T_UL, NULL, "-wp0" }, { "feEgG", 0, T_D, NULL, NULL, T_LD, "-wp0 +#" }, ! { "c", 0, T_I, NULL, NULL, NULL, "-w" }, ! { "s", 1, T_C, NULL, NULL, NULL, "-wp" }, { "p", 1, T_V, NULL, NULL, NULL, "-" }, { "n", 1, T_I, T_S, T_L, NULL, "" }, --- 1301,1308 ---- { "u", 0, T_UI, T_UI, T_UL, NULL, "-wp0" }, { "feEgG", 0, T_D, NULL, NULL, T_LD, "-wp0 +#" }, ! { "c", 0, T_I, NULL, T_W, NULL, "-w" }, ! { "C", 0, T_W, NULL, NULL, NULL, "-w" }, ! { "s", 1, T_C, NULL, T_W, NULL, "-wp" }, ! { "S", 1, T_W, NULL, NULL, NULL, "-wp" }, { "p", 1, T_V, NULL, NULL, NULL, "-" }, { "n", 1, T_I, T_S, T_L, NULL, "" }, *************** *** 1312,1316 **** { "ouxX", 1, T_UI, T_US, T_UL, NULL, "*" }, { "efgEG", 1, T_F, NULL, T_D, T_LD, "*" }, ! { "s[c", 1, T_C, NULL, NULL, NULL, "*" }, { "p", 2, T_V, NULL, NULL, NULL, "*" }, { "n", 1, T_I, T_S, T_L, NULL, "" }, --- 1315,1322 ---- { "ouxX", 1, T_UI, T_US, T_UL, NULL, "*" }, { "efgEG", 1, T_F, NULL, T_D, T_LD, "*" }, ! { "sc", 1, T_C, NULL, T_W, NULL, "*" }, ! { "[", 1, T_C, NULL, NULL, NULL, "*" }, ! { "C", 1, T_W, NULL, NULL, NULL, "*" }, ! { "S", 1, T_W, NULL, NULL, NULL, "*" }, { "p", 2, T_V, NULL, NULL, NULL, "*" }, { "n", 1, T_I, T_S, T_L, NULL, "" }, *************** *** 1385,1403 **** static char tfaff[] = "too few arguments for format"; - - /* Don't rely on existence of strchr. */ - - static char * - my_strchr (string, c) - char *string; - int c; - { - char *p; - for (p = string; *p; p++) - if (*p == c) - return p; - - return 0; - } /* Check the argument list of a call to printf, scanf, etc. --- 1391,1394 ---- *************** *** 1503,1509 **** else { ! while (*format_chars != 0 && my_strchr (" +#0-", *format_chars) != 0) { ! if (my_strchr (flag_chars, *format_chars) != 0) { sprintf (message, "repeated `%c' flag in format", --- 1494,1500 ---- else { ! while (*format_chars != 0 && index (" +#0-", *format_chars) != 0) { ! if (index (flag_chars, *format_chars) != 0) { sprintf (message, "repeated `%c' flag in format", *************** *** 1517,1527 **** /* "If the space and + flags both appear, the space flag will be ignored." */ ! if (my_strchr (flag_chars, ' ') != 0 ! && my_strchr (flag_chars, '+') != 0) warning ("use of both ` ' and `+' flags in format"); /* "If the 0 and - flags both appear, the 0 flag will be ignored." */ ! if (my_strchr (flag_chars, '0') != 0 ! && my_strchr (flag_chars, '-') != 0) warning ("use of both `0' and `-' flags in format"); if (*format_chars == '*') --- 1508,1518 ---- /* "If the space and + flags both appear, the space flag will be ignored." */ ! if (index (flag_chars, ' ') != 0 ! && index (flag_chars, '+') != 0) warning ("use of both ` ' and `+' flags in format"); /* "If the 0 and - flags both appear, the 0 flag will be ignored." */ ! if (index (flag_chars, '0') != 0 ! && index (flag_chars, '-') != 0) warning ("use of both `0' and `-' flags in format"); if (*format_chars == '*') *************** *** 1541,1545 **** params = TREE_CHAIN (params); ++arg_num; ! if (TREE_TYPE (cur_param) != integer_type_node) { sprintf (message, --- 1532,1541 ---- params = TREE_CHAIN (params); ++arg_num; ! /* size_t is generally not valid here. ! It will work on most machines, because size_t and int ! have the same mode. But might as well warn anyway, ! since it will fail on other machines. */ ! if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) ! != integer_type_node) { sprintf (message, *************** *** 1564,1568 **** if a precision is specified, the 0 flag will be ignored. For other conversions, the behavior is undefined." */ ! if (my_strchr (flag_chars, '0') != 0) warning ("precision and `0' flag both used in one %%-sequence"); ++format_chars; --- 1560,1564 ---- if a precision is specified, the 0 flag will be ignored. For other conversions, the behavior is undefined." */ ! if (index (flag_chars, '0') != 0) warning ("precision and `0' flag both used in one %%-sequence"); ++format_chars; *************** *** 1584,1588 **** params = TREE_CHAIN (params); ++arg_num; ! if (TREE_TYPE (cur_param) != integer_type_node) { sprintf (message, --- 1580,1585 ---- params = TREE_CHAIN (params); ++arg_num; ! if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) ! != integer_type_node) { sprintf (message, *************** *** 1622,1626 **** { if (fci->format_chars == 0 ! || my_strchr (fci->format_chars, format_char) != 0) break; ++fci; --- 1619,1623 ---- { if (fci->format_chars == 0 ! || index (fci->format_chars, format_char) != 0) break; ++fci; *************** *** 1628,1632 **** if (fci->format_chars == 0) { ! if (format_char >= 040 && format_char <= 0177) sprintf (message, "unknown conversion type character `%c' in format", --- 1625,1629 ---- if (fci->format_chars == 0) { ! if (format_char >= 040 && format_char < 0177) sprintf (message, "unknown conversion type character `%c' in format", *************** *** 1639,1643 **** continue; } ! if (wide && my_strchr (fci->flag_chars, 'w') == 0) { sprintf (message, "width used with `%c' format", --- 1636,1640 ---- continue; } ! if (wide && index (fci->flag_chars, 'w') == 0) { sprintf (message, "width used with `%c' format", *************** *** 1645,1649 **** warning (message); } ! if (precise && my_strchr (fci->flag_chars, 'p') == 0) { sprintf (message, "precision used with `%c' format", --- 1642,1646 ---- warning (message); } ! if (precise && index (fci->flag_chars, 'p') == 0) { sprintf (message, "precision used with `%c' format", *************** *** 1653,1657 **** if (suppressed) { ! if (my_strchr (fci->flag_chars, '*') == 0) { sprintf (message, --- 1650,1654 ---- if (suppressed) { ! if (index (fci->flag_chars, '*') == 0) { sprintf (message, *************** *** 1664,1668 **** for (i = 0; flag_chars[i] != 0; ++i) { ! if (my_strchr (fci->flag_chars, flag_chars[i]) == 0) { sprintf (message, "flag `%c' used with type `%c'", --- 1661,1665 ---- for (i = 0; flag_chars[i] != 0; ++i) { ! if (index (fci->flag_chars, flag_chars[i]) == 0) { sprintf (message, "flag `%c' used with type `%c'", *************** *** 1727,1731 **** /* Check the type of the "real" argument, if there's a type we want. */ if (i == fci->pointer_count && wanted_type != 0 ! && wanted_type != cur_type /* If we want `void *', allow any pointer type. (Anything else would already have got a warning.) */ --- 1724,1728 ---- /* Check the type of the "real" argument, if there's a type we want. */ if (i == fci->pointer_count && wanted_type != 0 ! && wanted_type != TYPE_MAIN_VARIANT (cur_type) /* If we want `void *', allow any pointer type. (Anything else would already have got a warning.) */ *************** *** 1783,1789 **** tree name = NULL_TREE; ! /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! if (TREE_CODE (function) == NON_LVALUE_EXPR) ! function = TREE_OPERAND (function, 0); /* Convert anything with function type to a pointer-to-function. */ --- 1780,1785 ---- tree name = NULL_TREE; ! /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ ! STRIP_TYPE_NOPS (function); /* Convert anything with function type to a pointer-to-function. */ *************** *** 1916,1919 **** --- 1912,1917 ---- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here! We do not want an enumerator with value 0 + to convert automatically to a pointer. */ if (TREE_CODE (val) == NON_LVALUE_EXPR) val = TREE_OPERAND (val, 0); *************** *** 2003,2006 **** --- 2001,2009 ---- else if (TREE_UNSIGNED (type) == TREE_UNSIGNED (type1)) ; + /* Don't complain if the formal parameter type + is an enum, because we can't tell now whether + the value was an enum--even the same enum. */ + else if (TREE_CODE (type) == ENUMERAL_TYPE) + ; else if (TREE_CODE (val) == INTEGER_CST && int_fits_type_p (val, type)) *************** *** 2031,2035 **** #endif } ! result = tree_cons (0, parmval, result); } else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE --- 2034,2038 ---- #endif } ! result = tree_cons (NULL_TREE, parmval, result); } else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE *************** *** 2063,2067 **** we check for operands that were written with other binary operators in a way that is likely to confuse the user. */ ! tree parser_build_binary_op (code, arg1, arg2) --- 2066,2070 ---- we check for operands that were written with other binary operators in a way that is likely to confuse the user. */ ! tree parser_build_binary_op (code, arg1, arg2) *************** *** 2129,2132 **** --- 2132,2140 ---- } + /* Similarly, check for cases like 1<=i<=10 that are probably errors. */ + if (TREE_CODE_CLASS (code) == '<' && extra_warnings + && (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')) + warning ("comparisons like X<=Y<=Z do not have their mathematical meaning"); + class = TREE_CODE_CLASS (TREE_CODE (result)); *************** *** 2229,2237 **** code1 = TREE_CODE (type1); ! /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! if (TREE_CODE (op0) == NON_LVALUE_EXPR) ! op0 = TREE_OPERAND (op0, 0); ! if (TREE_CODE (op1) == NON_LVALUE_EXPR) ! op1 = TREE_OPERAND (op1, 0); /* If an error was already reported for one of the arguments, --- 2237,2243 ---- code1 = TREE_CODE (type1); ! /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ ! STRIP_TYPE_NOPS (op0); ! STRIP_TYPE_NOPS (op1); /* If an error was already reported for one of the arguments, *************** *** 2281,2285 **** resultcode = RDIV_EXPR; else ! shorten = 1; common = 1; } --- 2287,2293 ---- resultcode = RDIV_EXPR; else ! /* When dividing two signed integers, you have to promote to int. ! E.g. (short) -32868 / (short) -1 doesn't fit in a short. */ ! shorten = TREE_UNSIGNED (op0); common = 1; } *************** *** 2349,2358 **** if (TREE_CODE (op1) == INTEGER_CST) { ! if (TREE_INT_CST_LOW (op1) > 0) ! short_shift = 1; ! else if (TREE_INT_CST_LOW (op1) < 0) warning ("shift count is negative"); ! if (TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0)) ! warning ("shift count exceeds width of value shifted"); } /* Use the type of the value to be shifted. --- 2357,2371 ---- if (TREE_CODE (op1) == INTEGER_CST) { ! if (tree_int_cst_lt (op1, integer_zero_node)) warning ("shift count is negative"); ! else ! { ! if (TREE_INT_CST_LOW (op1) | TREE_INT_CST_HIGH (op1)) ! short_shift = 1; ! if (TREE_INT_CST_HIGH (op1) != 0 ! || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1) ! >= TYPE_PRECISION (type0))) ! warning ("shift count >= width of type"); ! } } /* Use the type of the value to be shifted. *************** *** 2363,2367 **** if (! flag_traditional) { ! if (TREE_TYPE (op1) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ --- 2376,2380 ---- if (! flag_traditional) { ! if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ *************** *** 2374,2383 **** if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { ! if (TREE_CODE (op1) == INTEGER_CST ! && TREE_INT_CST_LOW (op1) < 0) ! warning ("shift count is negative"); ! if (TREE_CODE (op1) == INTEGER_CST ! && TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0)) ! warning ("shift count exceeds width of value shifted"); /* Use the type of the value to be shifted. This is what most traditional C compilers do. */ --- 2387,2399 ---- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { ! if (TREE_CODE (op1) == INTEGER_CST) ! { ! if (tree_int_cst_lt (op1, integer_zero_node)) ! warning ("shift count is negative"); ! else if (TREE_INT_CST_HIGH (op1) != 0 ! || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1) ! >= TYPE_PRECISION (type0))) ! warning ("shift count >= width of type"); ! } /* Use the type of the value to be shifted. This is what most traditional C compilers do. */ *************** *** 2387,2391 **** if (! flag_traditional) { ! if (TREE_TYPE (op1) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ --- 2403,2407 ---- if (! flag_traditional) { ! if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ *************** *** 2399,2408 **** if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { ! if (TREE_CODE (op1) == INTEGER_CST ! && TREE_INT_CST_LOW (op1) < 0) ! warning ("shift count is negative"); ! if (TREE_CODE (op1) == INTEGER_CST ! && TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0)) ! warning ("shift count >= width of value shifted"); /* Use the type of the value to be shifted. This is what most traditional C compilers do. */ --- 2415,2427 ---- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { ! if (TREE_CODE (op1) == INTEGER_CST) ! { ! if (tree_int_cst_lt (op1, integer_zero_node)) ! warning ("shift count is negative"); ! else if (TREE_INT_CST_HIGH (op1) != 0 ! || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1) ! >= TYPE_PRECISION (type0))) ! warning ("shift count >= width of type"); ! } /* Use the type of the value to be shifted. This is what most traditional C compilers do. */ *************** *** 2412,2416 **** if (! flag_traditional) { ! if (TREE_TYPE (op1) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ --- 2431,2435 ---- if (! flag_traditional) { ! if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ *************** *** 3158,3163 **** /* Address of a static or external variable or ! function counts as a constant */ ! TREE_CONSTANT (addr) = staticp (arg); return addr; } --- 3177,3185 ---- /* Address of a static or external variable or ! file-scope function counts as a constant. */ ! if (staticp (arg) ! && ! (TREE_CODE (arg) == FUNCTION_DECL ! && DECL_CONTEXT (arg) != 0)) ! TREE_CONSTANT (addr) = 1; return addr; } *************** *** 3206,3210 **** /* Return nonzero if REF is an lvalue valid for this language. Lvalues can be assigned, unless their type has TYPE_READONLY. ! Lvalues can have their address taken, unless they have TREE_REGDECL. */ int --- 3228,3232 ---- /* Return nonzero if REF is an lvalue valid for this language. Lvalues can be assigned, unless their type has TYPE_READONLY. ! Lvalues can have their address taken, unless they have DECL_REGISTER. */ int *************** *** 3353,3358 **** case PARM_DECL: case RESULT_DECL: ! if (TREE_REGDECL (x) && !TREE_ADDRESSABLE (x) ! && TREE_NONLOCAL (x)) { if (TREE_PUBLIC (x)) --- 3375,3380 ---- case PARM_DECL: case RESULT_DECL: ! if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) ! && DECL_NONLOCAL (x)) { if (TREE_PUBLIC (x)) *************** *** 3365,3369 **** IDENTIFIER_POINTER (DECL_NAME (x))); } ! else if (TREE_REGDECL (x) && !TREE_ADDRESSABLE (x)) { if (TREE_PUBLIC (x)) --- 3387,3391 ---- IDENTIFIER_POINTER (DECL_NAME (x))); } ! else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)) { if (TREE_PUBLIC (x)) *************** *** 3450,3455 **** /* Quickly detect the usual case where op1 and op2 have the same type after promotion. */ ! if (type1 == type2) ! result_type = type1; else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE) && (code2 == INTEGER_TYPE || code2 == REAL_TYPE)) --- 3472,3482 ---- /* Quickly detect the usual case where op1 and op2 have the same type after promotion. */ ! if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) ! { ! if (type1 == type2) ! result_type = type1; ! else ! result_type = TYPE_MAIN_VARIANT (type1); ! } else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE) && (code2 == INTEGER_TYPE || code2 == REAL_TYPE)) *************** *** 3529,3532 **** --- 3556,3565 ---- } + /* Merge const and volatile flags of the incoming types. */ + result_type + = build_type_variant (result_type, + TREE_READONLY (op1) || TREE_READONLY (op2), + TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); + if (result_type != TREE_TYPE (op1)) op1 = convert (result_type, op1); *************** *** 3664,3672 **** if (field) { ! tree nvalue = build1 (CONVERT_EXPR, type, value); ! TREE_CONSTANT (nvalue) = TREE_CONSTANT (value); if (pedantic) pedwarn ("ANSI C forbids casts to union type"); ! return nvalue; } error ("cast to union type from type not present in union"); --- 3697,3717 ---- if (field) { ! char *name; ! tree nvalue; ! if (pedantic) pedwarn ("ANSI C forbids casts to union type"); ! 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 = ""; ! return digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, ! build_tree_list (field, value)), ! NULL_PTR, 0, 0, name); } error ("cast to union type from type not present in union"); *************** *** 3708,3712 **** if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE ! && TYPE_PRECISION (type) != TYPE_PRECISION (otype)) warning ("cast from pointer to integer of different size"); --- 3753,3758 ---- if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE ! && TYPE_PRECISION (type) != TYPE_PRECISION (otype) ! && !TREE_CONSTANT (value)) warning ("cast from pointer to integer of different size"); *************** *** 3714,3720 **** && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) /* Don't warn about converting 0 to pointer, provided the 0 was explicit--not cast or made by folding. */ ! && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value))) warning ("cast to pointer from integer of different size"); --- 3760,3770 ---- && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) + #if 0 /* Don't warn about converting 0 to pointer, provided the 0 was explicit--not cast or made by folding. */ ! && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)) ! #endif ! /* Don't warn about converting any constant. */ ! && !TREE_CONSTANT (value)) warning ("cast to pointer from integer of different size"); *************** *** 3753,3756 **** --- 3803,3808 ---- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here. We do not want an enumerator + whose value is 0 to count as a null pointer constant. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) rhs = TREE_OPERAND (rhs, 0); *************** *** 3912,3915 **** --- 3964,3969 ---- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here. We do not want an enumerator + whose value is 0 to count as a null pointer constant. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) rhs = TREE_OPERAND (rhs, 0); *************** *** 4088,4093 **** static tree ! initializer_constant_valid_p (value) tree value; { switch (TREE_CODE (value)) --- 4142,4148 ---- static tree ! initializer_constant_valid_p (value, endtype) tree value; + tree endtype; { switch (TREE_CODE (value)) *************** *** 4105,4109 **** case NON_LVALUE_EXPR: ! return initializer_constant_valid_p (TREE_OPERAND (value, 0)); case CONVERT_EXPR: --- 4160,4164 ---- case NON_LVALUE_EXPR: ! return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); case CONVERT_EXPR: *************** *** 4112,4120 **** if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0)); /* Allow conversions between real types. */ if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0)); /* Allow length-preserving conversions between integer types. */ if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE --- 4167,4175 ---- if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); /* Allow conversions between real types. */ if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); /* Allow length-preserving conversions between integer types. */ if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE *************** *** 4122,4131 **** && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (value)), TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0))))) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0)); /* Allow conversions between integer types only if explicit value. */ if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE) { ! tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0)); if (inner == null_pointer_node) return null_pointer_node; --- 4177,4187 ---- && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (value)), TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0))))) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); /* Allow conversions between integer types only if explicit value. */ if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE) { ! tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0), ! endtype); if (inner == null_pointer_node) return null_pointer_node; *************** *** 4137,4147 **** && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (value)), TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0))))) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0)); return 0; case PLUS_EXPR: { ! tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0)); ! tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1)); /* If either term is absolute, use the other terms relocation. */ if (valid0 == null_pointer_node) --- 4193,4213 ---- && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (value)), TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0))))) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0), ! endtype); ! /* Allow conversions to union types if the value inside is okay. */ ! if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) ! return initializer_constant_valid_p (TREE_OPERAND (value, 0), ! endtype); return 0; case PLUS_EXPR: + if (TREE_CODE (endtype) == INTEGER_TYPE + && TYPE_PRECISION (endtype) < POINTER_SIZE) + return 0; { ! tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), ! endtype); ! tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), ! endtype); /* If either term is absolute, use the other terms relocation. */ if (valid0 == null_pointer_node) *************** *** 4153,4159 **** case MINUS_EXPR: { ! tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0)); ! tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1)); /* Win if second argument is absolute. */ if (valid1 == null_pointer_node) --- 4219,4230 ---- case MINUS_EXPR: + if (TREE_CODE (endtype) == INTEGER_TYPE + && TYPE_PRECISION (endtype) < POINTER_SIZE) + return 0; { ! tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), ! endtype); ! tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), ! endtype); /* Win if second argument is absolute. */ if (valid1 == null_pointer_node) *************** *** 4189,4193 **** /* Digest the specified initializer into an expression. */ ! value = digest_init (type, init, 0, TREE_STATIC (decl), TREE_STATIC (decl) || pedantic, IDENTIFIER_POINTER (DECL_NAME (decl))); --- 4260,4264 ---- /* Digest the specified initializer into an expression. */ ! value = digest_init (type, init, NULL_PTR, TREE_STATIC (decl), TREE_STATIC (decl) || pedantic, IDENTIFIER_POINTER (DECL_NAME (decl))); *************** *** 4207,4211 **** } else if (TREE_STATIC (decl) ! && initializer_constant_valid_p (value) == 0) { error ("initializer for static variable uses complicated arithmetic"); --- 4278,4282 ---- } else if (TREE_STATIC (decl) ! && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0) { error ("initializer for static variable uses complicated arithmetic"); *************** *** 4230,4234 **** } ! /* Methods for storing and printing names for error messages. /* Implement a spelling stack that allows components of a name to be pushed --- 4301,4305 ---- } ! /* Methods for storing and printing names for error messages. */ /* Implement a spelling stack that allows components of a name to be pushed *************** *** 4496,4499 **** --- 4567,4572 ---- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + /* Do not use STRIP_NOPS here. We do not want an enumerator + whose value is 0 to count as a null pointer constant. */ if (TREE_CODE (init) == NON_LVALUE_EXPR) inside_init = TREE_OPERAND (init, 0); *************** *** 4563,4575 **** For an array, this is allowed only for a string constant. */ ! if (inside_init && (TREE_TYPE (inside_init) == type ! || (code == ARRAY_TYPE && TREE_TYPE (inside_init) ! && comptypes (TREE_TYPE (inside_init), type)) ! || (code == POINTER_TYPE ! && TREE_TYPE (inside_init) != 0 ! && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE ! || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE) ! && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), ! TREE_TYPE (type))))) { if (code == POINTER_TYPE --- 4636,4649 ---- For an array, this is allowed only for a string constant. */ ! if (inside_init && TREE_TYPE (inside_init) != 0 ! && ((TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)) ! == TYPE_MAIN_VARIANT (type)) ! || (code == ARRAY_TYPE ! && comptypes (TREE_TYPE (inside_init), type)) ! || (code == POINTER_TYPE ! && (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE ! || TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE) ! && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), ! TREE_TYPE (type))))) { if (code == POINTER_TYPE *************** *** 4594,4598 **** inside_init = error_mark_node; } ! else if (require_constant && initializer_constant_valid_p (inside_init) == 0) { error_init ("initializer element%s is not computable at load time", --- 4668,4673 ---- inside_init = error_mark_node; } ! else if (require_constant ! && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) { error_init ("initializer element%s is not computable at load time", *************** *** 4625,4629 **** element = error_mark_node; } ! else if (require_constant && initializer_constant_valid_p (element) == 0) { error_init ("initializer element%s is not computable at load time", --- 4700,4705 ---- element = error_mark_node; } ! else if (require_constant ! && initializer_constant_valid_p (element, TREE_TYPE (element)) == 0) { error_init ("initializer element%s is not computable at load time", *************** *** 4655,4678 **** } ! SAVE_SPELLING_DEPTH ! ({ ! if (ofwhat) ! push_string (ofwhat); ! push_member_name (IDENTIFIER_POINTER (DECL_NAME (field))); ! ! if (raw_constructor) ! result = process_init_constructor (type, inside_init, 0, ! require_constant, ! constructor_constant, 0); ! else if (tail != 0) ! { ! *tail = old_tail_contents; ! result = process_init_constructor (type, 0, tail, ! require_constant, ! constructor_constant, 0); ! } ! else ! result = 0; ! }); if (result) --- 4731,4747 ---- } ! if (raw_constructor) ! result = process_init_constructor (type, inside_init, NULL_PTR, ! require_constant, ! constructor_constant, ofwhat); ! else if (tail != 0) ! { ! *tail = old_tail_contents; ! result = process_init_constructor (type, NULL_TREE, tail, ! require_constant, ! constructor_constant, ofwhat); ! } ! else ! result = 0; if (result) *************** *** 4694,4698 **** return error_mark_node; } ! inside_init = element; } --- 4763,4779 ---- return error_mark_node; } ! else ! { ! /* Deal with extra levels of {...}. */ ! if (TREE_CODE (element) == CONSTRUCTOR ! && TREE_TYPE (element) == 0) ! { ! error_init ( ! "initializer for scalar%s requires one element", ! " `%s'", ofwhat); ! return error_mark_node; ! } ! inside_init = element; ! } } *************** *** 4724,4728 **** inside_init = error_mark_node; } ! else if (require_constant && initializer_constant_valid_p (inside_init) == 0) { error_init ("initializer element%s is not computable at load time", --- 4805,4810 ---- inside_init = error_mark_node; } ! else if (require_constant ! && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) { error_init ("initializer element%s is not computable at load time", *************** *** 4747,4756 **** if (raw_constructor) return process_init_constructor (type, inside_init, ! 0, constructor_constant, constructor_constant, ofwhat); else if (tail != 0) { *tail = old_tail_contents; ! return process_init_constructor (type, 0, tail, constructor_constant, constructor_constant, ofwhat); } --- 4829,4839 ---- if (raw_constructor) return process_init_constructor (type, inside_init, ! NULL_PTR, constructor_constant, constructor_constant, ofwhat); else if (tail != 0) { *tail = old_tail_contents; ! return process_init_constructor (type, NULL_TREE, tail, ! constructor_constant, constructor_constant, ofwhat); } *************** *** 4758,4764 **** /* Traditionally one can say `char x[100] = 0;'. */ return process_init_constructor (type, ! build_nt (CONSTRUCTOR, 0, ! tree_cons (0, inside_init, 0)), ! 0, constructor_constant, constructor_constant, ofwhat); } --- 4841,4849 ---- /* Traditionally one can say `char x[100] = 0;'. */ return process_init_constructor (type, ! build_nt (CONSTRUCTOR, NULL_TREE, ! tree_cons (NULL_TREE, ! inside_init, ! NULL_TREE)), ! NULL_PTR, constructor_constant, constructor_constant, ofwhat); } *************** *** 4819,4823 **** if (elts) ! tail = *elts; else tail = CONSTRUCTOR_ELTS (init); --- 4904,4912 ---- if (elts) ! { ! if (extra_warnings) ! warning ("aggregate has a partly bracketed initializer"); ! tail = *elts; ! } else tail = CONSTRUCTOR_ELTS (init); *************** *** 4832,4835 **** --- 4921,4928 ---- tree bound_type; tree one; + /* These are non-zero only within a range initializer. */ + tree start_index = 0, end_index = 0; + /* Within a range, this is the value for the elts in the range. */ + tree range_val = 0; /* If we have array bounds, set our bounds from that. Otherwise, *************** *** 4854,4879 **** index value that will override it. */ ! for (current_index = min_index; tail != 0; current_index = fold (build (PLUS_EXPR, bound_type, current_index, one))) { ! register tree next1; /* If this element specifies an index, move to that index before storing it in the new list. */ ! if (TREE_PURPOSE (tail) != 0) { int win = 0; ! if (TREE_CODE (TREE_PURPOSE (tail)) == IDENTIFIER_NODE) error ("field name used as index in array initializer"); ! else if (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST) error ("non-constant array index in initializer"); ! else if (tree_int_cst_lt (TREE_PURPOSE (tail), min_index) ! || (max_index && tree_int_cst_lt (max_index, ! TREE_PURPOSE (tail)))) error ("array index out of range in initializer"); else ! current_index = TREE_PURPOSE (tail), win = 1; if (!win) --- 4947,5028 ---- index value that will override it. */ ! for (current_index = min_index; tail != 0 || end_index; current_index = fold (build (PLUS_EXPR, bound_type, current_index, one))) { ! register tree next1 = 0; + /* Handle the case where we are inside of a range. + current_index increments through the range, + so just keep reusing the same element of TAIL + until the end of the range. */ + if (end_index != 0) + { + next1 = range_val; + if (!tree_int_cst_lt (current_index, end_index)) + end_index = 0; + } + /* If this element specifies an index, move to that index before storing it in the new list. */ ! else if (TREE_PURPOSE (tail) != 0) { int win = 0; + tree index = TREE_PURPOSE (tail); + + if (index && TREE_CODE (index) == NON_LVALUE_EXPR) + index = TREE_OPERAND (index, 0); + + /* Begin a range. */ + if (TREE_CODE (index) == TREE_LIST) + { + start_index = TREE_PURPOSE (index); + end_index = TREE_PURPOSE (TREE_CHAIN (index)); ! /* Expose constants. */ ! if (end_index && TREE_CODE (end_index) == NON_LVALUE_EXPR) ! end_index = TREE_OPERAND (end_index, 0); ! if (start_index && TREE_CODE (start_index) == NON_LVALUE_EXPR) ! start_index = TREE_OPERAND (start_index, 0); ! ! if ((TREE_CODE (start_index) == IDENTIFIER_NODE) ! || (TREE_CODE (end_index) == IDENTIFIER_NODE)) ! error ("field name used as index in array initializer"); ! else if ((TREE_CODE (start_index) != INTEGER_CST) ! || (TREE_CODE (end_index) != INTEGER_CST)) ! error ("non-constant array index in initializer"); ! else if (tree_int_cst_lt (start_index, min_index) ! || (max_index && tree_int_cst_lt (max_index, start_index)) ! || tree_int_cst_lt (end_index, min_index) ! || (max_index && tree_int_cst_lt (max_index, end_index))) ! error ("array index out of range in initializer"); ! else if (tree_int_cst_lt (end_index, start_index)) ! { ! /* If the range is empty, don't initialize any elements, ! but do reset current_index for the next initializer ! element. */ ! warning ("empty array initializer range"); ! tail = TREE_CHAIN (tail); ! current_index = end_index; ! continue; ! } ! else ! { ! current_index = start_index; ! win = 1; ! /* See if the first element is also the last. */ ! if (!tree_int_cst_lt (current_index, end_index)) ! end_index = 0; ! } ! } ! else if (TREE_CODE (index) == IDENTIFIER_NODE) error ("field name used as index in array initializer"); ! else if (TREE_CODE (index) != INTEGER_CST) error ("non-constant array index in initializer"); ! else if (tree_int_cst_lt (index, min_index) ! || (max_index && tree_int_cst_lt (max_index, index))) error ("array index out of range in initializer"); else ! current_index = index, win = 1; if (!win) *************** *** 4885,4889 **** /* Now digest the value specified. */ ! if (TREE_VALUE (tail) != 0) { tree tail1 = tail; --- 5034,5040 ---- /* Now digest the value specified. */ ! if (next1 != 0) ! ; ! else if (TREE_VALUE (tail) != 0) { tree tail1 = tail; *************** *** 4899,4903 **** /* Both of these are the same because a value here is an elt overall. */ ! constant_element, constant_element, 0); }); --- 5050,5055 ---- /* Both of these are the same because a value here is an elt overall. */ ! constant_element, constant_element, ! NULL_PTR); }); *************** *** 4908,4912 **** error_init ( "non-empty initializer for array%s of empty elements", ! " `%s'", 0); /* Just ignore what we were supposed to use. */ tail1 = 0; --- 5060,5064 ---- error_init ( "non-empty initializer for array%s of empty elements", ! " `%s'", NULL_PTR); /* Just ignore what we were supposed to use. */ tail1 = 0; *************** *** 4920,4928 **** } if (next1 == error_mark_node) erroneous = 1; else if (!TREE_CONSTANT (next1)) allconstant = 0; ! else if (initializer_constant_valid_p (next1) == 0) allsimple = 0; --- 5072,5083 ---- } + if (end_index != 0) + range_val = next1; + if (next1 == error_mark_node) erroneous = 1; else if (!TREE_CONSTANT (next1)) allconstant = 0; ! else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) allsimple = 0; *************** *** 4984,4988 **** field = temp, i = j, win = 1; else ! error_with_decl (temp, "no field `%s' in structure being initialized"); } if (!win) --- 5139,5144 ---- field = temp, i = j, win = 1; else ! error ("no field `%s' in structure being initialized", ! IDENTIFIER_POINTER (TREE_PURPOSE (tail))); } if (!win) *************** *** 5007,5011 **** next1 = digest_init (TREE_TYPE (field), TREE_VALUE (tail), &tail1, ! constant_element, constant_element, 0); }); if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) --- 5163,5168 ---- next1 = digest_init (TREE_TYPE (field), TREE_VALUE (tail), &tail1, ! constant_element, constant_element, ! NULL_PTR); }); if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) *************** *** 5023,5027 **** else if (!TREE_CONSTANT (next1)) allconstant = 0; ! else if (initializer_constant_valid_p (next1) == 0) allsimple = 0; --- 5180,5184 ---- else if (!TREE_CONSTANT (next1)) allconstant = 0; ! else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) allsimple = 0; *************** *** 5057,5060 **** --- 5214,5223 ---- /* For a union, get the initializer for 1 fld. */ + if (tail == 0) + { + error ("empty initializer for union"); + tail = build_tree_list (0, 0); + } + /* If this element specifies a field, initialize via that field. */ if (TREE_PURPOSE (tail) != 0) *************** *** 5062,5066 **** int win = 0; ! if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) error ("index value instead of field name in union initializer"); else --- 5225,5232 ---- int win = 0; ! if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL) ! /* Handle the case of a call by build_c_cast. */ ! field = TREE_PURPOSE (tail), win = 1; ! else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) error ("index value instead of field name in union initializer"); else *************** *** 5075,5079 **** field = temp, win = 1; else ! error_with_decl (temp, "no field `%s' in union being initialized"); } if (!win) --- 5241,5246 ---- field = temp, win = 1; else ! error ("no field `%s' in union being initialized", ! IDENTIFIER_POINTER (TREE_PURPOSE (tail))); } if (!win) *************** *** 5091,5095 **** next1 = digest_init (TREE_TYPE (field), TREE_VALUE (tail), &tail1, ! constant_value, constant_element, 0); }); if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) --- 5258,5262 ---- next1 = digest_init (TREE_TYPE (field), TREE_VALUE (tail), &tail1, ! constant_value, constant_element, NULL_PTR); }); if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) *************** *** 5107,5111 **** else if (!TREE_CONSTANT (next1)) allconstant = 0; ! else if (initializer_constant_valid_p (next1) == 0) allsimple = 0; members = tree_cons (field, next1, members); --- 5274,5278 ---- else if (!TREE_CONSTANT (next1)) allconstant = 0; ! else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) allsimple = 0; members = tree_cons (field, next1, members); *************** *** 5122,5131 **** { pedwarn_init ("excess elements in union initializer%s", ! " after `%s'", 0); } else { pedwarn_init ("excess elements in aggregate initializer%s", ! " after `%s'", 0); } } --- 5289,5298 ---- { pedwarn_init ("excess elements in union initializer%s", ! " after `%s'", NULL_PTR); } else { pedwarn_init ("excess elements in aggregate initializer%s", ! " after `%s'", NULL_PTR); } } *************** *** 5173,5177 **** } ! /* Record the contents of OUTPUTS before it is modifed. */ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) o[i] = TREE_VALUE (tail); --- 5340,5344 ---- } ! /* Record the contents of OUTPUTS before it is modified. */ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) o[i] = TREE_VALUE (tail); *************** *** 5273,5285 **** { tree index; if (warn_traditional ! && (TREE_TYPE (exp) == long_integer_type_node ! || TREE_TYPE (exp) == long_unsigned_type_node)) pedwarn ("`long' switch expression not converted to `int' in ANSI C"); exp = default_conversion (exp); type = TREE_TYPE (exp); ! index = get_unwidened (exp, 0); /* We can't strip a conversion from a signed type to an unsigned, because if we did, int_fits_type_p would do the wrong thing --- 5440,5453 ---- { tree index; + type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); if (warn_traditional ! && (type == long_integer_type_node ! || type == long_unsigned_type_node)) pedwarn ("`long' switch expression not converted to `int' in ANSI C"); exp = default_conversion (exp); type = TREE_TYPE (exp); ! index = get_unwidened (exp, NULL_TREE); /* We can't strip a conversion from a signed type to an unsigned, because if we did, int_fits_type_p would do the wrong thing diff -rc2N gcc-2.2.2/caller-save.c gcc-2.3.1/caller-save.c *** gcc-2.2.2/caller-save.c Sat Apr 11 20:29:24 1992 --- gcc-2.3.1/caller-save.c Thu Sep 3 19:25:24 1992 *************** *** 29,42 **** #include "expr.h" ! /* A mode for each hard register that we can save. This mode is wide enough ! to save the entire contents of the register and will be used whenever the ! register must be saved because it is live. */ ! static enum machine_mode regno_save_mode[FIRST_PSEUDO_REGISTER]; /* For each hard register, a place on the stack where it can be saved, if needed. */ ! static rtx regno_save_mem[FIRST_PSEUDO_REGISTER]; /* We will only make a register eligible for caller-save if it can be --- 29,47 ---- #include "expr.h" ! #define CEIL(x,y) (((x) + (y) - 1) / (y)) ! /* Modes for each hard register that we can save. The smallest mode is wide ! enough to save the entire contents of the register. When saving the ! register because it is live we first try to save in multi-register modes. ! If that is not possible the save is done one register at a time. */ + static enum machine_mode + regno_save_mode[FIRST_PSEUDO_REGISTER][MOVE_MAX / UNITS_PER_WORD + 1]; + /* For each hard register, a place on the stack where it can be saved, if needed. */ ! static rtx ! regno_save_mem[FIRST_PSEUDO_REGISTER][MOVE_MAX / UNITS_PER_WORD + 1]; /* We will only make a register eligible for caller-save if it can be *************** *** 46,51 **** be recognized. */ ! static enum insn_code reg_save_code[FIRST_PSEUDO_REGISTER]; ! static enum insn_code reg_restore_code[FIRST_PSEUDO_REGISTER]; /* Set of hard regs currently live (during scan of all insns). */ --- 51,58 ---- be recognized. */ ! static enum insn_code ! reg_save_code[FIRST_PSEUDO_REGISTER][MOVE_MAX / UNITS_PER_WORD + 1]; ! static enum insn_code ! reg_restore_code[FIRST_PSEUDO_REGISTER][MOVE_MAX / UNITS_PER_WORD + 1]; /* Set of hard regs currently live (during scan of all insns). */ *************** *** 57,60 **** --- 64,71 ---- static HARD_REG_SET hard_regs_saved; + /* Set of hard regs which need to be restored before referenced. */ + + static HARD_REG_SET hard_regs_need_restore; + /* Number of registers currently in hard_regs_saved. */ *************** *** 64,75 **** static void clear_reg_live (); static void restore_referenced_regs (); ! static void insert_save_restore (); /* Return a machine mode that is legitimate for hard reg REGNO and large ! enough to save the whole register. If we can't find one, ! return VOIDmode. */ static enum machine_mode ! choose_hard_reg_mode (regno) int regno; { --- 75,85 ---- static void clear_reg_live (); static void restore_referenced_regs (); ! static int insert_save_restore (); /* Return a machine mode that is legitimate for hard reg REGNO and large ! enough to save nregs. If we can't find one, return VOIDmode. */ static enum machine_mode ! choose_hard_reg_mode (regno, nregs) int regno; { *************** *** 82,86 **** for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) ! if (HARD_REGNO_NREGS (regno, mode) == 1 && HARD_REGNO_MODE_OK (regno, mode)) found_mode = mode; --- 92,96 ---- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) ! if (HARD_REGNO_NREGS (regno, mode) == nregs && HARD_REGNO_MODE_OK (regno, mode)) found_mode = mode; *************** *** 91,95 **** for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) ! if (HARD_REGNO_NREGS (regno, mode) == 1 && HARD_REGNO_MODE_OK (regno, mode)) found_mode = mode; --- 101,105 ---- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) ! if (HARD_REGNO_NREGS (regno, mode) == nregs && HARD_REGNO_MODE_OK (regno, mode)) found_mode = mode; *************** *** 98,102 **** return found_mode; ! if (HARD_REGNO_NREGS (regno, CCmode) == 1 && HARD_REGNO_MODE_OK (regno, CCmode)) return CCmode; --- 108,112 ---- return found_mode; ! if (HARD_REGNO_NREGS (regno, CCmode) == nregs && HARD_REGNO_MODE_OK (regno, CCmode)) return CCmode; *************** *** 123,127 **** int offset; rtx address; ! int i; /* First find all the registers that we need to deal with and all --- 133,137 ---- int offset; rtx address; ! int i, j; /* First find all the registers that we need to deal with and all *************** *** 133,145 **** if (call_used_regs[i] && ! call_fixed_regs[i]) { ! regno_save_mode[i] = choose_hard_reg_mode (i); ! if (regno_save_mode[i] == VOIDmode) { ! call_fixed_regs[i] = 1; ! SET_HARD_REG_BIT (call_fixed_reg_set, i); } } else ! regno_save_mode[i] = VOIDmode; } --- 143,158 ---- if (call_used_regs[i] && ! call_fixed_regs[i]) { ! for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++) { ! regno_save_mode[i][j] = choose_hard_reg_mode (i, j); ! if (regno_save_mode[i][j] == VOIDmode && j == 1) ! { ! call_fixed_regs[i] = 1; ! SET_HARD_REG_BIT (call_fixed_reg_set, i); ! } } } else ! regno_save_mode[i][1] = VOIDmode; } *************** *** 166,175 **** for (offset = 1 << (HOST_BITS_PER_INT / 2); offset; offset >>= 1) { ! address = gen_rtx (PLUS, Pmode, addr_reg, ! gen_rtx (CONST_INT, VOIDmode, offset)); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! if (regno_save_mode[i] != VOIDmode ! && ! strict_memory_address_p (regno_save_mode[i], address)) break; --- 179,187 ---- for (offset = 1 << (HOST_BITS_PER_INT / 2); offset; offset >>= 1) { ! address = gen_rtx (PLUS, Pmode, addr_reg, GEN_INT (offset)); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! if (regno_save_mode[i][1] != VOIDmode ! && ! strict_memory_address_p (regno_save_mode[i][1], address)) break; *************** *** 188,219 **** for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! if (regno_save_mode[i] != VOIDmode) ! { ! rtx mem = gen_rtx (MEM, regno_save_mode[i], address); ! rtx reg = gen_rtx (REG, regno_save_mode[i], i); ! rtx savepat = gen_rtx (SET, VOIDmode, mem, reg); ! rtx restpat = gen_rtx (SET, VOIDmode, reg, mem); ! rtx saveinsn = emit_insn (savepat); ! rtx restinsn = emit_insn (restpat); ! int ok; ! ! reg_save_code[i] = recog_memoized (saveinsn); ! reg_restore_code[i] = recog_memoized (restinsn); ! ! /* Now extract both insns and see if we can meet their constraints. */ ! ok = (reg_save_code[i] != -1 && reg_restore_code[i] != -1); ! if (ok) ! { ! insn_extract (saveinsn); ! ok = constrain_operands (reg_save_code[i], 1); ! insn_extract (restinsn); ! ok &= constrain_operands (reg_restore_code[i], 1); ! } ! if (! ok) ! { ! call_fixed_regs[i] = 1; ! SET_HARD_REG_BIT (call_fixed_reg_set, i); ! } } --- 200,236 ---- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++) ! if (regno_save_mode[i][j] != VOIDmode) ! { ! rtx mem = gen_rtx (MEM, regno_save_mode[i][j], address); ! rtx reg = gen_rtx (REG, regno_save_mode[i][j], i); ! rtx savepat = gen_rtx (SET, VOIDmode, mem, reg); ! rtx restpat = gen_rtx (SET, VOIDmode, reg, mem); ! rtx saveinsn = emit_insn (savepat); ! rtx restinsn = emit_insn (restpat); ! int ok; ! ! reg_save_code[i][j] = recog_memoized (saveinsn); ! reg_restore_code[i][j] = recog_memoized (restinsn); ! ! /* Now extract both insns and see if we can meet their constraints. */ ! ok = (reg_save_code[i][j] != -1 && reg_restore_code[i][j] != -1); ! if (ok) ! { ! insn_extract (saveinsn); ! ok = constrain_operands (reg_save_code[i][j], 1); ! insn_extract (restinsn); ! ok &= constrain_operands (reg_restore_code[i][j], 1); ! } ! if (! ok) ! { ! regno_save_mode[i][j] = VOIDmode; ! if (j == 1) ! { ! call_fixed_regs[i] = 1; ! SET_HARD_REG_BIT (call_fixed_reg_set, i); ! } ! } } *************** *** 228,235 **** init_save_areas () { ! int i; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! regno_save_mem[i] = 0; } --- 245,253 ---- init_save_areas () { ! int i, j; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++) ! regno_save_mem[i][j] = 0; } *************** *** 245,281 **** worst (largest) possible offsets. ! Set *PCHANGED to 1 if we had to allocate some memory for the save area. */ int setup_save_areas (pchanged) int *pchanged; { int ok = 1; ! int i; for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (reg_renumber[i] >= 0 && reg_n_calls_crossed[i] > 0) { int regno = reg_renumber[i]; ! int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i])); ! int j; ! for (j = regno; j < endregno; j++) ! if (call_used_regs[j] && regno_save_mem[j] == 0) { ! regno_save_mem[j] ! = assign_stack_local (regno_save_mode[j], ! GET_MODE_SIZE (regno_save_mode[j]), 0); ! *pchanged = 1; } } for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! if (regno_save_mem[i] != 0) ! ok &= strict_memory_address_p (regno_save_mode[i], ! XEXP (eliminate_regs (regno_save_mem[i], ! 0, 0), ! 0)); return ok; --- 263,358 ---- worst (largest) possible offsets. ! Set *PCHANGED to 1 if we had to allocate some memory for the save area. + Future work: + + In the fallback case we should iterate backwards across all possible + modes for the save, choosing the largest available one instead of + falling back to the smallest mode immediately. (eg TF -> DF -> SF). + + We do not try to use "move multiple" instructions that exist + on some machines (such as the 68k moveml). It could be a win to try + and use them when possible. The hard part is doing it in a way that is + machine independent since they might be saving non-consecutive + registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */ + int setup_save_areas (pchanged) int *pchanged; { + int i, j, k; + HARD_REG_SET hard_regs_used; int ok = 1; ! + /* Allocate space in the save area for the largest multi-register + pseudos first, then work backwards to single register + pseudos. */ + + /* Find and record all call-used hard-registers in this function. */ + CLEAR_HARD_REG_SET (hard_regs_used); for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (reg_renumber[i] >= 0 && reg_n_calls_crossed[i] > 0) { int regno = reg_renumber[i]; ! int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i])); ! int nregs = endregno - regno; ! ! for (j = 0; j < nregs; j++) ! { ! if (call_used_regs[regno+j]) ! SET_HARD_REG_BIT (hard_regs_used, regno+j); ! } ! } ! ! /* Now run through all the call-used hard-registers and allocate ! space for them in the caller-save area. Try to allocate space ! in a manner which allows multi-register saves/restores to be done. */ ! for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! for (j = MOVE_MAX / UNITS_PER_WORD; j > 0; j--) ! { ! int ok = 1; ! ! /* If no mode exists for this size, try another. Also break out ! if we have already saved this hard register. */ ! if (regno_save_mode[i][j] == VOIDmode || regno_save_mem[i][1] != 0) ! continue; ! ! for (k = 0; k < j; k++) { ! int regno = i + k; ! ok &= (TEST_HARD_REG_BIT (hard_regs_used, regno) != 0); } + + /* We have found an acceptable mode to store in. */ + if (ok) + { + + regno_save_mem[i][j] + = assign_stack_local (regno_save_mode[i][j], + GET_MODE_SIZE (regno_save_mode[i][j]), 0); + + /* Setup single word save area just in case... */ + for (k = 0; k < j; k++) + { + /* This should not depend on WORDS_BIG_ENDIAN. + The order of words in regs is the same as in memory. */ + rtx temp = gen_rtx (MEM, regno_save_mode[i+k][1], + XEXP (regno_save_mem[i][j], 0)); + + regno_save_mem[i+k][1] + = adj_offsettable_operand (temp, k * UNITS_PER_WORD); + } + *pchanged = 1; + } } for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++) ! if (regno_save_mem[i][j] != 0) ! ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]), ! XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0)); return ok; *************** *** 298,302 **** { regset regs_live = basic_block_live_at_start[b]; ! int offset, bit, i, j; int regno; --- 375,380 ---- { regset regs_live = basic_block_live_at_start[b]; ! REGSET_ELT_TYPE bit; ! int offset, i, j; int regno; *************** *** 314,317 **** --- 392,396 ---- CLEAR_HARD_REG_SET (hard_regs_saved); + CLEAR_HARD_REG_SET (hard_regs_need_restore); n_regs_saved = 0; *************** *** 319,323 **** { if (regs_live[offset] == 0) ! i += HOST_BITS_PER_INT; else for (bit = 1; bit && i < max_regno; bit <<= 1, i++) --- 398,402 ---- { if (regs_live[offset] == 0) ! i += REGSET_ELT_BITS; else for (bit = 1; bit && i < max_regno; bit <<= 1, i++) *************** *** 329,332 **** --- 408,412 ---- j++) SET_HARD_REG_BIT (hard_regs_live, j); + } *************** *** 367,375 **** if (code == CALL_INSN) ! for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! if (call_used_regs[regno] && ! call_fixed_regs[regno] ! && TEST_HARD_REG_BIT (hard_regs_live, regno) ! && ! TEST_HARD_REG_BIT (hard_regs_saved, regno)) ! insert_save_restore (insn, 1, regno, insn_mode); note_stores (PATTERN (insn), set_reg_live); --- 447,471 ---- if (code == CALL_INSN) ! { ! for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! if (call_used_regs[regno] && ! call_fixed_regs[regno] ! && TEST_HARD_REG_BIT (hard_regs_live, regno) ! && ! TEST_HARD_REG_BIT (hard_regs_saved, regno)) ! regno += insert_save_restore (insn, 1, regno, ! insn_mode, 0); ! #ifdef HARD_REG_SET ! hard_regs_need_restore = hard_regs_saved; ! #else ! COPY_HARD_REG_SET (hard_regs_need_restore, ! hard_regs_saved); ! #endif ! ! /* Must recompute n_regs_saved. */ ! n_regs_saved = 0; ! for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! if (TEST_HARD_REG_BIT (hard_regs_saved, regno)) ! n_regs_saved++; ! ! } note_stores (PATTERN (insn), set_reg_live); *************** *** 390,397 **** if (n_regs_saved) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! if (TEST_HARD_REG_BIT (hard_regs_saved, regno)) ! insert_save_restore ((GET_CODE (insn) == JUMP_INSN ! ? insn : NEXT_INSN (insn)), ! 0, regno, insn_mode); } } --- 486,494 ---- if (n_regs_saved) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) ! if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno)) ! regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN ! ? insn : NEXT_INSN (insn)), 0, ! regno, insn_mode, MOVE_MAX / UNITS_PER_WORD); ! } } *************** *** 423,427 **** for (i = regno; i < endregno; i++) ! SET_HARD_REG_BIT (hard_regs_live, i); } --- 520,528 ---- for (i = regno; i < endregno; i++) ! { ! SET_HARD_REG_BIT (hard_regs_live, i); ! CLEAR_HARD_REG_BIT (hard_regs_saved, i); ! CLEAR_HARD_REG_BIT (hard_regs_need_restore, i); ! } } *************** *** 443,447 **** for (i = regno; i < endregno; i++) ! CLEAR_HARD_REG_BIT (hard_regs_live, i); } --- 544,552 ---- for (i = regno; i < endregno; i++) ! { ! CLEAR_HARD_REG_BIT (hard_regs_live, i); ! CLEAR_HARD_REG_BIT (hard_regs_need_restore, i); ! CLEAR_HARD_REG_BIT (hard_regs_saved, i); ! } } *************** *** 460,463 **** --- 565,571 ---- int i, j; + if (code == CLOBBER) + return; + if (code == REG) { *************** *** 483,489 **** int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x)); ! for (i = regno; i < endregno; i ++) ! if (TEST_HARD_REG_BIT (hard_regs_saved, i)) ! insert_save_restore (insn, 0, i, insn_mode); } --- 591,598 ---- int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x)); ! for (i = regno; i < endregno; i++) ! if (TEST_HARD_REG_BIT (hard_regs_need_restore, i)) ! i += insert_save_restore (insn, 0, i, insn_mode, ! CEIL (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)); } *************** *** 504,508 **** /* Insert a sequence of insns to save or restore, SAVE_P says which, REGNO. Place these insns in front of INSN. INSN_MODE is the mode ! to assign to these insns. Note that we have verified in init_caller_save that we can do this --- 613,619 ---- /* Insert a sequence of insns to save or restore, SAVE_P says which, REGNO. Place these insns in front of INSN. INSN_MODE is the mode ! to assign to these insns. MAXRESTORE is the maximum number of registers ! which should be restored during this call (when SAVE_P == 0). It should ! never be less than 1 since we only work with entire registers. Note that we have verified in init_caller_save that we can do this *************** *** 510,525 **** since the address might not be valid so the insn might not be recognized. These insns will be reloaded and have register elimination done by ! find_reload, so we need not worry about that here. */ ! static void ! insert_save_restore (insn, save_p, regno, insn_mode) rtx insn; int save_p; int regno; enum machine_mode insn_mode; { rtx pat; enum insn_code code; ! int i; /* A common failure mode if register status is not correct in the RTL --- 621,639 ---- since the address might not be valid so the insn might not be recognized. These insns will be reloaded and have register elimination done by ! find_reload, so we need not worry about that here. ! Return the extra number of registers saved. */ ! ! static int ! insert_save_restore (insn, save_p, regno, insn_mode, maxrestore) rtx insn; int save_p; int regno; enum machine_mode insn_mode; + int maxrestore; { rtx pat; enum insn_code code; ! int i, numregs; /* A common failure mode if register status is not correct in the RTL *************** *** 530,534 **** step in debugging such problems. */ ! if (regno_save_mem[regno] == 0) abort (); --- 644,648 ---- step in debugging such problems. */ ! if (regno_save_mem[regno][1] == 0) abort (); *************** *** 556,575 **** if (save_p) { ! pat = gen_rtx (SET, VOIDmode, regno_save_mem[regno], ! gen_rtx (REG, regno_save_mode[regno], regno)); ! code = reg_save_code[regno]; ! SET_HARD_REG_BIT (hard_regs_saved, regno); ! n_regs_saved++; } else { ! pat = gen_rtx (SET, VOIDmode, ! gen_rtx (REG, regno_save_mode[regno], regno), ! regno_save_mem[regno]); ! code = reg_restore_code[regno]; ! CLEAR_HARD_REG_BIT (hard_regs_saved, regno); ! n_regs_saved--; ! } /* Emit the insn and set the code and mode. */ --- 670,753 ---- if (save_p) { ! int i, j, k; ! int ok; ! ! /* See if we can save several registers with a single instruction. ! Work backwards to the single register case. */ ! for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--) ! { ! ok = 1; ! if (regno_save_mem[regno][i] != 0) ! for (j = 0; j < i; j++) ! { ! if (! call_used_regs[regno + j] || call_fixed_regs[regno + j] ! || ! TEST_HARD_REG_BIT (hard_regs_live, regno + j) ! || TEST_HARD_REG_BIT (hard_regs_saved, regno + j)) ! ok = 0; ! } ! else ! continue; ! ! /* Must do this one save at a time */ ! if (! ok) ! continue; ! ! pat = gen_rtx (SET, VOIDmode, regno_save_mem[regno][i], ! gen_rtx (REG, GET_MODE (regno_save_mem[regno][i]), regno)); ! code = reg_save_code[regno][i]; ! ! /* Set hard_regs_saved for all the registers we saved. */ ! for (k = 0; k < i; k++) ! { ! SET_HARD_REG_BIT (hard_regs_saved, regno + k); ! SET_HARD_REG_BIT (hard_regs_need_restore, regno + k); ! n_regs_saved++; ! } ! ! numregs = i; ! break; ! } } else { ! int i, j, k; ! int ok; ! ! /* See if we can restore `maxrestore' registers at once. Work ! backwards to the single register case. */ ! for (i = maxrestore; i > 0; i--) ! { ! ok = 1; ! if (regno_save_mem[regno][i]) ! for (j = 0; j < i; j++) ! { ! if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j)) ! ok = 0; ! } ! else ! continue; + /* Must do this one restore at a time */ + if (! ok) + continue; + + pat = gen_rtx (SET, VOIDmode, + gen_rtx (REG, GET_MODE (regno_save_mem[regno][i]), + regno), + regno_save_mem[regno][i]); + code = reg_restore_code[regno][i]; + + + /* Clear status for all registers we restored. */ + for (k = 0; k < i; k++) + { + CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k); + n_regs_saved--; + } + + numregs = i; + break; + } + } /* Emit the insn and set the code and mode. */ *************** *** 577,579 **** --- 755,760 ---- PUT_MODE (insn, insn_mode); INSN_CODE (insn) = code; + + /* Tell our callers how many extra registers we saved/restored */ + return numregs - 1; } diff -rc2N gcc-2.2.2/calls.c gcc-2.3.1/calls.c *** gcc-2.2.2/calls.c Mon Jun 1 21:41:11 1992 --- gcc-2.3.1/calls.c Sun Oct 25 17:49:42 1992 *************** *** 51,54 **** --- 51,57 ---- registers. */ rtx reg; + /* If REG was promoted from the actual mode of the argument expression, + indicates whether the promotion is sign- or zero-extended. */ + int unsignedp; /* Number of registers to use. 0 means put the whole arg in registers. Also 0 if not passed in registers. */ *************** *** 115,119 **** /* Only expressions and references can contain calls. */ ! if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r') return 0; --- 118,123 ---- /* Only expressions and references can contain calls. */ ! if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r' ! && type != 'b') return 0; *************** *** 139,146 **** case BLOCK: ! /* Must not look at BLOCK_SUPERCONTEXT since it will point back to ! us. */ ! length = 3; ! break; case METHOD_CALL_EXPR: --- 143,163 ---- case BLOCK: ! { ! register tree local; ! ! for (local = BLOCK_VARS (exp); local; local = TREE_CHAIN (local)) ! if (DECL_INITIAL (local) != 0 && calls_alloca (DECL_INITIAL (local))) ! return 1; ! } ! { ! register tree subblock; ! ! for (subblock = BLOCK_SUBBLOCKS (exp); ! subblock; ! subblock = TREE_CHAIN (subblock)) ! if (calls_alloca (subblock)) ! return 1; ! } ! return 0; case METHOD_CALL_EXPR: *************** *** 265,270 **** int is_const; { ! rtx stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size); ! rtx struct_value_size_rtx = gen_rtx (CONST_INT, VOIDmode, struct_value_size); rtx call_insn; int already_popped = 0; --- 282,287 ---- int is_const; { ! rtx stack_size_rtx = GEN_INT (stack_size); ! rtx struct_value_size_rtx = GEN_INT (struct_value_size); rtx call_insn; int already_popped = 0; *************** *** 281,286 **** && (RETURN_POPS_ARGS (funtype, stack_size) > 0 || stack_size == 0)) { ! rtx n_pop = gen_rtx (CONST_INT, VOIDmode, ! RETURN_POPS_ARGS (funtype, stack_size)); rtx pat; --- 298,302 ---- && (RETURN_POPS_ARGS (funtype, stack_size) > 0 || stack_size == 0)) { ! rtx n_pop = GEN_INT (RETURN_POPS_ARGS (funtype, stack_size)); rtx pat; *************** *** 347,351 **** emit_insn (gen_rtx (CLOBBER, VOIDmode, stack_pointer_rtx)); stack_size -= RETURN_POPS_ARGS (funtype, stack_size); ! stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size); } --- 363,367 ---- emit_insn (gen_rtx (CLOBBER, VOIDmode, stack_pointer_rtx)); stack_size -= RETURN_POPS_ARGS (funtype, stack_size); ! stack_size_rtx = GEN_INT (stack_size); } *************** *** 443,447 **** #endif ! /* Size of the stack reserved for paramter registers. */ int reg_parm_stack_space = 0; --- 459,463 ---- #endif ! /* Size of the stack reserved for parameter registers. */ int reg_parm_stack_space = 0; *************** *** 515,519 **** Use abstraction instead of setting TREE_ADDRESSABLE directly. */ ! if (TREE_INLINE (fndecl) && extra_warnings && !flag_no_inline) warning_with_decl (fndecl, "can't inline call to `%s' which was declared inline"); mark_addressable (fndecl); --- 531,535 ---- Use abstraction instead of setting TREE_ADDRESSABLE directly. */ ! if (DECL_INLINE (fndecl) && extra_warnings && !flag_no_inline) warning_with_decl (fndecl, "can't inline call to `%s' which was declared inline"); mark_addressable (fndecl); *************** *** 595,599 **** /* If inlining succeeded, return. */ ! if ((int) temp != -1) { int i; --- 611,615 ---- /* If inlining succeeded, return. */ ! if ((HOST_WIDE_INT) temp != -1) { int i; *************** *** 653,663 **** start_sequence (); emit_stack_save (SAVE_BLOCK, &old_stack_level, 0); ! allocate_dynamic_stack_space (gen_rtx (CONST_INT, VOIDmode, ! adjust), ! 0, BITS_PER_UNIT); seq = get_insns (); end_sequence (); emit_insns_before (seq, NEXT_INSN (before_call)); ! emit_stack_restore (SAVE_BLOCK, old_stack_level, 0); } } --- 669,678 ---- start_sequence (); emit_stack_save (SAVE_BLOCK, &old_stack_level, 0); ! allocate_dynamic_stack_space (GEN_INT (adjust), ! NULL_RTX, BITS_PER_UNIT); seq = get_insns (); end_sequence (); emit_insns_before (seq, NEXT_INSN (before_call)); ! emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); } } *************** *** 768,772 **** /* Start updating where the next arg would go. */ ! INIT_CUMULATIVE_ARGS (args_so_far, funtype, 0); /* If struct_value_rtx is 0, it means pass the address --- 783,787 ---- /* Start updating where the next arg would go. */ ! INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_PTR); /* If struct_value_rtx is 0, it means pass the address *************** *** 843,846 **** --- 858,862 ---- { tree type = TREE_TYPE (TREE_VALUE (p)); + enum machine_mode mode; args[i].tree_value = TREE_VALUE (p); *************** *** 878,887 **** /* This is a variable-sized object. Make space on the stack for it. */ ! rtx size_rtx = expand_expr (size_in_bytes (type), 0, VOIDmode, 0); if (old_stack_level == 0) { ! emit_stack_save (SAVE_BLOCK, &old_stack_level, 0); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; --- 894,903 ---- /* This is a variable-sized object. Make space on the stack for it. */ ! rtx size_rtx = expand_expr (size_in_bytes (type), NULL_RTX, VOIDmode, 0); if (old_stack_level == 0) { ! emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; *************** *** 889,893 **** copy = gen_rtx (MEM, BLKmode, ! allocate_dynamic_stack_space (size_rtx, 0, TYPE_ALIGN (type))); } --- 905,909 ---- copy = gen_rtx (MEM, BLKmode, ! allocate_dynamic_stack_space (size_rtx, NULL_RTX, TYPE_ALIGN (type))); } *************** *** 903,916 **** #endif ! args[i].reg = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type, argpos < n_named_args); #ifdef FUNCTION_ARG_PARTIAL_NREGS if (args[i].reg) args[i].partial ! = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, TYPE_MODE (type), type, argpos < n_named_args); #endif ! args[i].pass_on_stack = MUST_PASS_IN_STACK (TYPE_MODE (type), type); /* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that --- 919,947 ---- #endif ! mode = TYPE_MODE (type); ! ! #ifdef PROMOTE_FUNCTION_ARGS ! /* Compute the mode in which the arg is actually to be extended to. */ ! if (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE ! || TREE_CODE (type) == BOOLEAN_TYPE || TREE_CODE (type) == CHAR_TYPE ! || TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == POINTER_TYPE ! || TREE_CODE (type) == OFFSET_TYPE) ! { ! int unsignedp = TREE_UNSIGNED (type); ! PROMOTE_MODE (mode, unsignedp, type); ! args[i].unsignedp = unsignedp; ! } ! #endif ! ! args[i].reg = FUNCTION_ARG (args_so_far, mode, type, argpos < n_named_args); #ifdef FUNCTION_ARG_PARTIAL_NREGS if (args[i].reg) args[i].partial ! = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, type, argpos < n_named_args); #endif ! args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type); /* If FUNCTION_ARG returned an (expr_list (nil) FOO), it means that *************** *** 1123,1127 **** { args[i].initial_value = args[i].value ! = expand_expr (args[i].tree_value, 0, VOIDmode, 0); preserve_temp_slots (args[i].value); free_temp_slots (); --- 1154,1158 ---- { args[i].initial_value = args[i].value ! = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0); preserve_temp_slots (args[i].value); free_temp_slots (); *************** *** 1144,1148 **** if (old_stack_level == 0) { ! emit_stack_save (SAVE_BLOCK, &old_stack_level, 0); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; --- 1175,1179 ---- if (old_stack_level == 0) { ! emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; *************** *** 1236,1240 **** argblock = virtual_outgoing_args_rtx; else ! argblock = push_block (gen_rtx (CONST_INT, VOIDmode, needed), 0, 0); /* We only really need to call `copy_to_reg' in the case where push --- 1267,1271 ---- argblock = virtual_outgoing_args_rtx; else ! argblock = push_block (GEN_INT (needed), 0, 0); /* We only really need to call `copy_to_reg' in the case where push *************** *** 1256,1267 **** { #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) ! rtx push_size = gen_rtx (CONST_INT, VOIDmode, ! reg_parm_stack_space + args_size.constant); #else ! rtx push_size = gen_rtx (CONST_INT, VOIDmode, args_size.constant); #endif if (old_stack_level == 0) { ! emit_stack_save (SAVE_BLOCK, &old_stack_level, 0); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; --- 1287,1297 ---- { #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE) ! rtx push_size = GEN_INT (reg_parm_stack_space + args_size.constant); #else ! rtx push_size = GEN_INT (args_size.constant); #endif if (old_stack_level == 0) { ! emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; *************** *** 1276,1280 **** highest_outgoing_arg_in_use = 0; } ! allocate_dynamic_stack_space (push_size, 0, BITS_PER_UNIT); } /* If argument evaluation might modify the stack pointer, copy the --- 1306,1310 ---- highest_outgoing_arg_in_use = 0; } ! allocate_dynamic_stack_space (push_size, NULL_RTX, BITS_PER_UNIT); } /* If argument evaluation might modify the stack pointer, copy the *************** *** 1335,1341 **** before the first push (the last arg). */ if (argblock == 0) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, ! (args_size.constant ! - original_args_size.constant))); #endif #endif --- 1365,1370 ---- before the first push (the last arg). */ if (argblock == 0) ! anti_adjust_stack (GEN_INT (args_size.constant ! - original_args_size.constant)); #endif #endif *************** *** 1353,1357 **** /* Generate an rtx (probably a pseudo-register) for the address. */ { ! funexp = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); free_temp_slots (); /* FUNEXP can't be BLKmode */ emit_queue (); --- 1382,1386 ---- /* Generate an rtx (probably a pseudo-register) for the address. */ { ! funexp = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); free_temp_slots (); /* FUNEXP can't be BLKmode */ emit_queue (); *************** *** 1376,1384 **** if (args[i].reg != 0 && ! args[i].pass_on_stack) { reg_parm_seen = 1; if (args[i].value == 0) { ! args[i].value = expand_expr (args[i].tree_value, 0, VOIDmode, 0); preserve_temp_slots (args[i].value); free_temp_slots (); --- 1405,1416 ---- if (args[i].reg != 0 && ! args[i].pass_on_stack) { + enum machine_mode mode; + reg_parm_seen = 1; if (args[i].value == 0) { ! args[i].value = expand_expr (args[i].tree_value, NULL_RTX, ! VOIDmode, 0); preserve_temp_slots (args[i].value); free_temp_slots (); *************** *** 1388,1391 **** --- 1420,1432 ---- emit_queue (); } + + /* If we are to promote the function arg to a wider mode, + do it now. */ + mode = (GET_CODE (args[i].reg) == EXPR_LIST + ? GET_MODE (XEXP (args[i].reg, 0)) : GET_MODE (args[i].reg)); + + if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != mode) + args[i].value = convert_to_mode (mode, args[i].value, + args[i].unsignedp); } *************** *** 1429,1433 **** save_area = assign_stack_temp (BLKmode, num_to_save, 1); emit_block_move (validize_mem (save_area), stack_area, ! gen_rtx (CONST_INT, VOIDmode, num_to_save), PARM_BOUNDARY / BITS_PER_UNIT); } --- 1470,1474 ---- save_area = assign_stack_temp (BLKmode, num_to_save, 1); emit_block_move (validize_mem (save_area), stack_area, ! GEN_INT (num_to_save), PARM_BOUNDARY / BITS_PER_UNIT); } *************** *** 1465,1471 **** after pushing the last arg. */ if (argblock == 0) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, ! (args_size.constant ! - original_args_size.constant))); #endif #endif --- 1506,1511 ---- after pushing the last arg. */ if (argblock == 0) ! anti_adjust_stack (GEN_INT (args_size.constant ! - original_args_size.constant)); #endif #endif *************** *** 1476,1480 **** #if ! defined(ALLOCATE_OUTGOING_ARGS) && defined(OUTGOING_REG_PARM_STACK_SPACE) if (must_preallocate == 0 && reg_parm_stack_space > 0) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, reg_parm_stack_space)); #endif --- 1516,1520 ---- #if ! defined(ALLOCATE_OUTGOING_ARGS) && defined(OUTGOING_REG_PARM_STACK_SPACE) if (must_preallocate == 0 && reg_parm_stack_space > 0) ! anti_adjust_stack (GEN_INT (reg_parm_stack_space)); #endif *************** *** 1484,1488 **** emit_move_insn (struct_value_rtx, force_reg (Pmode, ! force_operand (structure_value_addr, 0))); if (GET_CODE (struct_value_rtx) == REG) { --- 1524,1529 ---- emit_move_insn (struct_value_rtx, force_reg (Pmode, ! force_operand (structure_value_addr, ! NULL_RTX))); if (GET_CODE (struct_value_rtx) == REG) { *************** *** 1656,1660 **** TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); } ! else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))) /* TARGET and VALREG cannot be equal at this point because the latter would not have REG_FUNCTION_VALUE_P true, while the former would if --- 1697,1702 ---- TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); } ! else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)) ! && GET_MODE (target) == GET_MODE (valreg)) /* TARGET and VALREG cannot be equal at this point because the latter would not have REG_FUNCTION_VALUE_P true, while the former would if *************** *** 1667,1670 **** --- 1709,1736 ---- target = copy_to_reg (valreg); + #ifdef PROMOTE_FUNCTION_RETURN + /* If we promoted this return value, make the proper SUBREG. */ + if (GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) + { + enum machine_mode mode = GET_MODE (target); + int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp)); + + if (TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (exp)) == ENUMERAL_TYPE + || TREE_CODE (TREE_TYPE (exp)) == BOOLEAN_TYPE + || TREE_CODE (TREE_TYPE (exp)) == CHAR_TYPE + || TREE_CODE (TREE_TYPE (exp)) == REAL_TYPE + || TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE + || TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE) + { + PROMOTE_MODE (mode, unsignedp, TREE_TYPE (exp)); + } + + target = gen_rtx (SUBREG, TYPE_MODE (TREE_TYPE (exp)), target, 0); + SUBREG_PROMOTED_VAR_P (target) = 1; + SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp; + } + #endif + /* Perform all cleanups needed for the arguments of this call (i.e. destructors in C++). */ *************** *** 1676,1680 **** if (old_stack_level) { ! emit_stack_restore (SAVE_BLOCK, old_stack_level, 0); pending_stack_adjust = old_pending_adj; #ifdef ACCUMULATE_OUTGOING_ARGS --- 1742,1746 ---- if (old_stack_level) { ! emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); pending_stack_adjust = old_pending_adj; #ifdef ACCUMULATE_OUTGOING_ARGS *************** *** 1700,1706 **** else emit_block_move (stack_area, validize_mem (save_area), ! gen_rtx (CONST_INT, VOIDmode, ! high_to_save - low_to_save + 1, ! PARM_BOUNDARY / BITS_PER_UNIT)); } #endif --- 1766,1771 ---- else emit_block_move (stack_area, validize_mem (save_area), ! GEN_INT (high_to_save - low_to_save + 1), ! PARM_BOUNDARY / BITS_PER_UNIT); } #endif *************** *** 1720,1725 **** else emit_block_move (stack_area, validize_mem (args[i].save_area), ! gen_rtx (CONST_INT, VOIDmode, ! args[i].size.constant), PARM_BOUNDARY / BITS_PER_UNIT); } --- 1785,1789 ---- else emit_block_move (stack_area, validize_mem (args[i].save_area), ! GEN_INT (args[i].size.constant), PARM_BOUNDARY / BITS_PER_UNIT); } *************** *** 1735,1739 **** if (may_be_alloca && nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0); pop_temp_slots (); --- 1799,1803 ---- if (may_be_alloca && nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX); pop_temp_slots (); *************** *** 1862,1867 **** arg->size.constant, 1); emit_block_move (validize_mem (arg->save_area), stack_area, ! gen_rtx (CONST_INT, VOIDmode, ! arg->size.constant), PARM_BOUNDARY / BITS_PER_UNIT); } --- 1926,1930 ---- arg->size.constant, 1); emit_block_move (validize_mem (arg->save_area), stack_area, ! GEN_INT (arg->size.constant), PARM_BOUNDARY / BITS_PER_UNIT); } *************** *** 1917,1921 **** stack_arg_under_construction++; #endif ! arg->value = expand_expr (pval, partial ? 0 : arg->stack, VOIDmode, 0); #ifdef ACCUMULATE_OUTGOING_ARGS if (arg->pass_on_stack) --- 1980,1985 ---- stack_arg_under_construction++; #endif ! arg->value = expand_expr (pval, partial ? NULL_RTX : arg->stack, ! VOIDmode, 0); #ifdef ACCUMULATE_OUTGOING_ARGS if (arg->pass_on_stack) *************** *** 1995,1999 **** excess = (arg->size.constant - TREE_INT_CST_LOW (size) + partial * UNITS_PER_WORD); ! size_rtx = expand_expr (size, 0, VOIDmode, 0); } --- 2059,2063 ---- excess = (arg->size.constant - TREE_INT_CST_LOW (size) + partial * UNITS_PER_WORD); ! size_rtx = expand_expr (size, NULL_RTX, VOIDmode, 0); } diff -rc2N gcc-2.2.2/cccp.c gcc-2.3.1/cccp.c *** gcc-2.2.2/cccp.c Sat Jun 6 17:46:01 1992 --- gcc-2.3.1/cccp.c Sat Oct 24 21:06:43 1992 *************** *** 48,51 **** --- 48,59 ---- #endif + #if 0 /* We can't get ptrdiff_t, so I arranged not to need PTR_INT_TYPE. */ + #ifdef __STDC__ + #define PTR_INT_TYPE ptrdiff_t + #else + #define PTR_INT_TYPE long + #endif + #endif /* 0 */ + #include "pcp.h" *************** *** 68,72 **** #include #include - #include #ifndef VMS --- 76,79 ---- *************** *** 75,87 **** #include #else - #define index strchr - #define rindex strrchr #include #include #endif /* USG */ #endif /* not VMS */ - - extern char *index (); - extern char *rindex (); /* VMS-specific definitions */ --- 82,89 ---- *************** *** 98,101 **** --- 100,105 ---- #define fopen(fname,mode) VMS_fopen(fname,mode) #define freopen(fname,mode,ofile) VMS_freopen(fname,mode,ofile) + #define strncat(dst,src,cnt) VMS_strncat(dst,src,cnt) + static char * VMS_strncat (); static int VMS_read (); static int VMS_write (); *************** *** 106,113 **** --- 110,121 ---- typedef struct { unsigned :16, :16, :16; } vms_ino_t; #define ino_t vms_ino_t + #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */ #ifdef __GNUC__ #define BSTRING /* VMS/GCC supplies the bstring routines */ #endif /* __GNUC__ */ #endif /* VMS */ + + extern char *index (); + extern char *rindex (); #ifndef O_RDONLY *************** *** 120,128 **** #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) #ifndef S_ISREG #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif ! /* Exported declarations. */ char *xmalloc (); --- 128,172 ---- #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) + /* Find the largest host integer type and set its size and type. */ + + #ifndef HOST_BITS_PER_WIDE_INT + + #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT + #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG + #define HOST_WIDE_INT long + #else + #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT + #define HOST_WIDE_INT int + #endif + + #endif + #ifndef S_ISREG #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif ! /* Define a generic NULL if one hasn't already been defined. */ ! ! #ifndef NULL ! #define NULL 0 ! #endif ! ! #ifndef GENERIC_PTR ! #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) ! #define GENERIC_PTR void * ! #else ! #define GENERIC_PTR char * ! #endif ! #endif ! ! #ifndef NULL_PTR ! #define NULL_PTR ((GENERIC_PTR)0) ! #endif ! ! #ifndef INCLUDE_LEN_FUDGE ! #define INCLUDE_LEN_FUDGE 0 ! #endif ! ! /* Forward declarations. */ char *xmalloc (); *************** *** 181,184 **** --- 225,229 ---- static void add_import (); + static void append_include_chain (); static void deps_output (); static void make_undef (); *************** *** 206,210 **** static void print_containing_files (); static int lookup_import (); ! static int lookup_include (); static int check_preconditions (); static void pcfinclude (); --- 251,256 ---- static void print_containing_files (); static int lookup_import (); ! static int redundant_include_p (); ! static is_system_include (); static int check_preconditions (); static void pcfinclude (); *************** *** 256,260 **** static char *check_precompiled (); ! static struct macrodef create_definition (); static void dump_single_macro (); --- 302,306 ---- static char *check_precompiled (); ! /* static struct macrodef create_definition (); [moved below] */ static void dump_single_macro (); *************** *** 271,279 **** static char *progname; ! /* Nonzero means handle C++ comment syntax and use ! extra default include directories for C++. */ static int cplusplus; /* Nonzero means handle #import, for objective C. */ --- 317,328 ---- static char *progname; ! /* Nonzero means use extra default include directories for C++. */ static int cplusplus; + /* Nonzero means handle cplusplus style comments */ + + static int cplusplus_comments; + /* Nonzero means handle #import, for objective C. */ *************** *** 510,514 **** --- 559,568 ---- static struct file_name_list *include = 0; /* First dir to search */ /* First dir to search for */ + /* This is the first element to use for #include <...>. + If it is 0, use the entire chain for such includes. */ static struct file_name_list *first_bracket_include = 0; + /* This is the first element in the chain that corresponds to + a directory of system header files. */ + static struct file_name_list *first_system_include = 0; static struct file_name_list *last_include = 0; /* Last in chain */ *************** *** 547,550 **** --- 601,606 ---- }; + static struct macrodef create_definition (); + /* Structure allocated for every #define. For a simple replacement *************** *** 615,619 **** * { wow(one, two); } -> { process( two, one, two); } * if this "rest_arg" is used with the concat token '##' and if it is not ! * supplied then the token attached to with ## will not be outputed. Ex: * #define wow(a, b...) process(b ## , a, ## b) * { wow(1, 2); } -> { process( 2, 1,2); } --- 671,675 ---- * { wow(one, two); } -> { process( two, one, two); } * if this "rest_arg" is used with the concat token '##' and if it is not ! * supplied then the token attached to with ## will not be outputted. Ex: * #define wow(a, b...) process(b ## , a, ## b) * { wow(1, 2); } -> { process( 2, 1,2); } *************** *** 753,760 **** /* Some definitions for the hash table. The hash function MUST be ! computed as shown in hashf () below. That is because the rescan loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to ! the hashf () function. Hashf () only exists for the sake of politeness, for use when speed isn't so important. */ --- 809,816 ---- /* Some definitions for the hash table. The hash function MUST be ! computed as shown in hashf below. That is because the rescan loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to ! the hashf function. hashf only exists for the sake of politeness, for use when speed isn't so important. */ *************** *** 867,888 **** static int deps_column; - /* File name which deps are being written to. - This is 0 if deps are being written to stdout. */ - static char *deps_file = 0; - /* Nonzero means -I- has been seen, so don't look for #include "foo" the source-file directory. */ static int ignore_srcdir; - /* Handler for SIGPIPE. */ - - static void - pipe_closed (signo) - /* If this is missing, some compilers complain. */ - int signo; - { - fatal ("output pipe has been closed"); - } - int main (argc, argv) --- 923,930 ---- *************** *** 914,917 **** --- 956,962 ---- int inhibit_output = 0; + /* File name which deps are being written to. + This is 0 if deps are being written to stdout. */ + char *deps_file = 0; /* Stream on which to print the dependency information. */ FILE *deps_stream = 0; *************** *** 962,977 **** no_output = 0; cplusplus = 0; ! ! #ifdef SIGPIPE ! signal (SIGPIPE, pipe_closed); ! #endif ! ! for (i = 0; include_defaults[i].fname; i++) ! max_include_len = MAX (max_include_len, ! strlen (include_defaults[i].fname)); ! /* Leave room for making file name longer when converting to VMS syntax. */ ! #ifdef VMS ! max_include_len += 10; ! #endif bzero (pend_files, argc * sizeof (char *)); --- 1007,1011 ---- no_output = 0; cplusplus = 0; ! cplusplus_comments = 0; bzero (pend_files, argc * sizeof (char *)); *************** *** 1021,1030 **** dirtmp->next = 0; /* New one goes on the end */ dirtmp->control_macro = 0; - if (after_include == 0) - after_include = dirtmp; - else - last_after_include->next = dirtmp; - last_after_include = dirtmp; /* Tail follows the last one */ - if (i + 1 == argc) fatal ("Directory name missing after -idirafter option"); --- 1055,1058 ---- *************** *** 1032,1037 **** dirtmp->fname = argv[++i]; ! if (strlen (dirtmp->fname) > max_include_len) ! max_include_len = strlen (dirtmp->fname); } break; --- 1060,1068 ---- dirtmp->fname = argv[++i]; ! if (after_include == 0) ! after_include = dirtmp; ! else ! last_after_include->next = dirtmp; ! last_after_include = dirtmp; /* Tail follows the last one */ } break; *************** *** 1077,1087 **** case 'l': if (! strcmp (argv[i], "-lang-c")) ! cplusplus = 0, objc = 0; if (! strcmp (argv[i], "-lang-c++")) ! cplusplus = 1, objc = 0; if (! strcmp (argv[i], "-lang-objc")) ! objc = 1, cplusplus = 0; if (! strcmp (argv[i], "-lang-objc++")) ! objc = 1, cplusplus = 1; if (! strcmp (argv[i], "-lang-asm")) lang_asm = 1; --- 1108,1118 ---- case 'l': if (! strcmp (argv[i], "-lang-c")) ! cplusplus = 0, cplusplus_comments = 0, objc = 0; if (! strcmp (argv[i], "-lang-c++")) ! cplusplus = 1, cplusplus_comments = 1, objc = 0; if (! strcmp (argv[i], "-lang-objc")) ! objc = 1, cplusplus = 0, cplusplus_comments = 1; if (! strcmp (argv[i], "-lang-objc++")) ! objc = 1, cplusplus = 1, cplusplus_comments = 1; if (! strcmp (argv[i], "-lang-asm")) lang_asm = 1; *************** *** 1091,1095 **** case '+': ! cplusplus = 1; break; --- 1122,1126 ---- case '+': ! cplusplus = 1, cplusplus_comments = 1; break; *************** *** 1144,1150 **** i++; deps_file = argv[i]; - deps_stream = fopen (argv[i], "a"); - if (deps_stream == 0) - pfatal_with_name (argv[i]); } else { /* For -M and -MM, write deps on standard output --- 1175,1178 ---- *************** *** 1264,1269 **** struct file_name_list *dirtmp; ! if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) ignore_srcdir = 1; else { dirtmp = (struct file_name_list *) --- 1292,1300 ---- struct file_name_list *dirtmp; ! if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) { ignore_srcdir = 1; + /* Don't use any preceding -I directories for #include <...>. */ + first_bracket_include = 0; + } else { dirtmp = (struct file_name_list *) *************** *** 1271,1279 **** dirtmp->next = 0; /* New one goes on the end */ dirtmp->control_macro = 0; - if (include == 0) - include = dirtmp; - else - last_include->next = dirtmp; - last_include = dirtmp; /* Tail follows the last one */ if (argv[i][2] != 0) dirtmp->fname = argv[i] + 2; --- 1302,1305 ---- *************** *** 1282,1290 **** else dirtmp->fname = argv[++i]; ! if (strlen (dirtmp->fname) > max_include_len) ! max_include_len = strlen (dirtmp->fname); ! if (ignore_srcdir && first_bracket_include == 0) ! first_bracket_include = dirtmp; ! } } break; --- 1308,1313 ---- else dirtmp->fname = argv[++i]; ! append_include_chain (dirtmp, dirtmp); ! } } break; *************** *** 1429,1432 **** --- 1452,1463 ---- /* Now handle the command line options. */ + /* Do undefines specified with -U. */ + for (i = 1; i < argc; i++) + if (pend_undefs[i]) { + if (debug_output) + output_line_command (fp, &outbuf, 0, same_file); + make_undef (pend_undefs[i], &outbuf); + } + /* Do assertions specified with -A. */ for (i = 1; i < argc; i++) *************** *** 1442,1453 **** } - /* Do undefines specified with -U. */ - for (i = 1; i < argc; i++) - if (pend_undefs[i]) { - if (debug_output) - output_line_command (fp, &outbuf, 0, same_file); - make_undef (pend_undefs[i], &outbuf); - } - done_initializing = 1; --- 1473,1476 ---- *************** *** 1491,1495 **** #if 0 /* Obsolete, now that we use semicolons as the path separator. */ #ifdef __MSDOS__ ! && (endp-startp != 1 || !isalpha (*startp))) #endif #endif --- 1514,1518 ---- #if 0 /* Obsolete, now that we use semicolons as the path separator. */ #ifdef __MSDOS__ ! && (endp-startp != 1 || !isalpha (*startp)) #endif #endif *************** *** 1502,1506 **** nstore[endp-startp] = '\0'; - max_include_len = MAX (max_include_len, endp-startp+2); include_defaults[num_dirs].fname = savestring (nstore); include_defaults[num_dirs].cplusplus = cplusplus; --- 1525,1528 ---- *************** *** 1518,1521 **** --- 1540,1544 ---- } + first_system_include = 0; /* Unless -fnostdinc, tack on the standard include file dirs to the specified list */ *************** *** 1547,1564 **** new->fname = str; new->control_macro = 0; ! ! /* Add elt to tail of list. */ ! if (include == 0) ! include = new; ! else ! last_include->next = new; ! /* Make sure list for #include <...> also has the standard dirs. */ ! if (ignore_srcdir && first_bracket_include == 0) ! first_bracket_include = new; ! /* Record new tail. */ ! last_include = new; ! /* Update max_include_len if necessary. */ ! if (this_len > max_include_len) ! max_include_len = this_len; } } --- 1570,1576 ---- new->fname = str; new->control_macro = 0; ! append_include_chain (new, new); ! if (first_system_include == 0) ! first_system_include = new; } } *************** *** 1571,1585 **** = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); new->control_macro = 0; - /* Add elt to tail of list. */ - if (include == 0) - include = new; - else - last_include->next = new; - /* Make sure list for #include <...> also has the standard dirs. */ - if (ignore_srcdir && first_bracket_include == 0) - first_bracket_include = new; - /* Record new tail. */ - last_include = new; new->fname = p->fname; } } --- 1583,1590 ---- = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); new->control_macro = 0; new->fname = p->fname; + append_include_chain (new, new); + if (first_system_include == 0) + first_system_include = new; } } *************** *** 1587,1600 **** /* Tack the after_include chain at the end of the include chain. */ ! if (last_include) ! last_include->next = after_include; ! else ! include = after_include; ! if (ignore_srcdir && first_bracket_include == 0) ! first_bracket_include = after_include; ! ! /* Terminate the after_include chain. */ ! if (last_after_include) ! last_after_include->next = 0; /* Scan the -imacros files before the main input. --- 1592,1598 ---- /* Tack the after_include chain at the end of the include chain. */ ! append_include_chain (after_include, last_after_include); ! if (first_system_include == 0) ! first_system_include = after_include; /* Scan the -imacros files before the main input. *************** *** 1610,1614 **** return FAILURE_EXIT_CODE; } ! finclude (fd, pend_files[i], &outbuf, 0, 0); } no_output--; --- 1608,1612 ---- return FAILURE_EXIT_CODE; } ! finclude (fd, pend_files[i], &outbuf, 0, NULL_PTR); } no_output--; *************** *** 1645,1649 **** s = spec; /* Find the space before the DEPS_TARGET, if there is one. */ ! /* Don't use `index'; that causes trouble on USG. */ while (*s != 0 && *s != ' ') s++; if (*s != 0) { --- 1643,1647 ---- s = spec; /* Find the space before the DEPS_TARGET, if there is one. */ ! /* This should use index. (mrs) */ while (*s != 0 && *s != ' ') s++; if (*s != 0) { *************** *** 1659,1665 **** deps_file = output_file; - deps_stream = fopen (output_file, "a"); - if (deps_stream == 0) - pfatal_with_name (output_file); } --- 1657,1660 ---- *************** *** 1707,1711 **** --- 1702,1710 ---- deps_output (p, 0); /* Supply our own suffix. */ + #ifndef VMS deps_output (".o : ", 0); + #else + deps_output (".obj : ", 0); + #endif deps_output (in_fname, 0); deps_output (" ", 0); *************** *** 1797,1801 **** return FAILURE_EXIT_CODE; } ! finclude (fd, pend_includes[i], &outbuf, 0, 0); } --- 1796,1800 ---- return FAILURE_EXIT_CODE; } ! finclude (fd, pend_includes[i], &outbuf, 0, NULL_PTR); } *************** *** 1817,1830 **** if (print_deps) { ! /* Don't actually write the deps file if compilation has failed. ! Delete it instead. */ ! if (errors > 0 && deps_file != 0) ! unlink (deps_file); ! else { fputs (deps_buffer, deps_stream); putc ('\n', deps_stream); ! if (deps_stream != stdout) { ! fclose (deps_stream); ! if (ferror (deps_stream)) fatal ("I/O error on output"); } --- 1816,1827 ---- if (print_deps) { ! /* Don't actually write the deps file if compilation has failed. */ ! if (errors == 0) { ! if (deps_file && ! (deps_stream = fopen (deps_file, "a"))) ! pfatal_with_name (deps_file); fputs (deps_buffer, deps_stream); putc ('\n', deps_stream); ! if (deps_file) { ! if (ferror (deps_stream) || fclose (deps_stream) != 0) fatal ("I/O error on output"); } *************** *** 1832,1836 **** } ! if (ferror (stdout)) fatal ("I/O error on output"); --- 1829,1833 ---- } ! if (ferror (stdout) || fclose (stdout) != 0) fatal ("I/O error on output"); *************** *** 1879,1892 **** dirtmp->next = 0; /* New one goes on the end */ dirtmp->control_macro = 0; - if (include == 0) - include = dirtmp; - else - last_include->next = dirtmp; - last_include = dirtmp; /* Tail follows the last one */ dirtmp->fname = name; ! if (strlen (dirtmp->fname) > max_include_len) ! max_include_len = strlen (dirtmp->fname); ! if (ignore_srcdir && first_bracket_include == 0) ! first_bracket_include = dirtmp; /* Advance past this name. */ --- 1876,1881 ---- dirtmp->next = 0; /* New one goes on the end */ dirtmp->control_macro = 0; dirtmp->fname = name; ! append_include_chain (dirtmp, dirtmp); /* Advance past this name. */ *************** *** 2098,2103 **** return "ARGSUSED"; } ! if ((linsize >= 11) && !strncmp (ibp, "LINTLIBRARY", 8)) { ! *cmdlen = 8; return "LINTLIBRARY"; } --- 2087,2092 ---- return "ARGSUSED"; } ! if ((linsize >= 11) && !strncmp (ibp, "LINTLIBRARY", 11)) { ! *cmdlen = 11; return "LINTLIBRARY"; } *************** *** 2224,2227 **** --- 2213,2217 ---- obp = op->bufp; RECACHE; + beg_of_line = ibp; *************** *** 2271,2281 **** } ! /* If this is expanding a macro definition, don't recognize ! preprocessor directives. */ ! if (ip->macro != 0) goto randomchar; if (ident_length) goto specialchar; /* # keyword: a # must be first nonblank char on the line */ if (beg_of_line == 0) --- 2261,2272 ---- } ! /* Recognize preprocessor directives only when reading ! directly from a file. */ ! if (ip->fname == 0) goto randomchar; if (ident_length) goto specialchar; + /* # keyword: a # must be first nonblank char on the line */ if (beg_of_line == 0) *************** *** 2288,2308 **** If not, this # is not special. */ bp = beg_of_line; ! while (1) { ! if (is_hor_space[*bp]) ! bp++; ! else if (*bp == '\\' && bp[1] == '\n') ! bp += 2; ! else if (*bp == '/' && bp[1] == '*') { ! bp += 2; ! while (!(*bp == '*' && bp[1] == '/')) bp++; ! bp += 2; ! } ! else if ((cplusplus || objc) && *bp == '/' && bp[1] == '/') { ! bp += 2; ! while (*bp++ != '\n') ; } - else break; - } if (bp + 1 != ibp) goto randomchar; --- 2279,2301 ---- If not, this # is not special. */ bp = beg_of_line; ! /* If -traditional, require # to be at beginning of line. */ ! if (!traditional) ! while (1) { ! if (is_hor_space[*bp]) bp++; ! else if (*bp == '\\' && bp[1] == '\n') ! bp += 2; ! else if (*bp == '/' && bp[1] == '*') { ! bp += 2; ! while (!(*bp == '*' && bp[1] == '/')) ! bp++; ! bp += 2; ! } ! else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { ! bp += 2; ! while (*bp++ != '\n') ; ! } ! else break; } if (bp + 1 != ibp) goto randomchar; *************** *** 2360,2371 **** while (1) { if (ibp >= limit) { ! if (traditional) { ! if (ip->macro != 0) { ! /* try harder: this string crosses a macro expansion boundary */ ! POPMACRO; ! RECACHE; ! continue; ! } ! } else { error_with_line (line_for_error (start_line), "unterminated string or character constant"); --- 2353,2365 ---- while (1) { if (ibp >= limit) { ! if (ip->macro != 0) { ! /* try harder: this string crosses a macro expansion boundary. ! This can happen naturally if -traditional. ! Otherwise, only -D can make a macro with an unmatched quote. */ ! POPMACRO; ! RECACHE; ! continue; ! } ! if (!traditional) { error_with_line (line_for_error (start_line), "unterminated string or character constant"); *************** *** 2431,2435 **** if (*ibp != '*' ! && !((cplusplus || objc) && *ibp == '/')) goto randomchar; if (ip->macro != 0) --- 2425,2429 ---- if (*ibp != '*' ! && !(cplusplus_comments && *ibp == '/')) goto randomchar; if (ip->macro != 0) *************** *** 3232,3236 **** newline_fix (bp); if (*bp == '*' ! || ((cplusplus || objc) && *bp == '/')) { U_CHAR *obp = bp - 1; ip->bufp = bp + 1; --- 3226,3230 ---- newline_fix (bp); if (*bp == '*' ! || (cplusplus_comments && *bp == '/')) { U_CHAR *obp = bp - 1; ip->bufp = bp + 1; *************** *** 3353,3357 **** { register U_CHAR *bp1 ! = skip_quoted_string (xp - 1, bp, ip->lineno, 0, 0, 0); while (xp != bp1) if (*xp == '\\') { --- 3347,3352 ---- { register U_CHAR *bp1 ! = skip_quoted_string (xp - 1, bp, ip->lineno, ! NULL_PTR, NULL_PTR, NULL_PTR); while (xp != bp1) if (*xp == '\\') { *************** *** 3367,3371 **** case '/': if (*xp == '*' ! || ((cplusplus || objc) && *xp == '/')) { ip->bufp = xp + 1; /* If we already copied the command through, --- 3362,3366 ---- case '/': if (*xp == '*' ! || (cplusplus_comments && *xp == '/')) { ip->bufp = xp + 1; /* If we already copied the command through, *************** *** 3416,3419 **** --- 3411,3425 ---- bcopy (buf, op->bufp, len); op->bufp += len; + } else if (kt->type == T_DEFINE && dump_macros == dump_names) { + U_CHAR *xp = buf; + U_CHAR *yp; + SKIP_WHITE_SPACE (xp); + yp = xp; + while (is_idchar[*xp]) xp++; + len = (xp - yp); + check_expand (op, len + 1); + *op->bufp++ = ' '; + bcopy (yp, op->bufp, len); + op->bufp += len; } } /* Don't we need a newline or #line? */ *************** *** 3645,3649 **** expanding the include line*/ FILE_BUF trybuf; /* It got expanded into here */ ! int system_header_p = 0; /* 0 for "...", 1 for <...> */ int pcf = -1; char *pcfbuf; --- 3651,3655 ---- expanding the include line*/ FILE_BUF trybuf; /* It got expanded into here */ ! int angle_brackets = 0; /* 0 for "...", 1 for <...> */ int pcf = -1; char *pcfbuf; *************** *** 3652,3656 **** f= -1; /* JF we iz paranoid! */ ! if (importing && warn_import && !instack[indepth].system_header_p && !import_warning) { import_warning = 1; --- 3658,3662 ---- f= -1; /* JF we iz paranoid! */ ! if (importing && warn_import && !inhibit_warnings && !instack[indepth].system_header_p && !import_warning) { import_warning = 1; *************** *** 3678,3686 **** switch (*fbeg++) { case '\"': ! fend = fbeg; ! while (fend != limit && *fend != '\"') ! fend++; ! if (*fend == '\"' && fend + 1 == limit) { FILE_BUF *fp; /* We have "filename". Figure out directory this source --- 3684,3710 ---- switch (*fbeg++) { case '\"': ! { FILE_BUF *fp; + /* Copy the operand text, concatenating the strings. */ + { + U_CHAR *fin = fbeg; + fbeg = (U_CHAR *) alloca (limit - fbeg + 1); + fend = fbeg; + while (fin != limit) { + while (fin != limit && *fin != '\"') + *fend++ = *fin++; + fin++; + if (fin == limit) + break; + /* If not at the end, there had better be another string. */ + /* Skip just horiz space, and don't go past limit. */ + while (fin != limit && is_hor_space[*fin]) fin++; + if (fin != limit && *fin == '\"') + fin++; + else + goto fail; + } + } + *fend++ = 0; /* We have "filename". Figure out directory this source *************** *** 3713,3717 **** strncpy (dsp[0].fname, nam, n); dsp[0].fname[n] = '\0'; ! if (n > max_include_len) max_include_len = n; } else { dsp[0].fname = 0; /* Current directory */ --- 3737,3742 ---- strncpy (dsp[0].fname, nam, n); dsp[0].fname[n] = '\0'; ! if (n + INCLUDE_LEN_FUDGE > max_include_len) ! max_include_len = n + INCLUDE_LEN_FUDGE; } else { dsp[0].fname = 0; /* Current directory */ *************** *** 3722,3726 **** break; } - goto fail; case '<': --- 3747,3750 ---- *************** *** 3728,3732 **** while (fend != limit && *fend != '>') fend++; if (*fend == '>' && fend + 1 == limit) { ! system_header_p = 1; /* If -I-, start with the first -I dir after the -I-. */ if (first_bracket_include) --- 3752,3756 ---- while (fend != limit && *fend != '>') fend++; if (*fend == '>' && fend + 1 == limit) { ! angle_brackets = 1; /* If -I-, start with the first -I dir after the -I-. */ if (first_bracket_include) *************** *** 3780,3784 **** strncpy (fname, fbeg, flen); fname[flen] = 0; ! if (lookup_include (fname)) return 0; if (importing) --- 3804,3808 ---- strncpy (fname, fbeg, flen); fname[flen] = 0; ! if (redundant_include_p (fname)) return 0; if (importing) *************** *** 3824,3828 **** if (f == -2) return 0; /* Already included this file */ ! if (lookup_include (fname)) { close (f); return 0; --- 3848,3852 ---- if (f == -2) return 0; /* Already included this file */ ! if (redundant_include_p (fname)) { close (f); return 0; *************** *** 3838,3845 **** strncpy (fname, fbeg, flen); fname[flen] = 0; ! error_from_errno (fname); ! /* For -M, add this file to the dependencies. */ ! if (print_deps > (system_header_p || (system_include_depth > 0))) { /* Break the line before this. */ deps_output ("", 0); --- 3862,3872 ---- strncpy (fname, fbeg, flen); fname[flen] = 0; ! if (search_start) ! error_from_errno (fname); ! else ! error ("No include path in which to find %s", fname); ! /* For -M, add this file to the dependencies. */ ! if (print_deps > (angle_brackets || (system_include_depth > 0))) { /* Break the line before this. */ deps_output ("", 0); *************** *** 3847,3851 **** /* If it was requested as a system header file, then assume it belongs in the first place to look for such. */ ! if (system_header_p) { for (searchptr = search_start; searchptr; searchptr = searchptr->next) { if (searchptr->fname) { --- 3874,3878 ---- /* If it was requested as a system header file, then assume it belongs in the first place to look for such. */ ! if (angle_brackets) { for (searchptr = search_start; searchptr; searchptr = searchptr->next) { if (searchptr->fname) { *************** *** 3894,3898 **** /* For -M, add this file to the dependencies. */ ! if (print_deps > (system_header_p || (system_include_depth > 0))) { deps_output ("", 0); deps_output (fname, 0); --- 3921,3925 ---- /* For -M, add this file to the dependencies. */ ! if (print_deps > (angle_brackets || (system_include_depth > 0))) { deps_output ("", 0); deps_output (fname, 0); *************** *** 3905,3909 **** fprintf (stderr, "%s\n", fname); ! if (system_header_p) system_include_depth++; --- 3932,3936 ---- fprintf (stderr, "%s\n", fname); ! if (angle_brackets) system_include_depth++; *************** *** 3950,3956 **** } else ! finclude (f, fname, op, system_header_p, searchptr); ! if (system_header_p) system_include_depth--; } --- 3977,3983 ---- } else ! finclude (f, fname, op, is_system_include (fname), searchptr); ! if (angle_brackets) system_include_depth--; } *************** *** 3963,3967 **** static int ! lookup_include (name) char *name; { --- 3990,3994 ---- static int ! redundant_include_p (name) char *name; { *************** *** 3975,3978 **** --- 4002,4031 ---- } + /* Return nonzero if the given FILENAME is an absolute pathname which + designates a file within one of the known "system" include file + directories. We assume here that if the given FILENAME looks like + it is the name of a file which resides either directly in a "system" + include file directory, or within any subdirectory thereof, then the + given file must be a "system" include file. This function tells us + if we should suppress pedantic errors/warnings for the given FILENAME. */ + + static int + is_system_include (filename) + register char *filename; + { + struct file_name_list *searchptr; + + for (searchptr = first_system_include; searchptr; + searchptr = searchptr->next) + if (searchptr->fname) { + register char *sys_dir = searchptr->fname; + register unsigned length = strlen (sys_dir); + + if (! strncmp (sys_dir, filename, length) && filename[length] == '/') + return 1; + } + return 0; + } + /* Process the contents of include file FNAME, already open on descriptor F, with output to OP. *************** *** 3998,4002 **** if (file_size_and_mode (f, &st_mode, &st_size) < 0) ! goto nope; /* Impossible? */ fp = &instack[indepth + 1]; --- 4051,4059 ---- if (file_size_and_mode (f, &st_mode, &st_size) < 0) ! { ! perror_with_name (fname); ! close (f); ! return; ! } fp = &instack[indepth + 1]; *************** *** 4036,4039 **** --- 4093,4097 ---- st_size = 0; basep = (U_CHAR *) xmalloc (bsize + 2); + fp->buf = basep; /* So it will get freed, on error. */ bufp = basep; *************** *** 4049,4060 **** bsize *= 2; basep = (U_CHAR *) xrealloc (basep, bsize + 2); bufp = basep + st_size; /* May have moved */ } } - fp->buf = (U_CHAR *) alloca (st_size + 2); fp->bufp = fp->buf; - bcopy (basep, fp->buf, st_size); fp->length = st_size; - free (basep); } --- 4107,4116 ---- bsize *= 2; basep = (U_CHAR *) xrealloc (basep, bsize + 2); + fp->buf = basep; bufp = basep + st_size; /* May have moved */ } } fp->bufp = fp->buf; fp->length = st_size; } *************** *** 4062,4065 **** --- 4118,4127 ---- close (f); + /* Must do this before calling trigraph_pcp, so that the correct file name + will be printed in warning messages. */ + + indepth++; + input_file_stack_tick++; + if (!no_trigraphs) trigraph_pcp (fp); *************** *** 4073,4079 **** fp->buf[fp->length] = '\0'; - indepth++; - input_file_stack_tick++; - output_line_command (fp, op, 0, enter_file); rescan (op, 0); --- 4135,4138 ---- *************** *** 4307,4312 **** prec += 6; ! mdef = create_definition (prec, lineend, 0); ! if (mdef.defn == 0) abort(); --- 4366,4371 ---- prec += 6; ! mdef = create_definition (prec, lineend, NULL_PTR); ! if (mdef.defn == 0) abort(); *************** *** 4375,4380 **** /* First skip to a longword boundary */ ! if ((int)cp & 3) ! cp += 4 - ((int)cp & 3); /* Now get the string. */ --- 4434,4444 ---- /* First skip to a longword boundary */ ! /* ??? Why a 4-byte boundary? On all machines? */ ! /* NOTE: This works correctly even if HOST_WIDE_INT ! is narrower than a pointer. ! Do not try risky measures here to get another type to use! ! Do not include gstddef.h or stddef.h--either one will fail! */ ! if ((HOST_WIDE_INT) cp & 3) ! cp += 4 - ((HOST_WIDE_INT) cp & 3); /* Now get the string. */ *************** *** 4440,4444 **** if (hp == NULL) { kp->chain = 0; ! install (tmpbuf.bufp, -1, T_PCSTRING, (int) kp, -1); } else if (hp->type == T_PCSTRING) { --- 4504,4508 ---- if (hp == NULL) { kp->chain = 0; ! install (tmpbuf.bufp, -1, T_PCSTRING, 0, (char *) kp, -1); } else if (hp->type == T_PCSTRING) { *************** *** 4695,4699 **** ++bp; /* skip exactly one blank/tab char */ /* now everything from bp before limit is the definition. */ ! defn = collect_expansion (bp, limit, -1, 0); defn->args.argnames = (U_CHAR *) ""; } --- 4759,4763 ---- ++bp; /* skip exactly one blank/tab char */ /* now everything from bp before limit is the definition. */ ! defn = collect_expansion (bp, limit, -1, NULL_PTR); defn->args.argnames = (U_CHAR *) ""; } *************** *** 4778,4782 **** if (debug_output && op) pass_thru_directive (buf, limit, op, keyword); ! install (mdef.symnam, mdef.symlen, T_MACRO, mdef.defn, hashcode); } } --- 4842,4847 ---- if (debug_output && op) pass_thru_directive (buf, limit, op, keyword); ! install (mdef.symnam, mdef.symlen, T_MACRO, 0, ! (char *) mdef.defn, hashcode); } } *************** *** 5157,5162 **** *exp_p++ = *limit++; } ! } else if (!traditional) { ! /* There is no trailing whitespace, so invent some. */ *exp_p++ = '\n'; *exp_p++ = ' '; --- 5222,5229 ---- *exp_p++ = *limit++; } ! } else if (!traditional && expected_delimiter == 0) { ! /* There is no trailing whitespace, so invent some in ANSI mode. ! But not if "inside a string" (which in ANSI mode ! happens only for -D option). */ *exp_p++ = '\n'; *exp_p++ = ' '; *************** *** 5451,5455 **** bp++; } else if (*bp == '"' || *bp == '\'') ! bp = skip_quoted_string (bp, limit, 0, 0, 0, &eofp); else while (! is_hor_space[*bp] && *bp != '(' && *bp != ')' --- 5518,5522 ---- bp++; } else if (*bp == '"' || *bp == '\'') ! bp = skip_quoted_string (bp, limit, 0, NULL_PTR, NULL_PTR, &eofp); else while (! is_hor_space[*bp] && *bp != '(' && *bp != ')' *************** *** 5832,5836 **** /* #pragma and its argument line have already been copied to the output file. ! Here just check for recognized pragmas. */ static int --- 5899,5903 ---- /* #pragma and its argument line have already been copied to the output file. ! Just check for some recognized pragmas that need validation here. */ static int *************** *** 5847,5850 **** --- 5914,5940 ---- do_once (); } + + if (!strncmp (buf, "implementation", 14)) { + /* Be quiet about `#pragma implementation' for a file only if it hasn't + been included yet. */ + struct file_name_list *ptr; + U_CHAR *p = buf + 14, *fname, *inc_fname; + SKIP_WHITE_SPACE (p); + if (*p == '\n' || *p != '\"') + return 0; + + fname = p + 1; + if (p = (U_CHAR *) strchr (fname, '\"')) + *p = '\0'; + + for (ptr = all_include_files; ptr; ptr = ptr->next) { + inc_fname = (U_CHAR *) rindex (ptr->fname, '/'); + inc_fname = inc_fname ? inc_fname + 1 : (U_CHAR *) ptr->fname; + if (inc_fname && !strcmp (inc_fname, fname)) + warning ("`#pragma implementation' for `%s' appears after file is included", + fname); + } + } + return 0; } *************** *** 5910,5914 **** value = eval_if_expression (buf, limit - buf); ! conditional_skip (ip, value == 0, T_IF, 0); return 0; } --- 6000,6004 ---- value = eval_if_expression (buf, limit - buf); ! conditional_skip (ip, value == 0, T_IF, NULL_PTR); return 0; } *************** *** 5970,5974 **** int value; ! save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, -1); pcp_inside_if = 1; temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1); --- 6060,6064 ---- int value; ! save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1); pcp_inside_if = 1; temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1); *************** *** 6006,6025 **** while (p != directive_start) { char c = *p++; ! switch (c) { ! case ' ': ! case '\t': ! case '\n': ! break; ! case '/': ! if (p != ip->bufp && *p == '*') { ! /* Skip this comment. */ ! int junk; ! U_CHAR *save_bufp = ip->bufp; ! ip->bufp = p + 1; ! p = skip_to_end_of_comment (ip, &junk, 1); ! ip->bufp = save_bufp; ! } ! break; ! default: goto fail; } --- 6096,6109 ---- while (p != directive_start) { char c = *p++; ! if (is_space[c]) ! ; ! else if (c == '/' && p != ip->bufp && *p == '*') { ! /* Skip this comment. */ ! int junk; ! U_CHAR *save_bufp = ip->bufp; ! ip->bufp = p + 1; ! p = skip_to_end_of_comment (ip, &junk, 1); ! ip->bufp = save_bufp; ! } else { goto fail; } *************** *** 6134,6138 **** newline_fix (bp); if (*bp == '*' ! || ((cplusplus || objc) && *bp == '/')) { ip->bufp = ++bp; bp = skip_to_end_of_comment (ip, &ip->lineno, 0); --- 6218,6222 ---- newline_fix (bp); if (*bp == '*' ! || (cplusplus_comments && *bp == '/')) { ip->bufp = ++bp; bp = skip_to_end_of_comment (ip, &ip->lineno, 0); *************** *** 6141,6145 **** case '\"': case '\'': ! bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, 0, 0); break; case '\\': --- 6225,6230 ---- case '\"': case '\'': ! bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, ! NULL_PTR, NULL_PTR); break; case '\\': *************** *** 6175,6179 **** bp++; bp += 2; ! } else if ((cplusplus || objc) && *bp == '/' && bp[1] == '/') { bp += 2; while (*bp++ != '\n') ; --- 6260,6264 ---- bp++; bp += 2; ! } else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { bp += 2; while (*bp++ != '\n') ; *************** *** 6202,6206 **** } bp += 2; ! } else if ((cplusplus || objc) && *bp == '/' && bp[1] == '/') { bp += 2; while (*bp++ != '\n') ; --- 6287,6291 ---- } bp += 2; ! } else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { bp += 2; while (*bp++ != '\n') ; *************** *** 6464,6468 **** } } ! else if ((cplusplus || objc) && p[1] == '/') { p += 2; while (*p && *p++ != '\n') ; --- 6549,6553 ---- } } ! else if (cplusplus_comments && p[1] == '/') { p += 2; while (*p && *p++ != '\n') ; *************** *** 6502,6506 **** *op->bufp++ = '*'; } ! if ((cplusplus || objc) && bp[-1] == '/') { if (output) { while (bp < limit) --- 6587,6591 ---- *op->bufp++ = '*'; } ! if (cplusplus_comments && bp[-1] == '/') { if (output) { while (bp < limit) *************** *** 6673,6677 **** { int eofp = 0; ! p = skip_quoted_string (p - 1, limit, 0, 0, 0, &eofp); if (eofp) return ip->bufp = p; --- 6758,6762 ---- { int eofp = 0; ! p = skip_quoted_string (p - 1, limit, 0, NULL_PTR, NULL_PTR, &eofp); if (eofp) return ip->bufp = p; *************** *** 6837,6841 **** continue; if (i < nargs || (nargs == 0 && i == 0)) { ! /* if we are working on last arg which absorbes rest of args... */ if (i == nargs - 1 && defn->rest_args) rest_args = 1; --- 6922,6926 ---- continue; if (i < nargs || (nargs == 0 && i == 0)) { ! /* if we are working on last arg which absorbs rest of args... */ if (i == nargs - 1 && defn->rest_args) rest_args = 1; *************** *** 6843,6847 **** } else ! parse_error = macarg (0, 0); if (parse_error) { error_with_line (line_for_error (start_line), parse_error); --- 6928,6932 ---- } else ! parse_error = macarg (NULL_PTR, 0); if (parse_error) { error_with_line (line_for_error (start_line), parse_error); *************** *** 6860,6867 **** } rest_zero = 0; ! if (nargs == 0 && i > 0) ! error ("arguments given to macro `%s'", hp->name); ! else if (i < nargs) { /* traditional C allows foo() if foo wants one argument. */ if (nargs == 1 && i == 0 && traditional) --- 6945,6955 ---- } + /* Don't output an error message if we have already output one for + a parse error above. */ rest_zero = 0; ! if (nargs == 0 && i > 0) { ! if (! parse_error) ! error ("arguments given to macro `%s'", hp->name); ! } else if (i < nargs) { /* traditional C allows foo() if foo wants one argument. */ if (nargs == 1 && i == 0 && traditional) *************** *** 6870,6873 **** --- 6958,6963 ---- else if (i == nargs - 1 && defn->rest_args) rest_zero = 1; + else if (parse_error) + ; else if (i == 0) error ("macro `%s' used without args", hp->name); *************** *** 6876,6881 **** else error ("macro `%s' used with only %d args", hp->name, i); ! } else if (i > nargs) ! error ("macro `%s' used with too many (%d) args", hp->name, i); /* Swallow the closeparen. */ --- 6966,6973 ---- else error ("macro `%s' used with only %d args", hp->name, i); ! } else if (i > nargs) { ! if (! parse_error) ! error ("macro `%s' used with too many (%d) args", hp->name, i); ! } /* Swallow the closeparen. */ *************** *** 7287,7291 **** if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); ! if ((cplusplus || objc) && bp[1] == '/') { *comments = 1; bp += 2; --- 7379,7383 ---- if (bp[1] == '\\' && bp[2] == '\n') newline_fix (bp + 1); ! if (cplusplus_comments && bp[1] == '/') { *comments = 1; bp += 2; *************** *** 7398,7402 **** newline_fix (ibp); /* Delete any comment. */ ! if ((cplusplus || objc) && ibp[0] == '/') { obp--; ibp++; --- 7490,7494 ---- newline_fix (ibp); /* Delete any comment. */ ! if (cplusplus_comments && ibp[0] == '/') { obp--; ibp++; *************** *** 7504,7507 **** --- 7596,7600 ---- error (msg, arg1, arg2, arg3) char *msg; + char *arg1, *arg2, *arg3; { int i; *************** *** 7556,7559 **** --- 7649,7653 ---- warning (msg, arg1, arg2, arg3) char *msg; + char *arg1, *arg2, *arg3; { int i; *************** *** 7585,7588 **** --- 7679,7683 ---- int line; char *msg; + char *arg1, *arg2, *arg3; { int i; *************** *** 7609,7612 **** --- 7704,7708 ---- pedwarn (msg, arg1, arg2, arg3) char *msg; + char *arg1, *arg2, *arg3; { if (pedantic_errors) *************** *** 7624,7627 **** --- 7720,7724 ---- int line; char *msg; + char *arg1, *arg2, *arg3; { int i; *************** *** 7766,7776 **** */ static HASHNODE * ! install (name, len, type, value, hash) U_CHAR *name; int len; enum node_type type; ! int value; int hash; - /* watch out here if sizeof (U_CHAR *) != sizeof (int) */ { register HASHNODE *hp; --- 7863,7873 ---- */ static HASHNODE * ! install (name, len, type, ivalue, value, hash) U_CHAR *name; int len; enum node_type type; ! int ivalue; ! char *value; int hash; { register HASHNODE *hp; *************** *** 7799,7803 **** hp->type = type; hp->length = len; ! hp->value.ival = value; hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); p = hp->name; --- 7896,7903 ---- hp->type = type; hp->length = len; ! if (hp->type == T_CONST) ! hp->value.ival = ivalue; ! else ! hp->value.cpval = value; hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); p = hp->name; *************** *** 7997,8001 **** putc (*p, of); else if (*p == '\"' || *p =='\'') { ! U_CHAR *p1 = skip_quoted_string (p, limit, 0, 0, 0, 0); fwrite (p, p1 - p, 1, of); p = p1 - 1; --- 8097,8102 ---- putc (*p, of); else if (*p == '\"' || *p =='\'') { ! U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR, ! NULL_PTR, NULL_PTR); fwrite (p, p1 - p, 1, of); p = p1 - 1; *************** *** 8076,8096 **** FILE_BUF *outp; { ! install ("__LINE__", -1, T_SPECLINE, 0, -1); ! install ("__DATE__", -1, T_DATE, 0, -1); ! install ("__FILE__", -1, T_FILE, 0, -1); ! install ("__BASE_FILE__", -1, T_BASE_FILE, 0, -1); ! install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, -1); ! install ("__VERSION__", -1, T_VERSION, 0, -1); ! install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, -1); ! install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, -1); ! install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, -1); ! install ("__TIME__", -1, T_TIME, 0, -1); if (!traditional) ! install ("__STDC__", -1, T_CONST, STDC_VALUE, -1); if (objc) ! install ("__OBJC__", -1, T_CONST, 1, -1); /* This is supplied using a -D by the compiler driver so that it is present only when truly compiling with GNU C. */ ! /* install ("__GNUC__", -1, T_CONST, 2, -1); */ if (debug_output) --- 8177,8197 ---- FILE_BUF *outp; { ! install ("__LINE__", -1, T_SPECLINE, 0, 0, -1); ! install ("__DATE__", -1, T_DATE, 0, 0, -1); ! install ("__FILE__", -1, T_FILE, 0, 0, -1); ! install ("__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1); ! install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1); ! install ("__VERSION__", -1, T_VERSION, 0, 0, -1); ! install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1); ! install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1); ! install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1); ! install ("__TIME__", -1, T_TIME, 0, 0, -1); if (!traditional) ! install ("__STDC__", -1, T_CONST, STDC_VALUE, 0, -1); if (objc) ! install ("__OBJC__", -1, T_CONST, 1, 0, -1); /* This is supplied using a -D by the compiler driver so that it is present only when truly compiling with GNU C. */ ! /* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */ if (debug_output) *************** *** 8121,8128 **** pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); - sprintf (directive, " __WCHAR_TYPE__ %s\n", WCHAR_TYPE); - output_line_command (inp, outp, 0, same_file); - pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); - sprintf (directive, " __DATE__ \"%s %2d %4d\"\n", monthnames[timebuf->tm_mon], --- 8222,8225 ---- *************** *** 8310,8317 **** /* pass NULL as output ptr to do_define since we KNOW it never does any output.... */ ! do_assert (buf, buf + strlen (buf) , NULL, kt); --indepth; } /* Add output to `deps_buffer' for the -M switch. STRING points to the text to be output. --- 8407,8447 ---- /* pass NULL as output ptr to do_define since we KNOW it never does any output.... */ ! do_assert (buf, buf + strlen (buf) , NULL_PTR, kt); --indepth; } + /* Append a chain of `struct file_name_list's + to the end of the main include chain. + FIRST is the beginning of the chain to append, and LAST is the end. */ + + static void + append_include_chain (first, last) + struct file_name_list *first, *last; + { + struct file_name_list *dir; + + if (!first || !last) + return; + + if (include == 0) + include = first; + else + last_include->next = first; + + if (first_bracket_include == 0) + first_bracket_include = first; + + for (dir = first; ; dir = dir->next) { + int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE; + if (len > max_include_len) + max_include_len = len; + if (dir == last) + break; + } + + last->next = NULL; + last_include = last; + } + /* Add output to `deps_buffer' for the -M switch. STRING points to the text to be output. *************** *** 8355,8372 **** register unsigned length; { - #ifdef VMS - short zero = 0; - long max_str = 65535; - - while (length > max_str) { - (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); - length -= max_str; - b += max_str; - } - (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b); - #else while (length-- > 0) *b++ = 0; - #endif /* not VMS */ } --- 8485,8490 ---- *************** *** 8377,8394 **** register unsigned length; { - #ifdef VMS - long max_str = 65535; - - while (length > max_str) { - (void) LIB$MOVC3 (&max_str, b1, b2); - length -= max_str; - b1 += max_str; - b2 += max_str; - } - (void) LIB$MOVC3 (&length, b1, b2); - #else while (length-- > 0) *b2++ = *b1++; - #endif /* not VMS */ } --- 8495,8500 ---- *************** *** 8399,8408 **** register unsigned length; { - #ifdef VMS - struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1}; - struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2}; - - return STR$COMPARE (&src1, &src2); - #else while (length-- > 0) if (*b1++ != *b2++) --- 8505,8508 ---- *************** *** 8410,8414 **** return 0; - #endif /* not VMS */ } #endif /* not BSTRING */ --- 8510,8513 ---- *************** *** 8420,8425 **** char *str, *arg; { - if (deps_file) - unlink (deps_file); fprintf (stderr, "%s: ", progname); fprintf (stderr, str, arg); --- 8519,8522 ---- *************** *** 8799,8801 **** --- 8896,8917 ---- } + /* Avoid run-time library bug, where copying M out of N+M characters with + N >= 65535 results in VAXCRTL's strncat falling into an infinite loop. + gcc-cpp exercises this particular bug. */ + + static char * + strncat (dst, src, cnt) + char *dst; + const char *src; + unsigned cnt; + { + register char *d = dst, *s = (char *) src; + register int n = cnt; /* convert to _signed_ type */ + + while (*d) d++; /* advance to end */ + while (--n >= 0) + if (!(*d++ = *s++)) break; + if (n < 0) *d = '\0'; + return dst; + } #endif /* VMS */ diff -rc2N gcc-2.2.2/cexp.y gcc-2.3.1/cexp.y *** gcc-2.2.2/cexp.y Thu Feb 13 01:33:18 1992 --- gcc-2.3.1/cexp.y Wed Oct 21 02:53:52 1992 *************** *** 20,24 **** what you give them. Help stamp out software-hoarding! ! Adapted from expread.y of GDB by Paul Rubin, July 1986. /* Parse a C expression from text in a string */ --- 20,24 ---- what you give them. Help stamp out software-hoarding! ! Adapted from expread.y of GDB by Paul Rubin, July 1986. */ /* Parse a C expression from text in a string */ *************** *** 34,37 **** --- 34,39 ---- #endif + #include + typedef unsigned char U_CHAR; *************** *** 44,47 **** --- 46,67 ---- }; + /* Define a generic NULL if one hasn't already been defined. */ + + #ifndef NULL + #define NULL 0 + #endif + + #ifndef GENERIC_PTR + #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) + #define GENERIC_PTR void * + #else + #define GENERIC_PTR char * + #endif + #endif + + #ifndef NULL_PTR + #define NULL_PTR ((GENERIC_PTR)0) + #endif + int yylex (); void yyerror (); *************** *** 56,59 **** --- 76,81 ---- extern unsigned char is_idstart[], is_idchar[], is_hor_space[]; + extern char *xmalloc (); + /* Flag for -pedantic. */ extern int pedantic; *************** *** 77,80 **** --- 99,110 ---- #define WCHAR_TYPE_SIZE INT_TYPE_SIZE #endif + + /* Yield nonzero if adding two numbers with A's and B's signs can yield a + number with SUM's sign, where A, B, and SUM are all C integers. */ + #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) + + static void integer_overflow (); + static long left_shift (); + static long right_shift (); %} *************** *** 126,129 **** --- 156,161 ---- exp : '-' exp %prec UNARY { $$.value = - $2.value; + if (($$.value & $2.value) < 0 && ! $2.unsignedp) + integer_overflow (); $$.unsignedp = $2.unsignedp; } | '!' exp %prec UNARY *************** *** 137,141 **** | '#' NAME { $$.value = check_assertion ($2.address, $2.length, ! 0, 0); $$.unsignedp = 0; } | '#' NAME --- 169,173 ---- | '#' NAME { $$.value = check_assertion ($2.address, $2.length, ! 0, NULL_PTR); $$.unsignedp = 0; } | '#' NAME *************** *** 154,160 **** { $$.unsignedp = $1.unsignedp || $3.unsignedp; if ($$.unsignedp) ! $$.value = (unsigned) $1.value * $3.value; else ! $$.value = $1.value * $3.value; } | exp '/' exp { if ($3.value == 0) --- 186,198 ---- { $$.unsignedp = $1.unsignedp || $3.unsignedp; if ($$.unsignedp) ! $$.value = (unsigned long) $1.value * $3.value; else ! { ! $$.value = $1.value * $3.value; ! if ($1.value ! && ($$.value / $1.value != $3.value ! || ($$.value & $1.value & $3.value) < 0)) ! integer_overflow (); ! } } | exp '/' exp { if ($3.value == 0) *************** *** 165,171 **** $$.unsignedp = $1.unsignedp || $3.unsignedp; if ($$.unsignedp) ! $$.value = (unsigned) $1.value / $3.value; else ! $$.value = $1.value / $3.value; } | exp '%' exp { if ($3.value == 0) --- 203,213 ---- $$.unsignedp = $1.unsignedp || $3.unsignedp; if ($$.unsignedp) ! $$.value = (unsigned long) $1.value / $3.value; else ! { ! $$.value = $1.value / $3.value; ! if (($$.value & $1.value & $3.value) < 0) ! integer_overflow (); ! } } | exp '%' exp { if ($3.value == 0) *************** *** 176,200 **** $$.unsignedp = $1.unsignedp || $3.unsignedp; if ($$.unsignedp) ! $$.value = (unsigned) $1.value % $3.value; else $$.value = $1.value % $3.value; } | exp '+' exp { $$.value = $1.value + $3.value; ! $$.unsignedp = $1.unsignedp || $3.unsignedp; } | exp '-' exp { $$.value = $1.value - $3.value; ! $$.unsignedp = $1.unsignedp || $3.unsignedp; } | exp LSH exp { $$.unsignedp = $1.unsignedp; ! if ($$.unsignedp) ! $$.value = (unsigned) $1.value << $3.value; else ! $$.value = $1.value << $3.value; } | exp RSH exp { $$.unsignedp = $1.unsignedp; ! if ($$.unsignedp) ! $$.value = (unsigned) $1.value >> $3.value; else ! $$.value = $1.value >> $3.value; } | exp EQUAL exp { $$.value = ($1.value == $3.value); --- 218,250 ---- $$.unsignedp = $1.unsignedp || $3.unsignedp; if ($$.unsignedp) ! $$.value = (unsigned long) $1.value % $3.value; else $$.value = $1.value % $3.value; } | exp '+' exp { $$.value = $1.value + $3.value; ! $$.unsignedp = $1.unsignedp || $3.unsignedp; ! if (! $$.unsignedp ! && ! possible_sum_sign ($1.value, $3.value, ! $$.value)) ! integer_overflow (); } | exp '-' exp { $$.value = $1.value - $3.value; ! $$.unsignedp = $1.unsignedp || $3.unsignedp; ! if (! $$.unsignedp ! && ! possible_sum_sign ($$.value, $3.value, ! $1.value)) ! integer_overflow (); } | exp LSH exp { $$.unsignedp = $1.unsignedp; ! if ($3.value < 0 && ! $3.unsignedp) ! $$.value = right_shift (&$1, -$3.value); else ! $$.value = left_shift (&$1, $3.value); } | exp RSH exp { $$.unsignedp = $1.unsignedp; ! if ($3.value < 0 && ! $3.unsignedp) ! $$.value = left_shift (&$1, -$3.value); else ! $$.value = right_shift (&$1, $3.value); } | exp EQUAL exp { $$.value = ($1.value == $3.value); *************** *** 206,210 **** { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned) $1.value <= $3.value; else $$.value = $1.value <= $3.value; } --- 256,260 ---- { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned long) $1.value <= $3.value; else $$.value = $1.value <= $3.value; } *************** *** 212,216 **** { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned) $1.value >= $3.value; else $$.value = $1.value >= $3.value; } --- 262,266 ---- { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned long) $1.value >= $3.value; else $$.value = $1.value >= $3.value; } *************** *** 218,222 **** { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned) $1.value < $3.value; else $$.value = $1.value < $3.value; } --- 268,272 ---- { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned long) $1.value < $3.value; else $$.value = $1.value < $3.value; } *************** *** 224,228 **** { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned) $1.value > $3.value; else $$.value = $1.value > $3.value; } --- 274,278 ---- { $$.unsignedp = 0; if ($1.unsignedp || $3.unsignedp) ! $$.value = (unsigned long) $1.value > $3.value; else $$.value = $1.value > $3.value; } *************** *** 293,300 **** { register char *p = lexptr; - register long n = 0; register int c; register int base = 10; register int len = olen; for (c = 0; c < len; c++) --- 343,353 ---- { register char *p = lexptr; register int c; + register unsigned long n = 0, nd, ULONG_MAX_over_base; register int base = 10; register int len = olen; + register int overflow = 0; + register int digit, largest_digit = 0; + int spec_long = 0; for (c = 0; c < len; c++) *************** *** 315,347 **** base = 8; ! while (len > 0) { c = *p++; - len--; - if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; ! if (c >= '0' && c <= '9') { ! n *= base; ! n += c - '0'; ! } else if (base == 16 && c >= 'a' && c <= 'f') { ! n *= base; ! n += c - 'a' + 10; ! } else { /* `l' means long, and `u' means unsigned. */ while (1) { if (c == 'l' || c == 'L') ! ; else if (c == 'u' || c == 'U') ! yylval.integer.unsignedp = 1; else break; ! if (len == 0) break; c = *p++; - len--; } /* Don't look for any more digits after the suffixes. */ break; } } --- 368,412 ---- base = 8; ! ULONG_MAX_over_base = (unsigned long) -1 / base; ! ! for (; len > 0; len--) { c = *p++; ! if (c >= '0' && c <= '9') ! digit = c - '0'; ! else if (base == 16 && c >= 'a' && c <= 'f') ! digit = c - 'a' + 10; ! else if (base == 16 && c >= 'A' && c <= 'F') ! digit = c - 'A' + 10; ! else { /* `l' means long, and `u' means unsigned. */ while (1) { if (c == 'l' || c == 'L') ! { ! if (spec_long) ! yyerror ("two `l's in integer constant"); ! spec_long = 1; ! } else if (c == 'u' || c == 'U') ! { ! if (yylval.integer.unsignedp) ! yyerror ("two `u's in integer constant"); ! yylval.integer.unsignedp = 1; ! } else break; ! if (--len == 0) break; c = *p++; } /* Don't look for any more digits after the suffixes. */ break; } + if (largest_digit < digit) + largest_digit = digit; + nd = n * base + digit; + overflow |= ULONG_MAX_over_base < n | nd < n; + n = nd; } *************** *** 351,357 **** } /* If too big to be signed, consider it unsigned. */ ! if (n < 0) ! yylval.integer.unsignedp = 1; lexptr = p; --- 416,432 ---- } + if (base <= largest_digit) + warning ("integer constant contains digits beyond the radix"); + + if (overflow) + warning ("integer constant out of range"); + /* If too big to be signed, consider it unsigned. */ ! if ((long) n < 0 && ! yylval.integer.unsignedp) ! { ! if (base == 10) ! warning ("integer constant is so large that it is unsigned"); ! yylval.integer.unsignedp = 1; ! } lexptr = p; *************** *** 365,372 **** }; - #ifndef NULL - #define NULL 0 - #endif - static struct token tokentab2[] = { {"&&", AND}, --- 440,443 ---- *************** *** 531,538 **** || ((result >> (num_bits - 1)) & 1) == 0) yylval.integer.value ! = result & ((unsigned) ~0 >> (HOST_BITS_PER_INT - num_bits)); else yylval.integer.value ! = result | ~((unsigned) ~0 >> (HOST_BITS_PER_INT - num_bits)); } else --- 602,609 ---- || ((result >> (num_bits - 1)) & 1) == 0) yylval.integer.value ! = result & ((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); else yylval.integer.value ! = result | ~((unsigned long) ~0 >> (HOST_BITS_PER_LONG - num_bits)); } else *************** *** 547,551 **** { wchar_t wc; ! (void) mbtowc (NULL, NULL, 0); if (mbtowc (& wc, token_buffer, num_chars) == num_chars) result = wc; --- 618,622 ---- { wchar_t wc; ! (void) mbtowc (NULL_PTR, NULL_PTR, 0); if (mbtowc (& wc, token_buffer, num_chars) == num_chars) result = wc; *************** *** 733,746 **** case 'x': { ! register int i = 0; for (;;) { c = *(*string_ptr)++; if (c >= '0' && c <= '9') ! i = (i << 4) + c - '0'; else if (c >= 'a' && c <= 'f') ! i = (i << 4) + c - 'a' + 10; else if (c >= 'A' && c <= 'F') ! i = (i << 4) + c - 'A' + 10; else { --- 804,817 ---- case 'x': { ! register unsigned i = 0, overflow = 0, digits_found = 0, digit; for (;;) { c = *(*string_ptr)++; if (c >= '0' && c <= '9') ! digit = c - '0'; else if (c >= 'a' && c <= 'f') ! digit = c - 'a' + 10; else if (c >= 'A' && c <= 'F') ! digit = c - 'A' + 10; else { *************** *** 748,753 **** break; } } ! if ((i & ~((1 << BITS_PER_UNIT) - 1)) != 0) { i &= (1 << BITS_PER_UNIT) - 1; --- 819,829 ---- break; } + overflow |= i ^ (i << 4 >> 4); + i = (i << 4) + digit; + digits_found = 1; } ! if (!digits_found) ! yyerror ("\\x used with no following hex digits"); ! if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) { i &= (1 << BITS_PER_UNIT) - 1; *************** *** 767,770 **** --- 843,888 ---- error (s); longjmp (parse_return_error, 1); + } + + static void + integer_overflow () + { + if (pedantic) + pedwarn ("integer overflow in preprocessor expression"); + } + + static long + left_shift (a, b) + struct constant *a; + unsigned long b; + { + if (b >= HOST_BITS_PER_LONG) + { + if (! a->unsignedp && a->value != 0) + integer_overflow (); + return 0; + } + else if (a->unsignedp) + return (unsigned long) a->value << b; + else + { + long l = a->value << b; + if (l >> b != a->value) + integer_overflow (); + return l; + } + } + + static long + right_shift (a, b) + struct constant *a; + unsigned long b; + { + if (b >= HOST_BITS_PER_LONG) + return a->unsignedp ? 0 : a->value >> (HOST_BITS_PER_LONG - 1); + else if (a->unsignedp) + return (unsigned long) a->value >> b; + else + return a->value >> b; } diff -rc2N gcc-2.2.2/collect2.c gcc-2.3.1/collect2.c *** gcc-2.2.2/collect2.c Wed Jun 10 15:25:16 1992 --- gcc-2.3.1/collect2.c Thu Oct 15 02:10:55 1992 *************** *** 29,33 **** #include #include - #include #include #include --- 29,32 ---- *************** *** 112,115 **** --- 111,119 ---- #include + /* Mips-news overrides this macro. */ + #ifndef MY_ISCOFF + #define MY_ISCOFF(X) ISCOFF (X) + #endif + #endif /* OBJECT_FORMAT_COFF */ *************** *** 199,203 **** --- 203,229 ---- generic *xcalloc (); generic *xmalloc (); + + extern char *index (); + extern char *rindex (); + #ifdef NO_DUP2 + dup2 (oldfd, newfd) + int oldfd; + int newfd; + { + int fdtmp[256]; + int fdx = 0; + int fd; + + if (oldfd == newfd) + return 0; + close (newfd); + while ((fd = dup (oldfd)) != newfd) /* good enough for low fd's */ + fdtmp[fdx++] = fd; + while (fdx > 0) + close (fdtmp[--fdx]); + } + #endif + char * my_strerror (e) *************** *** 354,359 **** --- 380,391 ---- { "GLOBAL_$D$", sizeof ("GLOBAL_$I$")-1, 2, 0 }, #endif + #ifdef CFRONT_LOSSAGE /* Don't collect cfront initialization functions. + cfront has its own linker procedure to collect them; + if collect2 gets them too, they get collected twice + when the cfront procedure is run and the compiler used + for linking happens to be GCC. */ { "sti__", sizeof ("sti__")-1, 1, 1 }, { "std__", sizeof ("std__")-1, 2, 1 }, + #endif /* CFRONT_LOSSAGE */ { NULL, 0, 0, 0 } }; *************** *** 462,471 **** fatal ("no arguments"); ! signal (SIGQUIT, handler); ! signal (SIGINT, handler); ! signal (SIGALRM, handler); ! signal (SIGHUP, handler); ! signal (SIGSEGV, handler); ! signal (SIGBUS, handler); /* Try to discover a valid linker/assembler/nm/strip to use. */ --- 494,509 ---- fatal ("no arguments"); ! if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) ! signal (SIGQUIT, handler); ! if (signal (SIGINT, SIG_IGN) != SIG_IGN) ! signal (SIGINT, handler); ! if (signal (SIGALRM, SIG_IGN) != SIG_IGN) ! signal (SIGALRM, handler); ! if (signal (SIGHUP, SIG_IGN) != SIG_IGN) ! signal (SIGHUP, handler); ! if (signal (SIGSEGV, SIG_IGN) != SIG_IGN) ! signal (SIGSEGV, handler); ! if (signal (SIGBUS, SIG_IGN) != SIG_IGN) ! signal (SIGBUS, handler); /* Try to discover a valid linker/assembler/nm/strip to use. */ *************** *** 484,488 **** if (prefix == (char *)0) { ! p = strrchr (argv[0], '/'); if (p != (char *)0) { --- 522,526 ---- if (prefix == (char *)0) { ! p = rindex (argv[0], '/'); if (p != (char *)0) { *************** *** 548,552 **** /* Determine the full path name of the C compiler to use. */ c_file_name = getenv ("COLLECT_GCC"); ! if (c_file_name == 0 || c_file_name[0] != '/') { c_file_name = xcalloc (clen + sizeof ("gcc"), 1); --- 586,593 ---- /* Determine the full path name of the C compiler to use. */ c_file_name = getenv ("COLLECT_GCC"); ! /* If this is absolute, it must be a file that exists. ! If it is relative, it must be something that execvp was able to find. ! Either way, we can pass it to execvp and find the same executable. */ ! if (c_file_name == 0) { c_file_name = xcalloc (clen + sizeof ("gcc"), 1); *************** *** 677,681 **** else if (first_file ! && (p = strrchr (arg, '.')) != (char *)0 && strcmp (p, ".o") == 0) { --- 718,722 ---- else if (first_file ! && (p = rindex (arg, '.')) != (char *)0 && strcmp (p, ".o") == 0) { *************** *** 855,860 **** { int pid; - void (*int_handler) (); - void (*quit_handler) (); if (vflag || debug) --- 896,899 ---- *************** *** 883,893 **** } - int_handler = (void (*) ())signal (SIGINT, SIG_IGN); - quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN); - do_wait (prog); - - signal (SIGINT, int_handler); - signal (SIGQUIT, quit_handler); } --- 922,926 ---- *************** *** 1181,1185 **** fatal ("%s: can't open as COFF file", prog_name); ! if (!ISCOFF (HEADER(ldptr).f_magic)) fatal ("%s: not a COFF file", prog_name); --- 1214,1218 ---- fatal ("%s: can't open as COFF file", prog_name); ! if (!MY_ISCOFF (HEADER (ldptr).f_magic)) fatal ("%s: not a COFF file", prog_name); *************** *** 1381,1389 **** load_hdr = (load_union_t *) (obj + offset); ! /* If modifing the program file, copy the header. */ if (rw) { load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size); ! bcopy (load_hdr, ptr, load_hdr->hdr.ldci_cmd_size); load_hdr = ptr; --- 1414,1422 ---- load_hdr = (load_union_t *) (obj + offset); ! /* If modifying the program file, copy the header. */ if (rw) { load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size); ! bcopy ((generic *)load_hdr, (generic *)ptr, load_hdr->hdr.ldci_cmd_size); load_hdr = ptr; *************** *** 1568,1572 **** print_load_command (load_hdr, offset, i); ! bcopy (load_hdr, obj + offset, size); offset += size; } --- 1601,1605 ---- print_load_command (load_hdr, offset, i); ! bcopy ((generic *)load_hdr, (generic *)(obj + offset), size); offset += size; } diff -rc2N gcc-2.2.2/combine.c gcc-2.3.1/combine.c *** gcc-2.2.2/combine.c Tue Jun 2 17:35:27 1992 --- gcc-2.3.1/combine.c Fri Oct 30 17:47:23 1992 *************** *** 74,79 **** combine anyway. */ - #include - #include "config.h" #include "gvarargs.h" --- 74,77 ---- *************** *** 89,92 **** --- 87,91 ---- #include "recog.h" #include "real.h" + #include /* It is not safe to use ordinary gen_lowpart in combine. *************** *** 250,264 **** If an entry is zero, it means that we don't know anything special. */ ! static int *reg_significant; /* Mode used to compute significance in reg_significant. It is the largest ! integer mode that can fit in HOST_BITS_PER_INT. */ static enum machine_mode significant_mode; ! /* Nonzero when reg_significant can be safely used. It is zero while ! computing reg_significant. This prevents propagating values based ! on previously set values, which can be incorrect if a variable ! is modified in a loop. */ static int significant_valid; --- 249,268 ---- If an entry is zero, it means that we don't know anything special. */ ! static HOST_WIDE_INT *reg_significant; /* Mode used to compute significance in reg_significant. It is the largest ! integer mode that can fit in HOST_BITS_PER_WIDE_INT. */ static enum machine_mode significant_mode; ! /* Nonzero if we know that a register has some leading bits that are always ! equal to the sign bit. */ ! ! static char *reg_sign_bit_copies; ! ! /* Nonzero when reg_significant and reg_sign_bit_copies can be safely used. ! It is zero while computing them and after combine has completed. This ! former test prevents propagating values based on previously set values, ! which can be incorrect if a variable is modified in a loop. */ static int significant_valid; *************** *** 270,283 **** struct undo { - rtx *where; - rtx old_contents; - int is_int; - }; - - struct undo_int - { - int *where; - int old_contents; int is_int; }; --- 274,280 ---- struct undo { int is_int; + union {rtx rtx; int i;} old_contents; + union {rtx *rtx; int *i;} where; }; *************** *** 303,318 **** static struct undobuf undobuf; ! /* Substitute NEWVAL, an rtx expression, into INTO, a place in a some insn. The substitution can be undone by undo_all. If INTO is already ! set to NEWVAL, do not record this change. */ #define SUBST(INTO, NEWVAL) \ ! do { if (undobuf.num_undo < MAX_UNDO) \ { \ - undobuf.undo[undobuf.num_undo].where = &INTO; \ - undobuf.undo[undobuf.num_undo].old_contents = INTO; \ undobuf.undo[undobuf.num_undo].is_int = 0; \ ! INTO = NEWVAL; \ ! if (undobuf.undo[undobuf.num_undo].old_contents != INTO) \ undobuf.num_undo++; \ } \ --- 300,318 ---- static struct undobuf undobuf; ! /* Substitute NEWVAL, an rtx expression, into INTO, a place in some insn. The substitution can be undone by undo_all. If INTO is already ! set to NEWVAL, do not record this change. Because computing NEWVAL might ! also call SUBST, we have to compute it before we put anything into ! the undo table. */ #define SUBST(INTO, NEWVAL) \ ! do { rtx _new = (NEWVAL); \ ! if (undobuf.num_undo < MAX_UNDO) \ { \ undobuf.undo[undobuf.num_undo].is_int = 0; \ ! undobuf.undo[undobuf.num_undo].where.rtx = &INTO; \ ! undobuf.undo[undobuf.num_undo].old_contents.rtx = INTO; \ ! INTO = _new; \ ! if (undobuf.undo[undobuf.num_undo].old_contents.rtx != INTO) \ undobuf.num_undo++; \ } \ *************** *** 326,336 **** do { if (undobuf.num_undo < MAX_UNDO) \ { \ ! struct undo_int *u \ ! = (struct undo_int *)&undobuf.undo[undobuf.num_undo]; \ ! u->where = (int *) &INTO; \ ! u->old_contents = INTO; \ ! u->is_int = 1; \ INTO = NEWVAL; \ ! if (u->old_contents != INTO) \ undobuf.num_undo++; \ } \ --- 326,334 ---- do { if (undobuf.num_undo < MAX_UNDO) \ { \ ! undobuf.undo[undobuf.num_undo].is_int = 1; \ ! undobuf.undo[undobuf.num_undo].where.i = (int *) &INTO; \ ! undobuf.undo[undobuf.num_undo].old_contents.i = INTO; \ INTO = NEWVAL; \ ! if (undobuf.undo[undobuf.num_undo].old_contents.i != INTO) \ undobuf.num_undo++; \ } \ *************** *** 357,365 **** static rtx make_extraction (); static int get_pos_from_mask (); static rtx make_field_assignment (); static rtx make_compound_operation (); static rtx apply_distributive_law (); static rtx simplify_and_const_int (); ! static unsigned significant_bits (); static int merge_outer_ops (); static rtx simplify_shift_const (); --- 355,366 ---- static rtx make_extraction (); static int get_pos_from_mask (); + static rtx force_to_mode (); + static rtx known_cond (); static rtx make_field_assignment (); static rtx make_compound_operation (); static rtx apply_distributive_law (); static rtx simplify_and_const_int (); ! static unsigned HOST_WIDE_INT significant_bits (); ! static int num_sign_bit_copies (); static int merge_outer_ops (); static rtx simplify_shift_const (); *************** *** 400,405 **** reg_last_set_table_tick = (short *) alloca (nregs * sizeof (short)); reg_last_set_label = (short *) alloca (nregs * sizeof (short)); ! reg_last_set_invalid = (char *) alloca (nregs * sizeof (short)); ! reg_significant = (int *) alloca (nregs * sizeof (int)); bzero (reg_last_death, nregs * sizeof (rtx)); --- 401,407 ---- reg_last_set_table_tick = (short *) alloca (nregs * sizeof (short)); reg_last_set_label = (short *) alloca (nregs * sizeof (short)); ! reg_last_set_invalid = (char *) alloca (nregs * sizeof (char)); ! reg_significant = (HOST_WIDE_INT *) alloca (nregs * sizeof (HOST_WIDE_INT)); ! reg_sign_bit_copies = (char *) alloca (nregs * sizeof (char)); bzero (reg_last_death, nregs * sizeof (rtx)); *************** *** 408,412 **** bzero (reg_last_set_table_tick, nregs * sizeof (short)); bzero (reg_last_set_invalid, nregs * sizeof (char)); ! bzero (reg_significant, nregs * sizeof (int)); init_recog_no_volatile (); --- 410,415 ---- bzero (reg_last_set_table_tick, nregs * sizeof (short)); bzero (reg_last_set_invalid, nregs * sizeof (char)); ! bzero (reg_significant, nregs * sizeof (HOST_WIDE_INT)); ! bzero (reg_sign_bit_copies, nregs * sizeof (char)); init_recog_no_volatile (); *************** *** 420,424 **** uid_cuid = (int *) alloca ((i + 1) * sizeof (int)); ! significant_mode = mode_for_size (HOST_BITS_PER_INT, MODE_INT, 0); /* Don't use reg_significant when computing it. This can cause problems --- 423,427 ---- uid_cuid = (int *) alloca ((i + 1) * sizeof (int)); ! significant_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0); /* Don't use reg_significant when computing it. This can cause problems *************** *** 463,467 **** for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! if ((next = try_combine (insn, XEXP (links, 0), 0)) != 0) goto retry; --- 466,470 ---- for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! if ((next = try_combine (insn, XEXP (links, 0), NULL_RTX)) != 0) goto retry; *************** *** 488,492 **** && sets_cc0_p (PATTERN (prev))) { ! if ((next = try_combine (insn, prev, 0)) != 0) goto retry; --- 491,495 ---- && sets_cc0_p (PATTERN (prev))) { ! if ((next = try_combine (insn, prev, NULL_RTX)) != 0) goto retry; *************** *** 506,510 **** && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn)))) { ! if ((next = try_combine (insn, prev, 0)) != 0) goto retry; --- 509,513 ---- && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn)))) { ! if ((next = try_combine (insn, prev, NULL_RTX)) != 0) goto retry; *************** *** 551,558 **** total_extras += combine_extras; total_successes += combine_successes; } /* Called via note_stores. If X is a pseudo that is used in more than ! one basic block, is narrower that HOST_BITS_PER_INT, and is being set, record what bits are significant. If we are clobbering X, ignore this "set" because the clobbered value won't be used. --- 554,563 ---- total_extras += combine_extras; total_successes += combine_successes; + + significant_valid = 0; } /* Called via note_stores. If X is a pseudo that is used in more than ! one basic block, is narrower that HOST_BITS_PER_WIDE_INT, and is being set, record what bits are significant. If we are clobbering X, ignore this "set" because the clobbered value won't be used. *************** *** 560,565 **** If we are setting only a portion of X and we can't figure out what portion, assume all bits will be used since we don't know what will ! be happening. */ static void set_significant (x, set) --- 565,574 ---- If we are setting only a portion of X and we can't figure out what portion, assume all bits will be used since we don't know what will ! be happening. + Similarly, set how many bits of X are known to be copies of the sign bit + at all locations in the function. This is the smallest number implied + by any set of X. */ + static void set_significant (x, set) *************** *** 567,575 **** rtx set; { if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_n_sets[REGNO (x)] > 1 && reg_basic_block[REGNO (x)] < 0 ! && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_INT) { if (GET_CODE (set) == CLOBBER) --- 576,586 ---- rtx set; { + int num; + if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_n_sets[REGNO (x)] > 1 && reg_basic_block[REGNO (x)] < 0 ! && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT) { if (GET_CODE (set) == CLOBBER) *************** *** 580,587 **** set = expand_field_assignment (set); if (SET_DEST (set) == x) ! reg_significant[REGNO (x)] ! |= significant_bits (SET_SRC (set), significant_mode); else ! reg_significant[REGNO (x)] = GET_MODE_MASK (GET_MODE (x)); } } --- 591,607 ---- set = expand_field_assignment (set); if (SET_DEST (set) == x) ! { ! reg_significant[REGNO (x)] ! |= significant_bits (SET_SRC (set), significant_mode); ! num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x)); ! if (reg_sign_bit_copies[REGNO (x)] == 0 ! || reg_sign_bit_copies[REGNO (x)] > num) ! reg_sign_bit_copies[REGNO (x)] = num; ! } else ! { ! reg_significant[REGNO (x)] = GET_MODE_MASK (GET_MODE (x)); ! reg_sign_bit_copies[REGNO (x)] = 0; ! } } } *************** *** 697,701 **** /* Don't combine with an insn that sets a register to itself if it has a REG_EQUAL note. This may be part of a REG_NO_CONFLICT sequence. */ ! || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, 0)) /* Can't merge a function call. */ || GET_CODE (src) == CALL --- 717,721 ---- /* Don't combine with an insn that sets a register to itself if it has a REG_EQUAL note. This may be part of a REG_NO_CONFLICT sequence. */ ! || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX)) /* Can't merge a function call. */ || GET_CODE (src) == CALL *************** *** 704,708 **** || (succ && FIND_REG_INC_NOTE (succ, dest)) /* Don't combine the end of a libcall into anything. */ ! || find_reg_note (insn, REG_RETVAL, 0) /* Make sure that DEST is not used after SUCC but before I3. */ || (succ && ! all_adjacent --- 724,728 ---- || (succ && FIND_REG_INC_NOTE (succ, dest)) /* Don't combine the end of a libcall into anything. */ ! || find_reg_note (insn, REG_RETVAL, NULL_RTX) /* Make sure that DEST is not used after SUCC but before I3. */ || (succ && ! all_adjacent *************** *** 757,765 **** return 0; ! /* Don't substitute for a register intended as a clobberable operand. */ if (GET_CODE (PATTERN (i3)) == PARALLEL) for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--) if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER ! && rtx_equal_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), dest)) return 0; --- 777,789 ---- return 0; ! /* Don't substitute for a register intended as a clobberable operand. ! Similarly, don't substitute an expression containing a register that ! will be clobbered in I3. */ if (GET_CODE (PATTERN (i3)) == PARALLEL) for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--) if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER ! && (reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), ! src) ! || rtx_equal_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), dest))) return 0; *************** *** 1003,1007 **** || GET_RTX_CLASS (GET_CODE (i2)) != 'i' || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i') ! || find_reg_note (i3, REG_LIBCALL, 0)) return 0; --- 1027,1031 ---- || GET_RTX_CLASS (GET_CODE (i2)) != 'i' || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i') ! || find_reg_note (i3, REG_LIBCALL, NULL_RTX)) return 0; *************** *** 1142,1147 **** /* Verify that I2 and I1 are valid for combining. */ ! if (! can_combine_p (i2, i3, i1, 0, &i2dest, &i2src) ! || (i1 && ! can_combine_p (i1, i3, 0, i2, &i1dest, &i1src))) { undo_all (); --- 1166,1171 ---- /* Verify that I2 and I1 are valid for combining. */ ! if (! can_combine_p (i2, i3, i1, NULL_RTX, &i2dest, &i2src) ! || (i1 && ! can_combine_p (i1, i3, NULL_RTX, i2, &i1dest, &i1src))) { undo_all (); *************** *** 1233,1237 **** subst_insn = i3; - subst_low_cuid = i1 ? INSN_CUID (i1) : INSN_CUID (i2); /* It is possible that the source of I2 or I1 may be performing an --- 1257,1260 ---- *************** *** 1255,1261 **** cases were is_replaced is checked. */ if (i1) ! i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0); else ! i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0); previous_num_undos = undobuf.num_undo; --- 1278,1290 ---- cases were is_replaced is checked. */ if (i1) ! { ! subst_low_cuid = INSN_CUID (i1); ! i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0); ! } else ! { ! subst_low_cuid = INSN_CUID (i2); ! i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0); ! } previous_num_undos = undobuf.num_undo; *************** *** 1296,1300 **** && (cc_use = find_single_use (SET_DEST (newpat), i3, &undobuf.other_insn)) ! && ((compare_mode = SELECT_CC_MODE (GET_CODE (*cc_use), i2src)) != GET_MODE (SET_DEST (newpat)))) { --- 1325,1330 ---- && (cc_use = find_single_use (SET_DEST (newpat), i3, &undobuf.other_insn)) ! && ((compare_mode = SELECT_CC_MODE (GET_CODE (*cc_use), ! i2src, const0_rtx)) != GET_MODE (SET_DEST (newpat)))) { *************** *** 1329,1332 **** --- 1359,1363 ---- to avoid self-referential rtl. */ + subst_low_cuid = INSN_CUID (i2); newpat = subst (PATTERN (i3), i2dest, i2src, 0, ! i1_feeds_i3 && i1dest_in_i1src); *************** *** 1346,1350 **** isn't mentioned in any SETs in NEWPAT that are field assignments. */ ! if (! combinable_i3pat (0, &newpat, i1dest, 0, 0, 0)) { undo_all (); --- 1377,1382 ---- isn't mentioned in any SETs in NEWPAT that are field assignments. */ ! if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX, ! 0, NULL_PTR)) { undo_all (); *************** *** 1353,1356 **** --- 1385,1389 ---- n_occurrences = 0; + subst_low_cuid = INSN_CUID (i1); newpat = subst (newpat, i1dest, i1src, 0, 0); previous_num_undos = undobuf.num_undo; *************** *** 1359,1365 **** /* Fail if an autoincrement side-effect has been duplicated. Be careful to count all the ways that I2SRC and I1SRC can be used. */ ! if ((FIND_REG_INC_NOTE (i2, 0) != 0 && i2_is_used + added_sets_2 > 1) ! || (i1 != 0 && FIND_REG_INC_NOTE (i1, 0) != 0 && (n_occurrences + added_sets_1 + (added_sets_2 && ! i1_feeds_i3) > 1)) --- 1392,1398 ---- /* Fail if an autoincrement side-effect has been duplicated. Be careful to count all the ways that I2SRC and I1SRC can be used. */ ! if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0 && i2_is_used + added_sets_2 > 1) ! || (i1 != 0 && FIND_REG_INC_NOTE (i1, NULL_RTX) != 0 && (n_occurrences + added_sets_1 + (added_sets_2 && ! i1_feeds_i3) > 1)) *************** *** 1460,1463 **** --- 1493,1522 ---- } + /* See if this is an XOR. If so, perhaps the problem is that the + constant is out of range. Replace it with a complemented XOR with + a complemented constant; it might be in range. */ + + else if (insn_code_number < 0 && GET_CODE (newpat) == SET + && GET_CODE (SET_SRC (newpat)) == XOR + && GET_CODE (XEXP (SET_SRC (newpat), 1)) == CONST_INT + && ((temp = simplify_unary_operation (NOT, + GET_MODE (SET_SRC (newpat)), + XEXP (SET_SRC (newpat), 1), + GET_MODE (SET_SRC (newpat)))) + != 0)) + { + enum machine_mode i_mode = GET_MODE (SET_SRC (newpat)); + rtx pat + = gen_rtx_combine (SET, VOIDmode, SET_DEST (newpat), + gen_unary (NOT, i_mode, + gen_binary (XOR, i_mode, + XEXP (SET_SRC (newpat), 0), + temp))); + + insn_code_number = recog_for_combine (&pat, i3, &new_i3_notes); + if (insn_code_number >= 0) + newpat = pat; + } + /* If we were combining three insns and the result is a simple SET with no ASM_OPERANDS that wasn't recognized, try to split it into two *************** *** 1470,1484 **** { rtx m_split, *split; /* See if the MD file can split NEWPAT. If it can't, see if letting it ! use I2DEST as a scratch register will help. */ m_split = split_insns (newpat, i3); if (m_split == 0) ! m_split = split_insns (gen_rtx (PARALLEL, VOIDmode, ! gen_rtvec (2, newpat, ! gen_rtx (CLOBBER, VOIDmode, ! i2dest))), ! i3); if (m_split && GET_CODE (m_split) == SEQUENCE --- 1529,1559 ---- { rtx m_split, *split; + rtx ni2dest = i2dest; /* See if the MD file can split NEWPAT. If it can't, see if letting it ! use I2DEST as a scratch register will help. In the latter case, ! convert I2DEST to the mode of the source of NEWPAT if we can. */ m_split = split_insns (newpat, i3); if (m_split == 0) ! { ! /* If I2DEST is a hard register or the only use of a pseudo, ! we can change its mode. */ ! if (GET_MODE (SET_DEST (newpat)) != GET_MODE (i2dest) ! && GET_MODE (SET_DEST (newpat)) != VOIDmode ! && GET_CODE (i2dest) == REG ! && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER ! || (reg_n_sets[REGNO (i2dest)] == 1 && ! added_sets_2 ! && ! REG_USERVAR_P (i2dest)))) ! ni2dest = gen_rtx (REG, GET_MODE (SET_DEST (newpat)), ! REGNO (i2dest)); ! ! m_split = split_insns (gen_rtx (PARALLEL, VOIDmode, ! gen_rtvec (2, newpat, ! gen_rtx (CLOBBER, ! VOIDmode, ! ni2dest))), ! i3); ! } if (m_split && GET_CODE (m_split) == SEQUENCE *************** *** 1488,1497 **** INSN_CUID (i2)))) { newi2pat = PATTERN (XVECEXP (m_split, 0, 0)); ! newpat = PATTERN (XVECEXP (m_split, 0, 1)); i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); ! if (i2_code_number >= 0) ! insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); } --- 1563,1599 ---- INSN_CUID (i2)))) { + rtx i2set, i3set; + rtx newi3pat = PATTERN (XVECEXP (m_split, 0, 1)); newi2pat = PATTERN (XVECEXP (m_split, 0, 0)); ! ! i3set = single_set (XVECEXP (m_split, 0, 1)); ! i2set = single_set (XVECEXP (m_split, 0, 0)); + /* In case we changed the mode of I2DEST, replace it in the + pseudo-register table here. We can't do it above in case this + code doesn't get executed and we do a split the other way. */ + + if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER) + SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest); + i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); ! ! /* If I2 or I3 has multiple SETs, we won't know how to track ! register status, so don't use these insns. */ ! ! if (i2_code_number >= 0 && i2set && i3set) ! insn_code_number = recog_for_combine (&newi3pat, i3, ! &new_i3_notes); ! ! if (insn_code_number >= 0) ! newpat = newi3pat; ! ! /* It is possible that both insns now set the destination of I3. ! If so, we must show an extra use of it. */ ! ! if (insn_code_number >= 0 && GET_CODE (SET_DEST (i3set)) == REG ! && GET_CODE (SET_DEST (i2set)) == REG ! && REGNO (SET_DEST (i3set)) == REGNO (SET_DEST (i2set))) ! reg_n_sets[REGNO (SET_DEST (i2set))]++; } *************** *** 1499,1503 **** helps things be recognized. Verify that none of the registers are set between I2 and I3. */ ! else if ((split = find_split_point (&newpat)) != 0 #ifdef HAVE_cc0 && GET_CODE (i2dest) == REG --- 1601,1605 ---- helps things be recognized. Verify that none of the registers are set between I2 and I3. */ ! if (insn_code_number < 0 && (split = find_split_point (&newpat, i3)) != 0 #ifdef HAVE_cc0 && GET_CODE (i2dest) == REG *************** *** 1536,1541 **** && (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0) SUBST (*split, gen_rtx_combine (ASHIFT, GET_MODE (*split), ! XEXP (*split, 0), ! gen_rtx (CONST_INT, VOIDmode, i))); #ifdef INSN_SCHEDULING --- 1638,1642 ---- && (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0) SUBST (*split, gen_rtx_combine (ASHIFT, GET_MODE (*split), ! XEXP (*split, 0), GEN_INT (i))); #ifdef INSN_SCHEDULING *************** *** 1580,1588 **** SET_DEST (XVECEXP (newpat, 0, 0)))) { newi2pat = XVECEXP (newpat, 0, 0); newpat = XVECEXP (newpat, 0, 1); SUBST (SET_SRC (newpat), ! gen_lowpart_for_combine (GET_MODE (SET_SRC (newpat)), ! SET_DEST (newi2pat))); i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); if (i2_code_number >= 0) --- 1681,1691 ---- SET_DEST (XVECEXP (newpat, 0, 0)))) { + rtx ni2dest; + newi2pat = XVECEXP (newpat, 0, 0); + ni2dest = SET_DEST (XVECEXP (newpat, 0, 0)); newpat = XVECEXP (newpat, 0, 1); SUBST (SET_SRC (newpat), ! gen_lowpart_for_combine (GET_MODE (SET_SRC (newpat)), ni2dest)); i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); if (i2_code_number >= 0) *************** *** 1604,1608 **** PATTERN (i3) = newpat; ! distribute_links (gen_rtx (INSN_LIST, VOIDmode, i3, 0)); /* I3 now uses what used to be its destination and which is --- 1707,1711 ---- PATTERN (i3) = newpat; ! distribute_links (gen_rtx (INSN_LIST, VOIDmode, i3, NULL_RTX)); /* I3 now uses what used to be its destination and which is *************** *** 1621,1625 **** { if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' ! && reg_referenced_p (SET_DEST (newi2pat), PATTERN (insn))) { for (link = LOG_LINKS (insn); link; --- 1724,1728 ---- { if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' ! && reg_referenced_p (ni2dest, PATTERN (insn))) { for (link = LOG_LINKS (insn); link; *************** *** 1704,1712 **** if (REG_NOTE_KIND (note) == REG_UNUSED && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn))) ! remove_note (undobuf.other_insn, note); } distribute_notes (new_other_notes, undobuf.other_insn, ! undobuf.other_insn, 0, 0, 0); } --- 1807,1824 ---- if (REG_NOTE_KIND (note) == REG_UNUSED && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn))) ! { ! if (GET_CODE (XEXP (note, 0)) == REG) ! reg_n_deaths[REGNO (XEXP (note, 0))]--; ! ! remove_note (undobuf.other_insn, note); ! } } + for (note = new_other_notes; note; note = XEXP (note, 1)) + if (GET_CODE (XEXP (note, 0)) == REG) + reg_n_deaths[REGNO (XEXP (note, 0))]++; + distribute_notes (new_other_notes, undobuf.other_insn, ! undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX); } *************** *** 1820,1850 **** /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */ if (i3notes) ! distribute_notes (i3notes, i3, i3, newi2pat ? i2 : 0, elim_i2, elim_i1); if (i2notes) ! distribute_notes (i2notes, i2, i3, newi2pat ? i2 : 0, elim_i2, elim_i1); if (i1notes) ! distribute_notes (i1notes, i1, i3, newi2pat ? i2 : 0, elim_i2, elim_i1); if (midnotes) ! distribute_notes (midnotes, 0, i3, newi2pat ? i2 : 0, elim_i2, elim_i1); /* Distribute any notes added to I2 or I3 by recog_for_combine. We know these are REG_UNUSED and want them to go to the desired insn, ! so we always pass it as i3. */ if (newi2pat && new_i2_notes) ! distribute_notes (new_i2_notes, i2, i2, 0, 0, 0); if (new_i3_notes) ! distribute_notes (new_i3_notes, i3, i3, 0, 0, 0); /* If I3DEST was used in I3SRC, it really died in I3. We may need to ! put a REG_DEAD note for it somewhere. Similarly for I2 and I1. */ if (i3dest_killed) ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i3dest_killed, 0), ! 0, i3, newi2pat ? i2 : 0, 0, 0); if (i2dest_in_i2src) ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, 0), ! 0, i3, newi2pat ? i2 : 0, 0, 0); if (i1dest_in_i1src) ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, 0), ! 0, i3, newi2pat ? i2 : 0, 0, 0); distribute_links (i3links); --- 1932,2017 ---- /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3. */ if (i3notes) ! distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL_RTX, ! elim_i2, elim_i1); if (i2notes) ! distribute_notes (i2notes, i2, i3, newi2pat ? i2 : NULL_RTX, ! elim_i2, elim_i1); if (i1notes) ! distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL_RTX, ! elim_i2, elim_i1); if (midnotes) ! distribute_notes (midnotes, NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, ! elim_i2, elim_i1); /* Distribute any notes added to I2 or I3 by recog_for_combine. We know these are REG_UNUSED and want them to go to the desired insn, ! so we always pass it as i3. We have not counted the notes in ! reg_n_deaths yet, so we need to do so now. */ ! if (newi2pat && new_i2_notes) ! { ! for (temp = new_i2_notes; temp; temp = XEXP (temp, 1)) ! if (GET_CODE (XEXP (temp, 0)) == REG) ! reg_n_deaths[REGNO (XEXP (temp, 0))]++; ! ! distribute_notes (new_i2_notes, i2, i2, NULL_RTX, NULL_RTX, NULL_RTX); ! } ! if (new_i3_notes) ! { ! for (temp = new_i3_notes; temp; temp = XEXP (temp, 1)) ! if (GET_CODE (XEXP (temp, 0)) == REG) ! reg_n_deaths[REGNO (XEXP (temp, 0))]++; ! ! distribute_notes (new_i3_notes, i3, i3, NULL_RTX, NULL_RTX, NULL_RTX); ! } /* If I3DEST was used in I3SRC, it really died in I3. We may need to ! put a REG_DEAD note for it somewhere. Similarly for I2 and I1. ! Show an additional death due to the REG_DEAD note we make here. If ! we discard it in distribute_notes, we will decrement it again. */ ! if (i3dest_killed) ! { ! if (GET_CODE (i3dest_killed) == REG) ! reg_n_deaths[REGNO (i3dest_killed)]++; ! ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i3dest_killed, ! NULL_RTX), ! NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, ! NULL_RTX, NULL_RTX); ! } ! ! /* For I2 and I1, we have to be careful. If NEWI2PAT exists and sets ! I2DEST or I1DEST, the death must be somewhere before I2, not I3. If ! we passed I3 in that case, it might delete I2. */ ! if (i2dest_in_i2src) ! { ! if (GET_CODE (i2dest) == REG) ! reg_n_deaths[REGNO (i2dest)]++; ! ! if (newi2pat && reg_set_p (i2dest, newi2pat)) ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, NULL_RTX), ! NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX); ! else ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, NULL_RTX), ! NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, ! NULL_RTX, NULL_RTX); ! } ! if (i1dest_in_i1src) ! { ! if (GET_CODE (i1dest) == REG) ! reg_n_deaths[REGNO (i1dest)]++; ! ! if (newi2pat && reg_set_p (i1dest, newi2pat)) ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, NULL_RTX), ! NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX); ! else ! distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, NULL_RTX), ! NULL_RTX, i3, newi2pat ? i2 : NULL_RTX, ! NULL_RTX, NULL_RTX); ! } distribute_links (i3links); *************** *** 1854,1865 **** if (GET_CODE (i2dest) == REG) { ! /* The insn that previously set this register doesn't exist, and ! this life of the register may not exist either. Show that ! we don't know its value any more. If we don't do this and ! I2 set the register to a value that depended on its old contents, we will get confused. If this insn is used, thing will be set correctly in combine_instructions. */ - record_value_for_reg (i2dest, 0, 0); /* If the reg formerly set in I2 died only once and that was in I3, zero its use count so it won't make `reload' do any work. */ --- 2021,2042 ---- if (GET_CODE (i2dest) == REG) { ! rtx link; ! rtx i2_insn = 0, i2_val = 0, set; ! ! /* The insn that used to set this register doesn't exist, and ! this life of the register may not exist either. See if one of ! I3's links points to an insn that sets I2DEST. If it does, ! that is now the last known value for I2DEST. If we don't update ! this and I2 set the register to a value that depended on its old contents, we will get confused. If this insn is used, thing will be set correctly in combine_instructions. */ + for (link = LOG_LINKS (i3); link; link = XEXP (link, 1)) + if ((set = single_set (XEXP (link, 0))) != 0 + && rtx_equal_p (i2dest, SET_DEST (set))) + i2_insn = XEXP (link, 0), i2_val = SET_SRC (set); + + record_value_for_reg (i2dest, i2_insn, i2_val); + /* If the reg formerly set in I2 died only once and that was in I3, zero its use count so it won't make `reload' do any work. */ *************** *** 1869,1874 **** reg_n_sets[regno]--; if (reg_n_sets[regno] == 0 ! && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT] ! & (1 << (regno % HOST_BITS_PER_INT)))) reg_n_refs[regno] = 0; } --- 2046,2051 ---- reg_n_sets[regno]--; if (reg_n_sets[regno] == 0 ! && ! (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)))) reg_n_refs[regno] = 0; } *************** *** 1877,1881 **** if (i1 && GET_CODE (i1dest) == REG) { ! record_value_for_reg (i1dest, 0, 0); regno = REGNO (i1dest); if (! added_sets_1) --- 2054,2067 ---- if (i1 && GET_CODE (i1dest) == REG) { ! rtx link; ! rtx i1_insn = 0, i1_val = 0, set; ! ! for (link = LOG_LINKS (i3); link; link = XEXP (link, 1)) ! if ((set = single_set (XEXP (link, 0))) != 0 ! && rtx_equal_p (i1dest, SET_DEST (set))) ! i1_insn = XEXP (link, 0), i1_val = SET_SRC (set); ! ! record_value_for_reg (i1dest, i1_insn, i1_val); ! regno = REGNO (i1dest); if (! added_sets_1) *************** *** 1883,1892 **** reg_n_sets[regno]--; if (reg_n_sets[regno] == 0 ! && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT] ! & (1 << (regno % HOST_BITS_PER_INT)))) reg_n_refs[regno] = 0; } } /* If I3 is now an unconditional jump, ensure that it has a BARRIER following it since it may have initially been a --- 2069,2085 ---- reg_n_sets[regno]--; if (reg_n_sets[regno] == 0 ! && ! (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)))) reg_n_refs[regno] = 0; } } + /* Update reg_significant et al for any changes that may have been made + to this insn. */ + + note_stores (newpat, set_significant); + if (newi2pat) + note_stores (newi2pat, set_significant); + /* If I3 is now an unconditional jump, ensure that it has a BARRIER following it since it may have initially been a *************** *** 1912,1916 **** undobuf.num_undo = MAX_UNDO; for (i = undobuf.num_undo - 1; i >= 0; i--) ! *undobuf.undo[i].where = undobuf.undo[i].old_contents; obfree (undobuf.storage); --- 2105,2115 ---- undobuf.num_undo = MAX_UNDO; for (i = undobuf.num_undo - 1; i >= 0; i--) ! { ! if (undobuf.undo[i].is_int) ! *undobuf.undo[i].where.i = undobuf.undo[i].old_contents.i; ! else ! *undobuf.undo[i].where.rtx = undobuf.undo[i].old_contents.rtx; ! ! } obfree (undobuf.storage); *************** *** 1919,1923 **** /* Find the innermost point within the rtx at LOC, possibly LOC itself, ! where we have an arithmetic expression and return that point. try_combine will call this function to see if an insn can be split into --- 2118,2123 ---- /* Find the innermost point within the rtx at LOC, possibly LOC itself, ! where we have an arithmetic expression and return that point. LOC will ! be inside INSN. try_combine will call this function to see if an insn can be split into *************** *** 1925,1930 **** static rtx * ! find_split_point (loc) rtx *loc; { rtx x = *loc; --- 2125,2131 ---- static rtx * ! find_split_point (loc, insn) rtx *loc; + rtx insn; { rtx x = *loc; *************** *** 1944,1948 **** return loc; #endif ! return find_split_point (&SUBREG_REG (x)); case MEM: --- 2145,2149 ---- return loc; #endif ! return find_split_point (&SUBREG_REG (x), insn); case MEM: *************** *** 2013,2016 **** --- 2214,2228 ---- } } + + /* If that didn't work, perhaps the first operand is complex and + needs to be computed separately, so make a split point there. + This will occur on machines that just support REG + CONST + and have a constant moved through some previous computation. */ + + else if (GET_RTX_CLASS (GET_CODE (XEXP (XEXP (x, 0), 0))) != 'o' + && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG + && (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (XEXP (x, 0), 0)))) + == 'o'))) + return &XEXP (XEXP (x, 0), 0); } break; *************** *** 2033,2037 **** /* See if we can split SET_SRC as it stands. */ ! split = find_split_point (&SET_SRC (x)); if (split && split != &SET_SRC (x)) return split; --- 2245,2249 ---- /* See if we can split SET_SRC as it stands. */ ! split = find_split_point (&SET_SRC (x), insn); if (split && split != &SET_SRC (x)) return split; *************** *** 2041,2045 **** if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT && (GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0))) ! <= HOST_BITS_PER_INT) && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT && GET_CODE (XEXP (SET_DEST (x), 2)) == CONST_INT --- 2253,2257 ---- if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT && (GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0))) ! <= HOST_BITS_PER_WIDE_INT) && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT && GET_CODE (XEXP (SET_DEST (x), 2)) == CONST_INT *************** *** 2055,2059 **** rtx dest = XEXP (SET_DEST (x), 0); enum machine_mode mode = GET_MODE (dest); ! unsigned int mask = (1 << len) - 1; #if BITS_BIG_ENDIAN --- 2267,2271 ---- rtx dest = XEXP (SET_DEST (x), 0); enum machine_mode mode = GET_MODE (dest); ! unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1; #if BITS_BIG_ENDIAN *************** *** 2063,2080 **** if (src == mask) SUBST (SET_SRC (x), ! gen_binary (IOR, mode, dest, ! gen_rtx (CONST_INT, VOIDmode, src << pos))); else SUBST (SET_SRC (x), gen_binary (IOR, mode, gen_binary (AND, mode, dest, ! gen_rtx (CONST_INT, VOIDmode, ! (~ (mask << pos) ! & GET_MODE_MASK (mode)))), ! gen_rtx (CONST_INT, VOIDmode, src << pos))); SUBST (SET_DEST (x), dest); ! split = find_split_point (&SET_SRC (x)); if (split && split != &SET_SRC (x)) return split; --- 2275,2290 ---- if (src == mask) SUBST (SET_SRC (x), ! gen_binary (IOR, mode, dest, GEN_INT (src << pos))); else SUBST (SET_SRC (x), gen_binary (IOR, mode, gen_binary (AND, mode, dest, ! GEN_INT (~ (mask << pos) ! & GET_MODE_MASK (mode))), ! GEN_INT (src << pos))); SUBST (SET_DEST (x), dest); ! split = find_split_point (&SET_SRC (x), insn); if (split && split != &SET_SRC (x)) return split; *************** *** 2087,2090 **** --- 2297,2327 ---- switch (code) { + case AND: + /* If we are AND'ing with a large constant that is only a single + bit and the result is only being used in a context where we + need to know if it is zero or non-zero, replace it with a bit + extraction. This will avoid the large constant, which might + have taken more than one insn to make. If the constant were + not a valid argument to the AND but took only one insn to make, + this is no worse, but if it took more than one insn, it will + be better. */ + + if (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT + && GET_CODE (XEXP (SET_SRC (x), 0)) == REG + && (pos = exact_log2 (INTVAL (XEXP (SET_SRC (x), 1)))) >= 7 + && GET_CODE (SET_DEST (x)) == REG + && (split = find_single_use (SET_DEST (x), insn, NULL_PTR)) != 0 + && (GET_CODE (*split) == EQ || GET_CODE (*split) == NE) + && XEXP (*split, 0) == SET_DEST (x) + && XEXP (*split, 1) == const0_rtx) + { + SUBST (SET_SRC (x), + make_extraction (GET_MODE (SET_DEST (x)), + XEXP (SET_SRC (x), 0), + pos, NULL_RTX, 1, 1, 0, 0)); + return find_split_point (loc, insn); + } + break; + case SIGN_EXTEND: inner = XEXP (SET_SRC (x), 0); *************** *** 2115,2119 **** enum machine_mode mode = GET_MODE (SET_SRC (x)); ! if (unsignedp && len < HOST_BITS_PER_INT) { SUBST (SET_SRC (x), --- 2352,2362 ---- enum machine_mode mode = GET_MODE (SET_SRC (x)); ! /* For unsigned, we have a choice of a shift followed by an ! AND or two shifts. Use two shifts for field sizes where the ! constant might be too large. We assume here that we can ! always at least get 8-bit constants in an AND insn, which is ! true for every current RISC. */ ! ! if (unsignedp && len <= 8) { SUBST (SET_SRC (x), *************** *** 2122,2129 **** gen_rtx_combine (LSHIFTRT, mode, gen_lowpart_for_combine (mode, inner), ! gen_rtx (CONST_INT, VOIDmode, pos)), ! gen_rtx (CONST_INT, VOIDmode, (1 << len) - 1))); ! split = find_split_point (&SET_SRC (x)); if (split && split != &SET_SRC (x)) return split; --- 2365,2372 ---- gen_rtx_combine (LSHIFTRT, mode, gen_lowpart_for_combine (mode, inner), ! GEN_INT (pos)), ! GEN_INT (((HOST_WIDE_INT) 1 << len) - 1))); ! split = find_split_point (&SET_SRC (x), insn); if (split && split != &SET_SRC (x)) return split; *************** *** 2133,2146 **** SUBST (SET_SRC (x), gen_rtx_combine ! (ASHIFTRT, mode, gen_rtx_combine (ASHIFT, mode, gen_lowpart_for_combine (mode, inner), ! gen_rtx (CONST_INT, VOIDmode, ! (GET_MODE_BITSIZE (mode) ! - len - pos))), ! gen_rtx (CONST_INT, VOIDmode, ! GET_MODE_BITSIZE (mode) - len))); ! split = find_split_point (&SET_SRC (x)); if (split && split != &SET_SRC (x)) return split; --- 2376,2387 ---- SUBST (SET_SRC (x), gen_rtx_combine ! (unsignedp ? LSHIFTRT : ASHIFTRT, mode, gen_rtx_combine (ASHIFT, mode, gen_lowpart_for_combine (mode, inner), ! GEN_INT (GET_MODE_BITSIZE (mode) ! - len - pos)), ! GEN_INT (GET_MODE_BITSIZE (mode) - len))); ! split = find_split_point (&SET_SRC (x), insn); if (split && split != &SET_SRC (x)) return split; *************** *** 2188,2192 **** XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 1), 0)))); ! return find_split_point (loc); } --- 2429,2433 ---- XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 1), 0)))); ! return find_split_point (loc, insn); } *************** *** 2208,2212 **** case 'b': /* This is ZERO_EXTRACT and SIGN_EXTRACT. */ case '3': ! split = find_split_point (&XEXP (x, 2)); if (split) return split; --- 2449,2453 ---- case 'b': /* This is ZERO_EXTRACT and SIGN_EXTRACT. */ case '3': ! split = find_split_point (&XEXP (x, 2), insn); if (split) return split; *************** *** 2215,2219 **** case 'c': case '<': ! split = find_split_point (&XEXP (x, 1)); if (split) return split; --- 2456,2460 ---- case 'c': case '<': ! split = find_split_point (&XEXP (x, 1), insn); if (split) return split; *************** *** 2225,2229 **** return &XEXP (x, 0); ! split = find_split_point (&XEXP (x, 0)); if (split) return split; --- 2466,2470 ---- return &XEXP (x, 0); ! split = find_split_point (&XEXP (x, 0), insn); if (split) return split; *************** *** 2403,2406 **** --- 2644,2667 ---- } + /* We come back to here if we have replaced the expression with one of + a different code and it is likely that further simplification will be + possible. */ + + restart: + + /* If we have restarted more than 4 times, we are probably looping, so + give up. */ + if (++n_restarts > 4) + return x; + + /* If we are restarting at all, it means that we no longer know the + original mode of operand 0 (since we have probably changed the + form of X). */ + + if (n_restarts > 1) + op0_mode = VOIDmode; + + code = GET_CODE (x); + /* If this is a commutative operation, put a constant last and a complex expression first. We don't need to do this for comparisons here. */ *************** *** 2418,2421 **** --- 2679,2759 ---- } + /* If this is a PLUS, MINUS, or MULT, and the first operand is the + sign extension of a PLUS with a constant, reverse the order of the sign + extension and the addition. Note that this not the same as the original + code, but overflow is undefined for signed values. Also note that the + PLUS will have been partially moved "inside" the sign-extension, so that + the first operand of X will really look like: + (ashiftrt (plus (ashift A C4) C5) C4). + We convert this to + (plus (ashiftrt (ashift A C4) C2) C4) + and replace the first operand of X with that expression. Later parts + of this function may simplify the expression further. + + For example, if we start with (mult (sign_extend (plus A C1)) C2), + we swap the SIGN_EXTEND and PLUS. Later code will apply the + distributive law to produce (plus (mult (sign_extend X) C1) C3). + + We do this to simplify address expressions. */ + + if ((code == PLUS || code == MINUS || code == MULT) + && GET_CODE (XEXP (x, 0)) == ASHIFTRT + && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS + && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ASHIFT + && GET_CODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 1)) == CONST_INT + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT + && XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 1) == XEXP (XEXP (x, 0), 1) + && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT + && (temp = simplify_binary_operation (ASHIFTRT, mode, + XEXP (XEXP (XEXP (x, 0), 0), 1), + XEXP (XEXP (x, 0), 1))) != 0) + { + rtx new + = simplify_shift_const (NULL_RTX, ASHIFT, mode, + XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0), + INTVAL (XEXP (XEXP (x, 0), 1))); + + new = simplify_shift_const (NULL_RTX, ASHIFTRT, mode, new, + INTVAL (XEXP (XEXP (x, 0), 1))); + + SUBST (XEXP (x, 0), gen_binary (PLUS, mode, new, temp)); + } + + /* If this is a simple operation applied to an IF_THEN_ELSE, try + applying it to the arms of the IF_THEN_ELSE. This often simplifies + things. Don't deal with operations that change modes here. */ + + if ((GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c') + && GET_CODE (XEXP (x, 0)) == IF_THEN_ELSE) + { + /* Don't do this by using SUBST inside X since we might be messing + up a shared expression. */ + rtx cond = XEXP (XEXP (x, 0), 0); + rtx t_arm = subst (gen_binary (code, mode, XEXP (XEXP (x, 0), 1), + XEXP (x, 1)), + pc_rtx, pc_rtx, 0, 0); + rtx f_arm = subst (gen_binary (code, mode, XEXP (XEXP (x, 0), 2), + XEXP (x, 1)), + pc_rtx, pc_rtx, 0, 0); + + + x = gen_rtx (IF_THEN_ELSE, mode, cond, t_arm, f_arm); + goto restart; + } + + else if (GET_RTX_CLASS (code) == '1' + && GET_CODE (XEXP (x, 0)) == IF_THEN_ELSE + && GET_MODE (XEXP (x, 0)) == mode) + { + rtx cond = XEXP (XEXP (x, 0), 0); + rtx t_arm = subst (gen_unary (code, mode, XEXP (XEXP (x, 0), 1)), + pc_rtx, pc_rtx, 0, 0); + rtx f_arm = subst (gen_unary (code, mode, XEXP (XEXP (x, 0), 2)), + pc_rtx, pc_rtx, 0, 0); + + x = gen_rtx_combine (IF_THEN_ELSE, mode, cond, t_arm, f_arm); + goto restart; + } + /* Try to fold this expression in case we have constants that weren't present before. */ *************** *** 2429,2432 **** --- 2767,2775 ---- temp = simplify_relational_operation (code, op0_mode, XEXP (x, 0), XEXP (x, 1)); + #ifdef FLOAT_STORE_FLAG_VALUE + if (temp != 0 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) + temp = ((temp == const0_rtx) ? CONST0_RTX (GET_MODE (x)) + : immed_real_const_1 (FLOAT_STORE_FLAG_VALUE, GET_MODE (x))); + #endif break; case 'c': *************** *** 2442,2459 **** if (temp) ! x = temp; ! ! /* We come back to here if we have replaced the expression with one of ! a different code and it is likely that further simplification will be ! possible. */ ! ! restart: ! ! /* If we have restarted more than 4 times, we are probably looping, so ! give up. */ ! if (++n_restarts > 4) ! return x; ! ! code = GET_CODE (x); /* First see if we can apply the inverse distributive law. */ --- 2785,2789 ---- if (temp) ! x = temp, code = GET_CODE (temp); /* First see if we can apply the inverse distributive law. */ *************** *** 2577,2584 **** /* SUBREG of a hard register => just change the register number and/or mode. If the hard register is not valid in that mode, ! suppress this combination. */ if (GET_CODE (SUBREG_REG (x)) == REG ! && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER) { if (HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (x)) + SUBREG_WORD (x), --- 2907,2920 ---- /* SUBREG of a hard register => just change the register number and/or mode. If the hard register is not valid in that mode, ! suppress this combination. If the hard register is the stack, ! frame, or argument pointer, leave this as a SUBREG. */ if (GET_CODE (SUBREG_REG (x)) == REG ! && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER ! && REGNO (SUBREG_REG (x)) != FRAME_POINTER_REGNUM ! #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM ! && REGNO (SUBREG_REG (x)) != ARG_POINTER_REGNUM ! #endif ! && REGNO (SUBREG_REG (x)) != STACK_POINTER_REGNUM) { if (HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (x)) + SUBREG_WORD (x), *************** *** 2601,2605 **** { temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x), ! 0, op0_mode); if (temp) return temp; --- 2937,2941 ---- { temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x), ! 0, op0_mode); if (temp) return temp; *************** *** 2612,2632 **** /* If we are narrowing the object, we need to see if we can simplify the expression for the object knowing that we only need the ! low-order bits. We do this by computing an AND of the object ! with only the bits we care about. That will produce any needed ! simplifications. If the resulting computation is just the ! AND with the significant bits, our operand is the first operand ! of the AND. Otherwise, it is the resulting expression. */ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) ! && subreg_lowpart_p (x) ! && GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= HOST_BITS_PER_INT) ! { ! temp = simplify_and_const_int (0, GET_MODE (SUBREG_REG (x)), ! SUBREG_REG (x), GET_MODE_MASK (mode)); ! if (GET_CODE (temp) == AND && GET_CODE (XEXP (temp, 1)) == CONST_INT ! && INTVAL (XEXP (temp, 1)) == GET_MODE_MASK (mode)) ! temp = XEXP (temp, 0); ! return gen_lowpart_for_combine (mode, temp); ! } ! break; --- 2948,2957 ---- /* If we are narrowing the object, we need to see if we can simplify the expression for the object knowing that we only need the ! low-order bits. */ ! if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) ! && subreg_lowpart_p (x)) ! return force_to_mode (SUBREG_REG (x), mode, GET_MODE_BITSIZE (mode), ! NULL_RTX); break; *************** *** 2647,2650 **** --- 2972,2986 ---- } + /* (not (xor X C)) for C constant is (xor X D) with D = ~ C. */ + if (GET_CODE (XEXP (x, 0)) == XOR + && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT + && (temp = simplify_unary_operation (NOT, mode, + XEXP (XEXP (x, 0), 1), + mode)) != 0) + { + SUBST (XEXP (XEXP (x, 0), 1), temp); + return XEXP (x, 0); + } + /* (not (ashift 1 X)) is (rotate ~1 X). We used to do this for operands other than 1, but that is not valid. We could do a similar *************** *** 2702,2708 **** in2 = XEXP (in2, 0); else if (GET_CODE (in2) == CONST_INT ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT) ! in2 = gen_rtx (CONST_INT, VOIDmode, ! GET_MODE_MASK (mode) & ~ INTVAL (in2)); else in2 = gen_rtx_combine (NOT, GET_MODE (in2), in2); --- 3038,3043 ---- in2 = XEXP (in2, 0); else if (GET_CODE (in2) == CONST_INT ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) ! in2 = GEN_INT (GET_MODE_MASK (mode) & ~ INTVAL (in2)); else in2 = gen_rtx_combine (NOT, GET_MODE (in2), in2); *************** *** 2736,2756 **** } - /* (neg (abs X)) is X if X is a value known to be either -1 or 0. */ - if (GET_CODE (XEXP (x, 0)) == ABS - && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTRACT - && XEXP (XEXP (XEXP (x, 0), 0), 1) == const1_rtx) - || (GET_CODE (XEXP (XEXP (x, 0), 0)) == ASHIFTRT - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT - && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) - == GET_MODE_BITSIZE (mode) - 1)) - || ((temp = get_last_value (XEXP (XEXP (x, 0), 0))) != 0 - && ((GET_CODE (temp) == SIGN_EXTRACT - && XEXP (temp, 1) == const1_rtx) - || (GET_CODE (temp) == ASHIFTRT - && GET_CODE (XEXP (temp, 1)) == CONST_INT - && (INTVAL (XEXP (temp, 1)) - == GET_MODE_BITSIZE (mode) - 1)))))) - return XEXP (XEXP (x, 0), 0); - /* (neg (minus X Y)) can become (minus Y X). */ if (GET_CODE (XEXP (x, 0)) == MINUS --- 3071,3074 ---- *************** *** 2764,2767 **** --- 3082,3093 ---- } + /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */ + if (GET_CODE (XEXP (x, 0)) == XOR && XEXP (XEXP (x, 0), 1) == const1_rtx + && significant_bits (XEXP (XEXP (x, 0), 0), mode) == 1) + { + x = gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx); + goto restart; + } + /* NEG commutes with ASHIFT since it is multiplication. Only do this if we can then eliminate the NEG (e.g., *************** *** 2807,2812 **** { rtx temp1 = simplify_shift_const ! (0, ASHIFTRT, mode, ! simplify_shift_const (0, ASHIFT, mode, temp, GET_MODE_BITSIZE (mode) - 1 - i), GET_MODE_BITSIZE (mode) - 1 - i); --- 3133,3138 ---- { rtx temp1 = simplify_shift_const ! (NULL_RTX, ASHIFTRT, mode, ! simplify_shift_const (NULL_RTX, ASHIFT, mode, temp, GET_MODE_BITSIZE (mode) - 1 - i), GET_MODE_BITSIZE (mode) - 1 - i); *************** *** 2888,2896 **** && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (XEXP (x, 0), 1)) && (i = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) >= 0 ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == AND && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) ! == (1 << (i + 1)) - 1)) || (GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND && (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0))) --- 3214,3222 ---- && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (XEXP (x, 0), 1)) && (i = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) >= 0 ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == AND && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) ! == ((HOST_WIDE_INT) 1 << (i + 1)) - 1)) || (GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND && (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0))) *************** *** 2898,2903 **** { x = simplify_shift_const ! (0, ASHIFTRT, mode, ! simplify_shift_const (0, ASHIFT, mode, XEXP (XEXP (XEXP (x, 0), 0), 0), GET_MODE_BITSIZE (mode) - (i + 1)), --- 3224,3229 ---- { x = simplify_shift_const ! (NULL_RTX, ASHIFTRT, mode, ! simplify_shift_const (NULL_RTX, ASHIFT, mode, XEXP (XEXP (XEXP (x, 0), 0), 0), GET_MODE_BITSIZE (mode) - (i + 1)), *************** *** 2917,2922 **** { x = simplify_shift_const ! (0, ASHIFTRT, mode, ! simplify_shift_const (0, ASHIFT, mode, gen_rtx_combine (XOR, mode, XEXP (x, 0), const1_rtx), --- 3243,3248 ---- { x = simplify_shift_const ! (NULL_RTX, ASHIFTRT, mode, ! simplify_shift_const (NULL_RTX, ASHIFT, mode, gen_rtx_combine (XOR, mode, XEXP (x, 0), const1_rtx), *************** *** 2925,2928 **** --- 3251,3266 ---- goto restart; } + + /* If we are adding two things that have no bits in common, convert + the addition into an IOR. This will often be further simplified, + for example in cases like ((a & 1) + (a & 2)), which can + become a & 3. */ + + if ((significant_bits (XEXP (x, 0), mode) + & significant_bits (XEXP (x, 1), mode)) == 0) + { + x = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); + goto restart; + } break; *************** *** 2935,2939 **** && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0))) { ! x = simplify_and_const_int (0, mode, XEXP (x, 0), - INTVAL (XEXP (XEXP (x, 1), 1)) - 1); goto restart; --- 3273,3277 ---- && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0))) { ! x = simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0), - INTVAL (XEXP (XEXP (x, 1), 1)) - 1); goto restart; *************** *** 2970,2974 **** || GET_CODE (XEXP (x, 0)) == ROTATERT)) { ! x = simplify_shift_const (0, ASHIFT, mode, XEXP (x, 0), i); goto restart; } --- 3308,3312 ---- || GET_CODE (XEXP (x, 0)) == ROTATERT)) { ! x = simplify_shift_const (NULL_RTX, ASHIFT, mode, XEXP (x, 0), i); goto restart; } *************** *** 2992,2996 **** || GET_CODE (XEXP (x, 0)) == ROTATERT)) { ! x = simplify_shift_const (0, LSHIFTRT, mode, XEXP (x, 0), i); goto restart; } --- 3330,3334 ---- || GET_CODE (XEXP (x, 0)) == ROTATERT)) { ! x = simplify_shift_const (NULL_RTX, LSHIFTRT, mode, XEXP (x, 0), i); goto restart; } *************** *** 3057,3067 **** test the sign bit. */ if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! && STORE_FLAG_VALUE == 1 << (GET_MODE_BITSIZE (mode) - 1) && op1 == const0_rtx && mode == GET_MODE (op0) && (i = exact_log2 (significant_bits (op0, GET_MODE (op0)))) >= 0) { ! x = simplify_shift_const (0, ASHIFT, mode, op0, GET_MODE_BITSIZE (mode) - 1 - i); if (GET_CODE (x) == AND && XEXP (x, 1) == const_true_rtx) --- 3395,3406 ---- test the sign bit. */ if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT ! && (STORE_FLAG_VALUE ! == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) && op1 == const0_rtx && mode == GET_MODE (op0) && (i = exact_log2 (significant_bits (op0, GET_MODE (op0)))) >= 0) { ! x = simplify_shift_const (NULL_RTX, ASHIFT, mode, op0, GET_MODE_BITSIZE (mode) - 1 - i); if (GET_CODE (x) == AND && XEXP (x, 1) == const_true_rtx) *************** *** 3083,3100 **** case IF_THEN_ELSE: /* If we have (if_then_else FOO (pc) (label_ref BAR)) and FOO can be reversed, do so to avoid needing two sets of patterns for ! subtract-and-branch insns. */ ! if (XEXP (x, 1) == pc_rtx ! && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' ! && reversible_comparison_p (XEXP (x, 0))) { SUBST (XEXP (x, 0), ! gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))), ! GET_MODE (XEXP (x, 0)), ! XEXP (XEXP (x, 0), 0), ! XEXP (XEXP (x, 0), 1))); SUBST (XEXP (x, 1), XEXP (x, 2)); ! SUBST (XEXP (x, 2), pc_rtx); } break; --- 3422,3642 ---- case IF_THEN_ELSE: + /* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register + used in it is being compared against certain values. Get the + true and false comparisons and see if that says anything about the + value of each arm. */ + + if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' + && reversible_comparison_p (XEXP (x, 0)) + && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG) + { + HOST_WIDE_INT sig; + rtx from = XEXP (XEXP (x, 0), 0); + enum rtx_code true_code = GET_CODE (XEXP (x, 0)); + enum rtx_code false_code = reverse_condition (true_code); + rtx true_val = XEXP (XEXP (x, 0), 1); + rtx false_val = true_val; + rtx true_arm = XEXP (x, 1); + rtx false_arm = XEXP (x, 2); + int swapped = 0; + + /* If FALSE_CODE is EQ, swap the codes and arms. */ + + if (false_code == EQ) + { + swapped = 1, true_code = EQ, false_code = NE; + true_arm = XEXP (x, 2), false_arm = XEXP (x, 1); + } + + /* If we are comparing against zero and the expression being tested + has only a single significant bit, that is its value when it is + not equal to zero. Similarly if it is known to be -1 or 0. */ + + if (true_code == EQ && true_val == const0_rtx + && exact_log2 (sig = significant_bits (from, + GET_MODE (from))) >= 0) + false_code = EQ, false_val = GEN_INT (sig); + else if (true_code == EQ && true_val == const0_rtx + && (num_sign_bit_copies (from, GET_MODE (from)) + == GET_MODE_BITSIZE (GET_MODE (from)))) + false_code = EQ, false_val = constm1_rtx; + + /* Now simplify an arm if we know the value of the register + in the branch and it is used in the arm. Be carefull due to + the potential of locally-shared RTL. */ + + if (reg_mentioned_p (from, true_arm)) + true_arm = subst (known_cond (copy_rtx (true_arm), true_code, + from, true_val), + pc_rtx, pc_rtx, 0, 0); + if (reg_mentioned_p (from, false_arm)) + false_arm = subst (known_cond (copy_rtx (false_arm), false_code, + from, false_val), + pc_rtx, pc_rtx, 0, 0); + + SUBST (XEXP (x, 1), swapped ? false_arm : true_arm); + SUBST (XEXP (x, 2), swapped ? true_arm : false_arm); + } + /* If we have (if_then_else FOO (pc) (label_ref BAR)) and FOO can be reversed, do so to avoid needing two sets of patterns for ! subtract-and-branch insns. Similarly if we have a constant in that ! position or if the third operand is the same as the first operand ! of the comparison. */ ! ! if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' ! && reversible_comparison_p (XEXP (x, 0)) ! && (XEXP (x, 1) == pc_rtx || GET_CODE (XEXP (x, 1)) == CONST_INT ! || rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0)))) { SUBST (XEXP (x, 0), ! gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))), ! GET_MODE (XEXP (x, 0)), ! XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 1))); ! ! temp = XEXP (x, 1); SUBST (XEXP (x, 1), XEXP (x, 2)); ! SUBST (XEXP (x, 2), temp); ! } ! ! /* If the two arms are identical, we don't need the comparison. */ ! ! if (rtx_equal_p (XEXP (x, 1), XEXP (x, 2)) ! && ! side_effects_p (XEXP (x, 0))) ! return XEXP (x, 1); ! ! /* Look for cases where we have (abs x) or (neg (abs X)). */ ! ! if (GET_MODE_CLASS (mode) == MODE_INT ! && GET_CODE (XEXP (x, 2)) == NEG ! && rtx_equal_p (XEXP (x, 1), XEXP (XEXP (x, 2), 0)) ! && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' ! && rtx_equal_p (XEXP (x, 1), XEXP (XEXP (x, 0), 0)) ! && ! side_effects_p (XEXP (x, 1))) ! switch (GET_CODE (XEXP (x, 0))) ! { ! case GT: ! case GE: ! x = gen_unary (ABS, mode, XEXP (x, 1)); ! goto restart; ! case LT: ! case LE: ! x = gen_unary (NEG, mode, gen_unary (ABS, mode, XEXP (x, 1))); ! goto restart; ! } ! ! /* Look for MIN or MAX. */ ! ! if (GET_MODE_CLASS (mode) == MODE_INT ! && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' ! && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1)) ! && rtx_equal_p (XEXP (XEXP (x, 0), 1), XEXP (x, 2)) ! && ! side_effects_p (XEXP (x, 0))) ! switch (GET_CODE (XEXP (x, 0))) ! { ! case GE: ! case GT: ! x = gen_binary (SMAX, mode, XEXP (x, 1), XEXP (x, 2)); ! goto restart; ! case LE: ! case LT: ! x = gen_binary (SMIN, mode, XEXP (x, 1), XEXP (x, 2)); ! goto restart; ! case GEU: ! case GTU: ! x = gen_binary (UMAX, mode, XEXP (x, 1), XEXP (x, 2)); ! goto restart; ! case LEU: ! case LTU: ! x = gen_binary (UMIN, mode, XEXP (x, 1), XEXP (x, 2)); ! goto restart; ! } ! ! /* If we have something like (if_then_else (ne A 0) (OP X C) X), ! A is known to be either 0 or 1, and OP is an identity when its ! second operand is zero, this can be done as (OP X (mult A C)). ! Similarly if A is known to be 0 or -1 and also similarly if we have ! a ZERO_EXTEND or SIGN_EXTEND as long as X is already extended (so ! we don't destroy it). */ ! ! if (mode != VOIDmode ! && (GET_CODE (XEXP (x, 0)) == EQ || GET_CODE (XEXP (x, 0)) == NE) ! && XEXP (XEXP (x, 0), 1) == const0_rtx ! && (significant_bits (XEXP (XEXP (x, 0), 0), mode) == 1 ! || (num_sign_bit_copies (XEXP (XEXP (x, 0), 0), mode) ! == GET_MODE_BITSIZE (mode)))) ! { ! rtx nz = make_compound_operation (GET_CODE (XEXP (x, 0)) == NE ! ? XEXP (x, 1) : XEXP (x, 2)); ! rtx z = GET_CODE (XEXP (x, 0)) == NE ? XEXP (x, 2) : XEXP (x, 1); ! rtx dir = (significant_bits (XEXP (XEXP (x, 0), 0), mode) == 1 ! ? const1_rtx : constm1_rtx); ! rtx c = 0; ! enum machine_mode m = mode; ! enum rtx_code op, extend_op = 0; ! ! if ((GET_CODE (nz) == PLUS || GET_CODE (nz) == MINUS ! || GET_CODE (nz) == IOR || GET_CODE (nz) == XOR ! || GET_CODE (nz) == ASHIFT ! || GET_CODE (nz) == LSHIFTRT || GET_CODE (nz) == ASHIFTRT) ! && rtx_equal_p (XEXP (nz, 0), z)) ! c = XEXP (nz, 1), op = GET_CODE (nz); ! else if (GET_CODE (nz) == SIGN_EXTEND ! && (GET_CODE (XEXP (nz, 0)) == PLUS ! || GET_CODE (XEXP (nz, 0)) == MINUS ! || GET_CODE (XEXP (nz, 0)) == IOR ! || GET_CODE (XEXP (nz, 0)) == XOR ! || GET_CODE (XEXP (nz, 0)) == ASHIFT ! || GET_CODE (XEXP (nz, 0)) == LSHIFTRT ! || GET_CODE (XEXP (nz, 0)) == ASHIFTRT) ! && GET_CODE (XEXP (XEXP (nz, 0), 0)) == SUBREG ! && subreg_lowpart_p (XEXP (XEXP (nz, 0), 0)) ! && rtx_equal_p (SUBREG_REG (XEXP (XEXP (nz, 0), 0)), z) ! && (num_sign_bit_copies (z, GET_MODE (z)) ! >= (GET_MODE_BITSIZE (mode) ! - GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (nz, 0), 0)))))) ! { ! c = XEXP (XEXP (nz, 0), 1); ! op = GET_CODE (XEXP (nz, 0)); ! extend_op = SIGN_EXTEND; ! m = GET_MODE (XEXP (nz, 0)); ! } ! else if (GET_CODE (nz) == ZERO_EXTEND ! && (GET_CODE (XEXP (nz, 0)) == PLUS ! || GET_CODE (XEXP (nz, 0)) == MINUS ! || GET_CODE (XEXP (nz, 0)) == IOR ! || GET_CODE (XEXP (nz, 0)) == XOR ! || GET_CODE (XEXP (nz, 0)) == ASHIFT ! || GET_CODE (XEXP (nz, 0)) == LSHIFTRT ! || GET_CODE (XEXP (nz, 0)) == ASHIFTRT) ! && GET_CODE (XEXP (XEXP (nz, 0), 0)) == SUBREG ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT ! && subreg_lowpart_p (XEXP (XEXP (nz, 0), 0)) ! && rtx_equal_p (SUBREG_REG (XEXP (XEXP (nz, 0), 0)), z) ! && ((significant_bits (z, GET_MODE (z)) ! & ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (nz, 0), 0)))) ! == 0)) ! { ! c = XEXP (XEXP (nz, 0), 1); ! op = GET_CODE (XEXP (nz, 0)); ! extend_op = ZERO_EXTEND; ! m = GET_MODE (XEXP (nz, 0)); ! } ! ! if (c && ! side_effects_p (c) && ! side_effects_p (z)) ! { ! temp ! = gen_binary (MULT, m, ! gen_lowpart_for_combine (m, ! XEXP (XEXP (x, 0), 0)), ! gen_binary (MULT, m, c, dir)); ! ! temp = gen_binary (op, m, gen_lowpart_for_combine (m, z), temp); ! ! if (extend_op != 0) ! temp = gen_unary (extend_op, mode, temp); ! ! return temp; ! } } break; *************** *** 3121,3167 **** x = make_field_assignment (x); - /* If we have (set x (subreg:m1 (op:m2 ...) 0)) with OP being some - operation, and X being a REG or (subreg (reg)), we may be able to - convert this to (set (subreg:m2 x) (op)). - - We can always do this if M1 is narrower than M2 because that - means that we only care about the low bits of the result. - - However, on most machines (those with BYTE_LOADS_ZERO_EXTEND - not defined), we cannot perform a narrower operation that - requested since the high-order bits will be undefined. On - machine where BYTE_LOADS_ZERO_EXTEND are defined, however, this - transformation is safe as long as M1 and M2 have the same number - of words. */ - - if (GET_CODE (SET_SRC (x)) == SUBREG - && subreg_lowpart_p (SET_SRC (x)) - && GET_RTX_CLASS (GET_CODE (SUBREG_REG (SET_SRC (x)))) != 'o' - && (((GET_MODE_SIZE (GET_MODE (SET_SRC (x))) + (UNITS_PER_WORD - 1)) - / UNITS_PER_WORD) - == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_SRC (x)))) - + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)) - #ifndef BYTE_LOADS_ZERO_EXTEND - && (GET_MODE_SIZE (GET_MODE (SET_SRC (x))) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_SRC (x))))) - #endif - && (GET_CODE (SET_DEST (x)) == REG - || (GET_CODE (SET_DEST (x)) == SUBREG - && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))) - { - /* Get the object that will be the SUBREG_REG of the - SUBREG we are making. Note that SUBREG_WORD will always - be zero because this will either be a paradoxical SUBREG - or a SUBREG with the same number of words on the outside and - inside. */ - rtx object = (GET_CODE (SET_DEST (x)) == REG ? SET_DEST (x) - : SUBREG_REG (SET_DEST (x))); - - SUBST (SET_DEST (x), - gen_rtx (SUBREG, GET_MODE (SUBREG_REG (SET_SRC (x))), - object, 0)); - SUBST (SET_SRC (x), SUBREG_REG (SET_SRC (x))); - } - /* If we are setting CC0 or if the source is a COMPARE, look for the use of the comparison result and try to simplify it unless we already --- 3663,3666 ---- *************** *** 3195,3199 **** /* If this machine has CC modes other than CCmode, check to see if we need to use a different CC mode here. */ ! compare_mode = SELECT_CC_MODE (new_code, op0); /* If the mode changed, we have to change SET_DEST, the mode --- 3694,3698 ---- /* If this machine has CC modes other than CCmode, check to see if we need to use a different CC mode here. */ ! compare_mode = SELECT_CC_MODE (new_code, op0, op1); /* If the mode changed, we have to change SET_DEST, the mode *************** *** 3241,3245 **** || (old_code == EQ && new_code == NE)) && ! other_changed && op1 == const0_rtx ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_INT && (exact_log2 (mask = significant_bits (op0, GET_MODE (op0))) --- 3740,3745 ---- || (old_code == EQ && new_code == NE)) && ! other_changed && op1 == const0_rtx ! && (GET_MODE_BITSIZE (GET_MODE (op0)) ! <= HOST_BITS_PER_WIDE_INT) && (exact_log2 (mask = significant_bits (op0, GET_MODE (op0))) *************** *** 3255,3259 **** op0 = gen_binary (XOR, GET_MODE (op0), op0, ! gen_rtx (CONST_INT, VOIDmode, mask)); } } --- 3755,3759 ---- op0 = gen_binary (XOR, GET_MODE (op0), op0, ! GEN_INT (mask)); } } *************** *** 3294,3297 **** --- 3794,3832 ---- } + /* If we have (set x (subreg:m1 (op:m2 ...) 0)) with OP being some + operation, and X being a REG or (subreg (reg)), we may be able to + convert this to (set (subreg:m2 x) (op)). + + We can always do this if M1 is narrower than M2 because that + means that we only care about the low bits of the result. + + However, on most machines (those with BYTE_LOADS_ZERO_EXTEND + and BYTES_LOADS_SIGN_EXTEND not defined), we cannot perform a + narrower operation that requested since the high-order bits will + be undefined. On machine where BYTE_LOADS_*_EXTEND is defined, + however, this transformation is safe as long as M1 and M2 have + the same number of words. */ + + if (GET_CODE (SET_SRC (x)) == SUBREG + && subreg_lowpart_p (SET_SRC (x)) + && GET_RTX_CLASS (GET_CODE (SUBREG_REG (SET_SRC (x)))) != 'o' + && (((GET_MODE_SIZE (GET_MODE (SET_SRC (x))) + (UNITS_PER_WORD - 1)) + / UNITS_PER_WORD) + == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_SRC (x)))) + + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)) + #if ! defined(BYTE_LOADS_ZERO_EXTEND) && ! defined (BYTE_LOADS_SIGN_EXTEND) + && (GET_MODE_SIZE (GET_MODE (SET_SRC (x))) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_SRC (x))))) + #endif + && (GET_CODE (SET_DEST (x)) == REG + || (GET_CODE (SET_DEST (x)) == SUBREG + && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))) + { + SUBST (SET_DEST (x), + gen_lowpart_for_combine (GET_MODE (SUBREG_REG (SET_SRC (x))), + SET_DEST (x))); + SUBST (SET_SRC (x), SUBREG_REG (SET_SRC (x))); + } + #ifdef BYTE_LOADS_ZERO_EXTEND /* If we have (set FOO (subreg:M (mem:N BAR) 0)) with *************** *** 3310,3313 **** --- 3845,3899 ---- #endif + #ifndef HAVE_conditional_move + + /* If we don't have a conditional move, SET_SRC is an IF_THEN_ELSE, + and we are comparing an item known to be 0 or -1 against 0, use a + logical operation instead. Check for one of the arms being an IOR + of the other arm with some value. We compute three terms to be + IOR'ed together. In practice, at most two will be nonzero. Then + we do the IOR's. */ + + if (GET_CODE (SET_DEST (x)) != PC + && GET_CODE (SET_SRC (x)) == IF_THEN_ELSE + && (GET_CODE (XEXP (SET_SRC (x), 0)) == EQ + || GET_CODE (XEXP (SET_SRC (x), 0)) == NE) + && XEXP (XEXP (SET_SRC (x), 0), 1) == const0_rtx + && (num_sign_bit_copies (XEXP (XEXP (SET_SRC (x), 0), 0), + GET_MODE (XEXP (XEXP (SET_SRC (x), 0), 0))) + == GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (SET_SRC (x), 0), 0)))) + && ! side_effects_p (SET_SRC (x))) + { + rtx true = (GET_CODE (XEXP (SET_SRC (x), 0)) == NE + ? XEXP (SET_SRC (x), 1) : XEXP (SET_SRC (x), 2)); + rtx false = (GET_CODE (XEXP (SET_SRC (x), 0)) == NE + ? XEXP (SET_SRC (x), 2) : XEXP (SET_SRC (x), 1)); + rtx term1 = const0_rtx, term2, term3; + + if (GET_CODE (true) == IOR && rtx_equal_p (XEXP (true, 0), false)) + term1 = false, true = XEXP (true, 1), false = const0_rtx; + else if (GET_CODE (true) == IOR + && rtx_equal_p (XEXP (true, 1), false)) + term1 = false, true = XEXP (true, 0), false = const0_rtx; + else if (GET_CODE (false) == IOR + && rtx_equal_p (XEXP (false, 0), true)) + term1 = true, false = XEXP (false, 1), true = const0_rtx; + else if (GET_CODE (false) == IOR + && rtx_equal_p (XEXP (false, 1), true)) + term1 = true, false = XEXP (false, 0), true = const0_rtx; + + term2 = gen_binary (AND, GET_MODE (SET_SRC (x)), + XEXP (XEXP (SET_SRC (x), 0), 0), true); + term3 = gen_binary (AND, GET_MODE (SET_SRC (x)), + gen_unary (NOT, GET_MODE (SET_SRC (x)), + XEXP (XEXP (SET_SRC (x), 0), 0)), + false); + + SUBST (SET_SRC (x), + gen_binary (IOR, GET_MODE (SET_SRC (x)), + gen_binary (IOR, GET_MODE (SET_SRC (x)), + term1, term2), + term3)); + } + #endif break; *************** *** 3327,3333 **** { temp = gen_binary (AND, mode, XEXP (XEXP (x, 0), 0), ! gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (XEXP (XEXP (x, 0), 1)) ! & ~ INTVAL (XEXP (x, 1))))); return gen_binary (IOR, mode, temp, XEXP (x, 1)); } --- 3913,3918 ---- { temp = gen_binary (AND, mode, XEXP (XEXP (x, 0), 0), ! GEN_INT (INTVAL (XEXP (XEXP (x, 0), 1)) ! & ~ INTVAL (XEXP (x, 1)))); return gen_binary (IOR, mode, temp, XEXP (x, 1)); } *************** *** 3386,3390 **** } ! /* In the follow group of tests (and those in case IOR below), we start with some combination of logical operations and apply the distributive law followed by the inverse distributive law. --- 3971,4002 ---- } ! /* If we have (and A B) with A not an object but that is known to ! be -1 or 0, this is equivalent to the expression ! (if_then_else (ne A (const_int 0)) B (const_int 0)) ! We make this conversion because it may allow further ! simplifications and then allow use of conditional move insns. ! If the machine doesn't have condition moves, code in case SET ! will convert the IF_THEN_ELSE back to the logical operation. ! We build the IF_THEN_ELSE here in case further simplification ! is possible (e.g., we can convert it to ABS). */ ! ! if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) != 'o' ! && ! (GET_CODE (XEXP (x, 0)) == SUBREG ! && GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0)))) == 'o') ! && (num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0))) ! == GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))) ! { ! rtx op0 = XEXP (x, 0); ! rtx op1 = const0_rtx; ! enum rtx_code comp_code ! = simplify_comparison (NE, &op0, &op1); ! ! x = gen_rtx_combine (IF_THEN_ELSE, mode, ! gen_binary (comp_code, VOIDmode, op0, op1), ! XEXP (x, 1), const0_rtx); ! goto restart; ! } ! ! /* In the following group of tests (and those in case IOR below), we start with some combination of logical operations and apply the distributive law followed by the inverse distributive law. *************** *** 3454,3457 **** --- 4066,4075 ---- case IOR: + /* (ior A C) is C if all significant bits of A are on in C. */ + if (GET_CODE (XEXP (x, 1)) == CONST_INT + && (significant_bits (XEXP (x, 0), mode) + & ~ INTVAL (XEXP (x, 1))) == 0) + return XEXP (x, 1); + /* Convert (A & B) | A to A. */ if (GET_CODE (XEXP (x, 0)) == AND *************** *** 3534,3539 **** } else if (num_negated == 1) ! return gen_rtx_combine (NOT, mode, ! gen_rtx_combine (XOR, mode, in1, in2)); } --- 4152,4160 ---- } else if (num_negated == 1) ! { ! x = gen_unary (NOT, mode, ! gen_binary (XOR, mode, in1, in2)); ! goto restart; ! } } *************** *** 3575,3580 **** /* (xor (comparison foo bar) (const_int sign-bit)) when STORE_FLAG_VALUE is the sign bit. */ ! if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! && STORE_FLAG_VALUE == 1 << (GET_MODE_BITSIZE (mode) - 1) && XEXP (x, 1) == const_true_rtx && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' --- 4196,4202 ---- /* (xor (comparison foo bar) (const_int sign-bit)) when STORE_FLAG_VALUE is the sign bit. */ ! if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT ! && (STORE_FLAG_VALUE ! == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1)) && XEXP (x, 1) == const_true_rtx && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' *************** *** 3592,3598 **** /* If operand is something known to be positive, ignore the ABS. */ if (GET_CODE (XEXP (x, 0)) == FFS || GET_CODE (XEXP (x, 0)) == ABS ! || (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) <= HOST_BITS_PER_INT && ((significant_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0))) ! & (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))) == 0))) return XEXP (x, 0); --- 4214,4222 ---- /* If operand is something known to be positive, ignore the ABS. */ if (GET_CODE (XEXP (x, 0)) == FFS || GET_CODE (XEXP (x, 0)) == ABS ! || ((GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) ! <= HOST_BITS_PER_WIDE_INT) && ((significant_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0))) ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))) == 0))) return XEXP (x, 0); *************** *** 3600,3615 **** /* If operand is known to be only -1 or 0, convert ABS to NEG. */ ! if ((GET_CODE (XEXP (x, 0)) == SIGN_EXTRACT ! && XEXP (XEXP (x, 0), 1) == const1_rtx) ! || (GET_CODE (XEXP (x, 0)) == ASHIFTRT ! && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode) - 1) ! || ((temp = get_last_value (XEXP (x, 0))) != 0 ! && ((GET_CODE (temp) == SIGN_EXTRACT ! && XEXP (temp, 1) == const1_rtx) ! || (GET_CODE (temp) == ASHIFTRT ! && GET_CODE (XEXP (temp, 1)) == CONST_INT ! && (INTVAL (XEXP (temp, 1)) ! == GET_MODE_BITSIZE (mode) - 1))))) { x = gen_rtx_combine (NEG, mode, XEXP (x, 0)); --- 4224,4228 ---- /* If operand is known to be only -1 or 0, convert ABS to NEG. */ ! if (num_sign_bit_copies (XEXP (x, 0), mode) == GET_MODE_BITSIZE (mode)) { x = gen_rtx_combine (NEG, mode, XEXP (x, 0)); *************** *** 3637,3659 **** case ROTATE: case ROTATERT: - #ifdef SHIFT_COUNT_TRUNCATED - /* (*shift (sign_extend )) = (*shift ) (most machines). - True for all kinds of shifts and also for zero_extend. */ - if ((GET_CODE (XEXP (x, 1)) == SIGN_EXTEND - || GET_CODE (XEXP (x, 1)) == ZERO_EXTEND) - && FAKE_EXTEND_SAFE_P (mode, XEXP (XEXP (x, 1), 0))) - SUBST (XEXP (x, 1), - /* This is a perverse SUBREG, wider than its base. */ - gen_lowpart_for_combine (mode, XEXP (XEXP (x, 1), 0))); - - /* tege: Change (bitshifts ... (and ... mask), c) - to (bitshifts ... c) if mask just masks the bits the bitshift - insns do automatically on this machine. */ - if (GET_CODE (XEXP (x, 1)) == AND - && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT - && (~ INTVAL (XEXP (XEXP (x, 1), 1)) & GET_MODE_MASK (mode)) == 0) - SUBST (XEXP (x, 1), XEXP (XEXP (x, 1), 0)); - #endif - /* If this is a shift by a constant amount, simplify it. */ if (GET_CODE (XEXP (x, 1)) == CONST_INT) --- 4250,4253 ---- *************** *** 3664,3667 **** --- 4258,4270 ---- goto restart; } + + #ifdef SHIFT_COUNT_TRUNCATED + else if (GET_CODE (XEXP (x, 1)) != REG) + SUBST (XEXP (x, 1), + force_to_mode (XEXP (x, 1), GET_MODE (x), + exact_log2 (GET_MODE_BITSIZE (GET_MODE (x))), + NULL_RTX)); + #endif + break; } *************** *** 3767,3783 **** modewidth = GET_MODE_BITSIZE (GET_MODE (x)); if (modewidth >= pos - len) ! tem = simplify_shift_const (0, unsignedp ? LSHIFTRT : ASHIFTRT, GET_MODE (x), ! simplify_shift_const (0, ASHIFT, GET_MODE (x), XEXP (x, 0), modewidth - pos - len), modewidth - len); ! else if (unsignedp && len < HOST_BITS_PER_INT) ! tem = simplify_and_const_int (0, GET_MODE (x), ! simplify_shift_const (0, LSHIFTRT, GET_MODE (x), XEXP (x, 0), pos), ! (1 << len) - 1); else /* Any other cases we can't handle. */ --- 4370,4387 ---- modewidth = GET_MODE_BITSIZE (GET_MODE (x)); if (modewidth >= pos - len) ! tem = simplify_shift_const (NULL_RTX, unsignedp ? LSHIFTRT : ASHIFTRT, GET_MODE (x), ! simplify_shift_const (NULL_RTX, ASHIFT, ! GET_MODE (x), XEXP (x, 0), modewidth - pos - len), modewidth - len); ! else if (unsignedp && len < HOST_BITS_PER_WIDE_INT) ! tem = simplify_and_const_int (NULL_RTX, GET_MODE (x), ! simplify_shift_const (NULL_RTX, LSHIFTRT, GET_MODE (x), XEXP (x, 0), pos), ! ((HOST_WIDE_INT) 1 << len) - 1); else /* Any other cases we can't handle. */ *************** *** 3836,3842 **** #if BITS_BIG_ENDIAN if (GET_CODE (pos) == CONST_INT) ! pos = gen_rtx (CONST_INT, VOIDmode, ! (GET_MODE_BITSIZE (GET_MODE (inner)) - len ! - INTVAL (pos))); else if (GET_CODE (pos) == MINUS && GET_CODE (XEXP (pos, 1)) == CONST_INT --- 4440,4445 ---- #if BITS_BIG_ENDIAN if (GET_CODE (pos) == CONST_INT) ! pos = GEN_INT (GET_MODE_BITSIZE (GET_MODE (inner)) - len ! - INTVAL (pos)); else if (GET_CODE (pos) == MINUS && GET_CODE (XEXP (pos, 1)) == CONST_INT *************** *** 3847,3853 **** else pos = gen_binary (MINUS, GET_MODE (pos), ! gen_rtx (CONST_INT, VOIDmode, ! (GET_MODE_BITSIZE (GET_MODE (inner)) ! - len)), pos); #endif } --- 4450,4456 ---- else pos = gen_binary (MINUS, GET_MODE (pos), ! GEN_INT (GET_MODE_BITSIZE (GET_MODE (inner)) ! - len), ! pos); #endif } *************** *** 3875,3880 **** /* Compute a mask of LEN bits, if we can do this on the host machine. */ ! if (len < HOST_BITS_PER_INT) ! mask = gen_rtx (CONST_INT, VOIDmode, (1 << len) - 1); else break; --- 4478,4483 ---- /* Compute a mask of LEN bits, if we can do this on the host machine. */ ! if (len < HOST_BITS_PER_WIDE_INT) ! mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1); else break; *************** *** 3938,3941 **** --- 4541,4547 ---- int in_dest, in_compare; { + /* This mode describes the size of the storage area + to fetch the overall value from. Within that, we + ignore the POS lowest bits, etc. */ enum machine_mode is_mode = GET_MODE (inner); enum machine_mode inner_mode; *************** *** 3949,3957 **** /* Get some information about INNER and get the innermost object. */ if (GET_CODE (inner) == USE) /* We don't need to adjust the position because we set up the USE to pretend that it was a full-word object. */ spans_byte = 1, inner = XEXP (inner, 0); else if (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner)) ! inner = SUBREG_REG (inner); inner_mode = GET_MODE (inner); --- 4555,4573 ---- /* Get some information about INNER and get the innermost object. */ if (GET_CODE (inner) == USE) + /* (use:SI (mem:QI foo)) stands for (mem:SI foo). */ /* We don't need to adjust the position because we set up the USE to pretend that it was a full-word object. */ spans_byte = 1, inner = XEXP (inner, 0); else if (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner)) ! { ! /* If going from (subreg:SI (mem:QI ...)) to (mem:QI ...), ! consider just the QI as the memory to extract from. ! The subreg adds or removes high bits; its mode is ! irrelevant to the meaning of this extraction, ! since POS and LEN count from the lsb. */ ! if (GET_CODE (SUBREG_REG (inner)) == MEM) ! is_mode = GET_MODE (SUBREG_REG (inner)); ! inner = SUBREG_REG (inner); ! } inner_mode = GET_MODE (inner); *************** *** 3975,3982 **** if (tmode != BLKmode && ! (spans_byte && inner_mode != tmode) ! && ((pos == 0 && GET_CODE (inner) == REG && (! in_dest ! || (movstrict_optab->handlers[(int) tmode].insn_code ! != CODE_FOR_nothing))) || (GET_CODE (inner) == MEM && pos >= 0 && (pos --- 4591,4599 ---- if (tmode != BLKmode && ! (spans_byte && inner_mode != tmode) ! && ((pos == 0 && GET_CODE (inner) != MEM && (! in_dest ! || (GET_CODE (inner) == REG ! && (movstrict_optab->handlers[(int) tmode].insn_code ! != CODE_FOR_nothing)))) || (GET_CODE (inner) == MEM && pos >= 0 && (pos *************** *** 3990,3995 **** && ! MEM_VOLATILE_P (inner)))))) { - int offset = pos / BITS_PER_UNIT; - /* If INNER is a MEM, make a new MEM that encompasses just the desired field. If the original and current mode are the same, we need not --- 4607,4610 ---- *************** *** 3997,4009 **** If INNER is not a MEM, get a piece consisting of the just the field ! of interest (in this case INNER must be a REG and POS must be 0). */ if (GET_CODE (inner) == MEM) { ! #if BYTES_BIG_ENDIAN ! if (inner_mode != tmode) ! offset = (GET_MODE_SIZE (inner_mode) ! - GET_MODE_SIZE (tmode) - offset); ! #endif new = gen_rtx (MEM, tmode, plus_constant (XEXP (inner, 0), offset)); --- 4612,4625 ---- If INNER is not a MEM, get a piece consisting of the just the field ! of interest (in this case POS must be 0). */ if (GET_CODE (inner) == MEM) { ! int offset; ! /* POS counts from lsb, but make OFFSET count in memory order. */ ! if (BYTES_BIG_ENDIAN) ! offset = (GET_MODE_BITSIZE (is_mode) - len - pos) / BITS_PER_UNIT; ! else ! offset = pos / BITS_PER_UNIT; new = gen_rtx (MEM, tmode, plus_constant (XEXP (inner, 0), offset)); *************** *** 4012,4017 **** MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (inner); } else ! new = gen_lowpart_for_combine (tmode, inner); /* If this extraction is going into the destination of a SET, --- 4628,4642 ---- MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (inner); } + else if (GET_CODE (inner) == REG) + /* We can't call gen_lowpart_for_combine here since we always want + a SUBREG and it would sometimes return a new hard register. */ + new = gen_rtx (SUBREG, tmode, inner, + (WORDS_BIG_ENDIAN + && GET_MODE_SIZE (is_mode) > UNITS_PER_WORD + ? ((GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (tmode)) + / UNITS_PER_WORD) + : 0)); else ! new = force_to_mode (inner, tmode, len, NULL_RTX); /* If this extraction is going into the destination of a SET, *************** *** 4020,4024 **** if (in_dest) return (GET_CODE (new) == MEM ? new ! : gen_rtx_combine (STRICT_LOW_PART, VOIDmode, new)); /* Otherwise, sign- or zero-extend unless we already are in the --- 4645,4651 ---- if (in_dest) return (GET_CODE (new) == MEM ? new ! : (GET_CODE (new) != SUBREG ! ? gen_rtx (CLOBBER, tmode, const0_rtx) ! : gen_rtx_combine (STRICT_LOW_PART, VOIDmode, new))); /* Otherwise, sign- or zero-extend unless we already are in the *************** *** 4030,4037 **** } ! /* Unless this is in a COMPARE or we have a funny memory reference, ! don't do anything with field extracts starting at the low-order ! bit since they are simple AND operations. */ ! if (pos == 0 && ! in_dest && ! in_compare && ! spans_byte) return 0; --- 4657,4664 ---- } ! /* Unless this is a COMPARE or we have a funny memory reference, ! don't do anything with zero-extending field extracts starting at ! the low-order bit since they are simple AND operations. */ ! if (pos == 0 && ! in_dest && ! in_compare && ! spans_byte && unsignedp) return 0; *************** *** 4092,4099 **** pos_rtx = gen_rtx_combine (MINUS, GET_MODE (pos_rtx), ! gen_rtx (CONST_INT, VOIDmode, ! (MAX (GET_MODE_BITSIZE (is_mode), ! GET_MODE_BITSIZE (wanted_mem_mode)) ! - len)), pos_rtx); #endif --- 4719,4726 ---- pos_rtx = gen_rtx_combine (MINUS, GET_MODE (pos_rtx), ! GEN_INT (MAX (GET_MODE_BITSIZE (is_mode), ! GET_MODE_BITSIZE (wanted_mem_mode)) ! - len), ! pos_rtx); #endif *************** *** 4148,4152 **** /* If INNER is not memory, we can always get it into the proper mode. */ else if (GET_CODE (inner) != MEM) ! inner = gen_lowpart_for_combine (extraction_mode, inner); /* Adjust mode of POS_RTX, if needed. If we want a wider mode, we --- 4775,4782 ---- /* If INNER is not memory, we can always get it into the proper mode. */ else if (GET_CODE (inner) != MEM) ! inner = force_to_mode (inner, extraction_mode, ! (pos < 0 ? GET_MODE_BITSIZE (extraction_mode) ! : len + pos), ! NULL_RTX); /* Adjust mode of POS_RTX, if needed. If we want a wider mode, we *************** *** 4161,4170 **** /* Make POS_RTX unless we already have it and it is correct. */ if (pos_rtx == 0 || (pos >= 0 && INTVAL (pos_rtx) != pos)) ! pos_rtx = gen_rtx (CONST_INT, VOIDmode, pos); /* Make the required operation. See if we can use existing rtx. */ new = gen_rtx_combine (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT, ! extraction_mode, inner, ! gen_rtx (CONST_INT, VOIDmode, len), pos_rtx); if (! in_dest) new = gen_lowpart_for_combine (mode, new); --- 4791,4799 ---- /* Make POS_RTX unless we already have it and it is correct. */ if (pos_rtx == 0 || (pos >= 0 && INTVAL (pos_rtx) != pos)) ! pos_rtx = GEN_INT (pos); /* Make the required operation. See if we can use existing rtx. */ new = gen_rtx_combine (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT, ! extraction_mode, inner, GEN_INT (len), pos_rtx); if (! in_dest) new = gen_lowpart_for_combine (mode, new); *************** *** 4187,4192 **** IN_CODE says what kind of expression we are processing. Normally, it is ! SET. In a memory address (inside a MEM or PLUS, the latter being a ! kludge), it is MEM. When processing the arguments of a comparison or a COMPARE against zero, it is COMPARE. */ --- 4816,4821 ---- IN_CODE says what kind of expression we are processing. Normally, it is ! SET. In a memory address (inside a MEM, PLUS or minus, the latter two ! being kludges), it is MEM. When processing the arguments of a comparison or a COMPARE against zero, it is COMPARE. */ *************** *** 4200,4204 **** int mode_width = GET_MODE_BITSIZE (mode); enum rtx_code next_code; ! int i; rtx new = 0; char *fmt; --- 4829,4833 ---- int mode_width = GET_MODE_BITSIZE (mode); enum rtx_code next_code; ! int i, count; rtx new = 0; char *fmt; *************** *** 4208,4212 **** but once inside, go back to our default of SET. */ ! next_code = (code == MEM || code == PLUS ? MEM : ((code == COMPARE || GET_RTX_CLASS (code) == '<') && XEXP (x, 1) == const0_rtx) ? COMPARE --- 4837,4841 ---- but once inside, go back to our default of SET. */ ! next_code = (code == MEM || code == PLUS || code == MINUS ? MEM : ((code == COMPARE || GET_RTX_CLASS (code) == '<') && XEXP (x, 1) == const0_rtx) ? COMPARE *************** *** 4223,4231 **** an address. */ if (in_code == MEM && GET_CODE (XEXP (x, 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_INT && INTVAL (XEXP (x, 1)) >= 0) new = gen_rtx_combine (MULT, mode, XEXP (x, 0), ! gen_rtx (CONST_INT, VOIDmode, ! 1 << INTVAL (XEXP (x, 1)))); break; --- 4852,4860 ---- an address. */ if (in_code == MEM && GET_CODE (XEXP (x, 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT && INTVAL (XEXP (x, 1)) >= 0) new = gen_rtx_combine (MULT, mode, XEXP (x, 0), ! GEN_INT ((HOST_WIDE_INT) 1 ! << INTVAL (XEXP (x, 1)))); break; *************** *** 4265,4291 **** (GET_MODE_BITSIZE (mode) - INTVAL (XEXP (XEXP (x, 0), 1))), ! 0, i, 1, 0, in_code == COMPARE); /* On machines without logical shifts, if the operand of the AND is a logical shift and our mask turns off all the propagated sign bits, we can replace the logical shift with an arithmetic shift. */ ! else if ( ! #ifdef HAVE_ashrsi3 ! HAVE_ashrsi3 ! #else ! 0 ! #endif ! #ifdef HAVE_lshrsi3 ! && ! HAVE_lshrsi3 ! #else ! && 1 ! #endif && GET_CODE (XEXP (x, 0)) == LSHIFTRT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (x, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_INT ! && mode_width <= HOST_BITS_PER_INT) { ! unsigned mask = GET_MODE_MASK (mode); mask >>= INTVAL (XEXP (XEXP (x, 0), 1)); --- 4894,4912 ---- (GET_MODE_BITSIZE (mode) - INTVAL (XEXP (XEXP (x, 0), 1))), ! NULL_RTX, i, 1, 0, in_code == COMPARE); /* On machines without logical shifts, if the operand of the AND is a logical shift and our mask turns off all the propagated sign bits, we can replace the logical shift with an arithmetic shift. */ ! else if (ashr_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing ! && (lshr_optab->handlers[(int) mode].insn_code ! == CODE_FOR_nothing) && GET_CODE (XEXP (x, 0)) == LSHIFTRT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (x, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT ! && mode_width <= HOST_BITS_PER_WIDE_INT) { ! unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode); mask >>= INTVAL (XEXP (XEXP (x, 0), 1)); *************** *** 4301,4305 **** we are in a COMPARE. */ else if ((i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0) ! new = make_extraction (mode, XEXP (x, 0), 0, 0, i, 1, 0, in_code == COMPARE); --- 4922,4926 ---- we are in a COMPARE. */ else if ((i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0) ! new = make_extraction (mode, XEXP (x, 0), 0, NULL_RTX, i, 1, 0, in_code == COMPARE); *************** *** 4308,4312 **** else if (in_code == COMPARE && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0) ! new = make_extraction (mode, XEXP (x, 0), i, 0, 1, 1, 0, 1); break; --- 4929,4933 ---- else if (in_code == COMPARE && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0) ! new = make_extraction (mode, XEXP (x, 0), i, NULL_RTX, 1, 1, 0, 1); break; *************** *** 4315,4330 **** /* If the sign bit is known to be zero, replace this with an arithmetic shift. */ ! if ( ! #ifdef HAVE_ashrsi3 ! HAVE_ashrsi3 ! #else ! 0 ! #endif ! #ifdef HAVE_lshrsi3 ! && ! HAVE_lshrsi3 ! #else ! && 1 ! #endif ! && mode_width <= HOST_BITS_PER_INT && (significant_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0) --- 4936,4942 ---- /* If the sign bit is known to be zero, replace this with an arithmetic shift. */ ! if (ashr_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing ! && lshr_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing ! && mode_width <= HOST_BITS_PER_WIDE_INT && (significant_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0) *************** *** 4346,4350 **** (INTVAL (XEXP (x, 1)) - INTVAL (XEXP (XEXP (x, 0), 1))), ! 0, mode_width - INTVAL (XEXP (x, 1)), code == LSHIFTRT, 0, in_code == COMPARE); break; --- 4958,5006 ---- (INTVAL (XEXP (x, 1)) - INTVAL (XEXP (XEXP (x, 0), 1))), ! NULL_RTX, mode_width - INTVAL (XEXP (x, 1)), ! code == LSHIFTRT, 0, in_code == COMPARE); ! ! /* Similarly if we have (ashifrt (OP (ashift foo C1) C3) C2). In these ! cases, we are better off returning a SIGN_EXTEND of the operation. */ ! ! if (GET_CODE (XEXP (x, 1)) == CONST_INT ! && (GET_CODE (XEXP (x, 0)) == IOR || GET_CODE (XEXP (x, 0)) == AND ! || GET_CODE (XEXP (x, 0)) == XOR ! || GET_CODE (XEXP (x, 0)) == PLUS) ! && GET_CODE (XEXP (XEXP (x, 0), 0)) == ASHIFT ! && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) >= INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) ! && INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) < HOST_BITS_PER_WIDE_INT ! && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! && (INTVAL (XEXP (XEXP (x, 0), 1)) ! & (((HOST_WIDE_INT) 1 ! << INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))) - 1)) == 0) ! { ! HOST_WIDE_INT newop1 ! = (INTVAL (XEXP (XEXP (x, 0), 1)) ! >> INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))); ! ! new = make_extraction (mode, ! gen_binary (GET_CODE (XEXP (x, 0)), mode, ! XEXP (XEXP (XEXP (x, 0), 0), 0), ! GEN_INT (newop1)), ! (INTVAL (XEXP (x, 1)) ! - INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))), ! NULL_RTX, mode_width - INTVAL (XEXP (x, 1)), ! code == LSHIFTRT, 0, in_code == COMPARE); ! } ! ! /* Similarly for (ashiftrt (neg (ashift FOO C1)) C2). */ ! if (GET_CODE (XEXP (x, 1)) == CONST_INT ! && GET_CODE (XEXP (x, 0)) == NEG ! && GET_CODE (XEXP (XEXP (x, 0), 0)) == ASHIFT ! && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) >= INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))) ! new = make_extraction (mode, ! gen_unary (GET_CODE (XEXP (x, 0)), mode, ! XEXP (XEXP (XEXP (x, 0), 0), 0)), ! (INTVAL (XEXP (x, 1)) ! - INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))), ! NULL_RTX, mode_width - INTVAL (XEXP (x, 1)), code == LSHIFTRT, 0, in_code == COMPARE); break; *************** *** 4353,4357 **** if (new) { ! x = new; code = GET_CODE (x); } --- 5009,5013 ---- if (new) { ! x = gen_lowpart_for_combine (mode, new); code = GET_CODE (x); } *************** *** 4378,4382 **** static int get_pos_from_mask (m, plen) ! unsigned int m; int *plen; { --- 5034,5038 ---- static int get_pos_from_mask (m, plen) ! unsigned HOST_WIDE_INT m; int *plen; { *************** *** 4412,4415 **** --- 5068,5072 ---- { enum rtx_code code = GET_CODE (x); + enum machine_mode op_mode = mode; /* If X is narrower than MODE or if BITS is larger than the size of MODE, *************** *** 4438,4443 **** case CONST_INT: ! if (bits < HOST_BITS_PER_INT) ! x = gen_rtx (CONST_INT, VOIDmode, INTVAL (x) & ((1 << bits) - 1)); return x; --- 5095,5100 ---- case CONST_INT: ! if (bits < HOST_BITS_PER_WIDE_INT) ! x = GEN_INT (INTVAL (x) & (((HOST_WIDE_INT) 1 << bits) - 1)); return x; *************** *** 4454,4458 **** if (GET_CODE (XEXP (x, 1)) == CONST_INT) { ! int mask = INTVAL (XEXP (x, 1)); int len = exact_log2 (mask + 1); rtx op = XEXP (x, 0); --- 5111,5115 ---- if (GET_CODE (XEXP (x, 1)) == CONST_INT) { ! HOST_WIDE_INT mask = INTVAL (XEXP (x, 1)); int len = exact_log2 (mask + 1); rtx op = XEXP (x, 0); *************** *** 4465,4472 **** reg); ! if (bits < HOST_BITS_PER_INT) ! mask &= (1 << bits) - 1; ! x = simplify_and_const_int (x, mode, op, mask); /* If X is still an AND, see if it is an AND with a mask that --- 5122,5135 ---- reg); ! if (bits < HOST_BITS_PER_WIDE_INT) ! mask &= ((HOST_WIDE_INT) 1 << bits) - 1; ! ! /* If we have no AND in MODE, use the original mode for the ! operation. */ ! ! if (and_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! op_mode = GET_MODE (x); ! x = simplify_and_const_int (x, op_mode, op, mask); /* If X is still an AND, see if it is an AND with a mask that *************** *** 4475,4482 **** if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT ! && bits < HOST_BITS_PER_INT ! && INTVAL (XEXP (x, 1)) == (1 << bits) - 1) x = XEXP (x, 0); ! return x; } --- 5138,5146 ---- if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT ! && bits < HOST_BITS_PER_WIDE_INT ! && INTVAL (XEXP (x, 1)) == ((HOST_WIDE_INT) 1 << bits) - 1) x = XEXP (x, 0); ! ! break; } *************** *** 4489,4497 **** case XOR: /* For most binary operations, just propagate into the operation and ! change the mode. */ ! return gen_binary (code, mode, ! force_to_mode (XEXP (x, 0), mode, bits, reg), ! force_to_mode (XEXP (x, 1), mode, bits, reg)); case ASHIFT: --- 5153,5182 ---- case XOR: /* For most binary operations, just propagate into the operation and ! change the mode if we have an operation of that mode. */ ! if ((code == PLUS ! && add_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! || (code == MINUS ! && sub_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! || (code == MULT && (smul_optab->handlers[(int) mode].insn_code ! == CODE_FOR_nothing)) ! || (code == AND ! && and_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! || (code == IOR ! && ior_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! || (code == XOR && (xor_optab->handlers[(int) mode].insn_code ! == CODE_FOR_nothing))) ! op_mode = GET_MODE (x); ! ! x = gen_binary (code, op_mode, ! gen_lowpart_for_combine (op_mode, ! force_to_mode (XEXP (x, 0), ! mode, bits, ! reg)), ! gen_lowpart_for_combine (op_mode, ! force_to_mode (XEXP (x, 1), ! mode, bits, ! reg))); ! break; case ASHIFT: *************** *** 4504,4510 **** bits -= INTVAL (XEXP (x, 1)); ! return gen_binary (code, mode, ! force_to_mode (XEXP (x, 0), mode, bits, reg), ! XEXP (x, 1)); case LSHIFTRT: --- 5189,5205 ---- bits -= INTVAL (XEXP (x, 1)); ! if ((code == ASHIFT ! && ashl_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! || (code == LSHIFT && (lshl_optab->handlers[(int) mode].insn_code ! == CODE_FOR_nothing))) ! op_mode = GET_MODE (x); ! ! x = gen_binary (code, op_mode, ! gen_lowpart_for_combine (op_mode, ! force_to_mode (XEXP (x, 0), ! mode, bits, ! reg)), ! XEXP (x, 1)); ! break; case LSHIFTRT: *************** *** 4515,4535 **** if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) + bits <= GET_MODE_BITSIZE (mode)) ! return gen_binary (LSHIFTRT, mode, ! force_to_mode (XEXP (x, 0), mode, ! bits + INTVAL (XEXP (x, 1)), reg), ! XEXP (x, 1)); break; case NEG: case NOT: /* Handle these similarly to the way we handle most binary operations. */ ! return gen_unary (code, mode, ! force_to_mode (XEXP (x, 0), mode, bits, reg)); } ! /* Otherwise, just do the operation canonically. */ return gen_lowpart_for_combine (mode, x); } /* See if X, a SET operation, can be rewritten as a bit-field assignment. Return that assignment if so. --- 5210,5363 ---- if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) + bits <= GET_MODE_BITSIZE (mode)) ! { ! rtx inner = force_to_mode (XEXP (x, 0), mode, ! bits + INTVAL (XEXP (x, 1)), reg); ! ! if (lshr_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) ! op_mode = GET_MODE (x); ! ! x = gen_binary (LSHIFTRT, op_mode, ! gen_lowpart_for_combine (op_mode, inner), ! XEXP (x, 1)); ! } ! break; ! ! case ASHIFTRT: ! /* If this is a sign-extension operation that just affects bits ! we don't care about, remove it. */ ! ! if (GET_CODE (XEXP (x, 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) >= 0 ! && INTVAL (XEXP (x, 1)) <= GET_MODE_BITSIZE (GET_MODE (x)) - bits ! && GET_CODE (XEXP (x, 0)) == ASHIFT ! && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! && INTVAL (XEXP (XEXP (x, 0), 1)) == INTVAL (XEXP (x, 1))) ! return force_to_mode (XEXP (XEXP (x, 0), 0), mode, bits, reg); break; case NEG: case NOT: + if ((code == NEG + && neg_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) + || (code == NOT && (one_cmpl_optab->handlers[(int) mode].insn_code + == CODE_FOR_nothing))) + op_mode = GET_MODE (x); + /* Handle these similarly to the way we handle most binary operations. */ ! x = gen_unary (code, op_mode, ! gen_lowpart_for_combine (op_mode, ! force_to_mode (XEXP (x, 0), mode, ! bits, reg))); ! break; ! ! case IF_THEN_ELSE: ! /* We have no way of knowing if the IF_THEN_ELSE can itself be ! written in a narrower mode. We play it safe and do not do so. */ ! ! SUBST (XEXP (x, 1), ! gen_lowpart_for_combine (GET_MODE (x), ! force_to_mode (XEXP (x, 1), mode, ! bits, reg))); ! SUBST (XEXP (x, 2), ! gen_lowpart_for_combine (GET_MODE (x), ! force_to_mode (XEXP (x, 2), mode, ! bits, reg))); ! break; } ! /* Ensure we return a value of the proper mode. */ return gen_lowpart_for_combine (mode, x); } + /* Return the value of expression X given the fact that condition COND + is known to be true when applied to REG as its first operand and VAL + as its second. X is known to not be shared and so can be modified in + place. + + We only handle the simplest cases, and specifically those cases that + arise with IF_THEN_ELSE expressions. */ + + static rtx + known_cond (x, cond, reg, val) + rtx x; + enum rtx_code cond; + rtx reg, val; + { + enum rtx_code code = GET_CODE (x); + rtx new, temp; + char *fmt; + int i, j; + + if (side_effects_p (x)) + return x; + + if (cond == EQ && rtx_equal_p (x, reg)) + return val; + + /* If X is (abs REG) and we know something about REG's relationship + with zero, we may be able to simplify this. */ + + if (code == ABS && rtx_equal_p (XEXP (x, 0), reg) && val == const0_rtx) + switch (cond) + { + case GE: case GT: case EQ: + return XEXP (x, 0); + case LT: case LE: + return gen_unary (NEG, GET_MODE (XEXP (x, 0)), XEXP (x, 0)); + } + + /* The only other cases we handle are MIN, MAX, and comparisons if the + operands are the same as REG and VAL. */ + + else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == 'c') + { + if (rtx_equal_p (XEXP (x, 0), val)) + cond = swap_condition (cond), temp = val, val = reg, reg = temp; + + if (rtx_equal_p (XEXP (x, 0), reg) && rtx_equal_p (XEXP (x, 1), val)) + { + if (GET_RTX_CLASS (code) == '<') + return (comparison_dominates_p (cond, code) ? const_true_rtx + : (comparison_dominates_p (cond, + reverse_condition (code)) + ? const0_rtx : x)); + + else if (code == SMAX || code == SMIN + || code == UMIN || code == UMAX) + { + int unsignedp = (code == UMIN || code == UMAX); + + if (code == SMAX || code == UMAX) + cond = reverse_condition (cond); + + switch (cond) + { + case GE: case GT: + return unsignedp ? x : XEXP (x, 1); + case LE: case LT: + return unsignedp ? x : XEXP (x, 0); + case GEU: case GTU: + return unsignedp ? XEXP (x, 1) : x; + case LEU: case LTU: + return unsignedp ? XEXP (x, 0) : x; + } + } + } + } + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + SUBST (XEXP (x, i), known_cond (XEXP (x, i), cond, reg, val)); + else if (fmt[i] == 'E') + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + SUBST (XVECEXP (x, i, j), known_cond (XVECEXP (x, i, j), + cond, reg, val)); + } + + return x; + } + /* See if X, a SET operation, can be rewritten as a bit-field assignment. Return that assignment if so. *************** *** 4545,4549 **** rtx ourdest; rtx assign; ! int c1, pos, len; rtx other; enum machine_mode mode; --- 5373,5378 ---- rtx ourdest; rtx assign; ! HOST_WIDE_INT c1; ! int pos, len; rtx other; enum machine_mode mode; *************** *** 4624,4628 **** return x; ! assign = make_extraction (VOIDmode, dest, pos, 0, len, 1, 1, 0); /* The mode to use for the source is the mode of the assignment, or of --- 5453,5457 ---- return x; ! assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0); /* The mode to use for the source is the mode of the assignment, or of *************** *** 4634,4639 **** to the proper length and mode. */ ! src = force_to_mode (simplify_shift_const (0, LSHIFTRT, GET_MODE (src), ! other, pos), mode, len, dest); --- 5463,5468 ---- to the proper length and mode. */ ! src = force_to_mode (simplify_shift_const (NULL_RTX, LSHIFTRT, ! GET_MODE (src), other, pos), mode, len, dest); *************** *** 4770,4778 **** enum machine_mode mode; rtx varop; ! unsigned constop; { register enum machine_mode tmode; register rtx temp; ! unsigned significant; /* There is a large class of optimizations based on the principle that --- 5599,5607 ---- enum machine_mode mode; rtx varop; ! unsigned HOST_WIDE_INT constop; { register enum machine_mode tmode; register rtx temp; ! unsigned HOST_WIDE_INT significant; /* There is a large class of optimizations based on the principle that *************** *** 4789,4795 **** while (1) { ! /* If we ever encounter a mode wider than the host machine's word ! size, we can't compute the masks accurately, so give up. */ ! if (GET_MODE_BITSIZE (GET_MODE (varop)) > HOST_BITS_PER_INT) break; --- 5618,5624 ---- while (1) { ! /* If we ever encounter a mode wider than the host machine's widest ! integer size, we can't compute the masks accurately, so give up. */ ! if (GET_MODE_BITSIZE (GET_MODE (varop)) > HOST_BITS_PER_WIDE_INT) break; *************** *** 4821,4829 **** if (subreg_lowpart_p (varop) /* We can ignore the effect this SUBREG if it narrows the mode ! or, on machines where byte operations zero extend, if the constant masks to zero all the bits the mode doesn't have. */ && ((GET_MODE_SIZE (GET_MODE (varop)) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))) ! #ifdef BYTE_LOADS_ZERO_EXTEND || (0 == (constop & GET_MODE_MASK (GET_MODE (varop)) --- 5650,5658 ---- if (subreg_lowpart_p (varop) /* We can ignore the effect this SUBREG if it narrows the mode ! or, on machines where byte operations extend, if the constant masks to zero all the bits the mode doesn't have. */ && ((GET_MODE_SIZE (GET_MODE (varop)) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))) ! #if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND) || (0 == (constop & GET_MODE_MASK (GET_MODE (varop)) *************** *** 4870,4874 **** && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (varop, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (varop, 0), 1)) < HOST_BITS_PER_INT && GET_CODE (XEXP (varop, 1)) == CONST_INT && (INTVAL (XEXP (varop, 1)) --- 5699,5703 ---- && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (varop, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (varop, 0), 1)) < HOST_BITS_PER_WIDE_INT && GET_CODE (XEXP (varop, 1)) == CONST_INT && (INTVAL (XEXP (varop, 1)) *************** *** 4876,4882 **** GET_MODE (varop)) == 0)) { ! temp = gen_rtx (CONST_INT, VOIDmode, ! ((INTVAL (XEXP (varop, 1)) & constop) ! << INTVAL (XEXP (XEXP (varop, 0), 1)))); temp = gen_binary (GET_CODE (varop), GET_MODE (varop), XEXP (XEXP (varop, 0), 0), temp); --- 5705,5710 ---- GET_MODE (varop)) == 0)) { ! temp = GEN_INT ((INTVAL (XEXP (varop, 1)) & constop) ! << INTVAL (XEXP (XEXP (varop, 0), 1))); temp = gen_binary (GET_CODE (varop), GET_MODE (varop), XEXP (XEXP (varop, 0), 0), temp); *************** *** 4896,4902 **** (gen_rtx_combine (GET_CODE (varop), GET_MODE (varop), ! simplify_and_const_int (0, GET_MODE (varop), XEXP (varop, 0), constop), ! simplify_and_const_int (0, GET_MODE (varop), XEXP (varop, 1), constop)))); --- 5724,5730 ---- (gen_rtx_combine (GET_CODE (varop), GET_MODE (varop), ! simplify_and_const_int (NULL_RTX, GET_MODE (varop), XEXP (varop, 0), constop), ! simplify_and_const_int (NULL_RTX, GET_MODE (varop), XEXP (varop, 1), constop)))); *************** *** 4908,4915 **** && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (varop, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (varop, 0), 1)) < HOST_BITS_PER_INT) { ! temp = gen_rtx (CONST_INT, VOIDmode, ! constop << INTVAL (XEXP (XEXP (varop, 0), 1))); temp = gen_binary (XOR, GET_MODE (varop), XEXP (XEXP (varop, 0), 0), temp); --- 5736,5742 ---- && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (varop, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (varop, 0), 1)) < HOST_BITS_PER_WIDE_INT) { ! temp = GEN_INT (constop << INTVAL (XEXP (XEXP (varop, 0), 1))); temp = gen_binary (XOR, GET_MODE (varop), XEXP (XEXP (varop, 0), 0), temp); *************** *** 4923,4927 **** /* If we are just looking for the sign bit, we don't need this shift at all, even if it has a variable count. */ ! if (constop == 1 << (GET_MODE_BITSIZE (GET_MODE (varop)) - 1)) { varop = XEXP (varop, 0); --- 5750,5755 ---- /* If we are just looking for the sign bit, we don't need this shift at all, even if it has a variable count. */ ! if (constop == ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (GET_MODE (varop)) - 1))) { varop = XEXP (varop, 0); *************** *** 4938,4942 **** if (GET_CODE (XEXP (varop, 1)) == CONST_INT && INTVAL (XEXP (varop, 1)) >= 0 ! && INTVAL (XEXP (varop, 1)) < HOST_BITS_PER_INT) { int i = -1; --- 5766,5770 ---- if (GET_CODE (XEXP (varop, 1)) == CONST_INT && INTVAL (XEXP (varop, 1)) >= 0 ! && INTVAL (XEXP (varop, 1)) < HOST_BITS_PER_WIDE_INT) { int i = -1; *************** *** 5019,5023 **** /* If we have reached a constant, this whole thing is constant. */ if (GET_CODE (varop) == CONST_INT) ! return gen_rtx (CONST_INT, VOIDmode, constop & INTVAL (varop)); /* See what bits are significant in VAROP. */ --- 5847,5851 ---- /* If we have reached a constant, this whole thing is constant. */ if (GET_CODE (varop) == CONST_INT) ! return GEN_INT (constop & INTVAL (varop)); /* See what bits are significant in VAROP. */ *************** *** 5053,5058 **** /* Otherwise, return an AND. See how much, if any, of X we can use. */ else if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode) ! x = gen_rtx_combine (AND, mode, varop, ! gen_rtx (CONST_INT, VOIDmode, constop)); else --- 5881,5885 ---- /* Otherwise, return an AND. See how much, if any, of X we can use. */ else if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode) ! x = gen_rtx_combine (AND, mode, varop, GEN_INT (constop)); else *************** *** 5060,5064 **** if (GET_CODE (XEXP (x, 1)) != CONST_INT || INTVAL (XEXP (x, 1)) != constop) ! SUBST (XEXP (x, 1), gen_rtx (CONST_INT, VOIDmode, constop)); SUBST (XEXP (x, 0), varop); --- 5887,5891 ---- if (GET_CODE (XEXP (x, 1)) != CONST_INT || INTVAL (XEXP (x, 1)) != constop) ! SUBST (XEXP (x, 1), GEN_INT (constop)); SUBST (XEXP (x, 0), varop); *************** *** 5074,5084 **** a shift, AND, or zero_extract, we can do better. */ ! static unsigned significant_bits (x, mode) rtx x; enum machine_mode mode; { ! unsigned significant = GET_MODE_MASK (mode); ! unsigned inner_sig; enum rtx_code code; int mode_width = GET_MODE_BITSIZE (mode); --- 5901,5911 ---- a shift, AND, or zero_extract, we can do better. */ ! static unsigned HOST_WIDE_INT significant_bits (x, mode) rtx x; enum machine_mode mode; { ! unsigned HOST_WIDE_INT significant = GET_MODE_MASK (mode); ! unsigned HOST_WIDE_INT inner_sig; enum rtx_code code; int mode_width = GET_MODE_BITSIZE (mode); *************** *** 5093,5097 **** } ! if (mode_width > HOST_BITS_PER_INT) /* Our only callers in this case look for single bit values. So just return the mode mask. Those tests will then be false. */ --- 5920,5924 ---- } ! if (mode_width > HOST_BITS_PER_WIDE_INT) /* Our only callers in this case look for single bit values. So just return the mode mask. Those tests will then be false. */ *************** *** 5161,5169 **** #endif - #if STORE_FLAG_VALUE == -1 case NEG: ! if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<' ! || ((tem = get_last_value (XEXP (x, 0))) != 0 ! && GET_RTX_CLASS (GET_CODE (tem)) == '<')) significant = 1; --- 5988,5994 ---- #endif case NEG: ! if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x)) ! == GET_MODE_BITSIZE (GET_MODE (x))) significant = 1; *************** *** 5171,5175 **** significant |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (x))); break; ! #endif case TRUNCATE: --- 5996,6005 ---- significant |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (x))); break; ! ! case ABS: ! if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x)) ! == GET_MODE_BITSIZE (GET_MODE (x))) ! significant = 1; ! break; case TRUNCATE: *************** *** 5193,5197 **** inner_sig &= GET_MODE_MASK (GET_MODE (XEXP (x, 0))); if (inner_sig & ! (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))) inner_sig |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))); --- 6023,6028 ---- inner_sig &= GET_MODE_MASK (GET_MODE (XEXP (x, 0))); if (inner_sig & ! (((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1)))) inner_sig |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))); *************** *** 5206,5211 **** break; ! case XOR: ! case IOR: significant &= (significant_bits (XEXP (x, 0), mode) | significant_bits (XEXP (x, 1), mode)); --- 6037,6042 ---- break; ! case XOR: case IOR: ! case UMIN: case UMAX: case SMIN: case SMAX: significant &= (significant_bits (XEXP (x, 0), mode) | significant_bits (XEXP (x, 1), mode)); *************** *** 5221,5226 **** and the number of low-order zero bits for each value. */ { ! unsigned sig0 = significant_bits (XEXP (x, 0), mode); ! unsigned sig1 = significant_bits (XEXP (x, 1), mode); int width0 = floor_log2 (sig0) + 1; int width1 = floor_log2 (sig1) + 1; --- 6052,6057 ---- and the number of low-order zero bits for each value. */ { ! unsigned HOST_WIDE_INT sig0 = significant_bits (XEXP (x, 0), mode); ! unsigned HOST_WIDE_INT sig1 = significant_bits (XEXP (x, 1), mode); int width0 = floor_log2 (sig0) + 1; int width1 = floor_log2 (sig1) + 1; *************** *** 5264,5271 **** if (result_width < mode_width) ! significant &= (1 << result_width) - 1; if (result_low > 0) ! significant &= ~ ((1 << result_low) - 1); } break; --- 6095,6102 ---- if (result_width < mode_width) ! significant &= ((HOST_WIDE_INT) 1 << result_width) - 1; if (result_low > 0) ! significant &= ~ (((HOST_WIDE_INT) 1 << result_low) - 1); } break; *************** *** 5273,5289 **** case ZERO_EXTRACT: if (GET_CODE (XEXP (x, 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_INT) ! significant &= (1 << INTVAL (XEXP (x, 1))) - 1; break; case SUBREG: /* If the inner mode is a single word for both the host and target machines, we can compute this from which bits of the inner object are known significant. */ if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= BITS_PER_WORD ! && GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= HOST_BITS_PER_INT) { significant &= significant_bits (SUBREG_REG (x), mode); ! #ifndef BYTE_LOADS_ZERO_EXTEND /* On many CISC machines, accessing an object in a wider mode causes the high-order bits to become undefined. So they are --- 6104,6129 ---- case ZERO_EXTRACT: if (GET_CODE (XEXP (x, 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT) ! significant &= ((HOST_WIDE_INT) 1 << INTVAL (XEXP (x, 1))) - 1; break; case SUBREG: + /* If this is a SUBREG formed for a promoted variable that has + been zero-extended, we know that at least the high-order bits + are zero, though others might be too. */ + + if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x)) + significant = (GET_MODE_MASK (GET_MODE (x)) + & significant_bits (SUBREG_REG (x), GET_MODE (x))); + /* If the inner mode is a single word for both the host and target machines, we can compute this from which bits of the inner object are known significant. */ if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= BITS_PER_WORD ! && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) ! <= HOST_BITS_PER_WIDE_INT)) { significant &= significant_bits (SUBREG_REG (x), mode); ! #if ! defined(BYTE_LOADS_ZERO_EXTEND) && ! defined(BYTE_LOADS_SIGN_EXTEND) /* On many CISC machines, accessing an object in a wider mode causes the high-order bits to become undefined. So they are *************** *** 5310,5322 **** if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0 ! && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_INT) { enum machine_mode inner_mode = GET_MODE (x); int width = GET_MODE_BITSIZE (inner_mode); int count = INTVAL (XEXP (x, 1)); ! unsigned mode_mask = GET_MODE_MASK (inner_mode); ! unsigned op_significant = significant_bits (XEXP (x, 0), mode); ! unsigned inner = op_significant & mode_mask; ! unsigned outer = 0; if (mode_width > width) --- 6150,6163 ---- if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0 ! && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT) { enum machine_mode inner_mode = GET_MODE (x); int width = GET_MODE_BITSIZE (inner_mode); int count = INTVAL (XEXP (x, 1)); ! unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode); ! unsigned HOST_WIDE_INT op_significant ! = significant_bits (XEXP (x, 0), mode); ! unsigned HOST_WIDE_INT inner = op_significant & mode_mask; ! unsigned HOST_WIDE_INT outer = 0; if (mode_width > width) *************** *** 5332,5337 **** need to mark all the places it could have been copied to by the shift significant. */ ! if (inner & (1 << (width - 1 - count))) ! inner |= ((1 << count) - 1) << (width - count); } else if (code == LSHIFT || code == ASHIFT) --- 6173,6178 ---- need to mark all the places it could have been copied to by the shift significant. */ ! if (inner & ((HOST_WIDE_INT) 1 << (width - 1 - count))) ! inner |= (((HOST_WIDE_INT) 1 << count) - 1) << (width - count); } else if (code == LSHIFT || code == ASHIFT) *************** *** 5347,5352 **** case FFS: /* This is at most the number of bits in the mode. */ ! significant = (1 << (floor_log2 (mode_width) + 1)) - 1; break; } --- 6188,6198 ---- case FFS: /* This is at most the number of bits in the mode. */ ! significant = ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width) + 1)) - 1; break; + + case IF_THEN_ELSE: + significant &= (significant_bits (XEXP (x, 1), mode) + | significant_bits (XEXP (x, 2), mode)); + break; } *************** *** 5354,5357 **** --- 6200,6476 ---- } + /* Return the number of bits at the high-order end of X that are known to + be equal to the sign bit. This number will always be between 1 and + the number of bits in the mode of X. MODE is the mode to be used + if X is VOIDmode. */ + + static int + num_sign_bit_copies (x, mode) + rtx x; + enum machine_mode mode; + { + enum rtx_code code = GET_CODE (x); + int bitwidth; + int num0, num1, result; + unsigned HOST_WIDE_INT sig; + rtx tem; + + /* If we weren't given a mode, use the mode of X. If the mode is still + VOIDmode, we don't know anything. */ + + if (mode == VOIDmode) + mode = GET_MODE (x); + + if (mode == VOIDmode) + return 0; + + bitwidth = GET_MODE_BITSIZE (mode); + + switch (code) + { + case REG: + if (significant_valid && reg_sign_bit_copies[REGNO (x)] != 0) + return reg_sign_bit_copies[REGNO (x)]; + + tem = get_last_value (x); + if (tem != 0) + return num_sign_bit_copies (tem, mode); + break; + + #ifdef BYTE_LOADS_SIGN_EXTEND + case MEM: + /* Some RISC machines sign-extend all loads of smaller than a word. */ + return MAX (1, bitwidth - GET_MODE_BITSIZE (GET_MODE (x)) + 1); + #endif + + case CONST_INT: + /* If the constant is negative, take its 1's complement and remask. + Then see how many zero bits we have. */ + sig = INTVAL (x) & GET_MODE_MASK (mode); + if (sig & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) + sig = (~ sig) & GET_MODE_MASK (mode); + + return (sig == 0 ? bitwidth : bitwidth - floor_log2 (sig) - 1); + + case SUBREG: + /* If this is a SUBREG for a promoted object that is sign-extended + and we are looking at it in a wider mode, we know that at least the + high-order bits are known to be sign bit copies. */ + + if (SUBREG_PROMOTED_VAR_P (x) && ! SUBREG_PROMOTED_UNSIGNED_P (x)) + return (GET_MODE_BITSIZE (mode) - GET_MODE_BITSIZE (GET_MODE (x)) + + num_sign_bit_copies (SUBREG_REG (x), GET_MODE (x))); + + /* For a smaller object, just ignore the high bits. */ + if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))) + { + num0 = num_sign_bit_copies (SUBREG_REG (x), VOIDmode); + return MAX (1, (num0 + - (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) + - bitwidth))); + } + + #if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND) + /* For paradoxical SUBREGs, just look inside since, on machines with + one of these defined, we assume that operations are actually + performed on the full register. Note that we are passing MODE + to the recursive call, so the number of sign bit copies will + remain relative to that mode, not the inner mode. */ + + if (GET_MODE_SIZE (GET_MODE (x)) + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) + return num_sign_bit_copies (SUBREG_REG (x), mode); + #endif + + break; + + case SIGN_EXTRACT: + if (GET_CODE (XEXP (x, 1)) == CONST_INT) + return MAX (1, bitwidth - INTVAL (XEXP (x, 1))); + break; + + case SIGN_EXTEND: + return (bitwidth - GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) + + num_sign_bit_copies (XEXP (x, 0), VOIDmode)); + + case TRUNCATE: + /* For a smaller object, just ignore the high bits. */ + num0 = num_sign_bit_copies (XEXP (x, 0), VOIDmode); + return MAX (1, (num0 - (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) + - bitwidth))); + + case NOT: + return num_sign_bit_copies (XEXP (x, 0), mode); + + case ROTATE: case ROTATERT: + /* If we are rotating left by a number of bits less than the number + of sign bit copies, we can just subtract that amount from the + number. */ + if (GET_CODE (XEXP (x, 1)) == CONST_INT + && INTVAL (XEXP (x, 1)) >= 0 && INTVAL (XEXP (x, 1)) < bitwidth) + { + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + return MAX (1, num0 - (code == ROTATE ? INTVAL (XEXP (x, 1)) + : bitwidth - INTVAL (XEXP (x, 1)))); + } + break; + + case NEG: + /* In general, this subtracts one sign bit copy. But if the value + is known to be positive, the number of sign bit copies is the + same as that of the input. Finally, if the input has just one + significant bit, all the bits are copies of the sign bit. */ + sig = significant_bits (XEXP (x, 0), mode); + if (sig == 1) + return bitwidth; + + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + if (num0 > 1 + && (((HOST_WIDE_INT) 1 << (bitwidth - 1)) & sig)) + num0--; + + return num0; + + case IOR: case AND: case XOR: + case SMIN: case SMAX: case UMIN: case UMAX: + /* Logical operations will preserve the number of sign-bit copies. + MIN and MAX operations always return one of the operands. */ + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + num1 = num_sign_bit_copies (XEXP (x, 1), mode); + return MIN (num0, num1); + + case PLUS: case MINUS: + /* For addition and subtraction, we can have a 1-bit carry. However, + if we are subtracting 1 from a positive number, there will not + be such a carry. Furthermore, if the positive number is known to + be 0 or 1, we know the result is either -1 or 0. */ + + if (code == PLUS && XEXP (x, 1) == constm1_rtx) + { + sig = significant_bits (XEXP (x, 0), mode); + if ((((HOST_WIDE_INT) 1 << (bitwidth - 1)) & sig) == 0) + return (sig == 1 || sig == 0 ? bitwidth + : bitwidth - floor_log2 (sig)); + } + + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + num1 = num_sign_bit_copies (XEXP (x, 1), mode); + return MAX (1, MIN (num0, num1) - 1); + + case MULT: + /* The number of bits of the product is the sum of the number of + bits of both terms. However, unless one of the terms if known + to be positive, we must allow for an additional bit since negating + a negative number can remove one sign bit copy. */ + + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + num1 = num_sign_bit_copies (XEXP (x, 1), mode); + + result = bitwidth - (bitwidth - num0) - (bitwidth - num1); + if (result > 0 + && ((significant_bits (XEXP (x, 0), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) + && (significant_bits (XEXP (x, 1), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1)) != 0)) + result--; + + return MAX (1, result); + + case UDIV: + /* The result must be <= the first operand. */ + return num_sign_bit_copies (XEXP (x, 0), mode); + + case UMOD: + /* The result must be <= the scond operand. */ + return num_sign_bit_copies (XEXP (x, 1), mode); + + case DIV: + /* Similar to unsigned division, except that we have to worry about + the case where the divisor is negative, in which case we have + to add 1. */ + result = num_sign_bit_copies (XEXP (x, 0), mode); + if (result > 1 + && (significant_bits (XEXP (x, 1), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) + result --; + + return result; + + case MOD: + result = num_sign_bit_copies (XEXP (x, 1), mode); + if (result > 1 + && (significant_bits (XEXP (x, 1), mode) + & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0) + result --; + + return result; + + case ASHIFTRT: + /* Shifts by a constant add to the number of bits equal to the + sign bit. */ + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + if (GET_CODE (XEXP (x, 1)) == CONST_INT + && INTVAL (XEXP (x, 1)) > 0) + num0 = MIN (bitwidth, num0 + INTVAL (XEXP (x, 1))); + + return num0; + + case ASHIFT: + case LSHIFT: + /* Left shifts destroy copies. */ + if (GET_CODE (XEXP (x, 1)) != CONST_INT + || INTVAL (XEXP (x, 1)) < 0 + || INTVAL (XEXP (x, 1)) >= bitwidth) + return 1; + + num0 = num_sign_bit_copies (XEXP (x, 0), mode); + return MAX (1, num0 - INTVAL (XEXP (x, 1))); + + case IF_THEN_ELSE: + num0 = num_sign_bit_copies (XEXP (x, 1), mode); + num1 = num_sign_bit_copies (XEXP (x, 2), mode); + return MIN (num0, num1); + + #if STORE_FLAG_VALUE == -1 + case EQ: case NE: case GE: case GT: case LE: case LT: + case GEU: case GTU: case LEU: case LTU: + return bitwidth; + #endif + } + + /* If we haven't been able to figure it out by one of the above rules, + see if some of the high-order bits are known to be zero. If so, + count those bits and return one less than that amount. */ + + sig = significant_bits (x, mode); + return sig == GET_MODE_MASK (mode) ? 1 : bitwidth - floor_log2 (sig) - 1; + } + + /* Return the number of "extended" bits there are in X, when interpreted + as a quantity in MODE whose signedness is indicated by UNSIGNEDP. For + unsigned quantities, this is the number of high-order zero bits. + For signed quantities, this is the number of copies of the sign bit + minus 1. In both case, this function returns the number of "spare" + bits. For example, if two quantities for which this function returns + at least 1 are added, the addition is known not to overflow. + + This function will always return 0 unless called during combine, which + implies that it must be called from a define_split. */ + + int + extended_count (x, mode, unsignedp) + rtx x; + enum machine_mode mode; + int unsignedp; + { + if (significant_valid == 0) + return 0; + + return (unsignedp + ? (GET_MODE_BITSIZE (mode) - 1 + - floor_log2 (significant_bits (x, mode))) + : num_sign_bit_copies (x, mode) - 1); + } + /* This function is called from `simplify_shift_const' to merge two outer operations. Specifically, we have already found that we need *************** *** 5366,5370 **** MODE is the mode in which the operation will be done. No bits outside the width of this mode matter. It is assumed that the width of this mode ! is smaller than or equal to HOST_BITS_PER_INT. If *POP0 or OP1 are NIL, it means no operation is required. Only NEG, PLUS, --- 6485,6489 ---- MODE is the mode in which the operation will be done. No bits outside the width of this mode matter. It is assumed that the width of this mode ! is smaller than or equal to HOST_BITS_PER_WIDE_INT. If *POP0 or OP1 are NIL, it means no operation is required. Only NEG, PLUS, *************** *** 5378,5389 **** merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) enum rtx_code *pop0; ! int *pconst0; enum rtx_code op1; ! int const1; enum machine_mode mode; int *pcomp_p; { enum rtx_code op0 = *pop0; ! int const0 = *pconst0; const0 &= GET_MODE_MASK (mode); --- 6497,6508 ---- merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p) enum rtx_code *pop0; ! HOST_WIDE_INT *pconst0; enum rtx_code op1; ! HOST_WIDE_INT const1; enum machine_mode mode; int *pcomp_p; { enum rtx_code op0 = *pop0; ! HOST_WIDE_INT const0 = *pconst0; const0 &= GET_MODE_MASK (mode); *************** *** 5505,5509 **** /* We form (outer_op (code varop count) (outer_const)). */ enum rtx_code outer_op = NIL; ! int outer_const; rtx const_rtx; int complement_p = 0; --- 6624,6628 ---- /* We form (outer_op (code varop count) (outer_const)). */ enum rtx_code outer_op = NIL; ! HOST_WIDE_INT outer_const; rtx const_rtx; int complement_p = 0; *************** *** 5518,5522 **** return x; ! return gen_rtx (code, mode, varop, gen_rtx (CONST_INT, VOIDmode, count)); } --- 6637,6641 ---- return x; ! return gen_rtx (code, mode, varop, GEN_INT (count)); } *************** *** 5582,5593 **** abort (); /* We simplify the tests below and elsewhere by converting ASHIFTRT to LSHIFTRT if we know the sign bit is clear. `make_compound_operation' will convert it to a ASHIFTRT for those machines (such as Vax) that don't have a LSHIFTRT. */ ! if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_INT && code == ASHIFTRT ! && (significant_bits (varop, shift_mode) ! & (1 << (GET_MODE_BITSIZE (shift_mode) - 1))) == 0) code = LSHIFTRT; --- 6701,6723 ---- abort (); + /* An arithmetic right shift of a quantity known to be -1 or 0 + is a no-op. */ + if (code == ASHIFTRT + && (num_sign_bit_copies (varop, shift_mode) + == GET_MODE_BITSIZE (shift_mode))) + { + count = 0; + break; + } + /* We simplify the tests below and elsewhere by converting ASHIFTRT to LSHIFTRT if we know the sign bit is clear. `make_compound_operation' will convert it to a ASHIFTRT for those machines (such as Vax) that don't have a LSHIFTRT. */ ! if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT && code == ASHIFTRT ! && ((significant_bits (varop, shift_mode) ! & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (shift_mode) - 1))) ! == 0)) code = LSHIFTRT; *************** *** 5663,5667 **** the same number of words as what we've seen so far. Then store the widest mode in MODE. */ ! if (SUBREG_WORD (varop) == 0 && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop))) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) --- 6793,6799 ---- the same number of words as what we've seen so far. Then store the widest mode in MODE. */ ! if (subreg_lowpart_p (varop) ! && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop))) ! > GET_MODE_SIZE (GET_MODE (varop))) && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop))) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) *************** *** 5683,5688 **** { varop = gen_binary (ASHIFT, GET_MODE (varop), XEXP (varop, 0), ! gen_rtx (CONST_INT, VOIDmode, ! exact_log2 (INTVAL (XEXP (varop, 1))))); continue; } --- 6815,6819 ---- { varop = gen_binary (ASHIFT, GET_MODE (varop), XEXP (varop, 0), ! GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1)))));; continue; } *************** *** 5695,5700 **** { varop = gen_binary (LSHIFTRT, GET_MODE (varop), XEXP (varop, 0), ! gen_rtx (CONST_INT, VOIDmode, ! exact_log2 (INTVAL (XEXP (varop, 1))))); continue; } --- 6826,6830 ---- { varop = gen_binary (LSHIFTRT, GET_MODE (varop), XEXP (varop, 0), ! GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1))))); continue; } *************** *** 5721,5730 **** && INTVAL (XEXP (varop, 1)) >= 0 && INTVAL (XEXP (varop, 1)) < GET_MODE_BITSIZE (GET_MODE (varop)) ! && GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_INT ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT) { enum rtx_code first_code = GET_CODE (varop); int first_count = INTVAL (XEXP (varop, 1)); ! unsigned int mask; rtx mask_rtx; rtx inner; --- 6851,6860 ---- && INTVAL (XEXP (varop, 1)) >= 0 && INTVAL (XEXP (varop, 1)) < GET_MODE_BITSIZE (GET_MODE (varop)) ! && GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) { enum rtx_code first_code = GET_CODE (varop); int first_count = INTVAL (XEXP (varop, 1)); ! unsigned HOST_WIDE_INT mask; rtx mask_rtx; rtx inner; *************** *** 5746,5754 **** /* C3 has the low-order C1 bits zero. */ ! mask = GET_MODE_MASK (mode) & ~ ((1 << first_count) - 1); ! varop = simplify_and_const_int (0, result_mode, XEXP (varop, 0), mask); ! varop = simplify_shift_const (0, ASHIFT, result_mode, varop, count); count = first_count; --- 6876,6885 ---- /* C3 has the low-order C1 bits zero. */ ! mask = (GET_MODE_MASK (mode) ! & ~ (((HOST_WIDE_INT) 1 << first_count) - 1)); ! varop = simplify_and_const_int (NULL_RTX, result_mode, XEXP (varop, 0), mask); ! varop = simplify_shift_const (NULL_RTX, ASHIFT, result_mode, varop, count); count = first_count; *************** *** 5757,5768 **** } ! /* If this was (ashiftrt (ashift foo C1) C2) and we know ! something about FOO's previous value, we may be able to ! optimize this even though the code below can't handle this ! case. ! ! If FOO has J high-order bits equal to the sign bit with ! J > C1, then we can convert this to either an ASHIFT or ! a ASHIFTRT depending on the two counts. We cannot do this if VAROP's mode is not SHIFT_MODE. */ --- 6888,6895 ---- } ! /* If this was (ashiftrt (ashift foo C1) C2) and FOO has more ! than C1 high-order bits equal to the sign bit, we can convert ! this to either an ASHIFT or a ASHIFTRT depending on the ! two counts. We cannot do this if VAROP's mode is not SHIFT_MODE. */ *************** *** 5770,5792 **** if (code == ASHIFTRT && first_code == ASHIFT && GET_MODE (varop) == shift_mode ! && (inner = get_last_value (XEXP (varop, 0))) != 0) { ! if ((GET_CODE (inner) == CONST_INT ! && (INTVAL (inner) >> (HOST_BITS_PER_INT - (first_count + 1)) == 0 ! || (INTVAL (inner) >> (HOST_BITS_PER_INT - (first_count + 1)) == -1))) ! || (GET_CODE (inner) == SIGN_EXTEND ! && ((GET_MODE_BITSIZE (GET_MODE (inner)) ! - GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (inner)))) ! >= first_count)) ! || (GET_CODE (inner) == ASHIFTRT ! && GET_CODE (XEXP (inner, 1)) == CONST_INT ! && INTVAL (XEXP (inner, 1)) >= first_count)) ! { ! count -= first_count; ! if (count < 0) ! count = - count, code = ASHIFT; ! varop = XEXP (varop, 0); ! continue; ! } } --- 6897,6908 ---- if (code == ASHIFTRT && first_code == ASHIFT && GET_MODE (varop) == shift_mode ! && (num_sign_bit_copies (XEXP (varop, 0), shift_mode) ! > first_count)) { ! count -= first_count; ! if (count < 0) ! count = - count, code = ASHIFT; ! varop = XEXP (varop, 0); ! continue; } *************** *** 5819,5823 **** if (code == ASHIFTRT || (code == ROTATE && first_code == ASHIFTRT) ! || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_INT || (GET_MODE (varop) != result_mode && (first_code == ASHIFTRT || first_code == ROTATE --- 6935,6939 ---- if (code == ASHIFTRT || (code == ROTATE && first_code == ASHIFTRT) ! || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT || (GET_MODE (varop) != result_mode && (first_code == ASHIFTRT || first_code == ROTATE *************** *** 5829,5839 **** outer shift will. */ ! mask_rtx = gen_rtx (CONST_INT, VOIDmode, ! significant_bits (varop, GET_MODE (varop))); mask_rtx = simplify_binary_operation (code, result_mode, mask_rtx, ! gen_rtx (CONST_INT, VOIDmode, ! count)); /* Give up if we can't compute an outer operation to use. */ --- 6945,6953 ---- outer shift will. */ ! mask_rtx = GEN_INT (significant_bits (varop, GET_MODE (varop))); mask_rtx = simplify_binary_operation (code, result_mode, mask_rtx, ! GEN_INT (count)); /* Give up if we can't compute an outer operation to use. */ *************** *** 5877,5883 **** = simplify_binary_operation (code, mode, XEXP (varop, 0), ! gen_rtx (CONST_INT, ! VOIDmode, ! count)))) { varop = gen_rtx_combine (code, mode, new, XEXP (varop, 1)); --- 6991,6995 ---- = simplify_binary_operation (code, mode, XEXP (varop, 0), ! GEN_INT (count)))) { varop = gen_rtx_combine (code, mode, new, XEXP (varop, 1)); *************** *** 5890,5895 **** /* Make this fit the case below. */ varop = gen_rtx_combine (XOR, mode, XEXP (varop, 0), ! gen_rtx (CONST_INT, VOIDmode, ! GET_MODE_MASK (mode))); continue; --- 7002,7006 ---- /* Make this fit the case below. */ varop = gen_rtx_combine (XOR, mode, XEXP (varop, 0), ! GEN_INT (GET_MODE_MASK (mode))); continue; *************** *** 5930,5936 **** && (new = simplify_binary_operation (code, result_mode, XEXP (varop, 1), ! gen_rtx (CONST_INT, ! VOIDmode, ! count))) != 0 && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop), INTVAL (new), result_mode, &complement_p)) --- 7041,7045 ---- && (new = simplify_binary_operation (code, result_mode, XEXP (varop, 1), ! GEN_INT (count))) != 0 && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop), INTVAL (new), result_mode, &complement_p)) *************** *** 5944,5950 **** the inverse distributive law. */ { ! rtx lhs = simplify_shift_const (0, code, result_mode, XEXP (varop, 0), count); ! rtx rhs = simplify_shift_const (0, code, result_mode, XEXP (varop, 1), count); --- 7053,7059 ---- the inverse distributive law. */ { ! rtx lhs = simplify_shift_const (NULL_RTX, code, result_mode, XEXP (varop, 0), count); ! rtx rhs = simplify_shift_const (NULL_RTX, code, result_mode, XEXP (varop, 1), count); *************** *** 5965,5974 **** && GET_MODE (XEXP (varop, 0)) == result_mode && count == GET_MODE_BITSIZE (result_mode) - 1 ! && GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_INT && ((STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (result_mode) - 1)))) && significant_bits (XEXP (varop, 0), result_mode) == 1 ! && merge_outer_ops (&outer_op, &outer_const, XOR, 1, ! result_mode, &complement_p)) { varop = XEXP (varop, 0); --- 7074,7084 ---- && GET_MODE (XEXP (varop, 0)) == result_mode && count == GET_MODE_BITSIZE (result_mode) - 1 ! && GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT && ((STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (result_mode) - 1)))) && significant_bits (XEXP (varop, 0), result_mode) == 1 ! && merge_outer_ops (&outer_op, &outer_const, XOR, ! (HOST_WIDE_INT) 1, result_mode, ! &complement_p)) { varop = XEXP (varop, 0); *************** *** 5979,5987 **** case NEG: ! /* If we are doing an arithmetic right shift of something known ! to be -1 or 0, we don't need the shift. */ ! if (code == ASHIFTRT && significant_bits (XEXP (varop, 0), result_mode) == 1) { count = 0; continue; --- 7089,7098 ---- case NEG: ! /* (lshiftrt (neg A) C) where A is either 0 or 1 and C is one less ! than the number of bits in the mode is equivalent to A. */ ! if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1 && significant_bits (XEXP (varop, 0), result_mode) == 1) { + varop = XEXP (varop, 0); count = 0; continue; *************** *** 5991,5996 **** NEG outside to allow shifts to combine. */ if (code == ASHIFT ! && merge_outer_ops (&outer_op, &outer_const, NEG, 0, ! result_mode, &complement_p)) { varop = XEXP (varop, 0); --- 7102,7108 ---- NEG outside to allow shifts to combine. */ if (code == ASHIFT ! && merge_outer_ops (&outer_op, &outer_const, NEG, ! (HOST_WIDE_INT) 0, result_mode, ! &complement_p)) { varop = XEXP (varop, 0); *************** *** 6000,6019 **** case PLUS: ! /* Similar to case above. If X is 0 or 1 then X - 1 is -1 or 0. */ ! if (XEXP (varop, 1) == constm1_rtx && code == ASHIFTRT ! && significant_bits (XEXP (varop, 0), result_mode) == 1) ! { ! count = 0; ! continue; ! } ! ! /* If we have the same operands as above but we are shifting the ! sign bit into the low-order bit, we are exclusive-or'ing ! the operand of the PLUS with a one. */ if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1 && XEXP (varop, 1) == constm1_rtx && significant_bits (XEXP (varop, 0), result_mode) == 1 ! && merge_outer_ops (&outer_op, &outer_const, XOR, 1, ! result_mode, &complement_p)) { count = 0; --- 7112,7124 ---- case PLUS: ! /* (lshiftrt (plus A -1) C) where A is either 0 or 1 and C ! is one less than the number of bits in the mode is ! equivalent to (xor A 1). */ if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1 && XEXP (varop, 1) == constm1_rtx && significant_bits (XEXP (varop, 0), result_mode) == 1 ! && merge_outer_ops (&outer_op, &outer_const, XOR, ! (HOST_WIDE_INT) 1, result_mode, ! &complement_p)) { count = 0; *************** *** 6029,6033 **** if ((code == ASHIFTRT || code == LSHIFTRT) ! && count < HOST_BITS_PER_INT && significant_bits (XEXP (varop, 1), result_mode) >> count == 0 && (significant_bits (XEXP (varop, 1), result_mode) --- 7134,7138 ---- if ((code == ASHIFTRT || code == LSHIFTRT) ! && count < HOST_BITS_PER_WIDE_INT && significant_bits (XEXP (varop, 1), result_mode) >> count == 0 && (significant_bits (XEXP (varop, 1), result_mode) *************** *** 6038,6042 **** } else if ((code == ASHIFTRT || code == LSHIFTRT) ! && count < HOST_BITS_PER_INT && 0 == (significant_bits (XEXP (varop, 0), result_mode) >> count) --- 7143,7147 ---- } else if ((code == ASHIFTRT || code == LSHIFTRT) ! && count < HOST_BITS_PER_WIDE_INT && 0 == (significant_bits (XEXP (varop, 0), result_mode) >> count) *************** *** 6054,6060 **** && (new = simplify_binary_operation (ASHIFT, result_mode, XEXP (varop, 1), ! gen_rtx (CONST_INT, ! VOIDmode, ! count))) != 0 && merge_outer_ops (&outer_op, &outer_const, PLUS, INTVAL (new), result_mode, &complement_p)) --- 7159,7163 ---- && (new = simplify_binary_operation (ASHIFT, result_mode, XEXP (varop, 1), ! GEN_INT (count))) != 0 && merge_outer_ops (&outer_op, &outer_const, PLUS, INTVAL (new), result_mode, &complement_p)) *************** *** 6117,6121 **** const_rtx = XEXP (x, 1); else ! const_rtx = gen_rtx (CONST_INT, VOIDmode, count); if (x && GET_CODE (XEXP (x, 0)) == SUBREG --- 7220,7224 ---- const_rtx = XEXP (x, 1); else ! const_rtx = GEN_INT (count); if (x && GET_CODE (XEXP (x, 0)) == SUBREG *************** *** 6145,6149 **** turn off all the bits that the shift would have turned off. */ if (orig_code == LSHIFTRT && result_mode != shift_mode) ! x = simplify_and_const_int (0, shift_mode, x, GET_MODE_MASK (result_mode) >> orig_count); --- 7248,7252 ---- turn off all the bits that the shift would have turned off. */ if (orig_code == LSHIFTRT && result_mode != shift_mode) ! x = simplify_and_const_int (NULL_RTX, shift_mode, x, GET_MODE_MASK (result_mode) >> orig_count); *************** *** 6158,6175 **** if (outer_op != NIL) { ! if (GET_MODE_BITSIZE (result_mode) < HOST_BITS_PER_INT) outer_const &= GET_MODE_MASK (result_mode); if (outer_op == AND) ! x = simplify_and_const_int (0, result_mode, x, outer_const); else if (outer_op == SET) /* This means that we have determined that the result is equivalent to a constant. This should be rare. */ ! x = gen_rtx (CONST_INT, VOIDmode, outer_const); else if (GET_RTX_CLASS (outer_op) == '1') x = gen_unary (outer_op, result_mode, x); else ! x = gen_binary (outer_op, result_mode, x, ! gen_rtx (CONST_INT, VOIDmode, outer_const)); } --- 7261,7277 ---- if (outer_op != NIL) { ! if (GET_MODE_BITSIZE (result_mode) < HOST_BITS_PER_WIDE_INT) outer_const &= GET_MODE_MASK (result_mode); if (outer_op == AND) ! x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const); else if (outer_op == SET) /* This means that we have determined that the result is equivalent to a constant. This should be rare. */ ! x = GEN_INT (outer_const); else if (GET_RTX_CLASS (outer_op) == '1') x = gen_unary (outer_op, result_mode, x); else ! x = gen_binary (outer_op, result_mode, x, GEN_INT (outer_const)); } *************** *** 6401,6413 **** for (i = previous_num_undos; i < undobuf.num_undo; i++) if (!undobuf.undo[i].is_int ! && GET_CODE (undobuf.undo[i].old_contents) == code ! && GET_MODE (undobuf.undo[i].old_contents) == mode) { for (j = 0; j < n_args; j++) ! if (XEXP (undobuf.undo[i].old_contents, j) != args[j]) break; if (j == n_args) ! return undobuf.undo[i].old_contents; } --- 7503,7515 ---- for (i = previous_num_undos; i < undobuf.num_undo; i++) if (!undobuf.undo[i].is_int ! && GET_CODE (undobuf.undo[i].old_contents.rtx) == code ! && GET_MODE (undobuf.undo[i].old_contents.rtx) == mode) { for (j = 0; j < n_args; j++) ! if (XEXP (undobuf.undo[i].old_contents.rtx, j) != args[j]) break; if (j == n_args) ! return undobuf.undo[i].old_contents.rtx; } *************** *** 6436,6439 **** --- 7538,7547 ---- { rtx result; + rtx tem; + + if (GET_RTX_CLASS (code) == 'c' + && (GET_CODE (op0) == CONST_INT + || (CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT))) + tem = op0, op0 = op1, op1 = tem; if (GET_RTX_CLASS (code) == '<') *************** *** 6508,6512 **** comparison is compatible with the shift. */ if (GET_CODE (op0) == GET_CODE (op1) ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_INT && ((GET_CODE (op0) == ROTATE && (code == NE || code == EQ)) || ((GET_CODE (op0) == LSHIFTRT --- 7616,7620 ---- comparison is compatible with the shift. */ if (GET_CODE (op0) == GET_CODE (op1) ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT && ((GET_CODE (op0) == ROTATE && (code == NE || code == EQ)) || ((GET_CODE (op0) == LSHIFTRT *************** *** 6518,6526 **** && GET_CODE (XEXP (op0, 1)) == CONST_INT && INTVAL (XEXP (op0, 1)) >= 0 ! && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_INT && XEXP (op0, 1) == XEXP (op1, 1)) { enum machine_mode mode = GET_MODE (op0); ! unsigned mask = GET_MODE_MASK (mode); int shift_count = INTVAL (XEXP (op0, 1)); --- 7626,7634 ---- && GET_CODE (XEXP (op0, 1)) == CONST_INT && INTVAL (XEXP (op0, 1)) >= 0 ! && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT && XEXP (op0, 1) == XEXP (op1, 1)) { enum machine_mode mode = GET_MODE (op0); ! unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode); int shift_count = INTVAL (XEXP (op0, 1)); *************** *** 6590,6598 **** enum machine_mode mode = GET_MODE (op0); int mode_width = GET_MODE_BITSIZE (mode); ! unsigned mask = GET_MODE_MASK (mode); int equality_comparison_p; int sign_bit_comparison_p; int unsigned_comparison_p; ! int const_op; /* We only want to handle integral modes. This catches VOIDmode, --- 7698,7706 ---- enum machine_mode mode = GET_MODE (op0); int mode_width = GET_MODE_BITSIZE (mode); ! unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode); int equality_comparison_p; int sign_bit_comparison_p; int unsigned_comparison_p; ! HOST_WIDE_INT const_op; /* We only want to handle integral modes. This catches VOIDmode, *************** *** 6610,6614 **** not on in our mode. */ const_op = INTVAL (op1); ! if (mode_width <= HOST_BITS_PER_INT) const_op &= mask; --- 7718,7722 ---- not on in our mode. */ const_op = INTVAL (op1); ! if (mode_width <= HOST_BITS_PER_WIDE_INT) const_op &= mask; *************** *** 6620,6624 **** && (code == EQ || code == NE || code == GE || code == GEU || code == LT || code == LTU) ! && mode_width <= HOST_BITS_PER_INT && exact_log2 (const_op) >= 0 && significant_bits (op0, mode) == const_op) --- 7728,7732 ---- && (code == EQ || code == NE || code == GE || code == GEU || code == LT || code == LTU) ! && mode_width <= HOST_BITS_PER_WIDE_INT && exact_log2 (const_op) >= 0 && significant_bits (op0, mode) == const_op) *************** *** 6628,6631 **** --- 7736,7751 ---- } + /* Similarly, if we are comparing a value known to be either -1 or + 0 with -1, change it to the opposite comparison against zero. */ + + if (const_op == -1 + && (code == EQ || code == NE || code == GT || code == LE + || code == GEU || code == LTU) + && num_sign_bit_copies (op0, mode) == mode_width) + { + code = (code == EQ || code == LE || code == GEU ? NE : EQ); + op1 = const0_rtx, const_op = 0; + } + /* Do some canonicalizations based on the comparison code. We prefer comparisons against zero and then prefer equality comparisons. *************** *** 6639,6643 **** { const_op -= 1; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); code = LE; /* ... fall through to LE case below. */ --- 7759,7763 ---- { const_op -= 1; ! op1 = GEN_INT (const_op); code = LE; /* ... fall through to LE case below. */ *************** *** 6651,6655 **** { const_op += 1; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); code = LT; } --- 7771,7775 ---- { const_op += 1; ! op1 = GEN_INT (const_op); code = LT; } *************** *** 6658,6664 **** a zero sign bit, we can replace this with == 0. */ else if (const_op == 0 ! && mode_width <= HOST_BITS_PER_INT && (significant_bits (op0, mode) ! & (1 << (mode_width - 1))) == 0) code = EQ; break; --- 7778,7784 ---- a zero sign bit, we can replace this with == 0. */ else if (const_op == 0 ! && mode_width <= HOST_BITS_PER_WIDE_INT && (significant_bits (op0, mode) ! & ((HOST_WIDE_INT) 1 << (mode_width - 1))) == 0) code = EQ; break; *************** *** 6669,6673 **** { const_op -= 1; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); code = GT; /* ... fall through to GT below. */ --- 7789,7793 ---- { const_op -= 1; ! op1 = GEN_INT (const_op); code = GT; /* ... fall through to GT below. */ *************** *** 6681,6685 **** { const_op += 1; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); code = GE; } --- 7801,7805 ---- { const_op += 1; ! op1 = GEN_INT (const_op); code = GE; } *************** *** 6688,6694 **** a zero sign bit, we can replace this with != 0. */ else if (const_op == 0 ! && mode_width <= HOST_BITS_PER_INT && (significant_bits (op0, mode) ! & (1 << (mode_width - 1))) == 0) code = NE; break; --- 7808,7814 ---- a zero sign bit, we can replace this with != 0. */ else if (const_op == 0 ! && mode_width <= HOST_BITS_PER_WIDE_INT && (significant_bits (op0, mode) ! & ((HOST_WIDE_INT) 1 << (mode_width - 1))) == 0) code = NE; break; *************** *** 6699,6706 **** { const_op -= 1; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); code = LEU; /* ... fall through ... */ } else break; --- 7819,7834 ---- { const_op -= 1; ! op1 = GEN_INT (const_op); code = LEU; /* ... fall through ... */ } + + /* (unsigned) < 0x80000000 is equivalent to >= 0. */ + else if (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1)) + { + const_op = 0, op1 = const0_rtx; + code = GE; + break; + } else break; *************** *** 6710,6713 **** --- 7838,7848 ---- if (const_op == 0) code = EQ; + + /* (unsigned) <= 0x7fffffff is equivalent to >= 0. */ + else if (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1) + { + const_op = 0, op1 = const0_rtx; + code = GE; + } break; *************** *** 6717,6724 **** { const_op -= 1; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); code = GTU; /* ... fall through ... */ } else break; --- 7852,7866 ---- { const_op -= 1; ! op1 = GEN_INT (const_op); code = GTU; /* ... fall through ... */ } + + /* (unsigned) >= 0x80000000 is equivalent to < 0. */ + else if (const_op == (HOST_WIDE_INT) 1 << (mode_width - 1)) + { + const_op = 0, op1 = const0_rtx; + code = LT; + } else break; *************** *** 6728,6731 **** --- 7870,7880 ---- if (const_op == 0) code = NE; + + /* (unsigned) > 0x7fffffff is equivalent to < 0. */ + else if (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1) + { + const_op = 0, op1 = const0_rtx; + code = LT; + } break; } *************** *** 6764,6768 **** op0 = XEXP (op0, 2); ! op1 = gen_rtx (CONST_INT, VOIDmode, i); const_op = i; --- 7913,7917 ---- op0 = XEXP (op0, 2); ! op1 = GEN_INT (i); const_op = i; *************** *** 6823,6829 **** if (sign_bit_comparison_p && (GET_CODE (XEXP (op0, 0)) == ABS ! || (mode_width <= HOST_BITS_PER_INT && (significant_bits (XEXP (op0, 0), mode) ! & (1 << (mode_width - 1))) == 0))) { op0 = XEXP (op0, 0); --- 7972,7978 ---- if (sign_bit_comparison_p && (GET_CODE (XEXP (op0, 0)) == ABS ! || (mode_width <= HOST_BITS_PER_WIDE_INT && (significant_bits (XEXP (op0, 0), mode) ! & ((HOST_WIDE_INT) 1 << (mode_width - 1))) == 0))) { op0 = XEXP (op0, 0); *************** *** 6878,6886 **** if (const_op == 0 && sign_bit_comparison_p && GET_CODE (XEXP (op0, 1)) == CONST_INT ! && mode_width <= HOST_BITS_PER_INT) { ! op0 = simplify_and_const_int (0, mode, XEXP (op0, 0), ! 1 << (mode_width - 1 ! - INTVAL (XEXP (op0, 1)))); code = (code == LT ? NE : EQ); continue; --- 8027,8036 ---- if (const_op == 0 && sign_bit_comparison_p && GET_CODE (XEXP (op0, 1)) == CONST_INT ! && mode_width <= HOST_BITS_PER_WIDE_INT) { ! op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0), ! ((HOST_WIDE_INT) 1 ! << (mode_width - 1 ! - INTVAL (XEXP (op0, 1))))); code = (code == LT ? NE : EQ); continue; *************** *** 6906,6912 **** if (! unsigned_comparison_p && (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) ! <= HOST_BITS_PER_INT) ! && ((unsigned) const_op ! < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) - 1)))) { op0 = XEXP (op0, 0); --- 8056,8063 ---- if (! unsigned_comparison_p && (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) ! <= HOST_BITS_PER_WIDE_INT) ! && ((unsigned HOST_WIDE_INT) const_op ! < (((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) - 1))))) { op0 = XEXP (op0, 0); *************** *** 6916,6923 **** case SUBREG: ! /* If the inner mode is smaller and we are extracting the low ! part, we can treat the SUBREG as if it were a ZERO_EXTEND. */ ! if (! subreg_lowpart_p (op0) ! || GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) >= mode_width) break; --- 8067,8105 ---- case SUBREG: ! /* Check for the case where we are comparing A - C1 with C2, ! both constants are smaller than 1/2 the maxium positive ! value in MODE, and the comparison is equality or unsigned. ! In that case, if A is either zero-extended to MODE or has ! sufficient sign bits so that the high-order bit in MODE ! is a copy of the sign in the inner mode, we can prove that it is ! safe to do the operation in the wider mode. This simplifies ! many range checks. */ ! ! if (mode_width <= HOST_BITS_PER_WIDE_INT ! && subreg_lowpart_p (op0) ! && GET_CODE (SUBREG_REG (op0)) == PLUS ! && GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT ! && INTVAL (XEXP (SUBREG_REG (op0), 1)) < 0 ! && (- INTVAL (XEXP (SUBREG_REG (op0), 1)) ! < GET_MODE_MASK (mode) / 2) ! && (unsigned) const_op < GET_MODE_MASK (mode) / 2 ! && (0 == (significant_bits (XEXP (SUBREG_REG (op0), 0), ! GET_MODE (SUBREG_REG (op0))) ! & ~ GET_MODE_MASK (mode)) ! || (num_sign_bit_copies (XEXP (SUBREG_REG (op0), 0), ! GET_MODE (SUBREG_REG (op0))) ! > (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) ! - GET_MODE_BITSIZE (mode))))) ! { ! op0 = SUBREG_REG (op0); ! continue; ! } ! ! /* If the inner mode is narrower and we are extracting the low part, ! we can treat the SUBREG as if it were a ZERO_EXTEND. */ ! if (subreg_lowpart_p (op0) ! && GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) < mode_width) ! /* Fall through */ ; ! else break; *************** *** 6927,6932 **** if ((unsigned_comparison_p || equality_comparison_p) && (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) ! <= HOST_BITS_PER_INT) ! && ((unsigned) const_op < GET_MODE_MASK (GET_MODE (XEXP (op0, 0))))) { --- 8109,8114 ---- if ((unsigned_comparison_p || equality_comparison_p) && (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) ! <= HOST_BITS_PER_WIDE_INT) ! && ((unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (GET_MODE (XEXP (op0, 0))))) { *************** *** 7008,7015 **** if (code == NE || (code == EQ && reversible_comparison_p (op0)) ! || (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_INT && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))) && (code == LT || (code == GE && reversible_comparison_p (op0))))) --- 8190,8198 ---- if (code == NE || (code == EQ && reversible_comparison_p (op0)) ! || (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && (STORE_FLAG_VALUE ! & (((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1)))) && (code == LT || (code == GE && reversible_comparison_p (op0))))) *************** *** 7047,7051 **** XEXP (op0, 1), XEXP (XEXP (op0, 0), 1)), ! 1); continue; } --- 8230,8234 ---- XEXP (op0, 1), XEXP (XEXP (op0, 0), 1)), ! (HOST_WIDE_INT) 1); continue; } *************** *** 7055,7064 **** in STORE_FLAG_VALUE, we can compare with X. */ if (const_op == 0 && equality_comparison_p ! && mode_width <= HOST_BITS_PER_INT && GET_CODE (XEXP (op0, 1)) == CONST_INT && GET_CODE (XEXP (op0, 0)) == LSHIFTRT && GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (op0, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (op0, 0), 1)) < HOST_BITS_PER_INT) { mask = ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode)) --- 8238,8247 ---- in STORE_FLAG_VALUE, we can compare with X. */ if (const_op == 0 && equality_comparison_p ! && mode_width <= HOST_BITS_PER_WIDE_INT && GET_CODE (XEXP (op0, 1)) == CONST_INT && GET_CODE (XEXP (op0, 0)) == LSHIFTRT && GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (op0, 0), 1)) >= 0 ! && INTVAL (XEXP (XEXP (op0, 0), 1)) < HOST_BITS_PER_WIDE_INT) { mask = ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode)) *************** *** 7080,7086 **** && const_op == 0 && GET_CODE (XEXP (op0, 1)) == CONST_INT ! && mode_width <= HOST_BITS_PER_INT && ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode)) ! == 1 << (mode_width - 1))) { op0 = XEXP (op0, 0); --- 8263,8269 ---- && const_op == 0 && GET_CODE (XEXP (op0, 1)) == CONST_INT ! && mode_width <= HOST_BITS_PER_WIDE_INT && ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode)) ! == (HOST_WIDE_INT) 1 << (mode_width - 1))) { op0 = XEXP (op0, 0); *************** *** 7116,7122 **** && INTVAL (XEXP (op0, 1)) >= 0 && ((INTVAL (XEXP (op0, 1)) + ! equality_comparison_p) ! < HOST_BITS_PER_INT) ! && (const_op & ~ ((1 << INTVAL (XEXP (op0, 1))) - 1)) == 0 ! && mode_width <= HOST_BITS_PER_INT && (significant_bits (XEXP (op0, 0), mode) & ~ (mask >> (INTVAL (XEXP (op0, 1)) --- 8299,8306 ---- && INTVAL (XEXP (op0, 1)) >= 0 && ((INTVAL (XEXP (op0, 1)) + ! equality_comparison_p) ! < HOST_BITS_PER_WIDE_INT) ! && ((const_op ! & ((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1) == 0) ! && mode_width <= HOST_BITS_PER_WIDE_INT && (significant_bits (XEXP (op0, 0), mode) & ~ (mask >> (INTVAL (XEXP (op0, 1)) *************** *** 7124,7128 **** { const_op >>= INTVAL (XEXP (op0, 1)); ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); op0 = XEXP (op0, 0); continue; --- 8308,8312 ---- { const_op >>= INTVAL (XEXP (op0, 1)); ! op1 = GEN_INT (const_op); op0 = XEXP (op0, 0); continue; *************** *** 7132,7140 **** a particular bit. Convert it to the appropriate AND. */ if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 1)) == CONST_INT ! && mode_width <= HOST_BITS_PER_INT) { ! op0 = simplify_and_const_int (0, mode, XEXP (op0, 0), ! 1 << ( mode_width - 1 ! - INTVAL (XEXP (op0, 1)))); code = (code == LT ? NE : EQ); continue; --- 8316,8325 ---- a particular bit. Convert it to the appropriate AND. */ if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 1)) == CONST_INT ! && mode_width <= HOST_BITS_PER_WIDE_INT) { ! op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0), ! ((HOST_WIDE_INT) 1 ! << (mode_width - 1 ! - INTVAL (XEXP (op0, 1))))); code = (code == LT ? NE : EQ); continue; *************** *** 7148,7152 **** && INTVAL (XEXP (op0, 1)) == mode_width - 1) { ! op0 = simplify_and_const_int (0, mode, XEXP (op0, 0), 1); continue; } --- 8333,8338 ---- && INTVAL (XEXP (op0, 1)) == mode_width - 1) { ! op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0), ! (HOST_WIDE_INT) 1); continue; } *************** *** 7154,7157 **** --- 8340,8354 ---- case ASHIFTRT: + /* If this is an equality comparison with zero, we can do this + as a logical shift, which might be much simpler. */ + if (equality_comparison_p && const_op == 0 + && GET_CODE (XEXP (op0, 1)) == CONST_INT) + { + op0 = simplify_shift_const (NULL_RTX, LSHIFTRT, mode, + XEXP (op0, 0), + INTVAL (XEXP (op0, 1))); + continue; + } + /* If OP0 is a sign extension and CODE is not an unsigned comparison, do the comparison in a narrower mode. */ *************** *** 7162,7167 **** && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)), MODE_INT, 1)) != VOIDmode ! && ((unsigned) const_op <= GET_MODE_MASK (tmode) ! || (unsigned) - const_op <= GET_MODE_MASK (tmode))) { op0 = gen_lowpart_for_combine (tmode, XEXP (XEXP (op0, 0), 0)); --- 8359,8365 ---- && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)), MODE_INT, 1)) != VOIDmode ! && ((unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (tmode) ! || ((unsigned HOST_WIDE_INT) - const_op ! <= GET_MODE_MASK (tmode)))) { op0 = gen_lowpart_for_combine (tmode, XEXP (XEXP (op0, 0), 0)); *************** *** 7177,7184 **** if (GET_CODE (XEXP (op0, 1)) == CONST_INT && INTVAL (XEXP (op0, 1)) >= 0 ! && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_INT ! && mode_width <= HOST_BITS_PER_INT && (significant_bits (XEXP (op0, 0), mode) ! & ((1 << INTVAL (XEXP (op0, 1))) - 1)) == 0 && (const_op == 0 || (floor_log2 (const_op) + INTVAL (XEXP (op0, 1)) --- 8375,8382 ---- if (GET_CODE (XEXP (op0, 1)) == CONST_INT && INTVAL (XEXP (op0, 1)) >= 0 ! && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT ! && mode_width <= HOST_BITS_PER_WIDE_INT && (significant_bits (XEXP (op0, 0), mode) ! & (((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1)) == 0 && (const_op == 0 || (floor_log2 (const_op) + INTVAL (XEXP (op0, 1)) *************** *** 7186,7190 **** { const_op <<= INTVAL (XEXP (op0, 1)); ! op1 = gen_rtx (CONST_INT, VOIDmode, const_op); op0 = XEXP (op0, 0); continue; --- 8384,8388 ---- { const_op <<= INTVAL (XEXP (op0, 1)); ! op1 = GEN_INT (const_op); op0 = XEXP (op0, 0); continue; *************** *** 7231,7235 **** && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && (code == NE || code == EQ) ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_INT && (significant_bits (SUBREG_REG (op0), GET_MODE (SUBREG_REG (op0))) & ~ GET_MODE_MASK (GET_MODE (op0))) == 0 --- 8429,8433 ---- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT && (code == NE || code == EQ) ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT && (significant_bits (SUBREG_REG (op0), GET_MODE (SUBREG_REG (op0))) & ~ GET_MODE_MASK (GET_MODE (op0))) == 0 *************** *** 7243,7251 **** insns in all modes. If OP0's mode is an integer mode smaller than a word and we can't do a compare in that mode, see if there is a larger ! mode for which we can do the compare and where the only significant ! bits in OP0 and OP1 are those in the narrower mode. We can do ! this if this is an equality comparison, in which case we can ! merely widen the operation, or if we are testing the sign bit, in ! which case we can explicitly put in the test. */ mode = GET_MODE (op0); --- 8441,8446 ---- insns in all modes. If OP0's mode is an integer mode smaller than a word and we can't do a compare in that mode, see if there is a larger ! mode for which we can do the compare. There are a number of cases in ! which we can use the wider mode. */ mode = GET_MODE (op0); *************** *** 7254,7278 **** && cmp_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) for (tmode = GET_MODE_WIDER_MODE (mode); ! tmode != VOIDmode && GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_INT; tmode = GET_MODE_WIDER_MODE (tmode)) ! if (cmp_optab->handlers[(int) tmode].insn_code != CODE_FOR_nothing ! && (significant_bits (op0, tmode) & ~ GET_MODE_MASK (mode)) == 0 ! && (significant_bits (op1, tmode) & ~ GET_MODE_MASK (mode)) == 0 ! && (code == EQ || code == NE ! || (op1 == const0_rtx && (code == LT || code == GE) ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT))) ! { ! op0 = gen_lowpart_for_combine (tmode, op0); ! op1 = gen_lowpart_for_combine (tmode, op1); ! ! if (code == LT || code == GE) ! { ! op0 = gen_binary (AND, tmode, op0, ! gen_rtx (CONST_INT, VOIDmode, ! 1 << (GET_MODE_BITSIZE (mode) - 1))); ! code = (code == LT) ? NE : EQ; } ! break; } --- 8449,8492 ---- && cmp_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) for (tmode = GET_MODE_WIDER_MODE (mode); ! (tmode != VOIDmode ! && GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT); tmode = GET_MODE_WIDER_MODE (tmode)) ! if (cmp_optab->handlers[(int) tmode].insn_code != CODE_FOR_nothing) ! { ! /* If the only significant bits in OP0 and OP1 are those in the ! narrower mode and this is an equality or unsigned comparison, ! we can use the wider mode. Similarly for sign-extended ! values and equality or signed comparisons. */ ! if (((code == EQ || code == NE ! || code == GEU || code == GTU || code == LEU || code == LTU) ! && ((significant_bits (op0, tmode) & ~ GET_MODE_MASK (mode)) ! == 0) ! && ((significant_bits (op1, tmode) & ~ GET_MODE_MASK (mode)) ! == 0)) ! || ((code == EQ || code == NE ! || code == GE || code == GT || code == LE || code == LT) ! && (num_sign_bit_copies (op0, tmode) ! > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode)) ! && (num_sign_bit_copies (op1, tmode) ! > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode)))) ! { ! op0 = gen_lowpart_for_combine (tmode, op0); ! op1 = gen_lowpart_for_combine (tmode, op1); ! break; } ! /* If this is a test for negative, we can make an explicit ! test of the sign bit. */ ! ! if (op1 == const0_rtx && (code == LT || code == GE) ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) ! { ! op0 = gen_binary (AND, tmode, ! gen_lowpart_for_combine (tmode, op0), ! GEN_INT ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (mode) - 1))); ! code = (code == LT) ? NE : EQ; ! break; ! } } *************** *** 7439,7448 **** && SUBREG_REG (SET_DEST (setter)) == dest && subreg_lowpart_p (SET_DEST (setter))) ! record_value_for_reg ! (dest, record_dead_insn, ! gen_lowpart_for_combine (GET_MODE (SET_DEST (setter)), ! SET_SRC (setter))); else ! record_value_for_reg (dest, record_dead_insn, 0); } else if (GET_CODE (dest) == MEM --- 8653,8661 ---- && SUBREG_REG (SET_DEST (setter)) == dest && subreg_lowpart_p (SET_DEST (setter))) ! record_value_for_reg (dest, record_dead_insn, ! gen_lowpart_for_combine (GET_MODE (dest), ! SET_SRC (setter))); else ! record_value_for_reg (dest, record_dead_insn, NULL_RTX); } else if (GET_CODE (dest) == MEM *************** *** 7470,7474 **** reg_last_death[REGNO (XEXP (link, 0))] = insn; else if (REG_NOTE_KIND (link) == REG_INC) ! record_value_for_reg (XEXP (link, 0), insn, 0); } --- 8683,8687 ---- reg_last_death[REGNO (XEXP (link, 0))] = insn; else if (REG_NOTE_KIND (link) == REG_INC) ! record_value_for_reg (XEXP (link, 0), insn, NULL_RTX); } *************** *** 7561,7574 **** value = reg_last_set_value[regno]; ! /* If we don't have a value, it isn't for this basic block, or if it was ! set in a later insn that the ones we are processing, return 0. */ if (value == 0 || (reg_n_sets[regno] != 1 ! && (reg_last_set_label[regno] != label_tick ! || INSN_CUID (reg_last_set[regno]) >= subst_low_cuid))) return 0; ! /* If the value has all its register valid, return it. */ if (get_last_value_validate (&value, reg_last_set_label[regno], 0)) return value; --- 8774,8821 ---- value = reg_last_set_value[regno]; ! /* If we don't have a value or if it isn't for this basic block, return 0. */ if (value == 0 || (reg_n_sets[regno] != 1 ! && (reg_last_set_label[regno] != label_tick))) return 0; ! /* If the value was set in a later insn that the ones we are processing, ! we can't use it, but make a quick check to see if the previous insn ! set it to something. This is commonly the case when the same pseudo ! is used by repeated insns. */ ! ! if (reg_n_sets[regno] != 1 ! && INSN_CUID (reg_last_set[regno]) >= subst_low_cuid) ! { ! rtx insn, set; ! ! for (insn = prev_nonnote_insn (subst_insn); ! insn && INSN_CUID (insn) >= subst_low_cuid; ! insn = prev_nonnote_insn (insn)) ! ; ! ! if (insn ! && (set = single_set (insn)) != 0 ! && rtx_equal_p (SET_DEST (set), x)) ! { ! value = SET_SRC (set); ! ! /* Make sure that VALUE doesn't reference X. Replace any ! expliit references with a CLOBBER. If there are any remaining ! references (rare), don't use the value. */ ! ! if (reg_mentioned_p (x, value)) ! value = replace_rtx (copy_rtx (value), x, ! gen_rtx (CLOBBER, GET_MODE (x), const0_rtx)); ! ! if (reg_overlap_mentioned_p (x, value)) ! return 0; ! } ! else ! return 0; ! } ! ! /* If the value has all its registers valid, return it. */ if (get_last_value_validate (&value, reg_last_set_label[regno], 0)) return value; *************** *** 7709,7714 **** for (i = reg_dead_regno; i < reg_dead_endregno; i++) ! if (basic_block_live_at_start[block][i / HOST_BITS_PER_INT] ! & (1 << (i % HOST_BITS_PER_INT))) return 0; --- 8956,8961 ---- for (i = reg_dead_regno; i < reg_dead_endregno; i++) ! if (basic_block_live_at_start[block][i / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))) return 0; *************** *** 7728,7732 **** if (note) ! remove_note (insn, note); return note; --- 8975,8982 ---- if (note) ! { ! reg_n_deaths[regno]--; ! remove_note (insn, note); ! } return note; *************** *** 7773,7776 **** --- 9023,9028 ---- else *pnotes = gen_rtx (EXPR_LIST, REG_DEAD, x, *pnotes); + + reg_n_deaths[regno]++; } *************** *** 7943,7948 **** /* These notes say something about results of an insn. We can only support them if they used to be on I3 in which case they ! remain on I3. Otherwise they are ignored. */ ! if (from_insn == i3) place = i3; break; --- 9195,9209 ---- /* These notes say something about results of an insn. We can only support them if they used to be on I3 in which case they ! remain on I3. Otherwise they are ignored. ! ! If the note refers to an expression that is not a constant, we ! must also ignore the note since we cannot tell whether the ! equivalence is still true. It might be possible to do ! slightly better than this (we only have a problem if I2DEST ! or I1DEST is present in the expression), but it doesn't ! seem worth the trouble. */ ! ! if (from_insn == i3 ! && (XEXP (note, 0) == 0 || CONSTANT_P (XEXP (note, 0)))) place = i3; break; *************** *** 7978,7982 **** else { ! tem = find_reg_note (XEXP (note, 0), REG_LIBCALL, 0); place = prev_real_insn (from_insn); if (tem && place) --- 9239,9243 ---- else { ! tem = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX); place = prev_real_insn (from_insn); if (tem && place) *************** *** 7991,7995 **** else { ! tem = find_reg_note (XEXP (note, 0), REG_RETVAL, 0); place = next_real_insn (from_insn); if (tem && place) --- 9252,9256 ---- else { ! tem = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX); place = next_real_insn (from_insn); if (tem && place) *************** *** 8022,8025 **** --- 9283,9298 ---- break; + /* If the register is used in both I2 and I3 and it dies in I3, + we might have added another reference to it. If reg_n_refs + was 2, bump it to 3. This has to be correct since the + register must have been set somewhere. The reason this is + done is because local-alloc.c treats 2 references as a + special case. */ + + if (place == i3 && i2 != 0 && GET_CODE (XEXP (note, 0)) == REG + && reg_n_refs[REGNO (XEXP (note, 0))]== 2 + && reg_referenced_p (XEXP (note, 0), PATTERN (i2))) + reg_n_refs[REGNO (XEXP (note, 0))] = 3; + if (place == 0) for (tem = prev_nonnote_insn (i3); *************** *** 8048,8052 **** PATTERN (tem) = pc_rtx; ! distribute_notes (REG_NOTES (tem), tem, tem, 0, 0, 0); distribute_links (LOG_LINKS (tem)); --- 9321,9326 ---- PATTERN (tem) = pc_rtx; ! distribute_notes (REG_NOTES (tem), tem, tem, ! NULL_RTX, NULL_RTX, NULL_RTX); distribute_links (LOG_LINKS (tem)); *************** *** 8187,8194 **** REG_NOTES (place) = note; } if (place2) ! REG_NOTES (place2) = gen_rtx (GET_CODE (note), REG_NOTE_KIND (note), ! XEXP (note, 0), REG_NOTES (place2)); } } --- 9461,9479 ---- REG_NOTES (place) = note; } + else if ((REG_NOTE_KIND (note) == REG_DEAD + || REG_NOTE_KIND (note) == REG_UNUSED) + && GET_CODE (XEXP (note, 0)) == REG) + reg_n_deaths[REGNO (XEXP (note, 0))]--; if (place2) ! { ! if ((REG_NOTE_KIND (note) == REG_DEAD ! || REG_NOTE_KIND (note) == REG_UNUSED) ! && GET_CODE (XEXP (note, 0)) == REG) ! reg_n_deaths[REGNO (XEXP (note, 0))]++; ! ! REG_NOTES (place2) = gen_rtx (GET_CODE (note), REG_NOTE_KIND (note), ! XEXP (note, 0), REG_NOTES (place2)); ! } } } diff -rc2N gcc-2.2.2/cond.awk gcc-2.3.1/cond.awk *** gcc-2.2.2/cond.awk --- gcc-2.3.1/cond.awk Wed Sep 30 09:36:08 1992 *************** *** 0 **** --- 1,10 ---- + # Simpleminded conditional-processor awk script + # to permit use of a single .y source file for C and Objective C. + # If objc=1, the ifobjc conditionals succeed. + # If objc=0, the ifc conditionals succeed. + /^ifobjc$/,/^end ifobjc$/ \ + { if (objc != 0 && $0 != "ifobjc" && $0 != "end ifobjc") print; next } + /^ifc$/,/^end ifc$/ \ + { if (objc == 0 && $0 != "ifc" && $0 != "end ifc") print; next } + + { print } diff -rc2N gcc-2.2.2/conditions.h gcc-2.3.1/conditions.h *** gcc-2.2.2/conditions.h Sat Mar 14 00:01:16 1992 --- gcc-2.3.1/conditions.h Mon Oct 12 17:31:04 1992 *************** *** 102,105 **** --- 102,109 ---- #define CC_INVERTED 0100 + /* Nonzero if we must convert signed condition operators to unsigned. + This is only used by machine description files. */ + #define CC_NOT_SIGNED 0200 + /* This is how to initialize the variable cc_status. final does this at appropriate moments. */ diff -rc2N gcc-2.2.2/config/a29k.c gcc-2.3.1/config/a29k.c *** gcc-2.2.2/config/a29k.c Sat Jun 13 17:45:12 1992 --- gcc-2.3.1/config/a29k.c Sat Oct 24 10:33:08 1992 *************** *** 1,4 **** /* Subroutines used for code generation on AMD Am29000. ! Copyright (C) 1987, 1988, 1990, 1991 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) --- 1,4 ---- /* Subroutines used for code generation on AMD Am29000. ! Copyright (C) 1987, 1988, 1990, 1991, 1992 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) *************** *** 35,38 **** --- 35,39 ---- #include "obstack.h" #include "tree.h" + #include "reload.h" #define min(A,B) ((A) < (B) ? (A) : (B)) *************** *** 100,104 **** } ! /* Returns 1 if OP cannot be moved in a single insn. */ int --- 101,105 ---- } ! /* Returns 1 if OP is a constant that cannot be moved in a single insn. */ int *************** *** 157,161 **** const_16_operand (op, mode) rtx op; ! enum machine_mode; { return shift_constant_operand (op, mode, 16); --- 158,162 ---- const_16_operand (op, mode) rtx op; ! enum machine_mode mode; { return shift_constant_operand (op, mode, 16); *************** *** 165,169 **** const_24_operand (op, mode) rtx op; ! enum machine_mode; { return shift_constant_operand (op, mode, 24); --- 166,170 ---- const_24_operand (op, mode) rtx op; ! enum machine_mode mode; { return shift_constant_operand (op, mode, 24); *************** *** 211,216 **** enum machine_mode mode; { ! return GET_MODE (op) == SImode && GET_CODE (op) == REG ! && REGNO (op) >= R_BP && REGNO (op) <= R_EXO; } --- 212,227 ---- enum machine_mode mode; { ! if (GET_CODE (op) != REG || GET_MODE (op) != mode) ! return 0; ! ! switch (GET_MODE_CLASS (mode)) ! { ! case MODE_PARTIAL_INT: ! return REGNO (op) >= R_BP && REGNO (op) <= R_CR; ! case MODE_INT: ! return REGNO (op) >= R_Q && REGNO (op) <= R_EXO; ! detault: ! return 0; ! } } *************** *** 277,281 **** gpc_reg_or_immediate_operand (op, mode) rtx op; ! enum machine_mode; { return gpc_reg_operand (op, mode) || immediate_operand (op, mode); --- 288,292 ---- gpc_reg_or_immediate_operand (op, mode) rtx op; ! enum machine_mode mode; { return gpc_reg_operand (op, mode) || immediate_operand (op, mode); *************** *** 288,292 **** and_operand (op, mode) rtx op; ! enum machine_mode; { return (srcb_operand (op, mode) --- 299,303 ---- and_operand (op, mode) rtx op; ! enum machine_mode mode; { return (srcb_operand (op, mode) *************** *** 302,306 **** add_operand (op, mode) rtx op; ! enum machine_mode; { return (srcb_operand (op, mode) --- 313,317 ---- add_operand (op, mode) rtx op; ! enum machine_mode mode; { return (srcb_operand (op, mode) *************** *** 308,311 **** --- 319,345 ---- && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256))); } + + /* Return 1 if OP is a valid address in a CALL_INSN. These are a SYMBOL_REF + to the current function, all SYMBOL_REFs if TARGET_SMALL_MEMORY, or + a sufficiently-small constant. */ + + int + call_operand (op, mode) + rtx op; + enum machine_mode mode; + { + switch (GET_CODE (op)) + { + case SYMBOL_REF: + return (TARGET_SMALL_MEMORY + || ! strcmp (XSTR (op, 0), current_function_name)); + + case CONST_INT: + return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000; + + default: + return 0; + } + } /* Return 1 if OP can be used as the input operand for a move insn. */ *************** *** 333,337 **** case CONST_INT: ! if (GET_MODE_CLASS (mode) != MODE_INT) return 0; --- 367,372 ---- case CONST_INT: ! if (GET_MODE_CLASS (mode) != MODE_INT ! && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; *************** *** 371,396 **** if (GET_CODE (op) == REG) ! return (mode == SImode || gpc_reg_operand (orig_op, mode) || (GET_MODE_CLASS (mode) == MODE_FLOAT && accum_reg_operand (orig_op, mode))); else if (GET_CODE (op) == MEM) ! return mode == SImode || mode == SFmode || TARGET_DW_ENABLE; ! else return 0; } ! /* Return 1 if OP is some extension operator. */ int ! extend_operator (op, mode) rtx op; enum machine_mode mode; { ! return ((mode == VOIDmode || GET_MODE (op) == mode) ! && (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)); } /* Return 1 if OP is a comparison operator that we have in floating-point. */ --- 406,518 ---- if (GET_CODE (op) == REG) ! return (gpc_reg_operand (orig_op, mode) ! || spec_reg_operand (orig_op, mode) || (GET_MODE_CLASS (mode) == MODE_FLOAT && accum_reg_operand (orig_op, mode))); else if (GET_CODE (op) == MEM) ! return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); else return 0; } ! /* Return 1 if OP is an item in memory, given that we are in reload. */ int ! reload_memory_operand (op, mode) rtx op; enum machine_mode mode; { ! int regno = true_regnum (op); ! ! return (! CONSTANT_P (op) ! && (regno == -1 ! || (GET_CODE (op) == REG ! && REGNO (op) >= FIRST_PSEUDO_REGISTER))); ! } ! ! /* Given an object for which reload_memory_operand is true, return the address ! of the operand, taking into account anything that reload may do. */ ! ! rtx ! a29k_get_reloaded_address (op) ! rtx op; ! { ! if (GET_CODE (op) == SUBREG) ! { ! if (SUBREG_WORD (op) != 0) ! abort (); ! ! op = SUBREG_REG (op); ! } ! ! if (GET_CODE (op) == REG) ! op = reg_equiv_mem[REGNO (op)]; ! ! return find_replacement (&XEXP (op, 0)); ! } ! ! /* Subfunction of the following function. Update the flags of any MEM ! found in part of X. */ ! ! static void ! a29k_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) ! rtx x; ! int in_struct_p, volatile_p, unchanging_p; ! { ! int i; ! ! switch (GET_CODE (x)) ! { ! case SEQUENCE: ! case PARALLEL: ! for (i = XVECLEN (x, 0) - 1; i >= 0; i--) ! a29k_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, ! unchanging_p); ! break; ! ! case INSN: ! a29k_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p, ! unchanging_p); ! break; ! ! case SET: ! a29k_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p, ! unchanging_p); ! a29k_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, unchanging_p); ! break; ! ! case MEM: ! MEM_IN_STRUCT_P (x) = in_struct_p; ! MEM_VOLATILE_P (x) = volatile_p; ! RTX_UNCHANGING_P (x) = unchanging_p; ! break; ! } } + /* Given INSN, which is either an INSN or a SEQUENCE generated to + perform a memory operation, look for any MEMs in either a SET_DEST or + a SET_SRC and copy the in-struct, unchanging, and volatile flags from + REF into each of the MEMs found. If REF is not a MEM, don't do + anything. */ + + void + a29k_set_memflags (insn, ref) + rtx insn; + rtx ref; + { + /* Note that it is always safe to get these flags, though they won't + be what we think if REF is not a MEM. */ + int in_struct_p = MEM_IN_STRUCT_P (ref); + int volatile_p = MEM_VOLATILE_P (ref); + int unchanging_p = RTX_UNCHANGING_P (ref); + + if (GET_CODE (ref) != MEM + || (! in_struct_p && ! volatile_p && ! unchanging_p)) + return; + + a29k_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p); + } + /* Return 1 if OP is a comparison operator that we have in floating-point. */ *************** *** 592,608 **** { int regno = -1; ! if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) ! regno = true_regnum (in); ! /* We can place anything into GENERAL_REGS and can put GENERAL_REGS ! into anything. */ if (class == GENERAL_REGS || (regno != -1 && regno < R_BP)) return NO_REGS; /* We can place 16-bit constants into a special register. */ ! if (GET_CODE (in) == CONST_INT ! && (GET_MODE_BITSIZE (mode) <= 16 ! || (unsigned) INTVAL (in) <= 65535) && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS)) return NO_REGS; --- 714,745 ---- { int regno = -1; + enum rtx_code code = GET_CODE (in); + + if (! CONSTANT_P (in)) + { + regno = true_regnum (in); ! /* A pseudo is the same as memory. */ ! if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER) ! code = MEM; ! } ! ! /* If we are transferring between memory and a multi-word mode or between ! memory and a mode smaller than a word without DW being enabled, we need ! BP. */ ! ! if (code == MEM ! && (GET_MODE_SIZE (mode) > UNITS_PER_WORD ! || (! TARGET_DW_ENABLE && GET_MODE_SIZE (mode) < UNITS_PER_WORD))) ! return BP_REGS; ! /* Otherwise, we can place anything into GENERAL_REGS and can put ! GENERAL_REGS into anything. */ if (class == GENERAL_REGS || (regno != -1 && regno < R_BP)) return NO_REGS; /* We can place 16-bit constants into a special register. */ ! if (code == CONST_INT ! && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535) && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS)) return NO_REGS; *************** *** 740,745 **** %Q means write a QImode operand (truncate constants to 8 bits) %M means write the low-order 16 bits of the constant %C means write the low-order 8 bits of the complement of the constant - %X means write the cntl values for LOAD with operand an extension op %b means write `f' is this is a reversed condition, `t' otherwise %B means write `t' is this is a reversed condition, `f' otherwise --- 877,882 ---- %Q means write a QImode operand (truncate constants to 8 bits) %M means write the low-order 16 bits of the constant + %m means write the low-order 16 bits shifted left 16 bits %C means write the low-order 8 bits of the complement of the constant %b means write `f' is this is a reversed condition, `t' otherwise %B means write `t' is this is a reversed condition, `f' otherwise *************** *** 808,816 **** return; ! case 'X': ! fprintf (file, "%d", ((GET_MODE (XEXP (x, 0)) == QImode ? 1 : 2) ! + (GET_CODE (x) == SIGN_EXTEND ? 16 : 0))); return; ! case 'b': if (GET_CODE (x) == GE) --- 945,954 ---- return; ! case 'm': ! if (! INT_P (x)) ! output_operand_lossage ("invalid %%m value"); ! fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16); return; ! case 'b': if (GET_CODE (x) == GE) *************** *** 879,883 **** if (dbr_sequence_length () == 0) { ! if (! strcmp (XSTR (x, 0), current_function_name)) fprintf (file, "+4\n\t%s,%d", a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1", --- 1017,1022 ---- if (dbr_sequence_length () == 0) { ! if (GET_CODE (x) == SYMBOL_REF ! && ! strcmp (XSTR (x, 0), current_function_name)) fprintf (file, "+4\n\t%s,%d", a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1", diff -rc2N gcc-2.2.2/config/a29k.h gcc-2.3.1/config/a29k.h *** gcc-2.2.2/config/a29k.h Sat Jun 13 17:44:54 1992 --- gcc-2.3.1/config/a29k.h Thu Oct 22 14:16:17 1992 *************** *** 1,4 **** /* Definitions of target machine for GNU compiler, for AMD Am29000 CPU. ! Copyright (C) 1988, 1990, 1991 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) --- 1,4 ---- /* Definitions of target machine for GNU compiler, for AMD Am29000 CPU. ! Copyright (C) 1988, 1990, 1991, 1992 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) *************** *** 93,96 **** --- 93,98 ---- {"user-registers", -16}, \ {"stack-check", 32}, \ + {"no-stack-check", - 32}, \ + {"storem-bug", -64}, \ {"no-storem-bug", 64}, \ {"reuse-arg-regs", -128}, \ *************** *** 123,126 **** --- 125,139 ---- #define WCHAR_TYPE_SIZE BITS_PER_UNIT + /* Define this macro if it is advisible 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) < 4) \ + (MODE) == SImode; + /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. *************** *** 308,312 **** {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ ! 0, 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, \ --- 321,325 ---- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 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, \ *************** *** 384,388 **** On 29k, the cpu registers can hold any mode. But a double-precision floating-point value should start at an even register. The special ! registers cannot hold floating-point values and the accumulators cannot hold integer values. --- 397,402 ---- On 29k, the cpu registers can hold any mode. But a double-precision floating-point value should start at an even register. The special ! registers cannot hold floating-point values, BP, CR, and FC cannot ! hold integer or floating-point values, and the accumulators cannot hold integer values. *************** *** 397,401 **** && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)) \ ! || ((REGNO) >= R_BP && (REGNO) < R_ACC (0) \ && GET_MODE_CLASS (MODE) != MODE_FLOAT \ && GET_MODE_CLASS (MODE) != MODE_COMPLEX_FLOAT) \ --- 411,417 ---- && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)) \ ! || ((REGNO) >= R_BP && (REGNO) <= R_CR \ ! && GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT) \ ! || ((REGNO) >= R_Q && (REGNO) < R_ACC (0) \ && GET_MODE_CLASS (MODE) != MODE_FLOAT \ && GET_MODE_CLASS (MODE) != MODE_COMPLEX_FLOAT) \ *************** *** 414,423 **** accumulator's restriction to only floating. This probably won't cause any great inefficiencies in practice. */ #define MODES_TIEABLE_P(MODE1, MODE2) \ ((MODE1) == (MODE2) \ ! || (GET_MODE_CLASS (MODE1) != MODE_FLOAT \ ! && GET_MODE_CLASS (MODE1) != MODE_COMPLEX_FLOAT \ ! && GET_MODE_CLASS (MODE2) != MODE_FLOAT \ ! && GET_MODE_CLASS (MODE2) != MODE_COMPLEX_FLOAT)) /* Specify the registers used for certain standard purposes. --- 430,438 ---- accumulator's restriction to only floating. This probably won't cause any great inefficiencies in practice. */ + #define MODES_TIEABLE_P(MODE1, MODE2) \ ((MODE1) == (MODE2) \ ! || (GET_MODE_CLASS (MODE1) == MODE_INT \ ! && GET_MODE_CLASS (MODE2) == MODE_INT)) /* Specify the registers used for certain standard purposes. *************** *** 469,485 **** class that represents their union. ! The 29k has six registers classes: GENERAL_REGS, SPECIAL_REGS, ! BP_REGS, Q_REGS, ACCUM_REGS, and ACCUM0_REGS. BP_REGS contains just BP and ! is used for the extract and insert operations to allow combinations; Q ! contains just the Q register. The latter two classes are used to represent ! the floating-point accumulator registers in the 29050. We also define the ! union class FLOAT_REGS to represent any register that can be used to hold a floating-point value. The union of SPECIAL_REGS and ACCUM_REGS isn't useful as the former cannot contain floating-point and the latter can only contain floating-point. */ ! enum reg_class { NO_REGS, GENERAL_REGS, BP_REGS, Q_REGS, SPECIAL_REGS, ! ACCUM0_REGS, ACCUM_REGS, FLOAT_REGS, ALL_REGS, ! LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES --- 484,500 ---- class that represents their union. ! The 29k has nine registers classes: LR0_REGS, GENERAL_REGS, SPECIAL_REGS, ! BP_REGS, FC_REGS, CR_REGS, Q_REGS, ACCUM_REGS, and ACCUM0_REGS. ! LR0_REGS, BP_REGS, FC_REGS, CR_REGS, and Q_REGS contain just the single ! register. The latter two classes are used to represent the floating-point ! accumulator registers in the 29050. We also define the union class ! FLOAT_REGS to represent any register that can be used to hold a floating-point value. The union of SPECIAL_REGS and ACCUM_REGS isn't useful as the former cannot contain floating-point and the latter can only contain floating-point. */ ! enum reg_class { NO_REGS, LR0_REGS, GENERAL_REGS, BP_REGS, FC_REGS, CR_REGS, ! Q_REGS, SPECIAL_REGS, ACCUM0_REGS, ACCUM_REGS, FLOAT_REGS, ! ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES *************** *** 488,493 **** #define REG_CLASS_NAMES \ ! {"NO_REGS", "GENERAL_REGS", "BP_REGS", "Q_REGS", "SPECIAL_REGS", \ ! "ACCUM0_REGS", "ACCUM_REGS", "FLOAT_REGS", "ALL_REGS" } /* Define which registers fit in which classes. --- 503,509 ---- #define REG_CLASS_NAMES \ ! {"NO_REGS", "LR0_REGS", "GENERAL_REGS", "BP_REGS", "FC_REGS", "CR_REGS", \ ! "Q_REGS", "SPECIAL_REGS", "ACCUM0_REGS", "ACCUM_REGS", "FLOAT_REGS", \ ! "ALL_REGS" } /* Define which registers fit in which classes. *************** *** 497,502 **** --- 513,521 ---- #define REG_CLASS_CONTENTS \ { {0, 0, 0, 0, 0, 0, 0}, \ + {0, 1, 0, 0, 0, 0, 0}, \ {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, 0}, \ {0, 0, 0, 0, 0, 0x20000, 0}, \ + {0, 0, 0, 0, 0, 0x40000, 0}, \ + {0, 0, 0, 0, 0, 0x80000, 0}, \ {0, 0, 0, 0, 0, 0x100000, 0}, \ {0, 0, 0, 0, 0, 0xfffe0000, 0xff}, \ *************** *** 513,520 **** --- 532,542 ---- #define REGNO_REG_CLASS(REGNO) \ ((REGNO) == R_BP ? BP_REGS \ + : (REGNO) == R_FC ? FC_REGS \ + : (REGNO) == R_CR ? CR_REGS \ : (REGNO) == R_Q ? Q_REGS \ : (REGNO) > R_BP && (REGNO) <= R_EXO ? SPECIAL_REGS \ : (REGNO) == R_ACC (0) ? ACCUM0_REGS \ : (REGNO) > R_ACC (0) ? ACCUM_REGS \ + : (REGNO) == R_LR (0) ? LR0_REGS \ : GENERAL_REGS) *************** *** 527,531 **** --- 549,556 ---- #define REG_CLASS_FROM_LETTER(C) \ ((C) == 'r' ? GENERAL_REGS \ + : (C) == 'l' ? LR0_REGS \ : (C) == 'b' ? BP_REGS \ + : (C) == 'f' ? FC_REGS \ + : (C) == 'c' ? CR_REGS \ : (C) == 'q' ? Q_REGS \ : (C) == 'h' ? SPECIAL_REGS \ *************** *** 606,609 **** --- 631,638 ---- secondary_reload_class (CLASS, MODE, IN) + /* This function is used to get the address of an object. */ + + extern struct rtx_def *a29k_get_reloaded_address (); + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. *************** *** 622,625 **** --- 651,663 ---- #define REGISTER_MOVE_COST(CLASS1, CLASS2) \ ((CLASS1) == GENERAL_REGS || (CLASS2) == GENERAL_REGS ? 2 : 4) + + /* A C statement (sans semicolon) to update the integer variable COST + based on the relationship between INSN that is dependent on + DEP_INSN through the dependence LINK. The default is to make no + adjustment to COST. On the a29k, ignore the cost of anti- and + output-dependencies. */ + #define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ + if (REG_NOTE_KIND (LINK) != 0) \ + (COST) = 0; /* Anti or output dependence. */ /* Stack layout; function entry, exit and calling. */ *************** *** 1545,1552 **** {"and_operand", {SUBREG, REG, CONST_INT}}, \ {"add_operand", {SUBREG, REG, CONST_INT}}, \ {"in_operand", {SUBREG, MEM, REG, CONST_INT, CONST, SYMBOL_REF, \ LABEL_REF, CONST_DOUBLE}}, \ {"out_operand", {SUBREG, REG, MEM}}, \ ! {"extend_operator", {ZERO_EXTEND, SIGN_EXTEND}}, \ {"fp_comparison_operator", {EQ, GT, GE}}, \ {"branch_operator", {GE, LT}}, \ --- 1583,1591 ---- {"and_operand", {SUBREG, REG, CONST_INT}}, \ {"add_operand", {SUBREG, REG, CONST_INT}}, \ + {"call_operand", {SYMBOL_REF, CONST_INT}}, \ {"in_operand", {SUBREG, MEM, REG, CONST_INT, CONST, SYMBOL_REF, \ LABEL_REF, CONST_DOUBLE}}, \ {"out_operand", {SUBREG, REG, MEM}}, \ ! {"reload_memory_operand", {SUBREG, REG, MEM}}, \ {"fp_comparison_operator", {EQ, GT, GE}}, \ {"branch_operator", {GE, LT}}, \ diff -rc2N gcc-2.2.2/config/a29k.md gcc-2.3.1/config/a29k.md *** gcc-2.2.2/config/a29k.md Sat Jun 13 17:45:36 1992 --- gcc-2.3.1/config/a29k.md Sat Oct 24 10:33:19 1992 *************** *** 1,4 **** ;;- Machine description for AMD Am29000 for GNU C compiler ! ;; Copyright (C) 1991 Free Software Foundation, Inc. ;; Contributed by Richard Kenner (kenner@nyu.edu) --- 1,4 ---- ;;- Machine description for AMD Am29000 for GNU C compiler ! ;; Copyright (C) 1991, 1992 Free Software Foundation, Inc. ;; Contributed by Richard Kenner (kenner@nyu.edu) *************** *** 32,36 **** (define_attr "type" ! "call,branch,load,store,fadd,fmul,fam,fdiv,dmul,dam,ddiv,multi,misc" (const_string "misc")) --- 32,36 ---- (define_attr "type" ! "call,branch,load,store,fadd,fmul,fam,fdiv,fsqrt,dmul,dam,ddiv,dsqrt,multi,misc" (const_string "misc")) *************** *** 48,53 **** ;; Define the function unit usages. We first define memory as a unit. ! (define_function_unit "memory" 1 2 (eq_attr "type" "load") 6 11) ! (define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 0) ;; Now define the function units for the floating-point support. Most --- 48,56 ---- ;; Define the function unit usages. We first define memory as a unit. ! (define_function_unit "memory" 1 0 (eq_attr "type" "load") 6 5 ! [(eq_attr "type" "load")]) ! (define_function_unit "memory" 1 0 (eq_attr "type" "load") 6 6 ! [(eq_attr "type" "store")]) ! (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) ;; Now define the function units for the floating-point support. Most *************** *** 60,71 **** (define_function_unit "multiplier" 1 0 (eq_attr "type" "fmul") 3 0) ! (define_function_unit "multiplier" 1 0 (eq_attr "type" "dmul") 6 8) ! (define_function_unit "multiplier" 1 0 (eq_attr "type" "fam") 6 8) ! (define_function_unit "multiplier" 1 0 (eq_attr "type" "dam") 9 8) (define_function_unit "adder" 1 0 (eq_attr "type" "fadd,fam,dam") 3 0) ! (define_function_unit "divider" 1 1 (eq_attr "type" "fdiv") 11 20) ! (define_function_unit "divider" 1 1 (eq_attr "type" "ddiv") 18 34) ;; ADD --- 63,76 ---- (define_function_unit "multiplier" 1 0 (eq_attr "type" "fmul") 3 0) ! (define_function_unit "multiplier" 1 0 (eq_attr "type" "dmul") 6 4) ! (define_function_unit "multiplier" 1 0 (eq_attr "type" "fam") 6 0) ! (define_function_unit "multiplier" 1 0 (eq_attr "type" "dam") 9 4) (define_function_unit "adder" 1 0 (eq_attr "type" "fadd,fam,dam") 3 0) ! (define_function_unit "divider" 1 0 (eq_attr "type" "fdiv") 11 10) ! (define_function_unit "divider" 1 0 (eq_attr "type" "fsqrt") 28 27) ! (define_function_unit "divider" 1 0 (eq_attr "type" "ddiv") 18 17) ! (define_function_unit "divider" 1 0 (eq_attr "type" "dsqrt") 57 56) ;; ADD *************** *** 132,139 **** }") (define_expand "call" [(parallel [(call (match_operand:SI 0 "" "") (match_operand 1 "" "")) ! (clobber (reg:SI 32))]) (match_operand 2 "" "")] "" --- 137,147 ---- }") + ;; We indicate that LR0 is clobbered in the CALL_INSN itself. Otherwise, + ;; reorg will think it is just clobbered by the called function. + (define_expand "call" [(parallel [(call (match_operand:SI 0 "" "") (match_operand 1 "" "")) ! (clobber (scratch:SI))]) (match_operand 2 "" "")] "" *************** *** 143,149 **** abort (); if (! TARGET_SMALL_MEMORY && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) ! operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), force_reg (Pmode, XEXP (operands[0], 0))); --- 151,159 ---- abort (); + /* We tell here whether this is a recursive call, since this insn may + later be inlined into another function. */ if (! TARGET_SMALL_MEMORY && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) ! operands[0] = gen_rtx (MEM, SImode, force_reg (Pmode, XEXP (operands[0], 0))); *************** *** 151,167 **** }") - (define_insn "" - [(call (match_operand:SI 0 "memory_operand" "m") - (match_operand 1 "" "")) - (clobber (reg:SI 32))] - "" - "calli lr0,%0%#" - [(set_attr "type" "call")]) - (define_expand "call_value" [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) ! (clobber (reg:SI 32))]) (match_operand 3 "" "")] "" --- 161,169 ---- }") (define_expand "call_value" [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) ! (clobber (scratch:SI))]) (match_operand 3 "" "")] "" *************** *** 171,177 **** abort (); if (! TARGET_SMALL_MEMORY && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) ! operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), force_reg (Pmode, XEXP (operands[1], 0))); --- 173,181 ---- abort (); + /* We tell here whether this is a recursive call, since this insn may + later be inlined into another function. */ if (! TARGET_SMALL_MEMORY && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) ! operands[1] = gen_rtx (MEM, SImode, force_reg (Pmode, XEXP (operands[1], 0))); *************** *** 180,198 **** (define_insn "" ! [(set (match_operand 0 "gpc_reg_operand" "=r") ! (call (match_operand:SI 1 "memory_operand" "m") ! (match_operand 2 "" ""))) ! (clobber (reg:SI 32))] ! "" ! "calli lr0,%1%#" [(set_attr "type" "call")]) (define_insn "" ! [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i")) (match_operand:SI 1 "general_operand" "g")) ! (clobber (reg:SI 32))] ! "GET_CODE (operands[0]) == SYMBOL_REF ! && (TARGET_SMALL_MEMORY ! || ! strcmp (XSTR (operands[0], 0), current_function_name))" "call lr0,%F0" [(set_attr "type" "call")]) --- 184,199 ---- (define_insn "" ! [(call (match_operand:SI 0 "memory_operand" "m") ! (match_operand 1 "" "")) ! (clobber (match_scratch:SI 2 "=l"))] ! "GET_CODE (XEXP (operands[0], 0)) != CONST_INT" ! "calli lr0,%0%#" [(set_attr "type" "call")]) (define_insn "" ! [(call (mem:SI (match_operand:SI 0 "call_operand" "i")) (match_operand:SI 1 "general_operand" "g")) ! (clobber (match_scratch:SI 2 "=l"))] ! "" "call lr0,%F0" [(set_attr "type" "call")]) *************** *** 200,209 **** (define_insn "" [(set (match_operand 0 "gpc_reg_operand" "=r") ! (call (mem:SI (match_operand:SI 1 "immediate_operand" "i")) (match_operand:SI 2 "general_operand" "g"))) ! (clobber (reg:SI 32))] ! "GET_CODE (operands[1]) == SYMBOL_REF ! && (TARGET_SMALL_MEMORY ! || ! strcmp (XSTR (operands[1], 0), current_function_name))" "call lr0,%F1" [(set_attr "type" "call")]) --- 201,217 ---- (define_insn "" [(set (match_operand 0 "gpc_reg_operand" "=r") ! (call (match_operand:SI 1 "memory_operand" "m") ! (match_operand 2 "" ""))) ! (clobber (match_scratch:SI 3 "=l"))] ! "GET_CODE (XEXP (operands[1], 0)) != CONST_INT" ! "calli lr0,%1%#" ! [(set_attr "type" "call")]) ! ! (define_insn "" ! [(set (match_operand 0 "gpc_reg_operand" "=r") ! (call (mem:SI (match_operand:SI 1 "call_operand" "i")) (match_operand:SI 2 "general_operand" "g"))) ! (clobber (match_scratch:SI 3 "=l"))] ! "" "call lr0,%F1" [(set_attr "type" "call")]) *************** *** 246,274 **** [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) ! (match_operand:SI 1 "const_0_operand" "")) (match_operand:SI 2 "cint_16_operand" "J"))] "" ! "* ! { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) << 16); ! return \"consth %0,%2\"; ! }") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0") ! (const_int 65535)) (match_operand:SI 2 "const_int_operand" "n")))] ! "(INTVAL (operands[1]) & 0xffff) == 0" "consth %0,%2") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0") ! (const_int 65535)) (and:SI (match_operand:SI 2 "immediate_operand" "i") (const_int -65536))))] "" "consth %0,%2") - ;; CONVERT --- 254,276 ---- [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) ! (match_operand:SI 1 "const_0_operand" "I")) (match_operand:SI 2 "cint_16_operand" "J"))] "" ! "consth %0,%m2") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")) (match_operand:SI 2 "const_int_operand" "n")))] ! "(INTVAL (operands[2]) & 0xffff) == 0" "consth %0,%2") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")) (and:SI (match_operand:SI 2 "immediate_operand" "i") (const_int -65536))))] "" "consth %0,%2") ;; CONVERT *************** *** 589,594 **** (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 8) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3)))))] "" "exbyte %0,%2,%1") --- 591,597 ---- (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 8) ! (ashift:PSI ! (match_operand:PSI 3 "register_operand" "b") ! (const_int 3)))))] "" "exbyte %0,%2,%1") *************** *** 598,603 **** (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int 8) ! (ashift:SI (match_operand:SI 2 "register_operand" "b") ! (const_int 3))))] "" "exbyte %0,%1,0") --- 601,607 ---- (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int 8) ! (ashift:PSI ! (match_operand:PSI 2 "register_operand" "b") ! (const_int 3))))] "" "exbyte %0,%1,0") *************** *** 606,614 **** [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 8) ! (match_operand:SI 1 "const_24_operand" "")) (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 8) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3))))] "" "exbyte %0,%2,%0") --- 610,619 ---- [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 8) ! (match_operand:PSI 1 "const_24_operand" "")) (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 8) ! (ashift:PSI ! (match_operand:PSI 3 "register_operand" "b") ! (const_int 3))))] "" "exbyte %0,%2,%0") *************** *** 630,664 **** size = INTVAL (operands[2]); pos = INTVAL (operands[3]); - if ((size != 8 && size != 16) || pos % size != 0) - FAIL; - - operands[3] = gen_rtx (ASHIFT, SImode, - force_reg (SImode, - gen_rtx (CONST_INT, VOIDmode, pos / 8)), - gen_rtx (CONST_INT, VOIDmode, 3)); - }") ! (define_expand "extv" ! [(set (match_operand:SI 0 "gpc_reg_operand" "") ! (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "") ! (match_operand:SI 2 "general_operand" "") ! (match_operand:SI 3 "general_operand" "")))] ! "" ! " ! { ! int pos; ! if (GET_CODE (operands[2]) != CONST_INT ! || GET_CODE (operands[3]) != CONST_INT) FAIL; ! pos = INTVAL (operands[3]); ! if (INTVAL (operands[2]) != 16 || pos % 16 != 0) ! FAIL; - operands[3] = gen_rtx (ASHIFT, SImode, - force_reg (SImode, - gen_rtx (CONST_INT, VOIDmode, pos / 8)), - gen_rtx (CONST_INT, VOIDmode, 3)); }") --- 635,651 ---- size = INTVAL (operands[2]); pos = INTVAL (operands[3]); ! /* Can't do this unless a byte extraction. If extracting the high ! or low byte, don't do this because a shift or AND is shorter. ! Don't do 16-bit extracts, since the only two are the high and low ! ends, and it is faster to do them with CONSTH and SRL. */ ! if (size != 8 || (pos != 8 && pos != 16)) FAIL; ! operands[3] = gen_rtx (ASHIFT, PSImode, ! force_reg (PSImode, GEN_INT (pos / 8)), ! GEN_INT (3)); }") *************** *** 670,675 **** (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 16) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3)))))] "" "exhw %0,%2,%1") --- 657,663 ---- (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 16) ! (ashift:PSI ! (match_operand:PSI 3 "register_operand" "b") ! (const_int 3)))))] "" "exhw %0,%2,%1") *************** *** 679,684 **** (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int 16) ! (ashift:SI (match_operand:SI 2 "register_operand" "b") ! (const_int 3))))] "" "exhw %0,%1,0") --- 667,673 ---- (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int 16) ! (ashift:PSI ! (match_operand:PSI 2 "register_operand" "b") ! (const_int 3))))] "" "exhw %0,%1,0") *************** *** 687,705 **** [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) ! (match_operand:SI 1 "const_16_operand" "")) (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 16) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3))))] "" "exhw %0,%2,%0") ;; EXHWS (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (sign_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int 16) ! (ashift:SI (match_operand:SI 2 "register_operand" "b") ! (const_int 3))))] "" "exhws %0,%1") --- 676,702 ---- [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) ! (match_operand:PSI 1 "const_16_operand" "")) (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") (const_int 16) ! (ashift:PSI ! (match_operand:PSI 3 "register_operand" "b") ! (const_int 3))))] "" "exhw %0,%2,%0") ;; EXHWS + ;; + ;; This is probably unused. The high-order 16-bits are obtained with an SRA + ;; insn. The low-order 16 bits are a sign-extend, which is a pair of + ;; shifts. Setting BP followed by the insn is equivalent, so we don't + ;; bother going to any trouble to generate this insn. + (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (sign_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int 16) ! (ashift:PSI ! (match_operand:PSI 2 "register_operand" "b") ! (const_int 3))))] "" "exhws %0,%1") *************** *** 709,725 **** [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r") ! (reg:QI 178)))] "" "extract %0,%1,%1") (define_expand "rotlsi3" ! [(set (reg:QI 178) ! (match_operand: SI 2 "gpc_reg_or_immediate_operand" "")) (set (match_operand:SI 0 "gpc_reg_operand" "") (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") ! (reg:QI 178)))] "" " ! { operands[2] = gen_lowpart (QImode, operands[2]); }") ;; FADD --- 706,729 ---- [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r") ! (match_operand:PSI 2 "register_operand" "f")))] "" "extract %0,%1,%1") (define_expand "rotlsi3" ! [(set (match_dup 3) ! (match_operand:SI 2 "gpc_reg_or_immediate_operand" "")) (set (match_operand:SI 0 "gpc_reg_operand" "") (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") ! (match_dup 3)))] "" " ! { operands[2] = gen_lowpart (PSImode, operands[2]); ! operands[3] = gen_reg_rtx (PSImode); ! }") ! ! ;; It would be nice to be able to have a define_split corresponding to the ! ;; above, but there is no way to tell combine we need a PSImode temporary. ! ;; If we put a (clobber (scratch:PSI)) there, combine would merge the above ! ;; two insns. This is bad because it then thinks only one insn is needed. ;; FADD *************** *** 896,901 **** [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 8) ! (ashift:SI (match_operand:SI 2 "register_operand" "b") ! (const_int 3))) (match_operand:SI 1 "srcb_operand" "rI"))] "" --- 900,906 ---- [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 8) ! (ashift:PSI ! (match_operand:PSI 2 "register_operand" "b") ! (const_int 3))) (match_operand:SI 1 "srcb_operand" "rI"))] "" *************** *** 904,925 **** (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (ashift:SI (const_int 255) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "r")) ! (ashift:SI (and:SI (match_operand:SI 2 "srcb_operand" "rI") ! (const_int 255)) ! (match_operand:SI 4 "const_24_operand" ""))))] ! "" ! "inbyte %0,%1,%2") ! ! (define_insn "" ! [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (ashift:SI (const_int 255) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "r")) ! (ashift:SI (match_operand:SI 2 "srcb_operand" "rI") ! (match_operand:SI 4 "const_24_operand" ""))))] "" "inbyte %0,%1,%2") --- 909,922 ---- (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI ! (not:SI ! (ashift:SI (const_int 255) ! (ashift:PSI ! (match_operand:PSI 3 "register_operand" "b") ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "r")) ! (ashift:SI (zero_extend:SI ! (match_operand:QI 2 "srcb_operand" "rI")) ! (ashift:PSI (match_dup 3) (const_int 3)))))] "" "inbyte %0,%1,%2") *************** *** 929,934 **** [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) ! (ashift:SI (match_operand:SI 2 "register_operand" "b") ! (const_int 3))) (match_operand:SI 1 "srcb_operand" "rI"))] "" --- 926,932 ---- [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) ! (ashift:PSI ! (match_operand:PSI 2 "register_operand" "b") ! (const_int 3))) (match_operand:SI 1 "srcb_operand" "rI"))] "" *************** *** 937,958 **** (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "r")) ! (ashift:SI (and:SI (match_operand:SI 2 "srcb_operand" "rI") ! (const_int 65535)) ! (match_operand:SI 4 "const_24_operand" ""))))] ! "" ! "inhw %0,%1,%2") ! ! (define_insn "" ! [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535) ! (ashift:SI (match_operand:SI 3 "register_operand" "b") ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "r")) ! (ashift:SI (match_operand:SI 2 "srcb_operand" "rI") ! (match_operand:SI 4 "const_24_operand" ""))))] "" "inhw %0,%1,%2") --- 935,948 ---- (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI ! (not:SI ! (ashift:SI (const_int 65535) ! (ashift:PSI ! (match_operand:PSI 3 "register_operand" "b") ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "r")) ! (ashift:SI (zero_extend:SI ! (match_operand:HI 2 "srcb_operand" "rI")) ! (ashift:PSI (match_dup 3) (const_int 3)))))] "" "inhw %0,%1,%2") *************** *** 977,984 **** FAIL; ! operands[2] = gen_rtx (ASHIFT, SImode, ! force_reg (SImode, ! gen_rtx (CONST_INT, VOIDmode, pos / 8)), ! gen_rtx (CONST_INT, VOIDmode, 3)); }") --- 967,973 ---- FAIL; ! operands[2] = gen_rtx (ASHIFT, PSImode, ! force_reg (PSImode, GEN_INT (pos / 8)), ! GEN_INT (3)); }") *************** *** 988,1023 **** (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int -4)))) ! (set (reg:SI 177) ! (and:SI (match_dup 1) ! (const_int 3)))] "! TARGET_DW_ENABLE" ! "load 0,17,%0,%1" [(set_attr "type" "load")]) (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r") ! (const_int -4)))) ! (set (reg:SI 177) ! (and:SI (match_dup 1) ! (const_int 2)))] ! "! TARGET_DW_ENABLE" ! "load 0,18,%0,%1" [(set_attr "type" "load")]) (define_insn "" ! [(set (match_operand 0 "gpc_reg_operand" "=r") ! (match_operator 2 "extend_operator" ! [(match_operand 1 "memory_operand" "m")]))] ! "TARGET_DW_ENABLE && GET_MODE (operands[0]) == GET_MODE (operands[2])" ! "load 0,%X2,%0,%1" [(set_attr "type" "load")]) ;; LOADM (define_expand "load_multiple" ! [(set (reg:SI 179) ! (match_dup 2)) ! (match_parallel 3 "" [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" ""))])] "" " --- 977,1037 ---- (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r") (const_int -4)))) ! (set (match_operand:PSI 2 "register_operand" "=b") ! (truncate:PSI (match_dup 1)))] "! TARGET_DW_ENABLE" ! "load 0,16,%0,%1" [(set_attr "type" "load")]) (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] ! "TARGET_DW_ENABLE" ! "load 0,1,%0,%1" [(set_attr "type" "load")]) (define_insn "" ! [(set (match_operand:HI 0 "gpc_reg_operand" "=r") ! (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] ! "TARGET_DW_ENABLE" ! "load 0,1,%0,%1" ! [(set_attr "type" "load")]) ! ! (define_insn "" ! [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] ! "TARGET_DW_ENABLE" ! "load 0,2,%0,%1" ! [(set_attr "type" "load")]) ! ! (define_insn "" ! [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))) ! (clobber (match_scratch:PSI 2 "=b"))] ! "TARGET_DW_ENABLE" ! "load 0,17,%0,%1" ! [(set_attr "type" "load")]) ! ! (define_insn "" ! [(set (match_operand:HI 0 "gpc_reg_operand" "=r") ! (sign_extend:HI (match_operand:QI 1 "memory_operand" "m"))) ! (clobber (match_scratch:PSI 2 "=b"))] ! "TARGET_DW_ENABLE" ! "load 0,17,%0,%1" ! [(set_attr "type" "load")]) ! ! (define_insn "" ! [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) ! (clobber (match_scratch:PSI 2 "=b"))] ! "TARGET_DW_ENABLE" ! "load 0,18,%0,%1" [(set_attr "type" "load")]) ;; LOADM (define_expand "load_multiple" ! [(set (match_dup 4) ! (match_operand:PSI 2 "const_int_operand" "")) ! (match_par_dup 3 [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" ""))])] "" " *************** *** 1040,1044 **** /* CR gets set to the number of registers minus one. */ ! operands[2] = gen_rtx (CONST_INT, VOIDmode, count - 1); operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2)); --- 1054,1058 ---- /* CR gets set to the number of registers minus one. */ ! operands[2] = GEN_INT(count - 1); operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2)); *************** *** 1047,1055 **** gen_rtx (REG, SImode, regno), gen_rtx (MEM, SImode, from)); ! XVECEXP (operands[3], 0, 1) ! = gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, R_CR)); ! XVECEXP (operands[3], 0, 2) ! = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR)); for (i = 1; i < count; i++) XVECEXP (operands[3], 0, i + 2) --- 1061,1069 ---- gen_rtx (REG, SImode, regno), gen_rtx (MEM, SImode, from)); ! operands[4] = gen_reg_rtx (PSImode); + XVECEXP (operands[3], 0, 1) = gen_rtx (USE, VOIDmode, operands[4]); + XVECEXP (operands[3], 0, 2) = gen_rtx (CLOBBER, VOIDmode, operands[4]); + for (i = 1; i < count; i++) XVECEXP (operands[3], 0, i + 2) *************** *** 1062,1067 **** [(set (match_operand 0 "gpc_reg_operand" "=r") (match_operand 1 "memory_operand" "m")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))] "GET_MODE (operands[0]) == GET_MODE (operands[1]) && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD --- 1076,1081 ---- [(set (match_operand 0 "gpc_reg_operand" "=r") (match_operand 1 "memory_operand" "m")) ! (use (match_operand:PSI 2 "register_operand" "+c")) ! (clobber (match_dup 2))] "GET_MODE (operands[0]) == GET_MODE (operands[1]) && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD *************** *** 1073,1078 **** [(set (match_operand 0 "gpc_reg_operand" "=&r") (match_operand 1 "memory_operand" "m")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))] "GET_MODE (operands[0]) == GET_MODE (operands[1]) && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD --- 1087,1092 ---- [(set (match_operand 0 "gpc_reg_operand" "=&r") (match_operand 1 "memory_operand" "m")) ! (use (match_operand:PSI 2 "register_operand" "+c")) ! (clobber (match_dup 2))] "GET_MODE (operands[0]) == GET_MODE (operands[1]) && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD *************** *** 1085,1090 **** [(set (match_operand:SI 1 "gpc_reg_operand" "=r") (match_operand:SI 2 "memory_operand" "m")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "! TARGET_29050" "loadm 0,0,%1,%2" --- 1099,1104 ---- [(set (match_operand:SI 1 "gpc_reg_operand" "=r") (match_operand:SI 2 "memory_operand" "m")) ! (use (match_operand:PSI 3 "register_operand" "+c")) ! (clobber (match_dup 3))])] "! TARGET_29050" "loadm 0,0,%1,%2" *************** *** 1095,1100 **** [(set (match_operand:SI 1 "gpc_reg_operand" "=&r") (match_operand:SI 2 "memory_operand" "m")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "TARGET_29050" "loadm 0,0,%1,%2" --- 1109,1114 ---- [(set (match_operand:SI 1 "gpc_reg_operand" "=&r") (match_operand:SI 2 "memory_operand" "m")) ! (use (match_operand:PSI 3 "register_operand" "+c")) ! (clobber (match_dup 3))])] "TARGET_29050" "loadm 0,0,%1,%2" *************** *** 1110,1113 **** --- 1124,1136 ---- mtsr %0,%1 mtsrim %0,%1") + + (define_insn "" + [(set (match_operand:PSI 0 "register_operand" "=h,h") + (truncate:PSI + (match_operand:SI 1 "gpc_reg_or_immediate_operand" "r,i")))] + "" + "@ + mtsr %0,%1 + mtsrim %0,%1") ;; MULTIPLY, MULTM, MULTMU *************** *** 1256,1259 **** --- 1279,1297 ---- "sll %0,%1,%Q2") + ;; SQRT + (define_insn "sqrtsf2" + [(set (match_operand:SF 0 "gpc_reg_operand" "=r") + (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "r")))] + "TARGET_29050" + "sqrt %0,%1,1" + [(set_attr "type" "fsqrt")]) + + (define_insn "sqrtdf2" + [(set (match_operand:DF 0 "gpc_reg_operand" "=r") + (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "r")))] + "TARGET_29050" + "sqrt %0,%1,2" + [(set_attr "type" "dsqrt")]) + ;; SRA (define_insn "ashrsi3" *************** *** 1315,1322 **** (define_expand "store_multiple_no_bug" ! [(set (reg:SI 179) ! (match_dup 2)) ! (match_parallel 3 "" [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" ""))])] "" " --- 1353,1360 ---- (define_expand "store_multiple_no_bug" ! [(set (match_dup 4) ! (match_operand:PSI 2 "const_int_operand" "")) ! (match_par_dup 3 [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" ""))])] "" " *************** *** 1339,1343 **** /* CR gets set to the number of registers minus one. */ ! operands[2] = gen_rtx (CONST_INT, VOIDmode, count - 1); operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2)); --- 1377,1381 ---- /* CR gets set to the number of registers minus one. */ ! operands[2] = GEN_INT(count - 1); operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2)); *************** *** 1346,1353 **** gen_rtx (MEM, SImode, from), gen_rtx (REG, SImode, regno)); ! XVECEXP (operands[3], 0, 1) ! = gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, R_CR)); ! XVECEXP (operands[3], 0, 2) ! = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR)); for (i = 1; i < count; i++) --- 1384,1390 ---- gen_rtx (MEM, SImode, from), gen_rtx (REG, SImode, regno)); ! operands[4] = gen_reg_rtx (PSImode); ! XVECEXP (operands[3], 0, 1) = gen_rtx (USE, VOIDmode, operands[4]); ! XVECEXP (operands[3], 0, 2) = gen_rtx (CLOBBER, VOIDmode, operands[4]); for (i = 1; i < count; i++) *************** *** 1359,1364 **** (define_expand "store_multiple_bug" ! [(match_parallel 3 "" [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" ""))])] "" " --- 1396,1402 ---- (define_expand "store_multiple_bug" ! [(match_par_dup 3 [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" "")) ! (use (match_operand:SI 2 "" ""))])] "" " *************** *** 1386,1390 **** gen_rtx (REG, SImode, regno)); XVECEXP (operands[3], 0, 1) ! = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR)); for (i = 1; i < count; i++) --- 1424,1428 ---- gen_rtx (REG, SImode, regno)); XVECEXP (operands[3], 0, 1) ! = gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, PSImode)); for (i = 1; i < count; i++) *************** *** 1398,1402 **** [(set (match_operand 0 "memory_operand" "=m") (match_operand 1 "gpc_reg_operand" "r")) ! (clobber (reg:SI 179))] "!TARGET_NO_STOREM_BUG && GET_MODE (operands[0]) == GET_MODE (operands[1]) --- 1436,1440 ---- [(set (match_operand 0 "memory_operand" "=m") (match_operand 1 "gpc_reg_operand" "r")) ! (clobber (match_scratch:PSI 2 "=c"))] "!TARGET_NO_STOREM_BUG && GET_MODE (operands[0]) == GET_MODE (operands[1]) *************** *** 1409,1413 **** [(set (match_operand:SI 1 "memory_operand" "=m") (match_operand:SI 2 "gpc_reg_operand" "r")) ! (clobber (reg:SI 179))])] "!TARGET_NO_STOREM_BUG" "mtsrim cr,%V0\;storem 0,0,%2,%1" --- 1447,1451 ---- [(set (match_operand:SI 1 "memory_operand" "=m") (match_operand:SI 2 "gpc_reg_operand" "r")) ! (clobber (match_scratch:PSI 3 "=c"))])] "!TARGET_NO_STOREM_BUG" "mtsrim cr,%V0\;storem 0,0,%2,%1" *************** *** 1417,1422 **** [(set (match_operand 0 "memory_operand" "=m") (match_operand 1 "gpc_reg_operand" "r")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))] "TARGET_NO_STOREM_BUG && GET_MODE (operands[0]) == GET_MODE (operands[1]) --- 1455,1460 ---- [(set (match_operand 0 "memory_operand" "=m") (match_operand 1 "gpc_reg_operand" "r")) ! (use (match_operand:PSI 2 "register_operand" "+c")) ! (clobber (match_dup 2))] "TARGET_NO_STOREM_BUG && GET_MODE (operands[0]) == GET_MODE (operands[1]) *************** *** 1429,1434 **** [(set (match_operand:SI 1 "memory_operand" "=m") (match_operand:SI 2 "gpc_reg_operand" "r")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "TARGET_NO_STOREM_BUG" "storem 0,0,%2,%1" --- 1467,1472 ---- [(set (match_operand:SI 1 "memory_operand" "=m") (match_operand:SI 2 "gpc_reg_operand" "r")) ! (use (match_operand:PSI 3 "register_operand" "+c")) ! (clobber (match_dup 3))])] "TARGET_NO_STOREM_BUG" "storem 0,0,%2,%1" *************** *** 1516,1521 **** result = expand_binop (SImode, xor_optab, operand_subword_force (operands[1], 0, SFmode), ! gen_rtx (CONST_INT, VOIDmode, 0x80000000), ! target, 0, OPTAB_WIDEN); if (result == 0) abort (); --- 1554,1558 ---- result = expand_binop (SImode, xor_optab, operand_subword_force (operands[1], 0, SFmode), ! GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); if (result == 0) abort (); *************** *** 1547,1552 **** result = expand_binop (SImode, xor_optab, operand_subword_force (operands[1], 0, DFmode), ! gen_rtx (CONST_INT, VOIDmode, 0x80000000), ! target, 0, OPTAB_WIDEN); if (result == 0) abort (); --- 1584,1588 ---- result = expand_binop (SImode, xor_optab, operand_subword_force (operands[1], 0, DFmode), ! GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); if (result == 0) abort (); *************** *** 1641,1644 **** --- 1677,1695 ---- }") + (define_expand "movpsi" + [(set (match_operand:PSI 0 "general_operand" "") + (match_operand:PSI 1 "general_operand" ""))] + "" + " + { + if (GET_CODE (operands[0]) == MEM + && ! gpc_reg_operand (operands[1], PSImode)) + operands[1] = copy_to_mode_reg (PSImode, operands[1]); + else if (spec_reg_operand (operands[0], PSImode) + && ! (register_operand (operands[1], PSImode) + || cint_16_operand (operands[1], PSImode))) + operands[1] = force_reg (PSImode, operands[1]); + }") + (define_split [(set (match_operand:SI 0 "gpc_reg_operand" "") *************** *** 1649,1720 **** (const_int 65535))) (set (match_dup 0) ! (ior:SI (and:SI (match_dup 0) ! (const_int 65535)) (and:SI (match_dup 1) (const_int -65536))))] ! "") ! ;; Subroutines to load/store halfwords. Use TAV (gr121) as scratch. We have ! ;; two versions of storehi, one when halfword writes are supported and one ! ;; where they aren't. (define_expand "loadhi" ! [(parallel [(set (match_dup 2) ! (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") (const_int -4)))) ! (set (reg:SI 177) ! (and:SI (match_dup 0) ! (const_int 2)))]) ! (set (match_operand:HI 1 "gpc_reg_operand" "") (zero_extract:SI (match_dup 2) (const_int 16) ! (ashift:SI (reg:SI 177) ! (const_int 3))))] "" ! " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! ! if (reload_in_progress) ! operands[2] = gen_rtx (REG, SImode, R_TAV); ! else ! operands[2] = gen_reg_rtx (SImode); ! }") (define_expand "storehinhww" ! [(parallel [(set (match_dup 2) (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") (const_int -4)))) ! (set (reg:SI 177) ! (and:SI (match_dup 0) ! (const_int 2)))]) (set (zero_extract:SI (match_dup 2) ! (const_int 8) ! (ashift:SI (reg:SI 177) ! (const_int 3))) ! (match_operand:HI 1 "gpc_reg_operand" "")) (set (mem:SI (match_dup 0)) (match_dup 2))] "" ! " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! ! if (reload_in_progress) ! operands[2] = gen_rtx (REG, SImode, R_TAV); ! else ! operands[2] = gen_reg_rtx (SImode); ! }") (define_expand "storehihww" ! [(set (reg:SI 177) ! (and:SI (match_operand:SI 0 "gpc_reg_operand" "") ! (const_int 3))) ! (set (match_dup 2) (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535) ! (ashift:SI (reg:SI 177) ! (const_int 3)))) ! (match_operand:HI 1 "gpc_reg_operand" "")) ! (ashift:SI (and:SI (match_dup 1) ! (const_int 65535)) ! (ashift:SI (reg:SI 177) ! (const_int 3))))) (set (mem:SI (and:SI (match_dup 0) (const_int -3))) --- 1700,1757 ---- (const_int 65535))) (set (match_dup 0) ! (ior:SI (zero_extend:SI (match_dup 2)) (and:SI (match_dup 1) (const_int -65536))))] ! " operands[2] = gen_lowpart (HImode, operands[0]); ") ! ;; Subroutines to load/store halfwords. Operands 0 and 1 are the output and ! ;; input, respectively, except that the address is passed for a MEM instead ! ;; of the MEM itself and the short item is passed in QImode. ! ;; ! ;; Operand 2 is a scratch general register and operand 3 is a scratch register ! ;; used for BP. When called before reload, pseudos are passed for both ! ;; operands. During reload, R_TAV is used for the general register, and ! ;; a reload register of class BR_REGS (R_VP) for BP. ! ;; ! ;; We have two versions of the store operations, for when halfword writes are ! ;; supported and when they are not. (define_expand "loadhi" ! [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") ! (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "") (const_int -4)))) ! (set (match_operand:PSI 3 "register_operand" "") ! (truncate:PSI (match_dup 1)))]) ! (set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extract:SI (match_dup 2) (const_int 16) ! (ashift:PSI (match_dup 3) (const_int 3))))] "" ! "") (define_expand "storehinhww" ! [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") (const_int -4)))) ! (set (match_operand:PSI 3 "register_operand" "") ! (truncate:PSI (match_dup 0)))]) (set (zero_extract:SI (match_dup 2) ! (const_int 16) ! (ashift:PSI (match_dup 3) (const_int 3))) ! (match_operand:SI 1 "gpc_reg_operand" "")) (set (mem:SI (match_dup 0)) (match_dup 2))] "" ! "") (define_expand "storehihww" ! [(set (match_operand:PSI 3 "register_operand" "") ! (truncate:PSI (match_operand:SI 0 "gpc_reg_operand" ""))) ! (set (match_operand:SI 2 "gpc_reg_operand" "") (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535) ! (ashift:PSI (match_dup 3) ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "")) ! (ashift:SI (zero_extend:SI (match_dup 4)) ! (ashift:PSI (match_dup 3) (const_int 3))))) (set (mem:SI (and:SI (match_dup 0) (const_int -3))) *************** *** 1722,1732 **** "" " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! ! if (reload_in_progress) ! operands[2] = gen_rtx (REG, SImode, R_TAV); ! else ! operands[2] = gen_reg_rtx (SImode); ! }") (define_expand "movhi" --- 1759,1763 ---- "" " ! { operands[4] = gen_lowpart (HImode, operands[1]); }") (define_expand "movhi" *************** *** 1741,1748 **** if (! TARGET_DW_ENABLE) { ! if (TARGET_BYTE_WRITES) ! emit_insn (gen_storehihww (XEXP (operands[0], 0), operands[1])); ! else ! emit_insn (gen_storehinhww (XEXP (operands[0], 0), operands[1])); DONE; } --- 1772,1785 ---- if (! TARGET_DW_ENABLE) { ! rtx general = gen_reg_rtx (SImode); ! rtx bp = gen_reg_rtx (PSImode); ! rtx (*fcn) () ! = TARGET_BYTE_WRITES ? gen_storehihww : gen_storehinhww; ! rtx seq = (*fcn) (XEXP (operands[0], 0), ! gen_lowpart (SImode, operands[1]), ! general, bp); ! ! a29k_set_memflags (seq, operands[0]); ! emit_insn (seq); DONE; } *************** *** 1752,1821 **** if (! TARGET_DW_ENABLE) { ! emit_insn (gen_loadhi (XEXP (operands[1], 0), operands[0])); DONE; } } }") ! ;; Subroutines to load/store bytes. Use TAV (gr121) as scratch. (define_expand "loadqi" ! [(parallel [(set (match_dup 2) ! (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") (const_int -4)))) ! (set (reg:SI 177) ! (and:SI (match_dup 0) ! (const_int 3)))]) ! (set (match_operand:QI 1 "gpc_reg_operand" "") (zero_extract:SI (match_dup 2) (const_int 8) ! (ashift:SI (reg:SI 177) ! (const_int 3))))] "" ! " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! ! if (reload_in_progress) ! operands[2] = gen_rtx (REG, SImode, R_TAV); ! else ! operands[2] = gen_reg_rtx (SImode); ! }") (define_expand "storeqinhww" ! [(parallel [(set (match_dup 2) (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") (const_int -4)))) ! (set (reg:SI 177) ! (and:SI (match_dup 0) ! (const_int 3)))]) (set (zero_extract:SI (match_dup 2) (const_int 8) ! (ashift:SI (reg:SI 177) ! (const_int 3))) ! (match_operand:QI 1 "gpc_reg_operand" "")) (set (mem:SI (match_dup 0)) (match_dup 2))] "" ! " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! ! if (reload_in_progress) ! operands[2] = gen_rtx (REG, SImode, R_TAV); ! else ! operands[2] = gen_reg_rtx (SImode); ! }") (define_expand "storeqihww" ! [(set (reg:SI 177) ! (and:SI (match_operand:SI 0 "gpc_reg_operand" "") ! (const_int 3))) ! (set (match_dup 2) (ior:SI (and:SI (not:SI (ashift:SI (const_int 255) ! (ashift:SI (reg:SI 177) ! (const_int 3)))) ! (match_operand:HI 1 "gpc_reg_operand" "")) ! (ashift:SI (and:SI (match_dup 1) ! (const_int 255)) ! (ashift:SI (reg:SI 177) ! (const_int 3))))) (set (mem:SI (and:SI (match_dup 0) (const_int -4))) --- 1789,1887 ---- if (! TARGET_DW_ENABLE) { ! rtx general = gen_reg_rtx (SImode); ! rtx bp = gen_reg_rtx (PSImode); ! rtx seq = gen_loadqi (gen_lowpart (SImode, operands[0]), ! XEXP (operands[1], 0), general, bp); ! ! a29k_set_memflags (seq, operands[1]); ! emit_insn (seq); DONE; } } }") + + (define_expand "reload_inhi" + [(parallel [(match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "reload_memory_operand" "m") + (match_operand:PSI 2 "register_operand" "=b")])] + "! TARGET_DW_ENABLE" + " + { rtx seq = gen_loadhi (gen_lowpart (SImode, operands[0]), + a29k_get_reloaded_address (operands[1]), + gen_rtx (REG, SImode, R_TAV), + operands[2]); + + a29k_set_memflags (seq, operands[1]); + emit_insn (seq); + DONE; + }") + + (define_expand "reload_outhi" + [(parallel [(match_operand:SI 0 "reload_memory_operand" "=m") + (match_operand:SI 1 "register_operand" "m") + (match_operand:PSI 2 "register_operand" "=b")])] + "! TARGET_DW_ENABLE" + " + { rtx (*fcn) () = TARGET_BYTE_WRITES ? gen_storehihww : gen_storehinhww; + rtx seq = (*fcn) (a29k_get_reloaded_address (operands[0]), + gen_lowpart (SImode, operands[1]), + gen_rtx (REG, SImode, R_TAV), operands[2]); + + a29k_set_memflags (seq, operands[0]); + emit_insn (seq); + DONE; + }") ! ;; Subroutines to load/store bytes. Operands 0 and 1 are the output and ! ;; input, respectively, except that the address is passed for a MEM instead ! ;; of the MEM itself and the short item is passed in QImode. ! ;; ! ;; Operand 2 is a scratch general register and operand 3 is a scratch register ! ;; used for BP. When called before reload, pseudos are passed for both ! ;; operands. During reload, R_TAV is used for the general register, and ! ;; a reload register of class BR_REGS (R_VP) for BP. ! ;; ! ;; We have two versions of the store operations, for when byte writes are ! ;; supported and when they are not. (define_expand "loadqi" ! [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") ! (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "") (const_int -4)))) ! (set (match_operand:PSI 3 "register_operand" "") ! (truncate:PSI (match_dup 1)))]) ! (set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extract:SI (match_dup 2) (const_int 8) ! (ashift:PSI (match_dup 3) (const_int 3))))] "" ! "") (define_expand "storeqinhww" ! [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") (const_int -4)))) ! (set (match_operand:PSI 3 "register_operand" "") ! (truncate:PSI (match_dup 0)))]) (set (zero_extract:SI (match_dup 2) (const_int 8) ! (ashift:PSI (match_dup 3) ! (const_int 3))) ! (match_operand:SI 1 "gpc_reg_operand" "")) (set (mem:SI (match_dup 0)) (match_dup 2))] "" ! "") (define_expand "storeqihww" ! [(set (match_operand:PSI 3 "register_operand" "") ! (truncate:PSI (match_operand:SI 0 "gpc_reg_operand" ""))) ! (set (match_operand:SI 2 "gpc_reg_operand" "") (ior:SI (and:SI (not:SI (ashift:SI (const_int 255) ! (ashift:PSI (match_dup 3) ! (const_int 3)))) ! (match_operand:SI 1 "gpc_reg_operand" "")) ! (ashift:SI (zero_extend:SI (match_dup 4)) ! (ashift:PSI (match_dup 3) ! (const_int 3))))) (set (mem:SI (and:SI (match_dup 0) (const_int -4))) *************** *** 1823,1833 **** "" " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! ! if (reload_in_progress) ! operands[2] = gen_rtx (REG, SImode, R_TAV); ! else ! operands[2] = gen_reg_rtx (SImode); ! }") (define_expand "movqi" --- 1889,1893 ---- "" " ! { operands[4] = gen_lowpart (QImode, operands[1]); }") (define_expand "movqi" *************** *** 1842,1850 **** if (! TARGET_DW_ENABLE) { ! if (TARGET_BYTE_WRITES) ! emit_insn (gen_storeqihww (XEXP (operands[0], 0), operands[1])); ! else ! emit_insn (gen_storeqinhww (XEXP (operands[0], 0), operands[1])); ! DONE; } } --- 1902,1915 ---- if (! TARGET_DW_ENABLE) { ! rtx general = gen_reg_rtx (SImode); ! rtx bp = gen_reg_rtx (PSImode); ! rtx (*fcn) () ! = TARGET_BYTE_WRITES ? gen_storeqihww : gen_storeqinhww; ! rtx seq = (*fcn) (XEXP (operands[0], 0), ! gen_lowpart (SImode, operands[1]), ! general, bp); ! ! a29k_set_memflags (seq, operands[0]); ! emit_insn (seq); } } *************** *** 1853,1861 **** if (! TARGET_DW_ENABLE) { ! emit_insn (gen_loadqi (XEXP (operands[1], 0), operands[0])); DONE; } } }") ;; Now the actual insns used to move data around. We include here the --- 1918,1964 ---- if (! TARGET_DW_ENABLE) { ! rtx general = gen_reg_rtx (SImode); ! rtx bp = gen_reg_rtx (PSImode); ! rtx seq = gen_loadqi (gen_lowpart (SImode, operands[0]), ! XEXP (operands[1], 0), general, bp); ! ! a29k_set_memflags (seq, operands[1]); ! emit_insn (seq); DONE; } } }") + + (define_expand "reload_inqi" + [(parallel [(match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "reload_memory_operand" "m") + (match_operand:PSI 2 "register_operand" "=b")])] + "! TARGET_DW_ENABLE" + " + { rtx seq = gen_loadqi (gen_lowpart (SImode, operands[0]), + a29k_get_reloaded_address (operands[1]), + gen_rtx (REG, SImode, R_TAV), + operands[2]); + + a29k_set_memflags (seq, operands[1]); + emit_insn (seq); + DONE; + }") + + (define_expand "reload_outqi" + [(parallel [(match_operand:SI 0 "reload_memory_operand" "=m") + (match_operand:SI 1 "register_operand" "m") + (match_operand:PSI 2 "register_operand" "=b")])] + "! TARGET_DW_ENABLE" + " + { rtx (*fcn) () = TARGET_BYTE_WRITES ? gen_storeqihww : gen_storeqinhww; + rtx seq = (*fcn) (a29k_get_reloaded_address (operands[0]), + gen_lowpart (SImode, operands[1]), + gen_rtx (REG, SImode, R_TAV), operands[2]); + + a29k_set_memflags (seq, operands[0]); + emit_insn (seq); + DONE; + }") ;; Now the actual insns used to move data around. We include here the *************** *** 1909,1915 **** (define_insn "" ! [(set (match_operand:DF 0 "out_operand" "=r,r,r,m") (match_operand:DF 1 "in_operand" "rE,F,m,r")) ! (clobber (reg:SI 179))] "(gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode)) --- 2012,2018 ---- (define_insn "" ! [(set (match_operand:DF 0 "out_operand" "=?r,?r,r,m") (match_operand:DF 1 "in_operand" "rE,F,m,r")) ! (clobber (match_scratch:PSI 2 "=X,X,&c,&c"))] "(gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode)) *************** *** 1923,1929 **** (define_insn "" ! [(set (match_operand:DF 0 "out_operand" "=r,r,&r,m,*a,r") (match_operand:DF 1 "in_operand" "rE,F,m,r,r,*a")) ! (clobber (reg:SI 179))] "(gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode)) --- 2026,2032 ---- (define_insn "" ! [(set (match_operand:DF 0 "out_operand" "=?r,?r,&r,m,?*a,?r") (match_operand:DF 1 "in_operand" "rE,F,m,r,r,*a")) ! (clobber (match_scratch:PSI 2 "=X,X,&c,&c,X,X"))] "(gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode)) *************** *** 1948,1974 **** [(set (match_operand:DF 0 "gpc_reg_operand" "") (match_operand:DF 1 "gpc_reg_or_float_constant_operand" "")) ! (clobber (reg:SI 179))] "reload_completed" ! [(set (match_dup 2) (match_dup 3)) ! (set (match_dup 4) (match_dup 5))] " { if (GET_CODE (operands[1]) == REG && REGNO (operands[0]) == REGNO (operands[1]) + 1) { ! operands[2] = operand_subword (operands[0], 1, 1, DFmode); ! operands[3] = operand_subword (operands[1], 1, 1, DFmode); ! operands[4] = operand_subword (operands[0], 0, 1, DFmode); ! operands[5] = operand_subword (operands[1], 0, 1, DFmode); } else { ! operands[2] = operand_subword (operands[0], 0, 1, DFmode); ! operands[3] = operand_subword (operands[1], 0, 1, DFmode); ! operands[4] = operand_subword (operands[0], 1, 1, DFmode); ! operands[5] = operand_subword (operands[1], 1, 1, DFmode); } ! if (operands[2] == 0 || operands[3] == 0 ! || operands[4] == 0 || operands[5] == 0) FAIL; }") --- 2051,2077 ---- [(set (match_operand:DF 0 "gpc_reg_operand" "") (match_operand:DF 1 "gpc_reg_or_float_constant_operand" "")) ! (clobber (match_scratch:PSI 2 ""))] "reload_completed" ! [(set (match_dup 3) (match_dup 4)) ! (set (match_dup 5) (match_dup 6))] " { if (GET_CODE (operands[1]) == REG && REGNO (operands[0]) == REGNO (operands[1]) + 1) { ! operands[3] = operand_subword (operands[0], 1, 1, DFmode); ! operands[4] = operand_subword (operands[1], 1, 1, DFmode); ! operands[5] = operand_subword (operands[0], 0, 1, DFmode); ! operands[6] = operand_subword (operands[1], 0, 1, DFmode); } else { ! operands[3] = operand_subword (operands[0], 0, 1, DFmode); ! operands[4] = operand_subword (operands[1], 0, 1, DFmode); ! operands[5] = operand_subword (operands[0], 1, 1, DFmode); ! operands[6] = operand_subword (operands[1], 1, 1, DFmode); } ! if (operands[3] == 0 || operands[4] == 0 ! || operands[5] == 0 || operands[6] == 0) FAIL; }") *************** *** 1978,1996 **** [(set (match_operand:DF 0 "out_operand" "") (match_operand:DF 1 "in_operand" "")) ! (clobber (reg:SI 179))] "TARGET_NO_STOREM_BUG && (memory_operand (operands[0], DFmode) || memory_operand (operands[1], DFmode))" ! [(set (reg:SI 179) (const_int 1)) (parallel [(set (match_dup 0) (match_dup 1)) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "") ;; DI move is similar to DF move. (define_insn "" ! [(set (match_operand:DI 0 "out_operand" "=r,r,m") (match_operand:DI 1 "in_operand" "rn,m,r")) ! (clobber (reg:SI 179))] "(gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode)) --- 2081,2099 ---- [(set (match_operand:DF 0 "out_operand" "") (match_operand:DF 1 "in_operand" "")) ! (clobber (reg:PSI 179))] "TARGET_NO_STOREM_BUG && (memory_operand (operands[0], DFmode) || memory_operand (operands[1], DFmode))" ! [(set (reg:PSI 179) (const_int 1)) (parallel [(set (match_dup 0) (match_dup 1)) ! (use (reg:PSI 179)) ! (clobber (reg:PSI 179))])] "") ;; DI move is similar to DF move. (define_insn "" ! [(set (match_operand:DI 0 "out_operand" "=?r,r,m") (match_operand:DI 1 "in_operand" "rn,m,r")) ! (clobber (match_scratch:PSI 2 "=X,&c,&c"))] "(gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode)) *************** *** 2003,2009 **** (define_insn "" ! [(set (match_operand:DI 0 "out_operand" "=r,&r,m") (match_operand:DI 1 "in_operand" "rn,m,r")) ! (clobber (reg:SI 179))] "(gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode)) --- 2106,2112 ---- (define_insn "" ! [(set (match_operand:DI 0 "out_operand" "=?r,&r,m") (match_operand:DI 1 "in_operand" "rn,m,r")) ! (clobber (match_scratch:PSI 2 "=X,&c,&c"))] "(gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode)) *************** *** 2018,2040 **** [(set (match_operand:DI 0 "gpc_reg_operand" "") (match_operand:DI 1 "gpc_reg_or_integer_constant_operand" "")) ! (clobber (reg:SI 179))] "reload_completed" ! [(set (match_dup 2) (match_dup 3)) ! (set (match_dup 4) (match_dup 5))] " { if (GET_CODE (operands[1]) == REG && REGNO (operands[0]) == REGNO (operands[1]) + 1) { ! operands[2] = operand_subword (operands[0], 1, 1, DImode); ! operands[3] = operand_subword (operands[1], 1, 1, DImode); ! operands[4] = operand_subword (operands[0], 0, 1, DImode); ! operands[5] = operand_subword (operands[1], 0, 1, DImode); } else { ! operands[2] = operand_subword (operands[0], 0, 1, DImode); ! operands[3] = operand_subword (operands[1], 0, 1, DImode); ! operands[4] = operand_subword (operands[0], 1, 1, DImode); ! operands[5] = operand_subword (operands[1], 1, 1, DImode); } }") --- 2121,2143 ---- [(set (match_operand:DI 0 "gpc_reg_operand" "") (match_operand:DI 1 "gpc_reg_or_integer_constant_operand" "")) ! (clobber (match_scratch:PSI 2 ""))] "reload_completed" ! [(set (match_dup 3) (match_dup 4)) ! (set (match_dup 5) (match_dup 6))] " { if (GET_CODE (operands[1]) == REG && REGNO (operands[0]) == REGNO (operands[1]) + 1) { ! operands[3] = operand_subword (operands[0], 1, 1, DImode); ! operands[4] = operand_subword (operands[1], 1, 1, DImode); ! operands[5] = operand_subword (operands[0], 0, 1, DImode); ! operands[6] = operand_subword (operands[1], 0, 1, DImode); } else { ! operands[3] = operand_subword (operands[0], 0, 1, DImode); ! operands[4] = operand_subword (operands[1], 0, 1, DImode); ! operands[5] = operand_subword (operands[0], 1, 1, DImode); ! operands[6] = operand_subword (operands[1], 1, 1, DImode); } }") *************** *** 2043,2054 **** [(set (match_operand:DI 0 "out_operand" "") (match_operand:DI 1 "in_operand" "")) ! (clobber (reg:SI 179))] "TARGET_NO_STOREM_BUG && (memory_operand (operands[0], DImode) || memory_operand (operands[1], DImode))" ! [(set (reg:SI 179) (const_int 1)) (parallel [(set (match_dup 0) (match_dup 1)) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "") --- 2146,2157 ---- [(set (match_operand:DI 0 "out_operand" "") (match_operand:DI 1 "in_operand" "")) ! (clobber (reg:PSI 179))] "TARGET_NO_STOREM_BUG && (memory_operand (operands[0], DImode) || memory_operand (operands[1], DImode))" ! [(set (reg:PSI 179) (const_int 1)) (parallel [(set (match_dup 0) (match_dup 1)) ! (use (reg:PSI 179)) ! (clobber (reg:PSI 179))])] "") *************** *** 2056,2062 **** ;; have constants. (define_insn "" ! [(set (match_operand:TI 0 "out_operand" "=r,r,m") (match_operand:TI 1 "in_operand" "r,m,r")) ! (clobber (reg:SI 179))] "(gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode)) --- 2159,2165 ---- ;; have constants. (define_insn "" ! [(set (match_operand:TI 0 "out_operand" "=?r,r,m") (match_operand:TI 1 "in_operand" "r,m,r")) ! (clobber (match_scratch:PSI 2 "=X,&c,&c"))] "(gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode)) *************** *** 2069,2075 **** (define_insn "" ! [(set (match_operand:TI 0 "out_operand" "=r,&r,m") (match_operand:TI 1 "in_operand" "r,m,r")) ! (clobber (reg:SI 179))] "(gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode)) --- 2172,2178 ---- (define_insn "" ! [(set (match_operand:TI 0 "out_operand" "=?r,&r,m") (match_operand:TI 1 "in_operand" "r,m,r")) ! (clobber (match_scratch:PSI 2 "=X,&c,&c"))] "(gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode)) *************** *** 2084,2093 **** [(set (match_operand:TI 0 "gpc_reg_operand" "") (match_operand:TI 1 "gpc_reg_operand" "")) ! (clobber (reg:SI 179))] "reload_completed" ! [(set (match_dup 2) (match_dup 3)) ! (set (match_dup 4) (match_dup 5)) ! (set (match_dup 6) (match_dup 7)) ! (set (match_dup 8) (match_dup 9))] " { --- 2187,2196 ---- [(set (match_operand:TI 0 "gpc_reg_operand" "") (match_operand:TI 1 "gpc_reg_operand" "")) ! (clobber (match_scratch:PSI 2 ""))] "reload_completed" ! [(set (match_dup 3) (match_dup 4)) ! (set (match_dup 5) (match_dup 6)) ! (set (match_dup 7) (match_dup 8)) ! (set (match_dup 9) (match_dup 10))] " { *************** *** 2095,2117 **** && REGNO (operands[0]) <= REGNO (operands[1]) + 3) { ! operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3); ! operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); ! operands[4] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); ! operands[5] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); ! operands[6] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); ! operands[7] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); ! operands[8] = gen_rtx (REG, SImode, REGNO (operands[0])); ! operands[9] = gen_rtx (REG, SImode, REGNO (operands[1])); } else { ! operands[2] = gen_rtx (REG, SImode, REGNO (operands[0])); ! operands[3] = gen_rtx (REG, SImode, REGNO (operands[1])); ! operands[4] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); ! operands[5] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); ! operands[6] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); ! operands[7] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); ! operands[8] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3); ! operands[9] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); } }") --- 2198,2220 ---- && REGNO (operands[0]) <= REGNO (operands[1]) + 3) { ! operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3); ! operands[4] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); ! operands[5] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); ! operands[6] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); ! operands[7] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); ! operands[8] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); ! operands[9] = gen_rtx (REG, SImode, REGNO (operands[0])); ! operands[10] = gen_rtx (REG, SImode, REGNO (operands[1])); } else { ! operands[3] = gen_rtx (REG, SImode, REGNO (operands[0])); ! operands[4] = gen_rtx (REG, SImode, REGNO (operands[1])); ! operands[5] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); ! operands[6] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); ! operands[7] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); ! operands[8] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); ! operands[9] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3); ! operands[10] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); } }") *************** *** 2120,2131 **** [(set (match_operand:TI 0 "out_operand" "") (match_operand:TI 1 "in_operand" "")) ! (clobber (reg:SI 179))] "TARGET_NO_STOREM_BUG && (memory_operand (operands[0], TImode) || memory_operand (operands[1], TImode))" ! [(set (reg:SI 179) (const_int 1)) (parallel [(set (match_dup 0) (match_dup 1)) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "") --- 2223,2234 ---- [(set (match_operand:TI 0 "out_operand" "") (match_operand:TI 1 "in_operand" "")) ! (clobber (reg:PSI 179))] "TARGET_NO_STOREM_BUG && (memory_operand (operands[0], TImode) || memory_operand (operands[1], TImode))" ! [(set (reg:PSI 179) (const_int 1)) (parallel [(set (match_dup 0) (match_dup 1)) ! (use (reg:PSI 179)) ! (clobber (reg:PSI 179))])] "") *************** *** 2173,2180 **** (define_insn "" [(set (match_operand:HI 0 "out_operand" "=r,r,r,m,r,*h,*h") (match_operand:HI 1 "in_operand" "r,i,m,r,*h,r,i"))] "gpc_reg_operand (operands[0], HImode) ! || gpc_reg_operand (operands[1], HImode)" "@ sll %0,%1,0 --- 2276,2302 ---- (define_insn "" + [(set (match_operand:PSI 0 "out_operand" "=*r,*r,*r,*r,m,h,h") + (match_operand:PSI 1 "in_operand" "r,i,m,h,r,r,J"))] + "(gpc_reg_operand (operands[0], PSImode) + || gpc_reg_operand (operands[1], PSImode) + || (spec_reg_operand (operands[0], PSImode) + && cint_16_operand (operands[1], PSImode)))" + "@ + sll %0,%1,0 + const %0,%1 + load 0,0,%0,%1 + mfsr %0,%1 + store 0,0,%1,%0 + mtsr %0,%1 + mtsrim %0,%1" + [(set_attr "type" "misc,multi,load,misc,store,misc,misc")]) + + (define_insn "" [(set (match_operand:HI 0 "out_operand" "=r,r,r,m,r,*h,*h") (match_operand:HI 1 "in_operand" "r,i,m,r,*h,r,i"))] "gpc_reg_operand (operands[0], HImode) ! || gpc_reg_operand (operands[1], HImode) ! || (spec_reg_operand (operands[0], HImode) ! && cint_16_operand (operands[1], HImode))" "@ sll %0,%1,0 *************** *** 2191,2195 **** (match_operand:QI 1 "in_operand" "r,i,m,r,*h,r,i"))] "gpc_reg_operand (operands[0], QImode) ! || gpc_reg_operand (operands[1], QImode)" "@ sll %0,%1,0 --- 2313,2319 ---- (match_operand:QI 1 "in_operand" "r,i,m,r,*h,r,i"))] "gpc_reg_operand (operands[0], QImode) ! || gpc_reg_operand (operands[1], QImode) ! || (spec_reg_operand (operands[0], HImode) ! && cint_16_operand (operands[1], HImode))" "@ sll %0,%1,0 *************** *** 2211,2219 **** ;; In other cases, handle similarly to SImode moves. ;; ! ;; However, indicate that DI, TI, and DF moves (can) clobber CR (reg 179). (define_expand "movdi" [(parallel [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" "")) ! (clobber (reg:SI 179))])] "" " --- 2335,2343 ---- ;; In other cases, handle similarly to SImode moves. ;; ! ;; However, indicate that DI, TI, and DF moves may clobber CR (reg 179). (define_expand "movdi" [(parallel [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" "")) ! (clobber (scratch:PSI))])] "" " *************** *** 2235,2239 **** [(parallel [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" "")) ! (clobber (reg:SI 179))])] "" " --- 2359,2363 ---- [(parallel [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" "")) ! (clobber (scratch:PSI))])] "" " *************** *** 2245,2249 **** [(parallel [(set (match_operand:TI 0 "general_operand" "") (match_operand:TI 1 "general_operand" "")) ! (clobber (reg:SI 179))])] "" " --- 2369,2373 ---- [(parallel [(set (match_operand:TI 0 "general_operand" "") (match_operand:TI 1 "general_operand" "")) ! (clobber (scratch:PSI))])] "" " *************** *** 2251,2255 **** --- 2375,2452 ---- if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (TImode, operands[1]); + + /* We can't handle constants in general because there is no rtl to represent + 128 bit constants. Splitting happens to work for CONST_INTs so we split + them for good code. Other constants will get forced to memory. */ + + if (GET_CODE (operands[1]) == CONST_INT) + { + rtx part0, part1, part2, part3; + + part0 = operand_subword (operands[0], 0, 1, TImode); + part1 = operand_subword (operands[0], 1, 1, TImode); + part2 = operand_subword (operands[0], 2, 1, TImode); + part3 = operand_subword (operands[0], 3, 1, TImode); + + emit_move_insn (part0, const0_rtx); + emit_move_insn (part1, const0_rtx); + emit_move_insn (part2, const0_rtx); + emit_move_insn (part3, const0_rtx); + + DONE; + } + else if (CONSTANT_P (operands[1])) + { + operands[1] = force_const_mem (TImode, operands[1]); + if (! memory_address_p (TImode, XEXP (operands[1], 0)) + && ! reload_in_progress) + operands[1] = change_address (operands[1], TImode, + XEXP (operands[1], 0)); + } }") + + ;; Here are the variants of the above for use during reload. + + (define_expand "reload_indf" + [(parallel [(set (match_operand:DF 0 "register_operand" "=r") + (match_operand:DF 1 "reload_memory_operand" "m")) + (clobber (match_operand:PSI 2 "register_operand" "=&b"))])] + "" + "") + + (define_expand "reload_outdf" + [(parallel [(set (match_operand:DF 0 "reload_memory_operand" "=m") + (match_operand:DF 1 "register_operand" "r")) + (clobber (match_operand:PSI 2 "register_operand" "=&b"))])] + "" + "") + + (define_expand "reload_indi" + [(parallel [(set (match_operand:DI 0 "register_operand" "=r") + (match_operand:DI 1 "reload_memory_operand" "m")) + (clobber (match_operand:PSI 2 "register_operand" "=&b"))])] + "" + "") + + (define_expand "reload_outdi" + [(parallel [(set (match_operand:DI 0 "reload_memory_operand" "=m") + (match_operand:DI 1 "register_operand" "r")) + (clobber (match_operand:PSI 2 "register_operand" "=&b"))])] + "" + "") + + (define_expand "reload_inti" + [(parallel [(set (match_operand:TI 0 "register_operand" "=r") + (match_operand:TI 1 "reload_memory_operand" "m")) + (clobber (match_operand:PSI 2 "register_operand" "=&b"))])] + "" + "") + + (define_expand "reload_outti" + [(parallel [(set (match_operand:TI 0 "reload_memory_operand" "=m") + (match_operand:TI 1 "register_operand" "r")) + (clobber (match_operand:PSI 2 "register_operand" "=&b"))])] + "" + "") ;; For compare operations, we simply store the comparison operands and diff -rc2N gcc-2.2.2/config/a29kunix.h gcc-2.3.1/config/a29kunix.h *** gcc-2.2.2/config/a29kunix.h Sat Jun 13 17:45:47 1992 --- gcc-2.3.1/config/a29kunix.h Mon Aug 17 07:31:48 1992 *************** *** 38,46 **** #undef LINK_SPEC ! #define LINK_SPEC "-c /usr/lib/default.ld" - /* We can't say "-lgcc" due to a bug in gld for now. */ - #define LINK_LIBGCC_SPECIAL - /* For some systems, it is best if double-word objects are aligned on a doubleword boundary. We want to maintain compatibility with MetaWare in --- 38,43 ---- #undef LINK_SPEC ! #define LINK_SPEC "-c default.ld%s" /* For some systems, it is best if double-word objects are aligned on a doubleword boundary. We want to maintain compatibility with MetaWare in *************** *** 49,52 **** --- 46,72 ---- #undef BIGGEST_ALIGNMENT #define BIGGEST_ALIGNMENT 64 + + /* Add shared data as a kludge for now. */ + + #undef ASM_FILE_START + #define ASM_FILE_START(FILE) \ + { char *p, *after_dir = main_input_filename; \ + if (TARGET_29050) \ + fprintf (FILE, "\t.cputype 29050\n"); \ + for (p = main_input_filename; *p; p++) \ + if (*p == '/') \ + after_dir = p + 1; \ + fprintf (FILE, "\t.file \"%s\"\n", after_dir); \ + if (flag_shared_data) \ + fprintf (FILE, "\t.sect .shdata,data\n"); \ + fprintf (FILE, "\t.sect .lit,lit\n"); } + + /* Output before shared data. */ + + #define SHARED_SECTION_ASM_OP "\t.use .shdata" + + /* If we want shared data, we have to turn off commons. */ + + #define OVERRIDE_OPTIONS if (flag_shared_data) flag_no_common = 1; #if 0 /* This would be needed except that the 29k doesn't have strict diff -rc2N gcc-2.2.2/config/aix386.h gcc-2.3.1/config/aix386.h *** gcc-2.2.2/config/aix386.h Thu Mar 19 15:42:02 1992 --- gcc-2.3.1/config/aix386.h Thu Sep 3 03:11:44 1992 *************** *** 31,38 **** #include "att386.h" - /* By default, target has a 80387. */ - - #define TARGET_DEFAULT 1 - /* Use crt1.o as a startup file and crtn.o as a closing file. */ --- 31,34 ---- *************** *** 80,97 **** #endif - /* Machines that use the AT&T assembler syntax - also return floating point values in an FP register. */ - /* 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 VALUE_REGNO(MODE) \ - (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0) - - /* 1 if N is a possible register number for a function value. */ - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) - /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. */ --- 76,79 ---- diff -rc2N gcc-2.2.2/config/aix386ng.h gcc-2.3.1/config/aix386ng.h *** gcc-2.2.2/config/aix386ng.h --- gcc-2.3.1/config/aix386ng.h Fri Oct 23 18:04:02 1992 *************** *** 0 **** --- 1,92 ---- + /* Definitions for IBM PS2 running AIX/386. + From: Minh Tran-Le + Copyright (C) 1988 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. */ + + + #include "i386.h" + + /* Get the generic definitions for system V.3. */ + + #include "svr3.h" + + /* Use the ATT assembler syntax. + This overrides at least one macro (ASM_OUTPUT_LABELREF) from svr3.h. */ + + #include "att386.h" + + /* Use crt1.o as a startup file and crtn.o as a closing file. */ + + #define STARTFILE_SPEC \ + "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} crtbegin.o%s" + + #define LIB_SPEC "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -lc \ + crtend.o%s crtn.o%s" + + /* Special flags for the linker. I don't know what they do. */ + + #define LINK_SPEC "%{K} %{!K:-K} %{T*} %{z:-lm}" + + /* Specify predefined symbols in preprocessor. */ + + #define CPP_PREDEFINES "-D_I386 -Di386 -DAIX -D_AIX" + + /* special flags for the aix assembler to generate the short form for all + qualifying forward reference */ + + #define ASM_SPEC "-s2" + + #undef ASM_FILE_START + #define ASM_FILE_START(FILE) \ + do { fprintf (FILE, "\t.file\t\"%s\"\n", dump_base_name); \ + if (optimize) \ + ASM_FILE_START_1 (FILE); \ + else \ + fprintf (FILE, "\t.noopt\n"); \ + } while (0) + + /* This was suggested, but it shouldn't be right for DBX output. -- RMS + #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) */ + + /* Writing `int' for a bitfield forces int alignment for the structure. */ + + #define PCC_BITFIELD_TYPE_MATTERS 1 + + #if 0 + /* Don't write a `.optim' pseudo; this assembler + is said to have a bug when .optim is used. */ + + #undef ASM_FILE_START_1 + #define ASM_FILE_START_1(FILE) fprintf (FILE, "\t.noopt\n"); + #endif + + /* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + + #undef FUNCTION_PROFILER + #define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "\tleal %sP%d,%%eax\n\tcall mcount\n", LPREFIX, (LABELNO)); + + /* Note that using bss_section here caused errors + in building shared libraries on system V.3. + but AIX 1.2 does not have yet shareable libraries on PS2 */ + #undef ASM_OUTPUT_LOCAL + #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ + (bss_section (), \ + ASM_OUTPUT_LABEL ((FILE), (NAME)), \ + fprintf ((FILE), "\t.set .,.+%u\n", (ROUNDED))) diff -rc2N gcc-2.2.2/config/alpha.c gcc-2.3.1/config/alpha.c *** gcc-2.2.2/config/alpha.c --- gcc-2.3.1/config/alpha.c Mon Oct 26 16:01:33 1992 *************** *** 0 **** --- 1,1521 ---- + /* Subroutines used for code generation on the DEC Alpha. + Copyright (C) 1992 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@nyu.edu) + + This file is part of GNU CC. + + GNU CC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + + #include + #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 "reload.h" + #include "expr.h" + #include "obstack.h" + #include "tree.h" + + /* Save information from a "cmpxx" operation until the branch or scc is + emitted. */ + + rtx alpha_compare_op0, alpha_compare_op1; + int alpha_compare_fp_p; + + /* Save the name of the current function as used by the assembler. This + is used by the epilogue. */ + + char *alpha_function_name; + + /* Nonzero if the current function needs gp. */ + + int alpha_function_needs_gp; + + /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ + + int + zap_mask (value) + HOST_WIDE_INT value; + { + int i; + + for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; + i++, value >>= 8) + if ((value & 0xff) != 0 && (value & 0xff) != 0xff) + return 0; + + return 1; + } + + /* Returns 1 if OP is either the constant zero or a register. If a + register, it must be in the proper mode unless MODE is VOIDmode. */ + + int + reg_or_0_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return op == const0_rtx || register_operand (op, mode); + } + + /* Return 1 if OP is an 8-bit constant or any register. */ + + int + reg_or_8bit_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return ((GET_CODE (op) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100) + || register_operand (op, mode)); + } + + /* Return 1 if the operand is a valid second operand to an add insn. */ + + int + add_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + if (GET_CODE (op) == CONST_INT) + return ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) < 0x10000 + || ((INTVAL (op) & 0xffff) == 0 + && (INTVAL (op) >> 31 == -1 + || INTVAL (op) >> 31 == 0))); + + return register_operand (op, mode); + } + + /* Return 1 if the operand is a valid second operand to a sign-extending + add insn. */ + + int + sext_add_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + if (GET_CODE (op) == CONST_INT) + return ((unsigned HOST_WIDE_INT) INTVAL (op) < 255 + || (unsigned HOST_WIDE_INT) (- INTVAL (op)) < 255); + + return register_operand (op, mode); + } + + /* Return 1 if OP is the constant 4 or 8. */ + + int + const48_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) == 4 || INTVAL (op) == 8)); + } + + /* Return 1 if OP is a valid first operand to an AND insn. */ + + int + and_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) + return (zap_mask (CONST_DOUBLE_LOW (op)) + && zap_mask (CONST_DOUBLE_HIGH (op))); + + if (GET_CODE (op) == CONST_INT) + return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100 + || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100 + || zap_mask (INTVAL (op))); + + return register_operand (op, mode); + } + + /* Return 1 if OP is a constant that is the width, in bits, of an integral + mode smaller than DImode. */ + + int + mode_width_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return (GET_CODE (op) == CONST_INT + && (INTVAL (op) == 8 || INTVAL (op) == 16 || INTVAL (op) == 32)); + } + + /* Return 1 if OP is a constant that is the width of an integral machine mode + smaller than an integer. */ + + int + mode_mask_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + #if HOST_BITS_PER_WIDE_INT == 32 + if (GET_CODE (op) == CONST_DOUBLE) + return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == -1; + #endif + + if (GET_CODE (op) == CONST_INT) + return (INTVAL (op) == 0xff + || INTVAL (op) == 0xffff + #if HOST_BITS_PER_WIDE_INT == 64 + || INTVAL (op) == 0xffffffff + #endif + ); + } + + /* Return 1 if OP is a multiple of 8 less than 64. */ + + int + mul8_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return (GET_CODE (op) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (op) < 64 + && (INTVAL (op) & 7) == 0); + } + + /* Return 1 if OP is the constant zero in floating-point. */ + + int + fp0_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return (GET_MODE (op) == mode + && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode)); + } + + /* Return 1 if OP is the floating-point constant zero or a register. */ + + int + reg_or_fp0_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return fp0_operand (op, mode) || register_operand (op, mode); + } + + /* Return 1 if OP is a register or a constant integer. */ + + + int + reg_or_cint_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return GET_CODE (op) == CONST_INT || register_operand (op, mode); + } + + /* Return 1 if OP is a valid operand for the source of a move insn. */ + + int + input_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) + return 0; + + if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode) + return 0; + + switch (GET_CODE (op)) + { + case LABEL_REF: + case SYMBOL_REF: + case CONST: + return mode == DImode; + + case REG: + return 1; + + case SUBREG: + if (register_operand (op, mode)) + return 1; + /* ... fall through ... */ + case MEM: + return mode != HImode && mode != QImode && general_operand (op, mode); + + case CONST_DOUBLE: + return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode); + + case CONST_INT: + return mode == QImode || mode == HImode || add_operand (op, mode); + } + + return 0; + } + + /* Return 1 if OP is a SYMBOL_REF for the current function. */ + + int + current_function_operand (op, mode) + rtx op; + enum machine_mode mode; + { + return (GET_CODE (op) == SYMBOL_REF + && ! strcmp (XSTR (op, 0), current_function_name)); + } + + /* Return 1 if OP is a valid Alpha comparison operator. Here we know which + comparisons are valid in which insn. */ + + int + alpha_comparison_operator (op, mode) + register rtx op; + enum machine_mode mode; + { + enum rtx_code code = GET_CODE (op); + + if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<') + return 0; + + return (code == EQ || code == LE || code == LT + || (mode == DImode && (code == LEU || code == LTU))); + } + + /* Return 1 if OP is a signed comparison operation. */ + + int + signed_comparison_operator (op, mode) + register rtx op; + enum machine_mode mode; + { + switch (GET_CODE (op)) + { + case EQ: case NE: case LE: case LT: case GE: case GT: + return 1; + } + + return 0; + } + + /* Return 1 if this is a divide or modulus operator. */ + + int + divmod_operator (op, mode) + register rtx op; + enum machine_mode mode; + { + switch (GET_CODE (op)) + { + case DIV: case MOD: case UDIV: case UMOD: + return 1; + } + + return 0; + } + + /* Return 1 if this memory address is a known aligned register plus + a constant. It must be a valid address. This means that we can do + this as an aligned reference plus some offset. + + Take into account what reload will do. + + We could say that out-of-range stack slots are alignable, but that would + complicate get_aligned_mem and it isn't worth the trouble since few + functions have large stack space. */ + + int + aligned_memory_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + if (GET_CODE (op) == SUBREG) + { + if (GET_MODE (op) != mode) + return 0; + op = SUBREG_REG (op); + mode = GET_MODE (op); + } + + if (reload_in_progress && GET_CODE (op) == REG + && REGNO (op) >= FIRST_PSEUDO_REGISTER) + op = reg_equiv_mem[REGNO (op)]; + + if (GET_CODE (op) != MEM || GET_MODE (op) != mode + || ! memory_address_p (mode, XEXP (op, 0))) + return 0; + + op = XEXP (op, 0); + + if (GET_CODE (op) == PLUS) + op = XEXP (op, 0); + + return (GET_CODE (op) == REG + && (REGNO (op) == STACK_POINTER_REGNUM || op == frame_pointer_rtx + || (REGNO (op) >= FIRST_VIRTUAL_REGISTER + && REGNO (op) <= LAST_VIRTUAL_REGISTER))); + } + + /* Similar, but return 1 if OP is a MEM which is not alignable. */ + + int + unaligned_memory_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + if (GET_CODE (op) == SUBREG) + { + if (GET_MODE (op) != mode) + return 0; + op = SUBREG_REG (op); + mode = GET_MODE (op); + } + + if (reload_in_progress && GET_CODE (op) == REG + && REGNO (op) >= FIRST_PSEUDO_REGISTER) + op = reg_equiv_mem[REGNO (op)]; + + if (GET_CODE (op) != MEM || GET_MODE (op) != mode) + return 0; + + op = XEXP (op, 0); + + if (! memory_address_p (mode, op)) + return 1; + + if (GET_CODE (op) == PLUS) + op = XEXP (op, 0); + + return (GET_CODE (op) != REG + || (REGNO (op) != STACK_POINTER_REGNUM && op != frame_pointer_rtx + && (REGNO (op) < FIRST_VIRTUAL_REGISTER + || REGNO (op) > LAST_VIRTUAL_REGISTER))); + } + + /* Return 1 if OP is any memory location. During reload a pseudo matches. */ + + int + any_memory_operand (op, mode) + register rtx op; + enum machine_mode mode; + { + return (GET_CODE (op) == MEM + || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) + || (reload_in_progress && GET_CODE (op) == REG + && REGNO (op) >= FIRST_PSEUDO_REGISTER) + || (reload_in_progress && GET_CODE (op) == SUBREG + && GET_CODE (SUBREG_REG (op)) == REG + && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)); + } + + /* REF is an alignable memory location. Place an aligned SImode + reference into *PALIGNED_MEM and the number of bits to shift into + *PBITNUM. */ + + void + get_aligned_mem (ref, paligned_mem, pbitnum) + rtx ref; + rtx *paligned_mem, *pbitnum; + { + rtx base; + HOST_WIDE_INT offset = 0; + + if (GET_CODE (ref) == SUBREG) + { + offset = SUBREG_WORD (ref) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) + - MIN (UNITS_PER_WORD, + GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); + ref = SUBREG_REG (ref); + } + + if (GET_CODE (ref) == REG) + ref = reg_equiv_mem[REGNO (ref)]; + + if (reload_in_progress) + base = find_replacement (&XEXP (ref, 0)); + else + base = XEXP (ref, 0); + + if (GET_CODE (base) == PLUS) + offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); + + *paligned_mem = gen_rtx (MEM, SImode, + plus_constant (base, offset & ~3)); + MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref); + MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref); + RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref); + + *pbitnum = GEN_INT ((offset & 3) * 8); + } + + /* Similar, but just get the address. Handle the two reload cases. */ + + rtx + get_unaligned_address (ref) + rtx ref; + { + rtx base; + HOST_WIDE_INT offset = 0; + + if (GET_CODE (ref) == SUBREG) + { + offset = SUBREG_WORD (ref) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) + - MIN (UNITS_PER_WORD, + GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); + ref = SUBREG_REG (ref); + } + + if (GET_CODE (ref) == REG) + ref = reg_equiv_mem[REGNO (ref)]; + + if (reload_in_progress) + base = find_replacement (&XEXP (ref, 0)); + else + base = XEXP (ref, 0); + + if (GET_CODE (base) == PLUS) + offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); + + return plus_constant (base, offset); + } + + /* Subfunction of the following function. Update the flags of any MEM + found in part of X. */ + + static void + alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) + rtx x; + int in_struct_p, volatile_p, unchanging_p; + { + int i; + + switch (GET_CODE (x)) + { + case SEQUENCE: + case PARALLEL: + for (i = XVECLEN (x, 0) - 1; i >= 0; i--) + alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, + unchanging_p); + break; + + case INSN: + alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p, + unchanging_p); + break; + + case SET: + alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p, + unchanging_p); + alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, + unchanging_p); + break; + + case MEM: + MEM_IN_STRUCT_P (x) = in_struct_p; + MEM_VOLATILE_P (x) = volatile_p; + RTX_UNCHANGING_P (x) = unchanging_p; + break; + } + } + + /* Given INSN, which is either an INSN or a SEQUENCE generated to + perform a memory operation, look for any MEMs in either a SET_DEST or + a SET_SRC and copy the in-struct, unchanging, and volatile flags from + REF into each of the MEMs found. If REF is not a MEM, don't do + anything. */ + + void + alpha_set_memflags (insn, ref) + rtx insn; + rtx ref; + { + /* Note that it is always safe to get these flags, though they won't + be what we think if REF is not a MEM. */ + int in_struct_p = MEM_IN_STRUCT_P (ref); + int volatile_p = MEM_VOLATILE_P (ref); + int unchanging_p = RTX_UNCHANGING_P (ref); + + if (GET_CODE (ref) != MEM + || (! in_struct_p && ! volatile_p && ! unchanging_p)) + return; + + alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p); + } + + /* Try to output insns to set TARGET equal to the constant C if it can be + done in less than N insns. Returns 1 if it can be done and the + insns have been emitted. If it would take more than N insns, zero is + returned and no insns and emitted. */ + + int + alpha_emit_set_const (target, c, n) + rtx target; + HOST_WIDE_INT c; + int n; + { + HOST_WIDE_INT new = c; + int i, bits; + + #if HOST_BITS_PER_WIDE_INT == 64 + /* We are only called for SImode and DImode. If this is SImode, ensure that + we are sign extended to a full word. This does not make any sense when + cross-compiling on a narrow machine. */ + + if (GET_MODE (target) == SImode) + c = (c & 0xffffffff) - 2 * (c & 0x80000000); + #endif + + /* If this is a sign-extended 32-bit constant, we can do this in at most + three insns, so do it if we have enough insns left. We always have + a sign-extended 32-bit constant when compiling on a narrow machine. */ + + if (HOST_BITS_PER_WIDE_INT != 64 + || c >> 31 == -1 || c >> 31 == 0) + { + HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); + HOST_WIDE_INT tmp1 = c - low; + HOST_WIDE_INT high + = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + HOST_WIDE_INT tmp2 = c - (high << 16) - low; + HOST_WIDE_INT extra = 0; + + if (tmp2) + { + extra = 0x4000; + tmp1 -= 0x40000000; + high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + } + + if (c == low || (low == 0 && extra == 0)) + { + emit_move_insn (target, GEN_INT (c)); + return 1; + } + else if (n >= 2 + (extra != 0)) + { + emit_move_insn (target, GEN_INT (low)); + if (extra != 0) + emit_insn (gen_add2_insn (target, GEN_INT (extra << 16))); + + emit_insn (gen_add2_insn (target, GEN_INT (high << 16))); + return 1; + } + } + + /* If we couldn't do it that way, try some other methods (that depend on + being able to compute in the target's word size). But if we have no + instructions left, don't bother. Also, don't even try if this is + SImode (in which case we should have already done something, but + do a sanity check here). */ + + if (n == 1 || HOST_BITS_PER_WIDE_INT < 64 || GET_MODE (target) != DImode) + return 0; + + /* First, see if can load a value into the target that is the same as the + constant except that all bytes that are 0 are changed to be 0xff. If we + can, then we can do a ZAPNOT to obtain the desired constant. */ + + for (i = 0; i < 64; i += 8) + if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0) + new |= (HOST_WIDE_INT) 0xff << i; + + if (alpha_emit_set_const (target, new, n - 1)) + { + emit_insn (gen_anddi3 (target, target, GEN_INT (c | ~ new))); + return 1; + } + + /* Find, see if we can load a related constant and then shift and possibly + negate it to get the constant we want. Try this once each increasing + numbers of insns. */ + + for (i = 1; i < n; i++) + { + /* First try complementing. */ + if (alpha_emit_set_const (target, ~ c, i)) + { + emit_insn (gen_one_cmpldi2 (target, target)); + return 1; + } + + /* First try to form a constant and do a left shift. We can do this + if some low-order bits are zero; the exact_log2 call below tells + us that information. The bits we are shifting out could be any + value, but here we'll just try the 0- and sign-extended forms of + the constant. To try to increase the chance of having the same + constant in more than one insn, start at the highest number of + bits to shift, but try all possibilities in case a ZAPNOT will + be useful. */ + + if ((bits = exact_log2 (c & - c)) > 0) + for (; bits > 0; bits--) + if (alpha_emit_set_const (target, c >> bits, i) + || alpha_emit_set_const (target, + ((unsigned HOST_WIDE_INT) c) >> bits, + i)) + { + emit_insn (gen_ashldi3 (target, target, GEN_INT (bits))); + return 1; + } + + /* Now try high-order zero bits. Here we try the shifted-in bits as + all zero and all ones. */ + + if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (c) - 1) > 0) + for (; bits > 0; bits--) + if (alpha_emit_set_const (target, c << bits, i) + || alpha_emit_set_const (target, + ((c << bits) + | (((HOST_WIDE_INT) 1 << bits) - 1)), + i)) + { + emit_insn (gen_lshrdi3 (target, target, GEN_INT (bits))); + return 1; + } + + /* Now try high-order 1 bits. We get that with a sign-extension. + But one bit isn't enough here. */ + + if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (~ c) - 2) > 0) + for (; bits > 0; bits--) + if (alpha_emit_set_const (target, c << bits, i) + || alpha_emit_set_const (target, + ((c << bits) + | (((HOST_WIDE_INT) 1 << bits) - 1)), + i)) + { + emit_insn (gen_ashrdi3 (target, target, GEN_INT (bits))); + return 1; + } + } + + return 0; + } + + /* Adjust the cost of a scheduling dependency. Return the new cost of + a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ + + int + alpha_adjust_cost (insn, link, dep_insn, cost) + rtx insn; + rtx link; + rtx dep_insn; + int cost; + { + rtx set; + + /* If the dependence is an anti-dependence, there is no cost. For an + output dependence, there is sometimes a cost, but it doesn't seem + worth handling those few cases. */ + + if (REG_NOTE_KIND (link) != 0) + return 0; + + /* If INSN is a store insn and DEP_INSN is setting the data being stored, + we can sometimes lower the cost. */ + + if (recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_ST + && (set = single_set (dep_insn)) != 0 + && GET_CODE (PATTERN (insn)) == SET + && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) + switch (get_attr_type (dep_insn)) + { + case TYPE_LD: + /* No savings here. */ + return cost; + + case TYPE_IMULL: + case TYPE_IMULQ: + /* In these cases, we save one cycle. */ + return cost - 2; + + default: + /* In all other cases, we save two cycles. */ + return MAX (0, cost - 4); + } + + /* Another case that needs adjustment is an arithmetic or logical + operation. It's cost is usually one cycle, but we default it to + two in the MD file. The only case that it is actually two is + for the address in loads and stores. */ + + if (recog_memoized (dep_insn) >= 0 + && get_attr_type (dep_insn) == TYPE_IADDLOG) + switch (get_attr_type (insn)) + { + case TYPE_LD: + case TYPE_ST: + return cost; + + default: + return 2; + } + + /* The final case is when a compare feeds into an integer branch. The cost + is only one cycle in that case. */ + + if (recog_memoized (dep_insn) >= 0 + && get_attr_type (dep_insn) == TYPE_ICMP + && recog_memoized (insn) >= 0 + && get_attr_type (insn) == TYPE_IBR) + return 2; + + /* Otherwise, return the default cost. */ + + return cost; + } + + /* Print an operand. Recognize special options, documented below. */ + + void + print_operand (file, x, code) + FILE *file; + rtx x; + char code; + { + int i; + + switch (code) + { + case 'r': + /* If this operand is the constant zero, write it as "$31". */ + if (GET_CODE (x) == REG) + fprintf (file, "%s", reg_names[REGNO (x)]); + else if (x == CONST0_RTX (GET_MODE (x))) + fprintf (file, "$31"); + else + output_operand_lossage ("invalid %%r value"); + + break; + + case 'R': + /* Similar, but for floating-point. */ + if (GET_CODE (x) == REG) + fprintf (file, "%s", reg_names[REGNO (x)]); + else if (x == CONST0_RTX (GET_MODE (x))) + fprintf (file, "$f31"); + else + output_operand_lossage ("invalid %%R value"); + + break; + + case 'N': + /* Write the 1's complement of a constant. */ + if (GET_CODE (x) != CONST_INT) + output_operand_lossage ("invalid %%N value"); + + fprintf (file, "%ld", ~ INTVAL (x)); + break; + + case 'P': + /* Write 1 << C, for a constant C. */ + if (GET_CODE (x) != CONST_INT) + output_operand_lossage ("invalid %%P value"); + + fprintf (file, "%ld", (HOST_WIDE_INT) 1 << INTVAL (x)); + break; + + case 'h': + /* Write the high-order 16 bits of a constant, sign-extended. */ + if (GET_CODE (x) != CONST_INT) + output_operand_lossage ("invalid %%h value"); + + fprintf (file, "%ld", INTVAL (x) >> 16); + break; + + case 'L': + /* Write the low-order 16 bits of a constant, sign-extended. */ + if (GET_CODE (x) != CONST_INT) + output_operand_lossage ("invalid %%L value"); + + fprintf (file, "%ld", (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000)); + break; + + case 'm': + /* Write mask for ZAP insn. */ + if (GET_CODE (x) == CONST_DOUBLE) + { + HOST_WIDE_INT mask = 0; + HOST_WIDE_INT value; + + value = CONST_DOUBLE_LOW (x); + for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; + i++, value >>= 8) + if (value & 0xff) + mask |= (1 << i); + + value = CONST_DOUBLE_HIGH (x); + for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; + i++, value >>= 8) + if (value & 0xff) + mask |= (1 << (i + sizeof (int))); + + fprintf (file, "%ld", mask & 0xff); + } + + else if (GET_CODE (x) == CONST_INT) + { + HOST_WIDE_INT mask = 0, value = INTVAL (x); + + for (i = 0; i < 8; i++, value >>= 8) + if (value & 0xff) + mask |= (1 << i); + + fprintf (file, "%ld", mask); + } + else + output_operand_lossage ("invalid %%m value"); + break; + + case 'M': + /* 'b', 'w', or 'l' as the value of the constant. */ + if (GET_CODE (x) != CONST_INT + || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32)) + output_operand_lossage ("invalid %%M value"); + + fprintf (file, "%s", + INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l"); + break; + + case 'U': + /* Similar, except do it from the mask. */ + if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff) + fprintf (file, "b"); + else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff) + fprintf (file, "w"); + #if HOST_BITS_PER_WIDE_INT == 32 + else if (GET_CODE (x) == CONST_DOUBLE + && CONST_DOUBLE_HIGH (x) == 0 + && CONST_DOUBLE_LOW (x) == -1) + fprintf (file, "l"); + #else + else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) + fprintf (file, "l"); + #endif + else + output_operand_lossage ("invalid %%U value"); + break; + + case 's': + /* Write the constant value divided by 8. */ + if (GET_CODE (x) != CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 + && (INTVAL (x) & 7) != 8) + output_operand_lossage ("invalid %%s value"); + + fprintf (file, "%ld", INTVAL (x) / 8); + break; + + case 'S': + /* Same, except compute (64 - c) / 8 */ + + if (GET_CODE (x) != CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 + && (INTVAL (x) & 7) != 8) + output_operand_lossage ("invalid %%s value"); + + fprintf (file, "%ld", (64 - INTVAL (x)) / 8); + break; + + case 'C': + /* Write out comparison name. */ + if (GET_RTX_CLASS (GET_CODE (x)) != '<') + output_operand_lossage ("invalid %%C value"); + + if (GET_CODE (x) == LEU) + fprintf (file, "ule"); + else if (GET_CODE (x) == LTU) + fprintf (file, "ult"); + else + fprintf (file, "%s", GET_RTX_NAME (GET_CODE (x))); + break; + + case 'D': + /* Similar, but write reversed code. We can't get an unsigned code + here. */ + if (GET_RTX_CLASS (GET_CODE (x)) != '<') + output_operand_lossage ("invalid %%D value"); + + fprintf (file, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x)))); + break; + + case 'E': + /* Write the divide or modulus operator. */ + switch (GET_CODE (x)) + { + case DIV: + fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q"); + break; + case UDIV: + fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q"); + break; + case MOD: + fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q"); + break; + case UMOD: + fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q"); + break; + default: + output_operand_lossage ("invalid %%E value"); + break; + } + break; + + case 'F': + /* Write the symbol; if the current function uses GP, write a + modified version. */ + if (GET_CODE (x) != SYMBOL_REF) + output_operand_lossage ("invalid %%F value"); + + output_addr_const (file, x); + if (alpha_function_needs_gp) + fprintf (file, "..ng"); + break; + + case 'A': + /* Write "_u" for unaligned access. */ + if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND) + fprintf (file, "_u"); + break; + + case 0: + if (GET_CODE (x) == REG) + fprintf (file, "%s", reg_names[REGNO (x)]); + else if (GET_CODE (x) == MEM) + output_address (XEXP (x, 0)); + else + output_addr_const (file, x); + break; + + default: + output_operand_lossage ("invalid %%xn code"); + } + } + + /* Do what is necessary for `va_start'. The argument is ignored; + We look at the current function to determine if stdargs or varargs + is used and fill in an initial va_list. A pointer to this constructor + is returned. */ + + struct rtx_def * + alpha_builtin_saveregs (arglist) + tree arglist; + { + rtx block, addr, argsize; + tree fntype = TREE_TYPE (current_function_decl); + int stdargs = (TYPE_ARG_TYPES (fntype) != 0 + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) + != void_type_node)); + int nregs = current_function_args_info; + + /* If we have a variable-sized argument already, we will have used all + the registers, so set up to indicate that. */ + + if (GET_CODE (current_function_arg_offset_rtx) != CONST_INT) + { + argsize = plus_constant (current_function_arg_offset_rtx, + ((6 - stdargs) * UNITS_PER_WORD + + UNITS_PER_WORD - 1)); + argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize, + build_int_2 (3, 0), argsize, 0); + } + else + { + /* If we are using memory, deduct the stdarg adjustment from it, + otherwise from the number of registers. Then compute the current + argument number. */ + + int memargs = ((INTVAL (current_function_arg_offset_rtx) + + UNITS_PER_WORD - 1) + / UNITS_PER_WORD); + + if (memargs) + memargs -= stdargs; + else + nregs -= stdargs; + + argsize = GEN_INT (MIN (nregs, 6) + memargs); + } + + /* Allocate the va_list constructor */ + block = assign_stack_local (BLKmode, 4 * UNITS_PER_WORD, BITS_PER_WORD); + RTX_UNCHANGING_P (block) = 1; + RTX_UNCHANGING_P (XEXP (block, 0)) = 1; + + /* Store the argsize as the __va_arg member. */ + emit_move_insn (change_address (block, DImode, XEXP (block, 0)), + argsize); + + /* Store the arg pointer in the __va_stack member. */ + emit_move_insn (change_address (block, Pmode, + plus_constant (XEXP (block, 0), + UNITS_PER_WORD)), + virtual_incoming_args_rtx); + + /* Allocate the integer register space, and store it as the + __va_ireg member. */ + addr = assign_stack_local (BLKmode, 6 * UNITS_PER_WORD, -1); + MEM_IN_STRUCT_P (addr) = 1; + RTX_UNCHANGING_P (addr) = 1; + RTX_UNCHANGING_P (XEXP (addr, 0)) = 1; + + emit_move_insn (change_address (block, Pmode, + plus_constant (XEXP (block, 0), + 2 * UNITS_PER_WORD)), + copy_to_reg (XEXP (addr, 0))); + + /* Now store the incoming integer registers. */ + if (nregs < 6) + move_block_from_reg + (16 + nregs, + change_address (addr, Pmode, + plus_constant (XEXP (addr, 0), + nregs * UNITS_PER_WORD)), + 6 - nregs); + + /* Allocate the FP register space, and store it as the + __va_freg member. */ + addr = assign_stack_local (BLKmode, 6 * UNITS_PER_WORD, -1); + MEM_IN_STRUCT_P (addr) = 1; + RTX_UNCHANGING_P (addr) = 1; + RTX_UNCHANGING_P (XEXP (addr, 0)) = 1; + + emit_move_insn (change_address (block, Pmode, + plus_constant (XEXP (block, 0), + 3 * UNITS_PER_WORD)), + copy_to_reg (XEXP (addr, 0))); + + /* Now store the incoming floating-point registers. If we are not + to use the floating-point registers, store the integer registers + in those locations too. */ + if (nregs < 6) + move_block_from_reg + (16 + 32 * (TARGET_FPREGS != 0) + nregs, + change_address (addr, Pmode, + plus_constant (XEXP (addr, 0), + nregs * UNITS_PER_WORD)), + 6 - nregs); + + /* Return the address of the va_list constructor, but don't put it in a + register. This fails when not optimizing and produces worse code when + optimizing. */ + return XEXP (block, 0); + } + + /* This page contains routines that are used to determine what the function + prologue and epilogue code will do and write them out. */ + + /* Compute the size of the save area in the stack. */ + + int + alpha_sa_size () + { + int size = 0; + int i; + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i]) + size++; + + return size * 8; + } + + /* Return non-zero if this function needs gp. It does if it has + an LDSYM insn. */ + + int + alpha_need_gp () + { + rtx insn; + + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER + && get_attr_type (insn) == TYPE_LDSYM) + return 1; + + return 0; + } + + /* Return 1 if GP is dead at after INSN. */ + + int + alpha_gp_dead_after (insn) + rtx insn; + { + int jump_count = 0; + int found = 0; + rtx p; + + /* If we aren't optimizing, don't do this optimization. More importantly, + JUMP_LABEL isn't properly set when not optimizing. */ + + if (optimize == 0) + return 0; + + /* If we are followed by a BARRIER, we don't return. */ + if (NEXT_INSN (insn) && GET_CODE (NEXT_INSN (insn)) == BARRIER) + return 1; + + /* Otherwise search for a use of GP before a return. */ + + for (p = next_active_insn (insn); p; p = next_active_insn (p)) + { + if (get_attr_type (p) == TYPE_LDSYM + || get_attr_type (p) == TYPE_JSR) + { + found = 1; + break; + } + + if (GET_CODE (p) == JUMP_INSN) + { + if (GET_CODE (PATTERN (p)) == RETURN) + break; + + if (! simplejump_p (p) || jump_count++ > 10) + { + found = 1; + break; + } + + p = JUMP_LABEL (p); + } + } + + /* Restore any operands destroyed by the attribute calls above. */ + insn_extract (insn); + + return ! found; + } + + /* Return 1 if this function can directly return via $26. */ + + int + direct_return () + { + return (reload_completed && alpha_sa_size () == 0 + && get_frame_size () == 0 + && current_function_pretend_args_size == 0); + } + + /* Write function prologue. */ + + void + output_prolog (file, size) + FILE *file; + int size; + { + HOST_WIDE_INT frame_size = ((size + current_function_outgoing_args_size + + current_function_pretend_args_size + + alpha_sa_size () + 15) & ~15); + int reg_offset = current_function_outgoing_args_size; + int start_reg_offset = reg_offset; + unsigned reg_mask = 0; + int i; + + /* If we need a GP, load it first. */ + alpha_function_needs_gp = alpha_need_gp (); + + if (alpha_function_needs_gp) + { + rtx insn; + + fprintf (file, "\tldgp $29,0($27)\n"); + + /* If we have a recursive call, put a special label here. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == CALL_INSN + && get_attr_type (insn) != TYPE_JSR) + { + fprintf (file, "%s..ng:\n", current_function_name); + break; + } + } + + /* Adjust the stack by the frame size. If the frame size is > 32768 + bytes, we have to load it into a register first and then subtract + from sp. Note that we are only allowed to adjust sp once in the + prologue. */ + + if (frame_size > 32768) + { + HOST_WIDE_INT low = (frame_size & 0xffff) - 2 * (frame_size & 0x8000); + HOST_WIDE_INT tmp1 = frame_size - low; + HOST_WIDE_INT high + = ((tmp1 >> 16) & 0xfff) - 2 * ((tmp1 >> 16) & 0x8000); + HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low; + HOST_WIDE_INT extra = 0; + int in_reg = 31; + + /* We haven't written code to handle frames > 4GB. */ + #if HOST_BITS_PER_LONG_INT == 64 + if ((unsigned HOST_WIDE_INT) frame_size >> 32 != 0) + abort (); + #endif + + if (tmp2) + { + extra = 0x4000; + tmp1 -= 0x40000000; + high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + } + + if (low != 0) + { + fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg); + in_reg = 28; + } + + if (extra) + { + fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg); + in_reg = 28; + } + + fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg); + + fprintf (file, "\tsubq $30,$28,$30\n"); + } + else if (frame_size) + fprintf (file, "\tlda $30,-%d($30)\n", frame_size); + + /* Write out the .frame line. If we need a frame pointer, we use + an offset of zero. */ + + if (frame_pointer_needed) + fprintf (file, "\t.frame $15,0,$26\n"); + else + fprintf (file, "\t.frame $30,%d,$26\n", frame_size); + + + /* Save register 26 if it is used. */ + if (regs_ever_live[26]) + { + reg_mask |= 1 << 26; + fprintf (file, "\tstq $26,%d($30)\n", reg_offset); + reg_offset += 8; + } + + /* Now save any other used register that are required to be saved. */ + for (i = 0; i < 32; i++) + if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26) + { + reg_mask |= 1 << i; + fprintf (file, "\tstq $%d,%d($30)\n", i, reg_offset); + reg_offset += 8; + } + + /* Print the register mask and do floating-point saves. */ + if (reg_mask) + fprintf (file, "\t.mask 0x%x,%d\n", reg_mask, + start_reg_offset - frame_size); + + start_reg_offset = reg_offset; + reg_mask = 0; + + for (i = 0; i < 32; i++) + if (! fixed_regs[i + 32] && ! call_used_regs[i + 32] + && regs_ever_live[i + 32]) + { + reg_mask |= 1 << i; + fprintf (file, "\tstt $f%d,%d($30)\n", i, reg_offset); + reg_offset += 8; + } + + /* Print the floating-point mask, if we've saved any fp register. */ + if (reg_mask) + fprintf (file, "\t.fmask 0x%x,%d\n", reg_mask, start_reg_offset); + + /* If we need a frame pointer, set it to the value of incoming stack + which we compute by adding back the frame size pointer. Because we + can subtract one more than we can add, we have to special-case + frame sizes of 32K. Note that there is no restriction that the frame + pointer be updated in one instruction. */ + + if (frame_pointer_needed) + { + if (frame_size == 32768) + fprintf (file, "\tlda $15,16384($30)\n\tlda $15,16384($15)\n"); + else if (frame_size > 32768) + fprintf (file, "\tadd $30,$28,$15\n"); + else + fprintf (file, "\tlda $15,%d($30)\n", frame_size); + } + } + + /* Write function epilogue. */ + + void + output_epilog (file, size) + FILE *file; + int size; + { + rtx insn = get_last_insn (); + HOST_WIDE_INT frame_size = ((size + current_function_outgoing_args_size + + current_function_pretend_args_size + + alpha_sa_size () + 15) & ~15); + int reg_offset = current_function_outgoing_args_size; + int reg_offset_from = STACK_POINTER_REGNUM; + int i; + + /* If the last insn was a BARRIER, we don't have to write anything except + the .end pseudo-op. */ + if (GET_CODE (insn) == NOTE) + insn = prev_nonnote_insn (insn); + if (insn == 0 || GET_CODE (insn) != BARRIER) + { + /* If we have a frame pointer, we restore the registers from an + offset from it, assuming that we can reach the offset. If not, + we have to compute the address using a scratch register. This is + messy, but should not be common. We have to copy the frame + pointer elsewhere here since we will be restoring it before we can + use it to restore the stack pointer. We use $25. */ + + if (frame_pointer_needed) + { + fprintf (file, "\tbis $15,$15,$25\n"); + + if (frame_size < 32768) + reg_offset -= frame_size, reg_offset_from = 25; + else + { + HOST_WIDE_INT low + = (frame_size & 0xffff) - 2 * (frame_size & 0x8000); + HOST_WIDE_INT tmp1 = frame_size - low; + HOST_WIDE_INT high + = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low; + int extra = 0xe; + int in_reg = 31; + + if (tmp2) + { + extra = 0x4000; + tmp1 -= 0x40000000; + high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + } + + if (low != 0) + { + fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg); + in_reg = 28; + } + + if (extra) + { + fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg); + in_reg = 28; + } + + fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg); + + fprintf (file, "\taddq $25,$28,$28\n"); + + reg_offset_from = 28; + } + } + + /* Restore all the registers, starting with the return address + register. */ + if (regs_ever_live[26]) + { + fprintf (file, "\tldq $26,%d($%d)\n", reg_offset, reg_offset_from); + reg_offset += 8; + } + + /* Now restore any other used register that that we saved. */ + for (i = 0; i < 32; i++) + if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] + && i != 26) + { + fprintf (file, "\tldq $%d,%d($%d)\n", + i, reg_offset, reg_offset_from); + reg_offset += 8; + } + + for (i = 0; i < 32; i++) + if (! fixed_regs[i + 32] && ! call_used_regs[i + 32] + && regs_ever_live[i + 32]) + { + fprintf (file, "\tldt $f%d,%d($%d)\n", + i, reg_offset, reg_offset_from); + reg_offset += 8; + } + + /* Restore the stack. If we have a frame pointer, use it. Otherwise, + add the size back into the stack, handling the large frame size. */ + + if (frame_pointer_needed) + fprintf (file, "\tbis $25,$25,$30\n"); + else if (frame_size > 32767) + { + HOST_WIDE_INT low + = (frame_size & 0xffff) - 2 * (frame_size & 0x8000); + HOST_WIDE_INT tmp1 = frame_size - low; + HOST_WIDE_INT high + = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low; + HOST_WIDE_INT extra = 0; + int in_reg = 31; + + /* We haven't written code to handle frames > 4GB. */ + #if HOST_BITS_PER_LONG_INT == 64 + if ((unsigned HOST_WIDE_INT) frame_size >> 32 != 0) + abort (); + #endif + + if (tmp2) + { + extra = 0x4000; + tmp1 -= 0x40000000; + high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); + } + + if (low != 0) + { + fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg); + in_reg = 28; + } + + if (extra) + { + fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg); + in_reg = 28; + } + + fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg); + + fprintf (file, "\taddq $30,$28,$30\n"); + } + else if (frame_size) + fprintf (file, "\tlda $30,%d($30)\n", frame_size); + + /* Now return to the caller. */ + fprintf (file, "\tret $31,($26),1\n"); + } + + /* End the function. */ + fprintf (file, "\t.end %s\n", alpha_function_name); + } diff -rc2N gcc-2.2.2/config/alpha.h gcc-2.3.1/config/alpha.h *** gcc-2.2.2/config/alpha.h --- gcc-2.3.1/config/alpha.h Sat Oct 24 10:33:23 1992 *************** *** 0 **** --- 1,1559 ---- + /* Definitions of target machine for GNU compiler, for DEC Alpha. + Copyright (C) 1992 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@nyu.edu) + + This file is part of GNU CC. + + GNU CC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + + /* Names to predefine in the preprocessor for this target machine. */ + + #define CPP_PREDEFINES "\ + -Dunix -D__osf__ -D__alpha -D__alpha__ -D_LONGLONG -DSYSTYPE_BSD \ + -D_SYSTYPE_BSD" + + /* Write out the correct language type definition for the header files. */ + #define CPP_SPEC "\ + %{.c: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \ + %{.h: -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} \ + %{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \ + %{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \ + %{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C}" + + /* Set the spec to use for signed char. The default tests the above macro + but DEC's compiler can't handle the conditional in a "constant" + operand. */ + + #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" + + /* Right now Alpha OSF/1 doesn't seem to have debugging or profiled + libraries. */ + + #define LIB_SPEC "-lc" + + /* Print subsidiary information on the compiler version in use. */ + #define TARGET_VERSION + + /* Define the location for the startup file on OSF/1 for Alpha. */ + + #define MD_STARTFILE_PREFIX "/usr/lib/cmplrs/cc/" + + /* Run-time compilation parameters selecting different hardware subsets. */ + + extern int target_flags; + + /* This means that floating-point support exists in the target implementation + of the Alpha architecture. This is usually the default. */ + + #define TARGET_FP (target_flags & 1) + + /* This means that floating-point registers are allowed to be used. Note + that Alpha implementations without FP operations are required to + provide the FP registers. */ + + #define TARGET_FPREGS (target_flags & 2) + + /* 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 \ + { {"no-soft-float", 1}, \ + {"soft-float", -1}, \ + {"fp-regs", 2}, \ + {"no-fp-regs", -3}, \ + {"", TARGET_DEFAULT} } + + #define TARGET_DEFAULT 3 + + /* Define this macro to change register usage conditional on target flags. + + On the Alpha, we use this to disable the floating-point registers when + they don't exist. */ + + #define CONDITIONAL_REGISTER_USAGE \ + if (! TARGET_FPREGS) \ + for (i = 32; i < 64; i++) \ + fixed_regs[i] = call_used_regs[i] = 1; + + /* Define this to change the optimizations performed by default. */ + + #define OPTIMIZATION_OPTIONS(LEVEL) \ + { \ + if ((LEVEL) > 0) \ + { \ + flag_force_addr = 1; \ + flag_force_mem = 1; \ + flag_omit_frame_pointer = 1; \ + } \ + } + + /* target machine storage layout */ + + /* Define the size of `int'. The default is the same as the word size. */ + #define INT_TYPE_SIZE 32 + + /* Define the size of `long long'. The default is the twice the word size. */ + #define LONG_LONG_TYPE_SIZE 64 + + /* The two floating-point formats we support are S-floating, which is + 4 bytes, and T-floating, which is 8 bytes. `float' is S and `double' + and `long double' are T. */ + + #define FLOAT_TYPE_SIZE 32 + #define DOUBLE_TYPE_SIZE 64 + #define LONG_DOUBLE_TYPE_SIZE 64 + + #define WCHAR_TYPE "short unsigned int" + #define WCHAR_TYPE_SIZE 16 + + /* Define this macro if it is advisible 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. + + For Alpha, we always store objects in a full register. 32-bit objects + are always sign-extended, but smaller objects retain their signedness. */ + + #define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ + if (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ + { \ + if ((MODE) == SImode) \ + (UNSIGNEDP) = 0; \ + (MODE) = DImode; \ + } + + /* Define this if function arguments should also be promoted using the above + procedure. */ + + #define PROMOTE_FUNCTION_ARGS + + /* Likewise, if the function return value is promoted. */ + + #define PROMOTE_FUNCTION_RETURN + + /* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. + + There are no such instructions on the Alpha, but the documentation + is little endian. */ + #define BITS_BIG_ENDIAN 0 + + /* Define this if most significant byte of a word is the lowest numbered. + This is false on the Alpha. */ + #define BYTES_BIG_ENDIAN 0 + + /* Define this if most significant word of a multiword number is lowest + numbered. + + For Alpha we can decide arbitrarily since there are no machine instructions + for them. Might as well be consistent with bytes. */ + #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 64 + + /* Width of a word, in units (bytes). */ + #define UNITS_PER_WORD 8 + + /* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ + #define POINTER_SIZE 64 + + /* Allocation boundary (in *bits*) for storing arguments in argument list. */ + #define PARM_BOUNDARY 64 + + /* Boundary (in *bits*) on which stack pointer should be aligned. */ + #define STACK_BOUNDARY 64 + + /* Allocation boundary (in *bits*) for the code of a function. */ + #define FUNCTION_BOUNDARY 64 + + /* Alignment of field after `int : 0' in a structure. */ + #define EMPTY_FIELD_BOUNDARY 64 + + /* 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 + + /* Align loop starts for optimal branching. + + Don't do this until they fix the assembler. */ + + /* #define ASM_OUTPUT_LOOP_ALIGN(FILE) \ + ASM_OUTPUT_ALIGN (FILE, 5) */ + + /* This is how to align an instruction for optimal branching. + On Alpha we'll get better performance by aligning on a quadword + boundary. */ + #define ASM_OUTPUT_ALIGN_CODE(FILE) \ + ASM_OUTPUT_ALIGN ((FILE), 4) + + /* No data type wants to be aligned rounder than this. */ + #define BIGGEST_ALIGNMENT 64 + + /* Make strings word-aligned so strcpy from constants will be faster. */ + #define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + (TREE_CODE (EXP) == STRING_CST \ + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (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) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) + + /* Set this non-zero if move instructions will actually fail to work + when given unaligned data. + + Since we get an error message when we do one, call them invalid. */ + + #define STRICT_ALIGNMENT 1 + + /* Set this non-zero if unaligned move instructions are extremely slow. + + On the Alpha, they trap. */ + /* #define SLOW_UNALIGNED_ACCESS 1 */ + + /* 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. + + We define all 32 integer registers, even though $31 is always zero, + and all 32 floating-point registers, even though $f31 is also + always zero. We do not bother defining the FP status register and + there are no other registers. */ + + #define FIRST_PSEUDO_REGISTER 64 + + /* 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, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 } + + /* 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, 0, 0, 0, 0, 0, 0, 0, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 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 } + + /* List the order in which to allocate registers. Each register must be + listed once, even those in FIXED_REGISTERS. + + We allocate in the following order: + $f1 (nonsaved floating-point register) + $f10-$f15 (likewise) + $f22-$f30 (likewise) + $f21-$f16 (likewise, but input args) + $f0 (nonsaved, but return value) + $f2-$f9 (saved floating-point registers) + $1-$8 (nonsaved integer registers) + $22-$25 (likewise) + $28 (likewise) + $0 (likewise, but return value) + $21-$16 (likewise, but input args) + $27 (procedure value) + $9-$14 (saved integer registers) + $26 (return PC) + $15 (frame pointer) + $29 (global pointer) + $30, $31, $f31 (stack pointer and always zero) */ + + #define REG_ALLOC_ORDER \ + {33, \ + 42, 43, 44, 45, \ + 54, 55, 56, 57, 58, 59, 60, 61, 62, \ + 53, 52, 51, 50, 49, 48, \ + 32, \ + 34, 35, 36, 37, 38, 39, 40, 41, \ + 1, 2, 3, 4, 5, 6, 7, 8, \ + 22, 23, 24, 25, \ + 28, \ + 0, \ + 21, 20, 19, 18, 17, 16, \ + 27, \ + 9, 10, 11, 12, 13, 14, \ + 26, \ + 15, \ + 29, \ + 30, 31, 63 } + + /* 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. + On Alpha, the integer registers can hold any mode. The floating-point + registers can hold 32-bit and 64-bit integers as well, but not 16-bit + or 8-bit values. If we only allowed the larger integers into FP registers, + we'd have to say that QImode and SImode aren't tiable, which is a + pain. So say all registers can hold everything and see how that works. */ + + #define HARD_REGNO_MODE_OK(REGNO, MODE) 1 + + /* 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) 1 + + /* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + + /* Alpha pc isn't overloaded on a register that the compiler knows about. */ + /* #define PC_REGNUM */ + + /* Register to use for pushing function arguments. */ + #define STACK_POINTER_REGNUM 30 + + /* Base register for access to local variables of the function. */ + #define FRAME_POINTER_REGNUM 15 + + /* 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 + + /* Base register for access to arguments of the function. */ + #define ARG_POINTER_REGNUM 15 + + /* Register in which static-chain is passed to a function. + + For the Alpha, this is based on an example; the calling sequence + doesn't seem to specify this. */ + #define STATIC_CHAIN_REGNUM 1 + + /* Register in which address to store a structure value + arrives in the function. On the Alpha, the address is passed + as a hidden argument. */ + #define STRUCT_VALUE 0 + + /* 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, FLOAT_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", "FLOAT_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, 0}, {0, ~0}, {~0, ~0} } + + /* 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) >= 32 ? FLOAT_REGS : 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) \ + ((C) == 'f' ? FLOAT_REGS : NO_REGS) + + /* Define this macro to change register usage conditional on target flags. */ + /* #define CONDITIONAL_REGISTER_USAGE */ + + /* The letters I, J, K, L, M, N, O, and 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. + + For Alpha: + `I' is used for the range of constants most insns can contain. + `J' is the constant zero. + `K' is used for the constant in an LDA insn. + `L' is used for the constant in a LDAH insn. + `M' is used for the constants that can be AND'ed with using a ZAP insn. + `N' is used for complemented 8-bit constants. + `O' is used for negated 8-bit constants. + `P' is used for the constants 1, 2 and 3. */ + + #define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VALUE) < 0x100 \ + : (C) == 'J' ? (VALUE) == 0 \ + : (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \ + : (C) == 'L' ? (((VALUE) & 0xffff) == 0 \ + && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \ + : (C) == 'M' ? zap_mask (VALUE) \ + : (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \ + : (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \ + : (C) == 'P' ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 3 \ + : 0) + + /* Similar, but for floating or large integer constants, and defining letters + G and H. Here VALUE is the CONST_DOUBLE rtx itself. + + For Alpha, `G' is the floating-point constant zero. `H' is a CONST_DOUBLE + that is the operand of a ZAP insn. */ + + #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))) \ + : (C) == 'H' ? (GET_MODE (VALUE) == VOIDmode \ + && zap_mask (CONST_DOUBLE_LOW (VALUE)) \ + && zap_mask (CONST_DOUBLE_HIGH (VALUE))) \ + : 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. + + On the Alpha, all constants except zero go into a floating-point + register via memory. */ + + #define PREFERRED_RELOAD_CLASS(X, CLASS) \ + (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \ + ? ((CLASS) == FLOAT_REGS ? NO_REGS : GENERAL_REGS) \ + : (CLASS)) + + /* Loading and storing HImode or QImode values to and from memory + usually requires a scratch register. The exceptions are loading + QImode and HImode from an aligned address to a general register. */ + + #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN) \ + (((GET_CODE (IN) == MEM \ + || (GET_CODE (IN) == REG && REGNO (IN) >= FIRST_PSEUDO_REGISTER) \ + || (GET_CODE (IN) == SUBREG \ + && (GET_CODE (SUBREG_REG (IN)) == MEM \ + || (GET_CODE (SUBREG_REG (IN)) == REG \ + && REGNO (SUBREG_REG (IN)) >= FIRST_PSEUDO_REGISTER)))) \ + && (((CLASS) == FLOAT_REGS \ + && ((MODE) == SImode || (MODE) == HImode || (MODE) == QImode)) \ + || (((MODE) == QImode || (MODE) == HImode) \ + && unaligned_memory_operand (IN, MODE)))) \ + ? GENERAL_REGS : NO_REGS) + + #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,OUT) \ + (((GET_CODE (OUT) == MEM \ + || (GET_CODE (OUT) == REG && REGNO (OUT) >= FIRST_PSEUDO_REGISTER) \ + || (GET_CODE (OUT) == SUBREG \ + && (GET_CODE (SUBREG_REG (OUT)) == MEM \ + || (GET_CODE (SUBREG_REG (OUT)) == REG \ + && REGNO (SUBREG_REG (OUT)) >= FIRST_PSEUDO_REGISTER)))) \ + && (((MODE) == HImode || (MODE) == QImode \ + || ((MODE) == SImode && (CLASS) == FLOAT_REGS)))) \ + ? GENERAL_REGS : NO_REGS) + + /* If we are copying between general and FP registers, we need a memory + location. */ + + #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) ((CLASS1) != (CLASS2)) + + /* 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) + + /* Define the cost of moving between registers of various classes. Moving + between FLOAT_REGS and anything else except float regs is expensive. + In fact, we make it quite expensive because we really don't want to + do these moves unless it is clearly worth it. Optimizations may + reduce the impact of not being able to allocate a pseudo to a + hard register. */ + + #define REGISTER_MOVE_COST(CLASS1, CLASS2) \ + (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) ? 2 : 20) + + /* A C expressions returning the cost of moving data of MODE from a register to + or from memory. + + On the Alpha, bump this up a bit. */ + + #define MEMORY_MOVE_COST(MODE) 6 + + /* Provide the cost of a branch. Exact meaning under development. */ + #define BRANCH_COST 5 + + /* Adjust the cost of dependencies. */ + + #define ADJUST_COST(INSN,LINK,DEP,COST) \ + (COST) = alpha_adjust_cost (INSN, LINK, DEP, COST) + + /* 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 (- current_function_pretend_args_size) + + /* If we generate an insn to push BYTES bytes, + this says how many the stack pointer really advances by. + On Alpha, don't define this because there are no push insns. */ + /* #define PUSH_ROUNDING(BYTES) */ + + /* Define this if the maximum size of all the outgoing args is to be + accumulated and pushed during the prologue. The amount can be + found in the variable current_function_outgoing_args_size. */ + #define ACCUMULATE_OUTGOING_ARGS + + /* Offset of first parameter from the argument pointer register value. */ + + #define FIRST_PARM_OFFSET(FNDECL) (- current_function_pretend_args_size) + + /* Definitions for register eliminations. + + We have one register that can be eliminated on the Alpha. The + frame pointer register can often be eliminated in favor of the stack + pointer register. + + In addition, we use the elimination mechanism to see if gp (r29) is needed. + Initially we assume that it isn't. If it is, we spill it. This is done + by making it an eliminable register. It doesn't matter what we replace + it with, since it will never occur in the rtl at this point. */ + + /* This is an array of structures. Each structure initializes one pair + of eliminable registers. The "from" register number is given first, + followed by "to". Eliminations of the same "from" register are listed + in order of preference. */ + + #define ELIMINABLE_REGS \ + {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { 29, 0}} + + /* Given FROM and TO register numbers, say whether this elimination is allowed. + Frame pointer elimination is automatically handled. + + We need gp (r29) if we have calls or load symbols + (tested in alpha_need_gp). + + All other eliminations are valid since the cases where FP can't be + eliminated are already handled. */ + + #define CAN_ELIMINATE(FROM, TO) ((FROM) == 29 ? ! alpha_need_gp () : 1) + + /* Define the offset between two registers, one to be eliminated, and the other + its replacement, at the start of a routine. */ + #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + { if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = (get_frame_size () + current_function_outgoing_args_size \ + + current_function_pretend_args_size \ + + alpha_sa_size () + 15) & ~ 15; \ + } + + /* Define this if stack space is still allocated for a parameter passed + in a register. */ + /* #define REG_PARM_STACK_SPACE */ + + /* Value is the number of bytes of arguments automatically + popped when returning from a subroutine call. + 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(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 0. + + On Alpha the value is found in $0 for integer functions and + $f0 for floating-point functions. */ + + #define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, \ + ((TREE_CODE (VALTYPE) == INTEGER_TYPE \ + || TREE_CODE (VALTYPE) == ENUMERAL_TYPE \ + || TREE_CODE (VALTYPE) == BOOLEAN_TYPE \ + || TREE_CODE (VALTYPE) == CHAR_TYPE \ + || TREE_CODE (VALTYPE) == POINTER_TYPE \ + || TREE_CODE (VALTYPE) == OFFSET_TYPE) \ + && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ + ? word_mode : TYPE_MODE (VALTYPE), \ + TARGET_FPREGS && TREE_CODE (VALTYPE) == REAL_TYPE ? 32 : 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, \ + TARGET_FPREGS && GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 0) + + /* 1 if N is a possible register number for a function value + as seen by the caller. */ + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 32) + + /* 1 if N is a possible register number for function argument passing. + On Alpha, these are $16-$21 and $f16-$f21. */ + + #define FUNCTION_ARG_REGNO_P(N) \ + (((N) >= 16 && (N) <= 21) || ((N) >= 16 + 32 && (N) <= 21 + 32)) + + /* 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, this is a single integer, which is a number of words + of arguments scanned so far. + Thus 6 or more means all following args should go on the stack. */ + + #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) (CUM) = 0 + + /* Define intermediate macro to compute the size (in registers) of an argument + for the Alpha. */ + + #define ALPHA_ARG_SIZE(MODE, TYPE, NAMED) \ + ((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) + + /* 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) \ + if (MUST_PASS_IN_STACK (MODE, TYPE)) \ + (CUM) = 6; \ + else \ + (CUM) += ALPHA_ARG_SIZE (MODE, TYPE, NAMED) + + /* 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 Alpha the first 6 words of args are normally in registers + and the rest are pushed. */ + + #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ + ((CUM) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ + ? gen_rtx(REG, (MODE), \ + (CUM) + 16 + (TARGET_FPREGS \ + && GET_MODE_CLASS (MODE) == MODE_FLOAT) * 32) : 0) + + /* This indicates that an argument is to be passed with an invisible reference + (i.e., a pointer to the object is passed). + + On the Alpha, we do this if it must be passed on the stack. */ + + #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ + (MUST_PASS_IN_STACK (MODE, TYPE)) + + /* Specify the padding direction of arguments. + + On the Alpha, we must pad upwards in order to be able to pass args in + registers. */ + + #define FUNCTION_ARG_PADDING(MODE, TYPE) upward + + /* 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) \ + ((CUM) < 6 && 6 < (CUM) + ALPHA_ARG_SIZE (MODE, TYPE, NAMED) \ + ? 6 - (CUM) : 0) + + /* Generate necessary RTL for __builtin_saveregs(). + ARGLIST is the argument list; see expr.c. */ + extern struct rtx_def *alpha_builtin_saveregs (); + #define EXPAND_BUILTIN_SAVEREGS(ARGLIST) alpha_builtin_saveregs (ARGLIST) + + /* 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 *alpha_compare_op0, *alpha_compare_op1; + extern int alpha_compare_fp_p; + + /* This macro produces the initial definition of a function name. On the + 29k, we need to save the function name for the epilogue. */ + + extern char *alpha_function_name; + + #define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ + { fprintf (FILE, "\t.ent %s 2\n", NAME); \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + alpha_function_name = NAME; \ + } + + /* 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) output_prolog (FILE, SIZE) + + /* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + + #define FUNCTION_PROFILER(FILE, LABELNO) + + /* 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) output_epilog (FILE, SIZE) + + + /* 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. We + use $28 (at) as a temporary. 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. */ + + #define TRAMPOLINE_TEMPLATE(FILE) \ + { \ + fprintf (FILE, "\tbis $27,$27,$28\n"); \ + fprintf (FILE, "\tldq $27,16($27)\n"); \ + fprintf (FILE, "\tldq $1,20($28)\n"); \ + fprintf (FILE, "\tjmp $31,0($27),0\n"); \ + fprintf (FILE, "\t.quad 0,0\n"); \ + } + + /* 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. We assume + here that a function will be called many more times than its address + is taken (e.g., it might be passed to qsort), so we take the trouble + to initialize the "hint" field in the JMP insn. */ + + #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ + { \ + rtx _temp, _temp1, _addr; \ + \ + _addr = memory_address (Pmode, plus_constant ((TRAMP), 16)); \ + emit_move_insn (gen_rtx (MEM, Pmode, _addr), (FNADDR)); \ + _addr = memory_address (Pmode, plus_constant ((TRAMP), 20)); \ + emit_move_insn (gen_rtx (MEM, Pmode, _addr), (CXT)); \ + \ + _temp = expand_shift (RSHIFT_EXPR, Pmode, (FNADDR), \ + build_int_2 (2, 0), NULL_RTX, 1); \ + _temp = expand_and (_temp, GEN_INT (0x1fff), 0); \ + \ + _addr = memory_address (SImode, plus_constant ((TRAMP), 12)); \ + _temp1 = force_reg (SImode, gen_rtx (MEM, SImode, _addr)); \ + _temp1 = expand_and (_temp, GEN_INT (0xfffe000), NULL_RTX); \ + _temp1 = expand_binop (SImode, ior_optab, _temp1, _temp, _temp1, 1, \ + OPTAB_WIDEN); \ + \ + emit_move_insn (gen_rtx (MEM, SImode, _addr), _temp1); \ + } + + /* Addressing modes, and classification of registers for them. */ + + /* #define HAVE_POST_INCREMENT */ + /* #define HAVE_POST_DECREMENT */ + + /* #define HAVE_PRE_DECREMENT */ + /* #define HAVE_PRE_INCREMENT */ + + /* 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_INDEX_P(REGNO) 0 + #define REGNO_OK_FOR_BASE_P(REGNO) \ + (((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)) + + /* Maximum number of registers that can appear in a valid memory address. */ + #define MAX_REGS_PER_ADDRESS 1 + + /* Recognize any constant value that is a valid address. For the Alpha, + there are only constants none since we want to use LDA to load any + symbolic addresses into registers. */ + + #define CONSTANT_ADDRESS_P(X) \ + (GET_CODE (X) == CONST_INT \ + && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000) + + /* Include all constant integers and constant doubles, but not + floating-point, except for floating-point zero. */ + + #define LEGITIMATE_CONSTANT_P(X) \ + (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ + || (X) == CONST0_RTX (GET_MODE (X))) + + /* 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) \ + (REGNO (X) < 32 || 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. + + For Alpha, we have either a constant address or the sum of a register + and a constant address, or just a register. For DImode, any of those + forms can be surrounded with an AND that clear the low-order three bits; + this is an "unaligned" access. + + We also allow a SYMBOL_REF that is the name of the current function as + valid address. This is for CALL_INSNs. It cannot be used in any other + context. + + First define the basic valid address. */ + + #define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \ + { if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \ + goto ADDR; \ + if (CONSTANT_ADDRESS_P (X)) \ + goto ADDR; \ + if (GET_CODE (X) == PLUS \ + && REG_P (XEXP (X, 0)) \ + && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ + && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ + goto ADDR; \ + } + + /* Now accept the simple address, or, for DImode only, an AND of a simple + address that turns off the low three bits. */ + + extern char *current_function_name; + + #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ + { GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, X, ADDR); \ + if ((MODE) == DImode \ + && GET_CODE (X) == AND \ + && GET_CODE (XEXP (X, 1)) == CONST_INT \ + && INTVAL (XEXP (X, 1)) == -8) \ + GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, XEXP (X, 0), ADDR); \ + if ((MODE) == Pmode && GET_CODE (X) == SYMBOL_REF \ + && ! strcmp (XSTR (X, 0), current_function_name)) \ + 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. + + For the Alpha, there are three cases we handle: + + (1) If the address is (plus reg const_int) and the CONST_INT is not a + valid offset, compute the high part of the constant and add it to the + register. Then our address is (plus temp low-part-const). + (2) If the address is (const (plus FOO const_int)), find the low-order + part of the CONST_INT. Then load FOO plus any high-order part of the + CONST_INT into a register. Our address is (plus reg low-part-const). + This is done to reduce the number of GOT entries. + (3) If we have a (plus reg const), emit the load as in (2), then add + the two registers, and finally generate (plus reg low-part-const) as + our address. */ + + #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ + { if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ + && GET_CODE (XEXP (X, 1)) == CONST_INT \ + && ! CONSTANT_ADDRESS_P (XEXP (X, 1))) \ + { \ + HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \ + HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \ + HOST_WIDE_INT highpart = val - lowpart; \ + rtx high = GEN_INT (highpart); \ + rtx temp = expand_binop (Pmode, add_optab, XEXP (x, 0), \ + high, 0, OPTAB_LIB_WIDEN); \ + \ + (X) = plus_constant (temp, lowpart); \ + goto WIN; \ + } \ + else if (GET_CODE (X) == CONST \ + && GET_CODE (XEXP (X, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT) \ + { \ + HOST_WIDE_INT val = INTVAL (XEXP (XEXP (X, 0), 1)); \ + HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \ + HOST_WIDE_INT highpart = val - lowpart; \ + rtx high = XEXP (XEXP (X, 0), 0); \ + \ + if (highpart) \ + high = plus_constant (high, highpart); \ + \ + (X) = plus_constant (force_reg (Pmode, high), lowpart); \ + goto WIN; \ + } \ + else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ + && GET_CODE (XEXP (X, 1)) == CONST \ + && GET_CODE (XEXP (XEXP (X, 1), 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (XEXP (X, 1), 0), 1)) == CONST_INT) \ + { \ + HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (X, 1), 0), 1)); \ + HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \ + HOST_WIDE_INT highpart = val - lowpart; \ + rtx high = XEXP (XEXP (XEXP (X, 1), 0), 0); \ + \ + if (highpart) \ + high = plus_constant (high, highpart); \ + \ + high = expand_binop (Pmode, add_optab, XEXP (X, 0), \ + force_reg (Pmode, high), \ + high, OPTAB_LIB_WIDEN); \ + (X) = plus_constant (high, lowpart); \ + goto WIN; \ + } \ + } + + /* Go to LABEL if ADDR (a legitimate address expression) + has an effect that depends on the machine mode it is used for. + On the Alpha this is true only for the unaligned modes. We can + simplify this test since we know that the address must be valid. */ + + #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ + { if (GET_CODE (ADDR) == AND) goto LABEL; } + + /* Compute the cost of an address. For the Alpha, all valid addresses are + the same cost. */ + + #define ADDRESS_COST(X) 0 + + /* Define this if some processing needs to be done immediately before + emitting code for an insn. */ + + /* #define FINAL_PRESCAN_INSN(INSN,OPERANDS,NOPERANDS) */ + + /* 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 + + /* This is the kind of divide that is easiest to do in the general case. */ + #define EASY_DIV_EXPR TRUNC_DIV_EXPR + + /* Define this as 1 if `char' should by default be signed; else as 0. */ + #define DEFAULT_SIGNED_CHAR 1 + + /* This flag, if defined, says the same insns that convert to a signed fixnum + also convert validly to an unsigned one. + + We actually lie a bit here as overflow conditions are different. But + they aren't being checked anyway. */ + + #define FIXUNS_TRUNC_LIKE_FIX_TRUNC + + /* Max number of bytes we can move to or from memory + in one reasonably fast instruction. */ + + #define MOVE_MAX 8 + + /* Largest number of bytes of an object that can be placed in a register. + On the Alpha we have plenty of registers, so use TImode. */ + #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode) + + /* Nonzero if access to memory by bytes is no faster than for words. + Also non-zero if doing byte operations (specifically shifts) in registers + is undesirable. + + On the Alpha, we want to not use the byte operation and instead use + masking operations to access fields; these will save instructions. */ + + #define SLOW_BYTE_ACCESS 1 + + /* Define if normal loads of shorter-than-word items from memory clears + the rest of the bits in the register. */ + /* #define BYTE_LOADS_ZERO_EXTEND */ + + /* Define if normal loads of shorter-than-word items from memory sign-extends + the rest of the bits in the register. */ + #define BYTE_LOADS_SIGN_EXTEND + + /* We aren't doing ANYTHING about debugging for now. */ + /* #define SDB_DEBUGGING_INFO */ + + /* Do not break .stabs pseudos into continuations. */ + #define DBX_CONTIN_LENGTH 0 + + /* Don't try to use the `x' type-cross-reference character in DBX data. + Also has the consequence of putting each struct, union or enum + into a separate .stabs, containing only cross-refs to the others. */ + #define DBX_NO_XREFS + + /* 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 + + /* Define the value returned by a floating-point comparison instruction. */ + + #define FLOAT_STORE_FLAG_VALUE 0.5 + + /* 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 DImode + + /* Mode of a function address in a call instruction (for indexing purposes). */ + + #define FUNCTION_MODE Pmode + + /* Define this if addresses of constant functions + shouldn't be put through pseudo regs where they can be cse'd. + Desirable on machines where ordinary constants are expensive + but a CALL with constant address is cheap. + + We define this on the Alpha so that gen_call and gen_call_value + get to see the SYMBOL_REF (for the hint field of the jsr). It will + then copy it into a register, thus actually letting the address be + cse'ed. */ + + #define NO_FUNCTION_CSE + + /* Define this if shift instructions ignore all but the low-order + few bits. */ + #define SHIFT_COUNT_TRUNCATED + + /* 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. + + We only care about the cost if it is valid in an insn, so all constants + are cheap. */ + + #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ + case CONST_INT: \ + case CONST_DOUBLE: \ + return 0; \ + case CONST: \ + case SYMBOL_REF: \ + case LABEL_REF: \ + return 6; \ + + /* Provide the costs of a rtl expression. This is in the body of a + switch on CODE. */ + + #define RTX_COSTS(X,CODE,OUTER_CODE) \ + case PLUS: \ + case MINUS: \ + if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ + return COSTS_N_INSNS (6); \ + break; \ + case MULT: \ + if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \ + return COSTS_N_INSNS (6); \ + else \ + return COSTS_N_INSNS (21); \ + case DIV: \ + case UDIV: \ + case MOD: \ + case UMOD: \ + if (GET_MODE (X) == SFmode) \ + return COSTS_N_INSNS (34); \ + else if (GET_MODE (X) == DFmode) \ + return COSTS_N_INSNS (63); \ + else \ + return COSTS_N_INSNS (70); \ + case MEM: \ + return COSTS_N_INSNS (3); + + /* Control the assembler format that we output. */ + + /* Output at beginning of assembler file. */ + + #define ASM_FILE_START(FILE) \ + { extern char *version_string; \ + char *p, *after_dir = main_input_filename; \ + \ + fprintf (FILE, "\t.verstamp 9 0 "); \ + for (p = version_string; *p != ' ' && *p != 0; p++) \ + fprintf (FILE, "%c", *p == '.' ? ' ' : *p); \ + fprintf (FILE, "\n\t.set noreorder\n"); \ + fprintf (FILE, "\t.set noat\n"); \ + for (p = main_input_filename; *p; p++) \ + if (*p == '/') \ + after_dir = p + 1; \ + fprintf (FILE, "\n\t.file 2 \"%s\"\n", after_dir); \ + } + + /* 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 "" + + #define TEXT_SECTION_ASM_OP ".text" + + /* Output before read-only data. */ + + #define READONLY_DATA_SECTION_ASM_OP ".rdata" + + /* Output before writable data. */ + + #define DATA_SECTION_ASM_OP ".data" + + /* Define an extra section for read-only data, a routine to enter it, and + indicate that it is for read-only data. */ + + #define EXTRA_SECTIONS readonly_data + + #define EXTRA_SECTION_FUNCTIONS \ + void \ + literal_section () \ + { \ + if (in_section != readonly_data) \ + { \ + fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \ + in_section = readonly_data; \ + } \ + } \ + + #define READONLY_DATA_SECTION literal_section + + /* 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", \ + "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", \ + "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", \ + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", \ + "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \ + "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",\ + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"} + + /* How to renumber registers for dbx and gdb. */ + + #define DBX_REGISTER_NUMBER(REGNO) (REGNO) + + /* 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.globl ", 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. */ + + #define ASM_OUTPUT_LABELREF(FILE,NAME) \ + fprintf (FILE, "%s", NAME) + + /* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + + #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + if ((PREFIX)[0] == 'L') \ + fprintf (FILE, "$%s%d:\n", & (PREFIX)[1], NUM + 32); \ + else \ + fprintf (FILE, "%s%d:\n", PREFIX, NUM); + + /* This is how to output a label for a jump table. Arguments are the same as + for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is + passed. */ + + #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \ + { ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, 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'. */ + + #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + if ((PREFIX)[0] == 'L') \ + sprintf (LABEL, "*$%s%d", & (PREFIX)[1], NUM + 32); \ + else \ + sprintf (LABEL, "*%s%d", PREFIX, NUM) + + /* This is how to output an assembler line defining a `double' constant. */ + + #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + fprintf (FILE, "\t.t_floating %.20e\n", (VALUE)) + + /* This is how to output an assembler line defining a `float' constant. */ + + #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + fprintf (FILE, "\t.s_floating %.20e\n", (VALUE)) + + /* 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")) + + /* This is how to output an assembler line defining a `long' constant. */ + + #define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \ + ( fprintf (FILE, "\t.quad "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + + /* Likewise for `char' and `short' constants. */ + + #define ASM_OUTPUT_SHORT(FILE,VALUE) \ + ( fprintf (FILE, "\t.word "), \ + 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")) + + /* We use the default ASCII-output routine, except that we don't write more + than 50 characters since the assembler doesn't support very long lines. */ + + #define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \ + do { \ + FILE *_hide_asm_out_file = (MYFILE); \ + unsigned char *_hide_p = (unsigned char *) (MYSTRING); \ + int _hide_thissize = (MYLENGTH); \ + int _size_so_far = 0; \ + { \ + FILE *asm_out_file = _hide_asm_out_file; \ + unsigned char *p = _hide_p; \ + int thissize = _hide_thissize; \ + int i; \ + fprintf (asm_out_file, "\t.ascii \""); \ + \ + for (i = 0; i < thissize; i++) \ + { \ + register int c = p[i]; \ + \ + if (_size_so_far ++ > 50 && i < thissize - 4) \ + _size_so_far = 0, fprintf (asm_out_file, "\"\n\t.ascii \""); \ + \ + if (c == '\"' || c == '\\') \ + putc ('\\', asm_out_file); \ + if (c >= ' ' && c < 0177) \ + putc (c, asm_out_file); \ + else \ + { \ + fprintf (asm_out_file, "\\%o", c); \ + /* After an octal-escape, if a digit follows, \ + terminate one string constant and start another. \ + The Vax assembler fails to stop reading the escape \ + after three digits, so this is the only way we \ + can get it to parse the data properly. */ \ + if (i < thissize - 1 \ + && p[i + 1] >= '0' && p[i + 1] <= '9') \ + fprintf (asm_out_file, "\"\n\t.ascii \""); \ + } \ + } \ + fprintf (asm_out_file, "\"\n"); \ + } \ + } \ + while (0) + /* 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) \ + fprintf (FILE, "\tsubq $30,8,$30\n\tst%s $%s%d,0($30)\n", \ + (REGNO) > 32 ? "t" : "q", (REGNO) > 32 ? "f" : "", \ + (REGNO) & 31); + + /* 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) \ + fprintf (FILE, "\tld%s $%s%d,0($30)\n\taddq $30,8,$30\n", \ + (REGNO) > 32 ? "t" : "q", (REGNO) > 32 ? "f" : "", \ + (REGNO) & 31); + + /* 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)) + + /* This is how to output an element of a case-vector that is absolute. */ + + #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\t.gprel32 $%d\n", (VALUE) + 32) + + /* This is how to output an element of a case-vector that is relative. + (Alpha does not use such vectors, but we must define this macro anyway.) */ + + #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort () + + /* 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) != 0) \ + fprintf (FILE, "\t.align %d\n", LOG); + + /* This is how to advance the location counter by SIZE bytes. */ + + #define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.space %d\n", (SIZE)) + + /* This says how to output an assembler line + to define a global common symbol. */ + + #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ + ( fputs ("\t.comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d\n", (SIZE))) + + /* This says how to output an assembler line + to define a local common symbol. */ + + #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE,ROUNDED) \ + ( fputs ("\t.lcomm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d\n", (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 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 + + /* 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) print_operand (FILE, X, CODE) + + /* Determine which codes are valid without a following integer. These must + not be alphabetic. */ + + #define PRINT_OPERAND_PUNCT_VALID_P(CODE) 0 + + /* Print a memory address as an operand to reference that memory location. */ + + #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ + { rtx addr = (ADDR); \ + int basereg = 31; \ + HOST_WIDE_INT offset = 0; \ + \ + if (GET_CODE (addr) == AND) \ + addr = XEXP (addr, 0); \ + \ + if (GET_CODE (addr) == REG) \ + basereg = REGNO (addr); \ + else if (GET_CODE (addr) == CONST_INT) \ + offset = INTVAL (addr); \ + else if (GET_CODE (addr) == PLUS \ + && GET_CODE (XEXP (addr, 0)) == REG \ + && GET_CODE (XEXP (addr, 1)) == CONST_INT) \ + basereg = REGNO (XEXP (addr, 0)), offset = INTVAL (XEXP (addr, 1)); \ + else \ + abort (); \ + \ + fprintf (FILE, "%d($%d)", offset, basereg); \ + } + /* Define the codes that are matched by predicates in alpha.c. */ + + #define PREDICATE_CODES \ + {"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ + {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \ + {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \ + {"add_operand", {SUBREG, REG, CONST_INT}}, \ + {"sext_add_operand", {SUBREG, REG, CONST_INT}}, \ + {"const48_operand", {CONST_INT}}, \ + {"and_operand", {SUBREG, REG, CONST_INT}}, \ + {"mode_mask_operand", {CONST_INT}}, \ + {"mul8_operand", {CONST_INT}}, \ + {"mode_width_operand", {CONST_INT}}, \ + {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \ + {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \ + {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \ + {"fp0_operand", {CONST_DOUBLE}}, \ + {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ + SYMBOL_REF, CONST, LABEL_REF}}, \ + {"aligned_memory_operand", {MEM}}, \ + {"unaligned_memory_operand", {MEM}}, \ + {"any_memory_operand", {MEM}}, diff -rc2N gcc-2.2.2/config/alpha.md gcc-2.3.1/config/alpha.md *** gcc-2.2.2/config/alpha.md --- gcc-2.3.1/config/alpha.md Mon Oct 26 16:01:36 1992 *************** *** 0 **** --- 1,3006 ---- + ;;- Machine description for DEC Alpha for GNU C compiler + ;; Copyright (C) 1992 Free Software Foundation, Inc. + ;; Contributed by Richard Kenner (kenner@nyu.edu) + + ;; This file is part of GNU CC. + + ;; GNU CC is free software; you can redistribute it and/or modify + ;; it under the terms of the GNU General Public License as published by + ;; the Free Software Foundation; either version 2, or (at your option) + ;; any later version. + + ;; GNU CC is distributed in the hope that it will be useful, + ;; but WITHOUT ANY WARRANTY; without even the implied warranty of + ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ;; GNU General Public License for more details. + + ;; You should have received a copy of the GNU General Public License + ;; along with GNU CC; see the file COPYING. If not, write to + ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. + + ;; Define an insn type attribute. This is used in function unit delay + ;; computations, among other purposes. For the most part, we use the names + ;; defined in the EV4 documentation, but add a few that we have to know about + ;; separately. + + (define_attr "type" + "ld,st,ibr,fbr,jsr,iaddlog,shiftcm,icmp,imull,imulq,fpop,fdivs,fdivt,ldsym" + (const_string "shiftcm")) + + ;; We include four function units: ABOX, which computes the address, + ;; BBOX, used for branches, EBOX, used for integer operations, and FBOX, + ;; used for FP operations. + ;; + ;; We assume that we have been successful in getting double issues and + ;; hence multiply all costs by two insns per cycle. The minimum time in + ;; a function unit is 2 cycle, which will tend to produce the double + ;; issues. + + ;; Memory delivers its result in three cycles. + (define_function_unit "abox" 1 0 (eq_attr "type" "ld,ldsym,st") 6 2) + + ;; Branches have no delay cost, but do tie up the unit for two cycles. + (define_function_unit "bbox" 1 1 (eq_attr "type" "ibr,fbr,jsr") 4 4) + + ;; Arithmetic insns are normally have their results available after two + ;; cycles. There are a number of exceptions. They are encoded in + ;; ADJUST_COST. Some of the other insns have similar exceptions. + + (define_function_unit "ebox" 1 0 (eq_attr "type" "iaddlog,shiftcm,icmp") 4 2) + + ;; These really don't take up the integer pipeline, but they do occupy + ;; IBOX1; we approximate here. + + (define_function_unit "ebox" 1 0 (eq_attr "type" "imull") 42 2) + (define_function_unit "ebox" 1 0 (eq_attr "type" "imulq") 46 2) + + (define_function_unit "imult" 1 0 (eq_attr "type" "imull") 42 38) + (define_function_unit "imult" 1 0 (eq_attr "type" "imulq") 46 42) + + (define_function_unit "fbox" 1 0 (eq_attr "type" "fpop") 12 2) + + (define_function_unit "fbox" 1 0 (eq_attr "type" "fdivs") 68 0) + (define_function_unit "fbox" 1 0 (eq_attr "type" "fdivt") 126 0) + + (define_function_unit "divider" 1 0 (eq_attr "type" "fdivs") 68 60) + (define_function_unit "divider" 1 0 (eq_attr "type" "fdivt") 126 118) + + ;; First define the arithmetic insns. Note that the 32-bit forms also + ;; sign-extend. + + ;; Note that we can do sign extensions in both FP and integer registers. + ;; However, the result must be in the same type of register as the input. + ;; The register preferencing code can't handle this case very well, so, for + ;; now, don't let the FP case show up here for preferencing. + (define_insn "extendsidi2" + [(set (match_operand:DI 0 "register_operand" "=r,r,f") + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,f")))] + "" + "@ + addl %1,$31,%0 + ldl %0,%1 + cvtlq %1,%0" + [(set_attr "type" "iaddlog,ld,fpop")]) + + (define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,%rJ,%rJ") + (match_operand:SI 2 "add_operand" "rI,K,L")))] + "" + "@ + addl %r1,%2,%0 + lda %0,%2(%r1) + ldah %0,%h2(%r1)" + [(set_attr "type" "iaddlog")]) + + (define_split + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "const_int_operand" "")))] + "! add_operand (operands[2], SImode)" + [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] + " + { + HOST_WIDE_INT val = INTVAL (operands[2]); + HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); + HOST_WIDE_INT rest = val - low; + + operands[3] = GEN_INT (rest); + operands[4] = GEN_INT (low); + }") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (sign_extend:DI + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ") + (match_operand:SI 2 "sext_add_operand" "rI,O"))))] + "" + "@ + addl %r1,%2,%0 + subl %r1,%n2,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "adddi3" + [(set (match_operand:DI 0 "register_operand" "=r,r,r") + (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,%rJ,%rJ") + (match_operand:DI 2 "add_operand" "rI,K,L")))] + "" + "@ + addq %r1,%2,%0 + lda %0,%2(%r1) + ldah %0,%h2(%r1)" + [(set_attr "type" "iaddlog")]) + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "const_int_operand" "")))] + "! add_operand (operands[2], DImode)" + [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] + " + { + HOST_WIDE_INT val = INTVAL (operands[2]); + HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); + HOST_WIDE_INT rest = val - low; + + operands[3] = GEN_INT (rest); + operands[4] = GEN_INT (low); + }") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const48_operand" "I")) + (match_operand:SI 3 "reg_or_8bit_operand" "rI")))] + "" + "s%2addl %r1,%3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI + (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const48_operand" "I")) + (match_operand:SI 3 "reg_or_8bit_operand" "rI"))))] + "" + "s%2addl %r1,%3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "const48_operand" "I")) + (match_operand:DI 3 "reg_or_8bit_operand" "rI")))] + "" + "s%2addq %r1,%3,%0" + [(set_attr "type" "iaddlog")]) + + ;; These variants of the above insns can occur if the third operand + ;; is the frame pointer. This is a kludge, but there doesn't + ;; seem to be a way around it. Only recognize them while reloading. + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=&r") + (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const48_operand" "I")) + (match_operand:SI 3 "register_operand" "r")) + (match_operand:SI 4 "const_int_operand" "rI")))] + "reload_in_progress" + "s%2addl %r1,%3,%0\;addl %0,%4,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=&r") + (sign_extend:DI + (plus:SI (plus:SI + (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const48_operand" "I")) + (match_operand:SI 3 "register_operand" "r")) + (match_operand:SI 4 "const_int_operand" "rI"))))] + "reload_in_progress" + "s%2addl %r1,%3,%0\;addl %0,%4,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "const48_operand" "I")) + (match_operand:DI 3 "register_operand" "r")) + (match_operand:DI 4 "const_int_operand" "rI")))] + "reload_in_progress" + "s%2addq %r1,%3,%0\;addq %0,%4,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))] + "" + "subl $31,%1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (neg:SI + (match_operand:SI 1 "reg_or_8bit_operand" "rI"))))] + "" + "subl $31,%1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "negdi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] + "" + "subq $31,%1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] + "" + "subl %r1,%2,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] + "" + "subl %r1,%2,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "subdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + "" + "subq %r1,%2,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const48_operand" "I")) + (match_operand:SI 3 "reg_or_8bit_operand" "rI")))] + "" + "s%2subl %r1,%3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI + (minus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (match_operand:SI 2 "const48_operand" "I")) + (match_operand:SI 3 "reg_or_8bit_operand" "rI"))))] + "" + "s%2subl %r1,%3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (minus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "const48_operand" "I")) + (match_operand:DI 3 "reg_or_8bit_operand" "rI")))] + "" + "s%2subq %r1,%3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") + (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] + "" + "mull %r1,%2,%0" + [(set_attr "type" "imull")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") + (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] + "" + "mull %r1,%2,%0" + [(set_attr "type" "imull")]) + + (define_insn "muldi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + "" + "mulq %r1,%2,%0" + [(set_attr "type" "imulq")]) + + ;; The divide and remainder operations always take their inputs from + ;; r24 and r25, put their output in r27, and clobber r23. + + (define_expand "divsi3" + [(parallel [(set (reg:SI 27) + (div:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:SI 0 "general_operand" "") + (reg:SI 27))] + "" + " + { rtx in0 = gen_rtx (REG, SImode, 24); + rtx in1 = gen_rtx (REG, SImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "udivsi3" + [(parallel [(set (reg:SI 27) + (udiv:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:SI 0 "general_operand" "") + (reg:SI 27))] + "" + " + { rtx in0 = gen_rtx (REG, SImode, 24); + rtx in1 = gen_rtx (REG, SImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "modsi3" + [(parallel [(set (reg:SI 27) + (mod:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:SI 0 "general_operand" "") + (reg:SI 27))] + "" + " + { rtx in0 = gen_rtx (REG, SImode, 24); + rtx in1 = gen_rtx (REG, SImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "umodsi3" + [(parallel [(set (reg:SI 27) + (umod:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:SI 0 "general_operand" "") + (reg:SI 27))] + "" + " + { rtx in0 = gen_rtx (REG, SImode, 24); + rtx in1 = gen_rtx (REG, SImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "divdi3" + [(parallel [(set (reg:DI 27) + (div:DI (match_operand:DI 1 "general_operand" "") + (match_operand:DI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:DI 0 "general_operand" "") + (reg:DI 27))] + "" + " + { rtx in0 = gen_rtx (REG, DImode, 24); + rtx in1 = gen_rtx (REG, DImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "udivdi3" + [(parallel [(set (reg:DI 27) + (udiv:DI (match_operand:DI 1 "general_operand" "") + (match_operand:DI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:DI 0 "general_operand" "") + (reg:DI 27))] + "" + " + { rtx in0 = gen_rtx (REG, DImode, 24); + rtx in1 = gen_rtx (REG, DImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "moddi3" + [(parallel [(set (reg:DI 27) + (mod:DI (match_operand:DI 1 "general_operand" "") + (match_operand:DI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:DI 0 "general_operand" "") + (reg:DI 27))] + "" + " + { rtx in0 = gen_rtx (REG, DImode, 24); + rtx in1 = gen_rtx (REG, DImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_expand "umoddi3" + [(parallel [(set (reg:DI 27) + (umod:DI (match_operand:DI 1 "general_operand" "") + (match_operand:DI 2 "general_operand" ""))) + (clobber (reg:DI 23))]) + (set (match_operand:DI 0 "general_operand" "") + (reg:DI 27))] + "" + " + { rtx in0 = gen_rtx (REG, DImode, 24); + rtx in1 = gen_rtx (REG, DImode, 25); + + emit_move_insn (in0, operands[1]); + emit_move_insn (in1, operands[2]); + operands[1] = in0, operands[2] = in1; + }") + + (define_insn "" + [(set (reg:SI 27) + (match_operator:SI 1 "divmod_operator" + [(reg:SI 24) (reg:SI 25)])) + (clobber (reg:DI 23))] + "" + "%E1 $24,$25,$27") + + (define_insn "" + [(set (reg:DI 27) + (match_operator:DI 1 "divmod_operator" + [(reg:DI 24) (reg:DI 25)])) + (clobber (reg:DI 23))] + "" + "%E1 $24,$25,$27") + + ;; Next are the basic logical operations. These only exist in DImode. + + (define_insn "anddi3" + [(set (match_operand:DI 0 "register_operand" "=r,r,r") + (and:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ") + (match_operand:DI 2 "and_operand" "rI,N,MH")))] + "" + "@ + and %r1,%2,%0 + bic %r1,%N2,%0 + zapnot %r1,%m2,%0" + [(set_attr "type" "iaddlog,iaddlog,shiftcm")]) + + ;; There are times when we can split and AND into two AND insns. This occurs + ;; when we can first clear any bytes and then clear anything else. For + ;; example "I & 0xffff07" is "(I & 0xffffff) & 0xffffffffffffff07". + ;; Only to this when running on 64-bit host since the computations are + ;; too messy otherwise. + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (and:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "const_int_operand" "")))] + "HOST_BITS_PER_WIDE_INT == 64 && ! and_operand (operands[2], DImode)" + [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))] + " + { + unsigned HOST_WIDE_INT mask1 = INTVAL (operands[2]); + unsigned HOST_WIDE_INT mask2 = mask1; + int i; + + /* For each byte that isn't all zeros, make it all ones. */ + for (i = 0; i < 64; i += 8) + if ((mask1 & ((HOST_WIDE_INT) 0xff << i)) != 0) + mask1 |= (HOST_WIDE_INT) 0xff << i; + + /* Now turn on any bits we've just turned off. */ + mask2 |= ~ mask1; + + operands[3] = GEN_INT (mask1); + operands[4] = GEN_INT (mask2); + }") + + (define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r") + (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] + "" + "zapnot %1,1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))] + "" + "zapnot %1,1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "zero_extendqidi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))] + "" + "zapnot %1,1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))] + "" + "zapnot %1,3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "zero_extendhidi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))] + "" + "zapnot %1,3,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "zero_extendsidi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))] + "" + "zapnot %1,15,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (and:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) + (match_operand:DI 2 "reg_or_0_operand" "rJ")))] + "" + "bic %r2,%1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "iordi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (ior:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + "" + "bis %r1,%2,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "one_cmpldi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] + "" + "ornot $31,%1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ior:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) + (match_operand:DI 2 "reg_or_0_operand" "rJ")))] + "" + "ornot %r2,%1,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "xordi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + "" + "xor %r1,%2,%0" + [(set_attr "type" "iaddlog")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI"))))] + "" + "eqv %r1,%2,%0" + [(set_attr "type" "iaddlog")]) + + ;; Next come the shifts and the various extract and insert operations. + + (define_insn "ashldi3" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "P,rI")))] + "" + "* + { + switch (which_alternative) + { + case 0: + if (operands[2] == const1_rtx) + return \"addq %r1,%r1,%0\"; + else + return \"s%P2addq %r1,0,%0\"; + case 1: + return \"sll %r1,%2,%0\"; + } + }" + [(set_attr "type" "iaddlog,shiftcm")]) + + ;; This is the same as (sign_extend (shift X [123])). + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashiftrt:DI (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "const_int_operand" "i")) + (const_int 32)))] + "INTVAL (operands[2]) >= 33 && INTVAL (operands[2]) <= 35" + "* + { + switch (INTVAL (operands[2])) + { + case 33: + return \"addl %r1,%r1,%0\"; + case 34: + return \"s4addl %r1,0,%0\"; + case 35: + return \"s8addl %r1,0,%0\"; + default: + abort (); + } + }" + [(set_attr "type" "iaddlog")]) + + (define_insn "lshrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + "" + "srl %r1,%2,%0") + + (define_insn "ashrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + "" + "sra %r1,%2,%0") + + (define_expand "extendqihi2" + [(set (match_dup 2) + (ashift:DI (match_operand:QI 1 "register_operand" "") + (const_int 56))) + (set (match_operand:HI 0 "register_operand" "") + (ashiftrt:DI (match_dup 2) + (const_int 56)))] + "" + " + { operands[0] = gen_lowpart (DImode, operands[0]); + operands[1] = gen_lowpart (DImode, operands[1]); + operands[2] = gen_reg_rtx (DImode); + }") + + (define_expand "extendqisi2" + [(set (match_dup 2) + (ashift:DI (match_operand:QI 1 "register_operand" "") + (const_int 56))) + (set (match_operand:SI 0 "register_operand" "") + (ashiftrt:DI (match_dup 2) + (const_int 56)))] + "" + " + { operands[0] = gen_lowpart (DImode, operands[0]); + operands[1] = gen_lowpart (DImode, operands[1]); + operands[2] = gen_reg_rtx (DImode); + }") + + (define_expand "extendqidi2" + [(set (match_dup 2) + (ashift:DI (match_operand:QI 1 "register_operand" "") + (const_int 56))) + (set (match_operand:DI 0 "register_operand" "") + (ashiftrt:DI (match_dup 2) + (const_int 56)))] + "" + " + { operands[1] = gen_lowpart (DImode, operands[1]); + operands[2] = gen_reg_rtx (DImode); + }") + + (define_expand "extendhisi2" + [(set (match_dup 2) + (ashift:DI (match_operand:HI 1 "register_operand" "") + (const_int 48))) + (set (match_operand:SI 0 "register_operand" "") + (ashiftrt:DI (match_dup 2) + (const_int 48)))] + "" + " + { operands[0] = gen_lowpart (DImode, operands[0]); + operands[1] = gen_lowpart (DImode, operands[1]); + operands[2] = gen_reg_rtx (DImode); + }") + + (define_expand "extendhidi2" + [(set (match_dup 2) + (ashift:DI (match_operand:HI 1 "register_operand" "") + (const_int 48))) + (set (match_operand:DI 0 "register_operand" "") + (ashiftrt:DI (match_dup 2) + (const_int 48)))] + "" + " + { operands[1] = gen_lowpart (DImode, operands[1]); + operands[2] = gen_reg_rtx (DImode); + }") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "mode_width_operand" "n") + (match_operand:DI 3 "mul8_operand" "I")))] + "" + "ext%M2l %r1,%s3,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (match_operand:DI 2 "mode_width_operand" "n") + (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI") + (const_int 3))))] + "" + "ext%M2l %r1,%3,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI + (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 8) + (ashift:DI + (plus:DI + (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) + (const_int 3))) + (const_int 56)))] + "" + "extqh %r1,%2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI + (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 16) + (ashift:DI + (plus:DI + (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -2)) + (const_int 3))) + (const_int 48)))] + "" + "extwh %r1,%2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI + (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 32) + (ashift:DI + (plus:DI + (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -4)) + (const_int 3))) + (const_int 32)))] + "" + "extlh %r1,%2,%0") + + ;; This converts an extXl into an extXh with an appropriate adjustment + ;; to the address calculation. + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "mode_width_operand" "") + (ashift:DI (match_operand:DI 3 "" "") + (const_int 3))) + (match_operand:DI 4 "const_int_operand" ""))) + (clobber (match_operand:DI 5 "register_operand" ""))] + "INTVAL (operands[4]) == 64 - INTVAL (operands[2])" + [(set (match_dup 5) (match_dup 6)) + (set (match_dup 0) + (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2) + (ashift:DI (plus:DI (match_dup 5) + (match_dup 7)) + (const_int 3))) + (match_dup 4)))] + " + { + operands[6] = plus_constant (operands[3], + INTVAL (operands[2]) / BITS_PER_UNIT); + operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT); + }") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) + (match_operand:DI 2 "mul8_operand" "I")))] + "" + "insbl %1,%s2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) + (match_operand:DI 2 "mul8_operand" "I")))] + "" + "inswl %1,%s2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (match_operand:DI 2 "mul8_operand" "I")))] + "" + "insll %1,%s2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) + (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int 3))))] + "" + "insbl %1,%2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) + (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int 3))))] + "" + "inswl %1,%2,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int 3))))] + "" + "insll %1,%2,%0") + + ;; We do not include the insXh insns because they are complex to express + ;; and it does not appear that we would ever want to generate them. + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (and:DI (ashift:DI + (match_operand:DI 2 "mode_mask_operand" "n") + (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI") + (const_int 3))) + (match_operand:DI 1 "reg_or_0_operand" "rJ")))] + "" + "msk%U2l %r1,%3,%0") + + ;; We do not include the mskXh insns because it does not appear we would ever + ;; generate one. + + ;; Floating-point operations. All the double-precision insns can extend + ;; from single, so indicate that. The exception are the ones that simply + ;; play with the sign bits; it's not clear what to do there. + + (define_insn "abssf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "cpys $f31,%R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "absdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "cpys $f31,%R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "negsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "cpysn %1,%R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "negdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "cpysn %1,%R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "addsf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "adds %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "adddf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "addt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (plus:DF (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "addt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (plus:DF (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "addt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "fix_truncdfdi2" + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "cvttq %R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "fix_truncsfdi2" + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "cvttq %R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "floatdisf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (float:SF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_FP" + "cvtqs %1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "floatdidf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (float:DF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_FP" + "cvtqt %1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m")))] + "TARGET_FP" + "@ + addt $f31,%1,%0 + lds %0,%1" + [(set_attr "type" "fpop,ld")]) + + (define_insn "truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "cvtts %R1,%0" + [(set_attr "type" "fpop")]) + + (define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "divs %R1,%R2,%0" + [(set_attr "type" "fdivs")]) + + (define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "divt %R1,%R2,%0" + [(set_attr "type" "fdivt")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "divt %R1,%R2,%0" + [(set_attr "type" "fdivt")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") + (float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "divt %R1,%R2,%0" + [(set_attr "type" "fdivt")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) + (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "divt %R1,%R2,%0" + [(set_attr "type" "fdivt")]) + + (define_insn "mulsf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "muls %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "mult %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (mult:DF (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "fG")) + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "mult %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (mult:DF (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "fG")) + (float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "mult %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "subsf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") + (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "subs %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "subdf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "subt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (minus:DF (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] + "TARGET_FP" + "subt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "subt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (minus:DF (float_extend:DF + (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] + "TARGET_FP" + "subt %R1,%R2,%0" + [(set_attr "type" "fpop")]) + + ;; Next are all the integer comparisons, and conditional moves and branches + ;; and some of the related define_expand's and define_split's. + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (match_operator:DI 1 "alpha_comparison_operator" + [(match_operand:DI 2 "reg_or_0_operand" "rJ") + (match_operand:DI 3 "reg_or_8bit_operand" "rI")]))] + "" + "cmp%C1 %r2,%3,%0" + [(set_attr "type" "icmp")]) + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (if_then_else:DI + (match_operator 2 "signed_comparison_operator" + [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ") + (const_int 0)]) + (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") + (match_operand:DI 4 "reg_or_8bit_operand" "0,rI")))] + "" + "@ + cmov%C2 %r3,%1,%0 + cmov%D2 %r3,%4,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (if_then_else:DI + (eq (zero_extract:DI (match_operand:DI 2 "reg_or_0_operand" "rJ,rJ") + (const_int 1) + (const_int 0)) + (const_int 0)) + (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") + (match_operand:DI 3 "reg_or_8bit_operand" "0,rI")))] + "" + "@ + cmovlbc %r2,%1,%0 + cmovlbs %r2,%3,%0") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (if_then_else:DI + (ne (zero_extract:DI (match_operand:DI 2 "reg_or_0_operand" "rJ,rJ") + (const_int 1) + (const_int 0)) + (const_int 0)) + (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") + (match_operand:DI 3 "reg_or_8bit_operand" "0,rI")))] + "" + "@ + cmovlbs %r2,%1,%0 + cmovlbc %r2,%3,%0") + + ;; This form is added since combine thinks that an IF_THEN_ELSE with both + ;; arms constant is a single insn, so it won't try to form it if combine + ;; knows they are really two insns. This occurs in divides by powers + ;; of two. + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (if_then_else:DI + (match_operator 2 "signed_comparison_operator" + [(match_operand:DI 3 "reg_or_0_operand" "rJ") + (const_int 0)]) + (plus:DI (match_dup 0) + (match_operand:DI 1 "reg_or_8bit_operand" "rI")) + (match_dup 0))) + (clobber (match_scratch:DI 4 "=&r"))] + "" + "addq %0,%1,%4\;cmov%C2 %r3,%4,%0") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI + (match_operator 2 "signed_comparison_operator" + [(match_operand:DI 3 "reg_or_0_operand" "") + (const_int 0)]) + (plus:DI (match_dup 0) + (match_operand:DI 1 "reg_or_8bit_operand" "")) + (match_dup 0))) + (clobber (match_operand:DI 4 "register_operand" ""))] + "" + [(set (match_dup 4) (plus:DI (match_dup 0) (match_dup 1))) + (set (match_dup 0) (if_then_else:DI (match_op_dup 2 + [(match_dup 3) + (const_int 0)]) + (match_dup 4) (match_dup 0)))] + "") + + (define_split + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI + (match_operator 1 "comparison_operator" + [(zero_extract:DI (match_operand:DI 2 "register_operand" "") + (const_int 1) + (match_operand:DI 3 "const_int_operand" "")) + (const_int 0)]) + (match_operand:DI 4 "reg_or_8bit_operand" "") + (match_operand:DI 5 "reg_or_8bit_operand" ""))) + (clobber (match_operand:DI 6 "register_operand" ""))])] + "INTVAL (operands[3]) != 0" + [(set (match_dup 6) + (lshiftrt:DI (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:DI (match_op_dup 1 + [(zero_extract:DI (match_dup 6) + (const_int 1) + (const_int 0)) + (const_int 0)]) + (match_dup 4) + (match_dup 5)))] + "") + + ;; For ABS, we have two choices, depending on whether the input and output + ;; registers are the same or not. + (define_expand "absdi2" + [(set (match_operand:DI 0 "register_operand" "") + (abs:DI (match_operand:DI 1 "register_operand" "")))] + "" + " + { if (rtx_equal_p (operands[0], operands[1])) + emit_insn (gen_absdi2_same (operands[0], gen_reg_rtx (DImode))); + else + emit_insn (gen_absdi2_diff (operands[0], operands[1])); + + DONE; + }") + + (define_expand "absdi2_same" + [(set (match_operand:DI 1 "register_operand" "") + (neg:DI (match_operand:DI 0 "register_operand" ""))) + (set (match_dup 0) + (if_then_else:DI (ge (match_dup 0) (const_int 0)) + (match_dup 0) + (match_dup 1)))] + "" + "") + + (define_expand "absdi2_diff" + [(set (match_operand:DI 0 "register_operand" "") + (neg:DI (match_operand:DI 1 "register_operand" ""))) + (set (match_dup 0) + (if_then_else:DI (lt (match_dup 1) (const_int 0)) + (match_dup 0) + (match_dup 1)))] + "" + "") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (abs:DI (match_dup 0))) + (clobber (match_operand:DI 2 "register_operand" ""))] + "" + [(set (match_dup 1) (neg:DI (match_dup 0))) + (set (match_dup 0) (if_then_else:DI (ge (match_dup 0) (const_int 0)) + (match_dup 0) (match_dup 1)))] + "") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (abs:DI (match_operand:DI 1 "register_operand" "")))] + "! rtx_equal_p (operands[0], operands[1])" + [(set (match_dup 0) (neg:DI (match_dup 1))) + (set (match_dup 0) (if_then_else:DI (lt (match_dup 1) (const_int 0)) + (match_dup 0) (match_dup 1)))] + "") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (neg:DI (abs:DI (match_dup 0)))) + (clobber (match_operand:DI 2 "register_operand" ""))] + "" + [(set (match_dup 1) (neg:DI (match_dup 0))) + (set (match_dup 0) (if_then_else:DI (le (match_dup 0) (const_int 0)) + (match_dup 0) (match_dup 1)))] + "") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (neg:DI (abs:DI (match_operand:DI 1 "register_operand" ""))))] + "! rtx_equal_p (operands[0], operands[1])" + [(set (match_dup 0) (neg:DI (match_dup 1))) + (set (match_dup 0) (if_then_else:DI (gt (match_dup 1) (const_int 0)) + (match_dup 0) (match_dup 1)))] + "") + + (define_expand "smaxdi3" + [(set (match_dup 3) + (le:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (eq (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "" + " + { operands[3] = gen_reg_rtx (DImode); + }") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (smax:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (clobber (match_operand:DI 3 "register_operand" ""))] + "operands[2] != const0_rtx" + [(set (match_dup 3) (le:DI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (if_then_else:DI (eq (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (smax:DI (match_operand:DI 1 "register_operand" "0") + (const_int 0)))] + "" + "cmovlt %0,0,%0") + + (define_expand "smindi3" + [(set (match_dup 3) + (lt:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (ne (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "" + " + { operands[3] = gen_reg_rtx (DImode); + }") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (smin:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (clobber (match_operand:DI 3 "register_operand" ""))] + "operands[2] != const0_rtx" + [(set (match_dup 3) (lt:DI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (if_then_else:DI (ne (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (smin:DI (match_operand:DI 1 "register_operand" "0") + (const_int 0)))] + "" + "cmovgt %0,0,%0") + + (define_expand "umaxdi3" + [(set (match_dup 3) + (leu:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (eq (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "" + " + { operands[3] = gen_reg_rtx (DImode); + }") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (umax:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (clobber (match_operand:DI 3 "register_operand" ""))] + "operands[2] != const0_rtx" + [(set (match_dup 3) (leu:DI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (if_then_else:DI (eq (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "") + + (define_expand "umindi3" + [(set (match_dup 3) + (ltu:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (ne (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "" + " + { operands[3] = gen_reg_rtx (DImode); + }") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (umin:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "reg_or_8bit_operand" ""))) + (clobber (match_operand:DI 3 "register_operand" ""))] + "operands[2] != const0_rtx" + [(set (match_dup 3) (ltu:DI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (if_then_else:DI (ne (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "") + + (define_insn "" + [(set (pc) + (if_then_else + (match_operator 1 "signed_comparison_operator" + [(match_operand:DI 2 "reg_or_0_operand" "rJ") + (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "b%C1 %r2,%0" + [(set_attr "type" "ibr")]) + + (define_insn "" + [(set (pc) + (if_then_else + (ne (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 1) + (const_int 0)) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "blbs %r1,%0" + [(set_attr "type" "ibr")]) + + (define_insn "" + [(set (pc) + (if_then_else + (eq (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + (const_int 1) + (const_int 0)) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "blbc %r1,%0" + [(set_attr "type" "ibr")]) + + (define_split + [(parallel + [(set (pc) + (if_then_else + (match_operator 1 "comparison_operator" + [(zero_extract:DI (match_operand:DI 2 "register_operand" "") + (const_int 1) + (match_operand:DI 3 "const_int_operand" "")) + (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (match_operand:DI 4 "register_operand" ""))])] + "INTVAL (operands[3]) != 0" + [(set (match_dup 4) + (lshiftrt:DI (match_dup 2) (match_dup 3))) + (set (pc) + (if_then_else (match_op_dup 1 + [(zero_extract:DI (match_dup 4) + (const_int 1) + (const_int 0)) + (const_int 0)]) + (label_ref (match_dup 0)) + (pc)))] + "") + + ;; The following are the corresponding floating-point insns. Recall + ;; we need to have variants that expand the arguments from SF mode + ;; to DFmode. + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (match_operator:DF 1 "alpha_comparison_operator" + [(match_operand:DF 2 "reg_or_fp0_operand" "fG") + (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] + "TARGET_FP" + "cmpt%C1 %R2,%R3,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (match_operator:DF 1 "alpha_comparison_operator" + [(float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG")) + (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] + "TARGET_FP" + "cmpt%C1 %R2,%R3,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (match_operator:DF 1 "alpha_comparison_operator" + [(match_operand:DF 2 "reg_or_fp0_operand" "fG") + (float_extend:DF + (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] + "TARGET_FP" + "cmpt%C1 %R2,%R3,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (match_operator:DF 1 "alpha_comparison_operator" + [(float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG")) + (float_extend:DF + (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] + "TARGET_FP" + "cmpt%C1 %R2,%R3,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF + (match_operator 3 "signed_comparison_operator" + [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") + (match_operand:DF 2 "fp0_operand" "G,G")]) + (match_operand:DF 1 "reg_or_fp0_operand" "fG,0") + (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] + "TARGET_FP" + "@ + fcmov%C3 %R4,%R1,%0 + fcmov%D3 %R4,%R5,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF + (match_operator 3 "signed_comparison_operator" + [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") + (match_operand:DF 2 "fp0_operand" "G,G")]) + (match_operand:SF 1 "reg_or_fp0_operand" "fG,0") + (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))] + "TARGET_FP" + "@ + fcmov%C3 %R4,%R1,%0 + fcmov%D3 %R4,%R5,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF + (match_operator 3 "signed_comparison_operator" + [(match_operand:DF 1 "reg_or_fp0_operand" "fG,fG") + (match_operand:DF 2 "fp0_operand" "G,G")]) + (float_extend:DF (match_operand:SF 4 "reg_or_fp0_operand" "fG,0")) + (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] + "TARGET_FP" + "@ + fcmov%C3 %R4,%R1,%0 + fcmov%D3 %R4,%R5,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF + (match_operator 3 "signed_comparison_operator" + [(float_extend:DF + (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) + (match_operand:DF 2 "fp0_operand" "G,G")]) + (match_operand:DF 1 "reg_or_fp0_operand" "fG,0") + (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] + "TARGET_FP" + "@ + fcmov%C3 %R4,%R1,%0 + fcmov%D3 %R4,%R5,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF + (match_operator 3 "signed_comparison_operator" + [(float_extend:DF + (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) + (match_operand:DF 2 "fp0_operand" "G,G")]) + (match_operand:SF 1 "reg_or_fp0_operand" "fG,0") + (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))] + "TARGET_FP" + "@ + fcmov%C3 %R4,%R1,%0 + fcmov%D3 %R4,%R5,%0" + [(set_attr "type" "fpop")]) + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF + (match_operator 3 "signed_comparison_operator" + [(float_extend:DF + (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) + (match_operand:DF 2 "fp0_operand" "G,G")]) + (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")) + (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] + "TARGET_FP" + "@ + fcmov%C3 %R4,%R1,%0 + fcmov%D3 %R4,%R5,%0" + [(set_attr "type" "fpop")]) + + (define_expand "smaxdf3" + [(set (match_dup 3) + (le:DF (match_operand:DF 1 "reg_or_fp0_operand" "") + (match_operand:DF 2 "reg_or_fp0_operand" ""))) + (set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (eq (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "TARGET_FP" + " + { operands[3] = gen_reg_rtx (DFmode); + }") + + (define_expand "smindf3" + [(set (match_dup 3) + (lt:DF (match_operand:DF 1 "reg_or_fp0_operand" "") + (match_operand:DF 2 "reg_or_fp0_operand" ""))) + (set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (ne (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "TARGET_FP" + " + { operands[3] = gen_reg_rtx (DFmode); + }") + + (define_expand "smaxsf3" + [(set (match_dup 3) + (le:DF (match_operand:SF 1 "reg_or_fp0_operand" "") + (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) + (set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (eq (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "TARGET_FP" + " + { operands[3] = gen_reg_rtx (SFmode); + }") + + (define_expand "sminsf3" + [(set (match_dup 3) + (lt:DF (match_operand:SF 1 "reg_or_fp0_operand" "") + (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) + (set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (ne (match_dup 3) (const_int 0)) + (match_dup 1) (match_dup 2)))] + "TARGET_FP" + " + { operands[3] = gen_reg_rtx (SFmode); + }") + + (define_insn "" + [(set (pc) + (if_then_else + (match_operator 1 "signed_comparison_operator" + [(match_operand:DF 2 "reg_or_fp0_operand" "fG") + (match_operand:DF 3 "fp0_operand" "G")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_FP" + "fb%C1 %R2,%0" + [(set_attr "type" "fbr")]) + + (define_insn "" + [(set (pc) + (if_then_else + (match_operator 1 "signed_comparison_operator" + [(float_extend:DF + (match_operand:SF 2 "reg_or_fp0_operand" "fG")) + (match_operand:DF 3 "fp0_operand" "G")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_FP" + "fb%C1 %R2,%0" + [(set_attr "type" "fbr")]) + + ;; These are the main define_expand's used to make conditional branches + ;; and compares. + + (define_expand "cmpdf" + [(set (cc0) (compare (match_operand:DF 0 "reg_or_fp0_operand" "") + (match_operand:DF 1 "reg_or_fp0_operand" "")))] + "" + " + { + alpha_compare_op0 = operands[0]; + alpha_compare_op1 = operands[1]; + alpha_compare_fp_p = 1; + DONE; + }") + + (define_expand "cmpdi" + [(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "") + (match_operand:DI 1 "reg_or_8bit_operand" "")))] + "" + " + { + alpha_compare_op0 = operands[0]; + alpha_compare_op1 = operands[1]; + alpha_compare_fp_p = 0; + DONE; + }") + + (define_expand "beq" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode; + operands[1] = gen_reg_rtx (mode); + operands[2] = gen_rtx (EQ, mode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode)); + }") + + (define_expand "bne" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode; + operands[1] = gen_reg_rtx (mode); + operands[2] = gen_rtx (EQ, mode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (EQ, VOIDmode, operands[1], CONST0_RTX (mode)); + }") + + (define_expand "blt" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode; + operands[1] = gen_reg_rtx (mode); + operands[2] = gen_rtx (LT, mode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode)); + }") + + (define_expand "ble" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + enum machine_mode mode = alpha_compare_fp_p ? DFmode : DImode; + operands[1] = gen_reg_rtx (mode); + operands[2] = gen_rtx (LE, mode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (mode)); + }") + + (define_expand "bgt" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + if (alpha_compare_fp_p) + { + operands[1] = gen_reg_rtx (DFmode); + operands[2] = gen_rtx (LT, DFmode, alpha_compare_op1, alpha_compare_op0); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (DFmode)); + } + else + { + operands[1] = gen_reg_rtx (DImode); + operands[2] = gen_rtx (LE, DImode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); + } + }") + + (define_expand "bge" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + if (alpha_compare_fp_p) + { + operands[1] = gen_reg_rtx (DFmode); + operands[2] = gen_rtx (LE, DFmode, alpha_compare_op1, alpha_compare_op0); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], CONST0_RTX (DFmode)); + } + else + { + operands[1] = gen_reg_rtx (DImode); + operands[2] = gen_rtx (LT, DImode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); + } + }") + + (define_expand "bltu" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + operands[1] = gen_reg_rtx (DImode); + operands[2] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], const0_rtx); + }") + + (define_expand "bleu" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + operands[1] = gen_reg_rtx (DImode); + operands[2] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (NE, VOIDmode, operands[1], const0_rtx); + }") + + (define_expand "bgtu" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + operands[1] = gen_reg_rtx (DImode); + operands[2] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); + }") + + (define_expand "bgeu" + [(set (match_dup 1) (match_dup 2)) + (set (pc) + (if_then_else (match_dup 3) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + " + { + operands[1] = gen_reg_rtx (DImode); + operands[2] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1); + operands[3] = gen_rtx (EQ, VOIDmode, operands[1], const0_rtx); + }") + + (define_expand "seq" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (EQ, DImode, alpha_compare_op0, alpha_compare_op1); + }") + + (define_expand "sne" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1)) + (set (match_dup 0) (xor:DI (match_dup 0) (const_int 1)))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (EQ, DImode, alpha_compare_op0, alpha_compare_op1); + }") + + (define_expand "slt" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LT, DImode, alpha_compare_op0, alpha_compare_op1); + }") + + (define_expand "sle" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LE, DImode, alpha_compare_op0, alpha_compare_op1); + }") + + (define_expand "sgt" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LT, DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); + }") + + (define_expand "sge" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LE, DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); + }") + + (define_expand "sltu" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LTU, DImode, alpha_compare_op0, alpha_compare_op1); + }") + + (define_expand "sleu" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LEU, DImode, alpha_compare_op0, alpha_compare_op1); + }") + + (define_expand "sgtu" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LTU, DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); + }") + + (define_expand "sgeu" + [(set (match_operand:DI 0 "register_operand" "") + (match_dup 1))] + "" + " + { + if (alpha_compare_fp_p) + FAIL; + + operands[1] = gen_rtx (LEU, DImode, force_reg (DImode, alpha_compare_op1), + alpha_compare_op0); + }") + + ;; These define_split definitions are used in cases when comparisons have + ;; not be stated in the correct way and we need to reverse the second + ;; comparison. For example, x >= 7 has to be done as x < 6 with the + ;; comparison that tests the result being reversed. We have one define_split + ;; for each use of a comparison. They do not match valid insns and need + ;; not generate valid insns. + ;; + ;; We can also handle equality comparisons (and inequality comparisons in + ;; cases where the resulting add cannot overflow) with out-of-range numbers by + ;; doing an add followed by a comparison with zero. For this case, we + ;; also have an SImode pattern since we can merge the add and sign + ;; extend and the order doesn't matter. + ;; + ;; We do not do this for floating-point, since it isn't clear how the "wrong" + ;; operation could have been generated. + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI + (match_operator 1 "comparison_operator" + [(match_operand:DI 2 "reg_or_0_operand" "") + (match_operand:DI 3 "reg_or_cint_operand" "")]) + (match_operand:DI 4 "reg_or_cint_operand" "") + (match_operand:DI 5 "reg_or_cint_operand" ""))) + (clobber (match_operand:DI 6 "register_operand" ""))] + "operands[3] != const0_rtx" + [(set (match_dup 6) (match_dup 7)) + (set (match_dup 0) + (if_then_else:DI (match_dup 8) (match_dup 4) (match_dup 5)))] + " + { enum rtx_code code = GET_CODE (operands[1]); + int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); + + /* If we are comparing for equality with a constant and that constant + appears in the arm when the register equals the constant, use the + register since that is more likely to match (and to produce better code + if both would). */ + + if (code == EQ && GET_CODE (operands[3]) == CONST_INT + && rtx_equal_p (operands[4], operands[3])) + operands[4] = operands[2]; + + else if (code == NE && GET_CODE (operands[3]) == CONST_INT + && rtx_equal_p (operands[5], operands[3])) + operands[5] = operands[2]; + + if ((code == NE || code == EQ + || (extended_count (operands[2], DImode, unsignedp) >= 1 + && extended_count (operands[3], DImode, unsignedp) >= 1)) + && GET_CODE (operands[3]) == CONST_INT + && (unsigned) INTVAL (operands[3]) > 255) + { + operands[7] = gen_rtx (PLUS, DImode, operands[2], + GEN_INT (- INTVAL (operands[3]))); + operands[8] = gen_rtx (code, VOIDmode, operands[6], const0_rtx); + } + + else if (code == EQ || code == LE || code == LT + || code == LEU || code == LTU) + { + operands[7] = gen_rtx (code, DImode, operands[2], operands[3]); + operands[8] = gen_rtx (NE, VOIDmode, operands[6], const0_rtx); + } + else + { + operands[7] = gen_rtx (reverse_condition (code), DImode, operands[2], + operands[3]); + operands[8] = gen_rtx (EQ, VOIDmode, operands[6], const0_rtx); + } + }") + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI + (match_operator 1 "comparison_operator" + [(match_operand:SI 2 "reg_or_0_operand" "") + (match_operand:SI 3 "const_int_operand" "")]) + (match_operand:DI 4 "reg_or_8bit_operand" "") + (match_operand:DI 5 "reg_or_8bit_operand" ""))) + (clobber (match_operand:DI 6 "register_operand" ""))] + "(unsigned) INTVAL (operands[3]) > 255" + [(set (match_dup 6) (match_dup 7)) + (set (match_dup 0) + (if_then_else:DI (match_dup 8) (match_dup 4) (match_dup 5)))] + " + { enum rtx_code code = GET_CODE (operands[1]); + int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); + + if ((code != NE && code != EQ + && ! (extended_count (operands[2], DImode, unsignedp) >= 1 + && extended_count (operands[3], DImode, unsignedp) >= 1))) + FAIL; + + operands[7] = gen_rtx (SIGN_EXTEND, DImode, + gen_rtx (PLUS, SImode, operands[2], + GEN_INT (- INTVAL (operands[3])))); + operands[8] = gen_rtx (GET_CODE (operands[1]), VOIDmode, operands[6], + const0_rtx); + }") + + (define_split + [(set (pc) + (if_then_else + (match_operator 1 "comparison_operator" + [(match_operand:DI 2 "reg_or_0_operand" "") + (match_operand:DI 3 "reg_or_cint_operand" "")]) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (match_operand:DI 4 "register_operand" ""))] + "operands[3] != const0_rtx" + [(set (match_dup 4) (match_dup 5)) + (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))] + " + { enum rtx_code code = GET_CODE (operands[1]); + int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); + + if ((code == NE || code == EQ + || (extended_count (operands[2], DImode, unsignedp) >= 1 + && extended_count (operands[3], DImode, unsignedp) >= 1)) + && GET_CODE (operands[3]) == CONST_INT + && (unsigned) INTVAL (operands[3]) > 255) + { + operands[5] = gen_rtx (PLUS, DImode, operands[2], + GEN_INT (- INTVAL (operands[3]))); + operands[6] = gen_rtx (code, VOIDmode, operands[4], const0_rtx); + } + + else if (code == EQ || code == LE || code == LT + || code == LEU || code == LTU) + { + operands[5] = gen_rtx (code, DImode, operands[2], operands[3]); + operands[6] = gen_rtx (NE, VOIDmode, operands[4], const0_rtx); + } + else + { + operands[5] = gen_rtx (reverse_condition (code), DImode, operands[2], + operands[3]); + operands[6] = gen_rtx (EQ, VOIDmode, operands[4], const0_rtx); + } + }") + + (define_split + [(set (pc) + (if_then_else + (match_operator 1 "comparison_operator" + [(match_operand:SI 2 "reg_or_0_operand" "") + (match_operand:SI 3 "const_int_operand" "")]) + (label_ref (match_operand 0 "" "")) + (pc))) + (clobber (match_operand:DI 4 "register_operand" ""))] + "INTVAL (operands[3]) < 0 + && (GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" + [(set (match_dup 4) (match_dup 5)) + (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))] + " + { operands[5] = gen_rtx (SIGN_EXTEND, DImode, + gen_rtx (PLUS, SImode, operands[2], + GEN_INT (- INTVAL (operands[3])))); + operands[6] = gen_rtx (GET_CODE (operands[1]), VOIDmode, + operands[4], const0_rtx); + }") + + ;; Here are the CALL and unconditional branch insns. + + (define_expand "call" + [(parallel [(call (mem:DI (match_dup 2)) + (match_operand 1 "" "")) + (use (match_operand:DI 0 "" "")) + (clobber (reg:DI 26))])] + "" + " + { if (GET_CODE (operands[0]) != MEM) + abort (); + operands[0] = XEXP (operands[0], 0); + + operands[2] = gen_rtx (REG, DImode, 27); + emit_move_insn (operands[2], operands[0]); + + if (GET_CODE (operands[0]) != SYMBOL_REF) + operands[0] = const0_rtx; + }") + + (define_expand "call_value" + [(parallel [(set (match_operand 0 "" "") + (call (mem:DI (match_dup 3)) + (match_operand 2 "" ""))) + (use (match_operand:DI 1 "" "")) + (clobber (reg:DI 26))])] + "" + " + { if (GET_CODE (operands[1]) != MEM) + abort (); + + operands[1] = XEXP (operands[1], 0); + + operands[3] = gen_rtx (REG, DImode, 27); + emit_move_insn (operands[3], operands[1]); + + if (GET_CODE (operands[1]) != SYMBOL_REF) + operands[1] = const0_rtx; + }") + + (define_insn "" + [(call (mem:DI (reg:DI 27)) + (match_operand 0 "" "")) + (use (match_operand:DI 1 "" "")) + (clobber (reg:DI 26))] + "" + "* + { if (alpha_gp_dead_after (insn)) + return \"jsr $26,($27),%1\"; + else + return \"jsr $26,($27),%1\;ldgp $29,0($26)\"; + }" + [(set_attr "type" "jsr")]) + + (define_insn "" + [(set (match_operand 0 "register_operand" "=rf") + (call (mem:DI (reg:DI 27)) + (match_operand 1 "" ""))) + (use (match_operand:DI 2 "" "")) + (clobber (reg:DI 26))] + "" + "* + { if (alpha_gp_dead_after (insn)) + return \"jsr $26,($27),%2\"; + else + return \"jsr $26,($27),%2\;ldgp $29,0($26)\"; + }" + [(set_attr "type" "jsr")]) + + (define_insn "" + [(call (mem:DI (match_operand 1 "current_function_operand" "i")) + (match_operand 0 "" "")) + (use (match_dup 1)) + (clobber (reg:DI 26))] + "" + "bsr $26,%F1" + [(set_attr "type" "ibr")]) + + (define_insn "" + [(set (match_operand 0 "register_operand" "=rf") + (call (mem:DI (match_operand 1 "current_function_operand" "i")) + (match_operand 2 "" ""))) + (use (match_dup 1)) + (clobber (reg:DI 26))] + "" + "bsr $26,%F1" + [(set_attr "type" "ibr")]) + + (define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "br $31,%l0" + [(set_attr "type" "ibr")]) + + (define_insn "return" + [(return)] + "direct_return ()" + "ret $31,($26),1" + [(set_attr "type" "ibr")]) + + (define_insn "indirect_jump" + [(set (pc) (match_operand:DI 0 "register_operand" "r"))] + "" + "jmp $31,(%0),0" + [(set_attr "type" "ibr")]) + + (define_insn "nop" + [(const_int 0)] + "" + "bis $31,$31,$31" + [(set_attr "type" "iaddlog")]) + + (define_expand "tablejump" + [(set (match_dup 3) + (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) + (parallel [(set (pc) (plus:DI (match_dup 3) (reg:DI 29))) + (use (label_ref (match_operand 1 "" ""))) + (clobber (match_scratch:DI 2 "=r"))])] + "" + " + { operands[3] = gen_reg_rtx (DImode); }") + + (define_insn "" + [(set (pc) + (plus:DI (match_operand:DI 0 "register_operand" "r") + (reg:DI 29))) + (use (label_ref (match_operand 1 "" ""))) + (clobber (match_scratch:DI 2 "=r"))] + "" + "* + { rtx best_label = 0; + rtx jump_table_insn = next_active_insn (operands[1]); + + if (GET_CODE (jump_table_insn) == JUMP_INSN + && GET_CODE (PATTERN (jump_table_insn)) == ADDR_VEC) + { + rtx jump_table = PATTERN (jump_table_insn); + int n_labels = XVECLEN (jump_table, 0); + int best_count = -1; + int i, j; + + for (i = 0; i < n_labels; i++) + { + int count = 1; + + for (j = i + 1; j < n_labels; j++) + if (XEXP (XVECEXP (jump_table, 0, i), 0) + == XEXP (XVECEXP (jump_table, 0, j), 0)) + count++; + + if (count > best_count) + best_count = count, best_label = XVECEXP (jump_table, 0, i); + } + } + + if (best_label) + { + operands[3] = best_label; + return \"addq %0,$29,%2\;jmp $31,(%2),%3\"; + } + else + return \"addq %0,$29,%2\;jmp $31,(%2),0\"; + }" + [(set_attr "type" "ibr")]) + + ;; Finally, we have the basic data motion insns. The byte and word insns + ;; are done via define_expand. Start with the floating-point insns, since + ;; they are simpler. + + (define_insn "" + [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m") + (match_operand:SF 1 "input_operand" "r,m,rG,f,G,m,fG"))] + "register_operand (operands[0], SFmode) + || reg_or_fp0_operand (operands[1], SFmode)" + "@ + bis %1,%1,%0 + ldl %0,%1 + stl %r1,%0 + cpys %1,%1,%0 + cpys $f31,$f31,%0 + lds %0,%1 + sts %R1,%0" + [(set_attr "type" "iaddlog,ld,st,fpop,fpop,ld,st")]) + + (define_insn "" + [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m") + (match_operand:DF 1 "input_operand" "r,m,rG,f,G,m,fG"))] + "register_operand (operands[0], DFmode) + || reg_or_fp0_operand (operands[1], DFmode)" + "@ + bis %1,%1,%0 + ldq %0,%1 + stq %r1,%0 + cpys %1,%1,%0 + cpys $f31,$f31,%0 + ldt %0,%1 + stt %R1,%0" + [(set_attr "type" "iaddlog,ld,st,fpop,fpop,ld,st")]) + + (define_expand "movsf" + [(set (match_operand:SF 0 "nonimmediate_operand" "") + (match_operand:SF 1 "general_operand" ""))] + "" + " + { + if (GET_CODE (operands[0]) == MEM + && ! reg_or_fp0_operand (operands[1], SFmode)) + operands[1] = force_reg (SFmode, operands[1]); + }") + + (define_expand "movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" + " + { + if (GET_CODE (operands[0]) == MEM + && ! reg_or_fp0_operand (operands[1], DFmode)) + operands[1] = force_reg (DFmode, operands[1]); + }") + + ;; There is a problem with 32-bit values in FP registers. We keep such + ;; values in the register as a quadword. This is done on loads by using + ;; the cvtlq instruction. On stores, we can't do anything directly from + ;; floating-point registers. Disallow such an operation and let reload + ;; use an integer register instead. Don't encourage 32-bit values to + ;; be placed in FP registers at all. + + (define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,*f") + (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,*f,J,m"))] + "register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode)" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%1 + ldah %0,%h1 + ldl %0,%1 + stl %r1,%0 + cpys %1,%1,%0 + cpys $f31,$f31,%0 + lds %0,%1\;cvtlq %0,%0" + [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ld,st,fpop,fpop,ld")]) + + (define_insn "" + [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,f,f") + (match_operand:HI 1 "input_operand" "r,J,I,n,f,J"))] + "register_operand (operands[0], HImode) + || register_operand (operands[1], HImode)" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%L1 + cpys %1,%1,%0 + cpys $f31,$f31,%0" + [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,fpop,fpop")]) + + (define_insn "" + [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,f,f") + (match_operand:QI 1 "input_operand" "r,J,I,n,f,J"))] + "register_operand (operands[0], QImode) + || register_operand (operands[1], QImode)" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%L1 + cpys %1,%1,%0 + cpys $f31,$f31,%0" + [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,fpop,fpop")]) + + ;; We do two major things here: handle mem->mem and construct long + ;; constants. + + (define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " + { + if (GET_CODE (operands[0]) == MEM + && ! reg_or_0_operand (operands[1], SImode)) + operands[1] = force_reg (SImode, operands[1]); + + if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode)) + ; + else if (GET_CODE (operands[1]) == CONST_INT) + { + if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 3)) + DONE; + else + abort (); + } + }") + + ;; Split a load of a large constant into the appropriate two-insn + ;; sequence. + + (define_split + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "const_int_operand" ""))] + "! add_operand (operands[1], SImode)" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] + " + { if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 2)) + DONE; + else + FAIL; + }") + + (define_insn "" + [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,m") + (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,m,fG"))] + "register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode)" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%1 + ldah %0,%h1 + lda %0,%1 + ldq%A1 %0,%1 + stq%A0 %r1,%0 + cpys %1,%1,%0 + cpys $f31,$f31,%0 + ldt %0,%1 + stt %R1,%0" + [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ldsym,ld,st,fpop,fpop,ld,st")]) + + ;; We do three major things here: handle mem->mem, put 64-bit constants in + ;; memory, and construct long 32-bit constants. + + (define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " + { + if (GET_CODE (operands[0]) == MEM + && ! reg_or_0_operand (operands[1], DImode)) + operands[1] = force_reg (DImode, operands[1]); + + if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode)) + ; + else if (GET_CODE (operands[1]) == CONST_INT + && alpha_emit_set_const (operands[0], INTVAL (operands[1]), 3)) + DONE; + else if (CONSTANT_P (operands[1])) + { + operands[1] = force_const_mem (DImode, operands[1]); + if (reload_in_progress) + { + emit_move_insn (operands[0], XEXP (operands[1], 0)); + XEXP (operands[1], 0) = operands[0]; + } + else + operands[1] = validize_mem (operands[1]); + } + else + abort (); + }") + + ;; Split a load of a large constant into the appropriate two-insn + ;; sequence. + + (define_split + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "const_int_operand" ""))] + "! add_operand (operands[1], DImode)" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] + " + { if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 2)) + DONE; + else + FAIL; + }") + + ;; These are the partial-word cases. + ;; + ;; First we have the code to load an aligned word. Operand 0 is the register + ;; in which to place the result. It's mode is QImode or HImode. Operand 1 + ;; is an SImode MEM at the low-order byte of the proper word. Operand 2 is the + ;; number of bits within the word that the value is. Operand 3 is an SImode + ;; scratch register. If operand 0 is a hard register, operand 3 may be the + ;; same register. It is allowed to conflict with operand 1 as well. + + (define_expand "aligned_loadqi" + [(set (match_operand:SI 3 "register_operand" "") + (match_operand:SI 1 "memory_operand" "")) + (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) + (zero_extract:DI (subreg:DI (match_dup 3) 0) + (const_int 8) + (match_operand:DI 2 "const_int_operand" "")))] + + "" + "") + + (define_expand "aligned_loadhi" + [(set (match_operand:SI 3 "register_operand" "") + (match_operand:SI 1 "memory_operand" "")) + (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0) + (zero_extract:DI (subreg:DI (match_dup 3) 0) + (const_int 16) + (match_operand:DI 2 "const_int_operand" "")))] + + "" + "") + + ;; Similar for unaligned loads. For QImode, we use the sequence from the + ;; Alpha Architecture manual. However, for HImode, we do not. HImode pointers + ;; are normally aligned to the byte boundary, so an HImode object cannot + ;; cross a longword boundary. We could use a sequence similar to that for + ;; QImode, but that would fail if the pointer, was, in fact, not aligned. + ;; Instead, we clear bit 1 in the address and do an ldl. If the low-order + ;; bit was not aligned, this will trap and the trap handler will do what is + ;; needed. + ;; + ;; Here operand 1 is the address. Operands 2 and 3 are temporaries, where + ;; operand 3 can overlap the input and output registers. + + (define_expand "unaligned_loadqi" + [(set (match_operand:DI 2 "register_operand" "") + (mem:DI (and:DI (match_operand:DI 1 "address_operand" "") + (const_int -8)))) + (set (match_operand:DI 3 "register_operand" "") + (match_dup 1)) + (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) + (zero_extract:DI (match_dup 2) + (const_int 8) + (ashift:DI (match_dup 3) (const_int 3))))] + "" + "") + + ;; For this, the address must already be in a register. We also need two + ;; DImode temporaries, neither of which may overlap the input (and hence the + ;; output, since they might be the same register), but both of which may + ;; be the same. + + (define_expand "unaligned_loadhi" + [(set (match_operand:DI 2 "register_operand" "") + (and:DI (match_operand:DI 1 "register_operand" "") + (const_int -7))) + (set (match_operand:DI 3 "register_operand" "") + (mem:DI (match_dup 2))) + (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0) + (zero_extract:DI (match_dup 3) + (const_int 16) + (ashift:DI (match_dup 1) (const_int 3))))] + "" + "") + + ;; Storing an aligned byte or word requires two temporaries. Operand 0 is the + ;; aligned SImode MEM. Operand 1 is the register containing the + ;; byte or word to store. Operand 2 is the number of bits within the word that + ;; the value should be placed. Operands 3 and 4 are SImode temporaries. + + (define_expand "aligned_store" + [(set (match_operand:SI 3 "register_operand" "") + (match_operand:SI 0 "memory_operand" "")) + (set (subreg:DI (match_dup 3) 0) + (and:DI (subreg:DI (match_dup 3) 0) (match_dup 5))) + (set (subreg:DI (match_operand:SI 4 "register_operand" "") 0) + (ashift:DI (zero_extend:DI (match_operand 1 "register_operand" "")) + (match_operand:DI 2 "const_int_operand" ""))) + (set (subreg:DI (match_dup 4) 0) + (ior:DI (subreg:DI (match_dup 4) 0) (subreg:DI (match_dup 3) 0))) + (set (match_dup 0) (match_dup 4))] + "" + " + { operands[5] = GEN_INT (~ (GET_MODE_MASK (GET_MODE (operands[1])) + << INTVAL (operands[2]))); + }") + + ;; For the unaligned byte case, we use code similar to that in the + ;; Architecture book, but reordered to lower the number of registers + ;; required. Operand 0 is the address. Operand 1 is the data to store. + ;; Operands 2, 3, and 4 are DImode temporaries, where the last two may + ;; be the same temporary, if desired. If the address is in a register, + ;; operand 2 can be that register. + + (define_expand "unaligned_storeqi" + [(set (match_operand:DI 3 "register_operand" "") + (mem:DI (and:DI (match_operand:DI 0 "address_operand" "") + (const_int -8)))) + (set (match_operand:DI 2 "register_operand" "") + (match_dup 0)) + (set (match_dup 3) + (and:DI (ashift:DI (const_int 255) + (ashift:DI (match_dup 2) (const_int 3))) + (match_dup 3))) + (set (match_operand:DI 4 "register_operand" "") + (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "")) + (ashift:DI (match_dup 2) (const_int 3)))) + (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3))) + (set (mem:DI (and:DI (match_dup 0) (const_int -8))) + (match_dup 4))] + "" + "") + + ;; This is the code for storing into an unaligned short. It uses the same + ;; trick as loading from an unaligned short. It needs lots of temporaries. + ;; However, during reload, we only have two registers available. So we + ;; repeat code so that only two temporaries are available. During RTL + ;; generation, we can use different pseudos for each temporary and CSE + ;; will remove the redundancies. During reload, we have to settle with + ;; what we get. Luckily, unaligned accesses of this kind produced during + ;; reload are quite rare. + ;; + ;; Operand 0 is the address of the memory location. Operand 1 contains the + ;; data to store. The rest of the operands are all temporaries, with + ;; various overlap possibilities during reload. See reload_outhi for + ;; details of this use. + + (define_expand "unaligned_storehi" + [(set (match_operand:DI 2 "register_operand" "") + (match_operand:DI 0 "address_operand" "")) + (set (match_operand:DI 3 "register_operand" "") + (and:DI (match_dup 2) (const_int -7))) + (set (match_operand:DI 4 "register_operand" "") + (mem:DI (match_dup 3))) + (set (match_operand:DI 5 "register_operand" "") + (and:DI (ashift:DI (const_int 65535) + (ashift:DI (match_dup 2) (const_int 3))) + (match_dup 4))) + (set (match_operand:DI 6 "register_operand" "") + (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "")) + (ashift:DI (match_dup 2) (const_int 3)))) + (set (match_operand:DI 7 "register_operand" "") + (ior:DI (match_dup 5) (match_dup 6))) + (set (match_operand:DI 8 "register_operand" "") (match_dup 0)) + (set (match_operand:DI 9 "register_operand" "") + (and:DI (match_dup 8) (const_int -7))) + (set (mem:DI (match_dup 9)) (match_dup 7))] + "" + "") + + ;; Here are the define_expand's for QI and HI moves that use the above + ;; patterns. We have the normal sets, plus the ones that need scratch + ;; registers for reload. + + (define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " + { extern rtx get_unaligned_address (); + + /* If the output is not a register, the input must be. */ + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (QImode, operands[1]); + + /* Handle four memory cases, unaligned and aligned for either the input + or the output. The only case where we can be called during reload is + for aligned loads; all other cases require temporaries. */ + + if (GET_CODE (operands[1]) == MEM + || (GET_CODE (operands[1]) == SUBREG + && GET_CODE (SUBREG_REG (operands[1])) == MEM) + || (reload_in_progress && GET_CODE (operands[1]) == REG + && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) + || (reload_in_progress && GET_CODE (operands[1]) == SUBREG + && GET_CODE (SUBREG_REG (operands[1])) == REG + && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) + { + if (aligned_memory_operand (operands[1], QImode)) + { + rtx aligned_mem, bitnum; + rtx scratch = (reload_in_progress + ? gen_rtx (REG, SImode, REGNO (operands[0])) + : gen_reg_rtx (SImode)); + + get_aligned_mem (operands[1], &aligned_mem, &bitnum); + + emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum, + scratch)); + } + else + { + /* Don't pass these as parameters since that makes the generated + code depend on parameter evaluation order which will cause + bootstrap failures. */ + + rtx temp1 = gen_reg_rtx (DImode); + rtx temp2 = gen_reg_rtx (DImode); + rtx seq = gen_unaligned_loadqi (operands[0], + get_unaligned_address (operands[1]), + temp1, temp2); + + alpha_set_memflags (seq, operands[1]); + emit_insn (seq); + } + + DONE; + } + + else if (GET_CODE (operands[0]) == MEM + || (GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == MEM) + || (reload_in_progress && GET_CODE (operands[0]) == REG + && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) + || (reload_in_progress && GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == REG + && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) + { + if (aligned_memory_operand (operands[0], QImode)) + { + rtx aligned_mem, bitnum; + rtx temp1 = gen_reg_rtx (SImode); + rtx temp2 = gen_reg_rtx (SImode); + + get_aligned_mem (operands[0], &aligned_mem, &bitnum); + + emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, + temp1, temp2)); + } + else + { + rtx temp1 = gen_reg_rtx (DImode); + rtx temp2 = gen_reg_rtx (DImode); + rtx temp3 = gen_reg_rtx (DImode); + rtx seq = gen_unaligned_storeqi (get_unaligned_address (operands[0]), + operands[1], temp1, temp2, temp3); + + alpha_set_memflags (seq, operands[0]); + emit_insn (seq); + } + DONE; + } + }") + + (define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " + { extern rtx get_unaligned_address (); + + /* If the output is not a register, the input must be. */ + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (HImode, operands[1]); + + /* Handle four memory cases, unaligned and aligned for either the input + or the output. The only case where we can be called during reload is + for aligned loads; all other cases require temporaries. */ + + if (GET_CODE (operands[1]) == MEM + || (GET_CODE (operands[1]) == SUBREG + && GET_CODE (SUBREG_REG (operands[1])) == MEM) + || (reload_in_progress && GET_CODE (operands[1]) == REG + && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) + || (reload_in_progress && GET_CODE (operands[1]) == SUBREG + && GET_CODE (SUBREG_REG (operands[1])) == REG + && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) + { + if (aligned_memory_operand (operands[1], HImode)) + { + rtx aligned_mem, bitnum; + rtx scratch = (reload_in_progress + ? gen_rtx (REG, SImode, REGNO (operands[0])) + : gen_reg_rtx (SImode)); + + get_aligned_mem (operands[1], &aligned_mem, &bitnum); + + emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum, + scratch)); + } + else + { + rtx addr + = force_reg (DImode, + force_operand (get_unaligned_address (operands[1]), + NULL_RTX)); + rtx scratch1 = gen_reg_rtx (DImode); + rtx scratch2 = gen_reg_rtx (DImode); + rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch1, + scratch2); + + alpha_set_memflags (seq, operands[1]); + emit_insn (seq); + } + + DONE; + } + + else if (GET_CODE (operands[0]) == MEM + || (GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == MEM) + || (reload_in_progress && GET_CODE (operands[0]) == REG + && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) + || (reload_in_progress && GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == REG + && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) + { + if (aligned_memory_operand (operands[0], HImode)) + { + rtx aligned_mem, bitnum; + rtx temp1 = gen_reg_rtx (SImode); + rtx temp2 = gen_reg_rtx (SImode); + + get_aligned_mem (operands[0], &aligned_mem, &bitnum); + + emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, + temp1, temp2)); + } + else + { + rtx temp1 = gen_reg_rtx (DImode); + rtx temp2 = gen_reg_rtx (DImode); + rtx temp3 = gen_reg_rtx (DImode); + rtx temp4 = gen_reg_rtx (DImode); + rtx temp5 = gen_reg_rtx (DImode); + rtx temp6 = gen_reg_rtx (DImode); + rtx temp7 = gen_reg_rtx (DImode); + rtx temp8 = gen_reg_rtx (DImode); + rtx seq = gen_unaligned_storehi (get_unaligned_address (operands[0]), + operands[1], temp1, temp2,temp3, + temp4, temp5, temp6,temp7, temp8); + + alpha_set_memflags (seq, operands[0]); + emit_insn (seq); + } + + DONE; + } + }") + + ;; Here are the versions for reload. Note that in the unaligned cases + ;; we know that the operand must not be a pseudo-register because stack + ;; slots are always aligned references. + + (define_expand "reload_inqi" + [(parallel [(match_operand:QI 0 "register_operand" "=r") + (match_operand:QI 1 "unaligned_memory_operand" "m") + (match_operand:DI 2 "register_operand" "=&r")])] + "" + " + { extern rtx get_unaligned_address (); + rtx addr = get_unaligned_address (operands[1]); + rtx seq = gen_unaligned_loadqi (operands[0], addr, operands[2], + gen_rtx (REG, DImode, REGNO (operands[0]))); + + alpha_set_memflags (seq, operands[1]); + emit_insn (seq); + DONE; + }") + + (define_expand "reload_inhi" + [(parallel [(match_operand:HI 0 "register_operand" "=r") + (match_operand:HI 1 "unaligned_memory_operand" "m") + (match_operand:TI 2 "register_operand" "=&r")])] + "" + " + { extern rtx get_unaligned_address (); + rtx addr = get_unaligned_address (operands[1]); + rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); + rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); + rtx seq; + + if (GET_CODE (addr) != REG) + { + emit_insn (gen_rtx (SET, VOIDmode, scratch2, addr)); + addr = scratch2; + } + + seq = gen_unaligned_loadhi (operands[0], addr, scratch1, scratch1); + alpha_set_memflags (seq, operands[1]); + emit_insn (seq); + DONE; + }") + + (define_expand "reload_outqi" + [(parallel [(match_operand:QI 0 "any_memory_operand" "=m") + (match_operand:QI 1 "register_operand" "r") + (match_operand:TI 2 "register_operand" "=&r")])] + "" + " + { extern rtx get_unaligned_address (); + + if (aligned_memory_operand (operands[0], QImode)) + { + rtx aligned_mem, bitnum; + + get_aligned_mem (operands[0], &aligned_mem, &bitnum); + + emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, + gen_rtx (REG, SImode, REGNO (operands[2])), + gen_rtx (REG, SImode, + REGNO (operands[2]) + 1))); + } + else + { + rtx addr = get_unaligned_address (operands[0]); + rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); + rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); + rtx seq; + + if (GET_CODE (addr) == REG) + scratch1 = addr; + + seq = gen_unaligned_storeqi (addr, operands[1], scratch1, + scratch2, scratch2); + alpha_set_memflags (seq, operands[0]); + emit_insn (seq); + } + + DONE; + }") + + (define_expand "reload_outhi" + [(parallel [(match_operand:HI 0 "any_memory_operand" "=m") + (match_operand:HI 1 "register_operand" "r") + (match_operand:TI 2 "register_operand" "=&r")])] + "" + " + { extern rtx get_unaligned_address (); + + if (aligned_memory_operand (operands[0], HImode)) + { + rtx aligned_mem, bitnum; + + get_aligned_mem (operands[0], &aligned_mem, &bitnum); + + emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, + gen_rtx (REG, SImode, REGNO (operands[2])), + gen_rtx (REG, SImode, + REGNO (operands[2]) + 1))); + } + else + { + rtx addr = get_unaligned_address (operands[0]); + rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); + rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); + rtx scratch_a = GET_CODE (addr) == REG ? addr : scratch1; + rtx seq; + + seq = gen_unaligned_storehi (addr, operands[1], scratch_a, + scratch2, scratch2, scratch2, + scratch1, scratch2, scratch_a, + scratch1); + alpha_set_memflags (seq, operands[0]); + emit_insn (seq); + } + + DONE; + }") + + ;;- Local variables: + ;;- mode:emacs-lisp + ;;- comment-start: ";;- " + ;;- eval: (set-syntax-table (copy-sequence (syntax-table))) + ;;- eval: (modify-syntax-entry ?[ "(]") + ;;- eval: (modify-syntax-entry ?] ")[") + ;;- eval: (modify-syntax-entry ?{ "(}") + ;;- eval: (modify-syntax-entry ?} "){") + ;;- End: diff -rc2N gcc-2.2.2/config/amix.h gcc-2.3.1/config/amix.h *** gcc-2.2.2/config/amix.h Thu Jun 11 01:04:23 1992 --- gcc-2.3.1/config/amix.h Mon Sep 7 02:16:12 1992 *************** *** 22,28 **** #include "m68kv4.h" ! /* Alter assembler syntax for fsgldiv. */ ! #define FSGLDIV_USE_S /* Names to predefine in the preprocessor for this target machine. For the --- 22,32 ---- #include "m68kv4.h" ! /* Alter assembler syntax for fsgldiv and fsglmul. ! It is highly likely that this is a generic SGS m68k assembler dependency. ! If so, it should eventually be handled in the m68ksgs.h ASM_OUTPUT_OPCODE ! macro, like the other SGS assembler quirks. -fnf */ ! #define FSGLDIV_USE_S /* Use fsgldiv.s, not fsgldiv.x */ ! #define FSGLMUL_USE_S /* Use fsglmul.s, not fsglmul.x */ /* Names to predefine in the preprocessor for this target machine. For the *************** *** 35,44 **** "-Dm68k -Dunix -DAMIX -Amachine(m68k) -Acpu(m68k) -Asystem(unix) -Alint(off)" - /* This is the library routine that is used to transfer control from - the trampoline to the actual nested function. FIXME: This needs to - be implemented still. -fnf */ - - #undef TRANSFER_FROM_TRAMPOLINE - /* At end of a switch table, define LDnnn iff the symbol LInnn was defined. Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)" --- 39,42 ---- *************** *** 53,57 **** do { \ if (switch_table_difference_label_flag) \ ! asm_fprintf ((FILE), "%s %LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM));\ switch_table_difference_label_flag = 0; \ } while (0) --- 51,55 ---- do { \ if (switch_table_difference_label_flag) \ ! asm_fprintf ((FILE), "\t%s %LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM));\ switch_table_difference_label_flag = 0; \ } while (0) *************** *** 86,90 **** #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ do { \ ! fprintf ((FILE), "%s\t%s,%u,%u\n", \ BSS_ASM_OP, (NAME), (SIZE), MAX ((ALIGN) / BITS_PER_UNIT, 4)); \ } while (0) --- 84,88 ---- #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ do { \ ! fprintf ((FILE), "\t%s\t%s,%u,%u\n", \ BSS_ASM_OP, (NAME), (SIZE), MAX ((ALIGN) / BITS_PER_UNIT, 4)); \ } while (0) diff -rc2N gcc-2.2.2/config/aoutos.h gcc-2.3.1/config/aoutos.h *** gcc-2.2.2/config/aoutos.h Thu Jan 16 23:31:24 1992 --- gcc-2.3.1/config/aoutos.h Tue Aug 4 15:11:36 1992 *************** *** 37,40 **** --- 37,43 ---- when configuring for the system. */ + /* Define a symbol indicating that we are using aoutos.h. */ + #define USING_AOUTOS_H + /* A C statement (sans semicolon) to output an element in the table of global constructors. diff -rc2N gcc-2.2.2/config/arm.c gcc-2.3.1/config/arm.c *** gcc-2.2.2/config/arm.c Sat Mar 14 00:15:24 1992 --- gcc-2.3.1/config/arm.c Thu Oct 29 05:47:35 1992 *************** *** 21,25 **** #include ! #include #include "config.h" #include "rtl.h" --- 21,25 ---- #include ! #include "assert.h" #include "config.h" #include "rtl.h" *************** *** 39,43 **** /* Some function declarations. */ - extern void *xmalloc (); extern FILE *asm_out_file; extern char *output_multi_immediate (); --- 39,42 ---- *************** *** 920,923 **** --- 919,930 ---- else { + /* Restore stack pointer if necessary. */ + if (frame_size) + { + operands[0] = operands[1] = stack_pointer_rtx; + operands[2] = gen_rtx (CONST_INT, VOIDmode, frame_size); + output_add_immediate (operands); + } + if (current_function_pretend_args_size == 0 && regs_ever_live[14]) { *************** *** 1013,1017 **** hash += *s; hash = hash % LABEL_HASH_SIZE; ! cur = xmalloc (sizeof (struct label_offset)); cur->name = real_name; cur->offset = arm_text_location; --- 1020,1024 ---- hash += *s; hash = hash % LABEL_HASH_SIZE; ! cur = (struct label_offset *) xmalloc (sizeof (struct label_offset)); cur->name = real_name; cur->offset = arm_text_location; diff -rc2N gcc-2.2.2/config/arm.h gcc-2.3.1/config/arm.h *** gcc-2.2.2/config/arm.h Sat Apr 18 15:55:11 1992 --- gcc-2.3.1/config/arm.h Thu Oct 22 06:40:06 1992 *************** *** 20,24 **** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! /* Sometimes the directive `riscos' is check. This does not imply that this tm file can be used unchanged to build a GCC for RISC OS. (Since in fact, it can't.) */ --- 20,24 ---- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! /* Sometimes the directive `riscos' is checked. This does not imply that this tm file can be used unchanged to build a GCC for RISC OS. (Since in fact, it can't.) */ *************** *** 842,848 **** /* Max number of bytes we can move from memory to memory ! in one reasonably fast instruction. ! On the ARM, there are no instructions which move memory to memory! */ ! #define MOVE_MAX 0 /* Define if normal loads of shorter-than-word items from memory clears --- 842,847 ---- /* Max number of bytes we can move from memory to memory ! in one reasonably fast instruction. */ ! #define MOVE_MAX 4 /* Define if normal loads of shorter-than-word items from memory clears *************** *** 878,884 **** /* Chars and shorts should be passed as ints. */ #define PROMOTE_PROTOTYPES 1 - - /* There is no support for s insns at present */ - #define STORE_FLAG_VALUE 0 /* The machine modes of pointers and functions */ --- 877,880 ---- diff -rc2N gcc-2.2.2/config/arm.md gcc-2.3.1/config/arm.md *** gcc-2.2.2/config/arm.md Sat Mar 14 00:15:27 1992 --- gcc-2.3.1/config/arm.md Sat Oct 24 17:46:27 1992 *************** *** 31,35 **** (define_insn "adddi3" ! [(set (match_operand:DI 0 "di_operand" "=r") (plus:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] --- 31,35 ---- (define_insn "adddi3" ! [(set (match_operand:DI 0 "di_operand" "=&r") (plus:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] *************** *** 42,47 **** (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (plus:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "general_operand" "r,n")))] "" "* --- 42,47 ---- (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (plus:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "general_operand" "r,n")))] "" "* *************** *** 57,62 **** (define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f") ! (plus:SF (match_operand:SF 1 "register_operand" "f") ! (match_operand:SF 2 "fpu_rhs_operand" "fG")))] "" "* --- 57,62 ---- (define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f") ! (plus:SF (match_operand:SF 1 "register_operand" "f") ! (match_operand:SF 2 "fpu_rhs_operand" "fG")))] "" "* *************** *** 66,71 **** (define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f") ! (plus:DF (match_operand:DF 1 "register_operand" "f") ! (match_operand:DF 2 "fpu_rhs_operand" "fG")))] "" "* --- 66,71 ---- (define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f") ! (plus:DF (match_operand:DF 1 "register_operand" "f") ! (match_operand:DF 2 "fpu_rhs_operand" "fG")))] "" "* *************** *** 74,78 **** (define_insn "subdi3" ! [(set (match_operand:DI 0 "di_operand" "=r") (minus:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] --- 74,78 ---- (define_insn "subdi3" ! [(set (match_operand:DI 0 "di_operand" "=&r") (minus:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] *************** *** 85,90 **** (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I") ! (match_operand:SI 2 "general_operand" "r,n,r")))] "" "* --- 85,90 ---- (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I") ! (match_operand:SI 2 "general_operand" "r,n,r")))] "" "* *************** *** 103,108 **** (define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f,f") ! (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") ! (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] "" "* --- 103,108 ---- (define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f,f") ! (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") ! (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] "" "* *************** *** 118,122 **** (define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f,f") ! (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] "" --- 118,122 ---- (define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f,f") ! (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] "" *************** *** 136,141 **** (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=&r") ! (mult:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r")))] "" "* --- 136,141 ---- (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=&r") ! (mult:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r")))] "" "* *************** *** 150,157 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=&r") ! (plus:SI ! (mult:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r")) ! (match_operand:SI 3 "register_operand" "r")))] "" "* --- 150,157 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=&r") ! (plus:SI ! (mult:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r")) ! (match_operand:SI 3 "register_operand" "r")))] "" "* *************** *** 164,171 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=&r") ! (plus:SI ! (match_operand:SI 3 "register_operand" "r") ! (mult:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r"))))] "" "* --- 164,171 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=&r") ! (plus:SI ! (match_operand:SI 3 "register_operand" "r") ! (mult:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r"))))] "" "* *************** *** 178,183 **** (define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") ! (mult:SF (match_operand:SF 1 "register_operand" "f") ! (match_operand:SF 2 "fpu_rhs_operand" "fG")))] "" "*return (arm_output_asm_insn (\"mufs\\t%0, %1, %2\", operands));") --- 178,183 ---- (define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") ! (mult:SF (match_operand:SF 1 "register_operand" "f") ! (match_operand:SF 2 "fpu_rhs_operand" "fG")))] "" "*return (arm_output_asm_insn (\"mufs\\t%0, %1, %2\", operands));") *************** *** 185,190 **** (define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") ! (mult:DF (match_operand:DF 1 "register_operand" "f") ! (match_operand:DF 2 "fpu_rhs_operand" "fG")))] "" "* --- 185,190 ---- (define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") ! (mult:DF (match_operand:DF 1 "register_operand" "f") ! (match_operand:DF 2 "fpu_rhs_operand" "fG")))] "" "* *************** *** 196,201 **** (define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f,f") ! (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") ! (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] "" "* --- 196,201 ---- (define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f,f") ! (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") ! (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] "" "* *************** *** 211,216 **** (define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f,f") ! (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") ! (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] "" "* --- 211,216 ---- (define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f,f") ! (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") ! (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] "" "* *************** *** 228,233 **** (define_insn "modsf3" [(set (match_operand:SF 0 "register_operand" "=f") ! (mod:SF (match_operand:SF 1 "register_operand" "f") ! (match_operand:SF 2 "fpu_rhs_operand" "fG")))] "" "* --- 228,233 ---- (define_insn "modsf3" [(set (match_operand:SF 0 "register_operand" "=f") ! (mod:SF (match_operand:SF 1 "register_operand" "f") ! (match_operand:SF 2 "fpu_rhs_operand" "fG")))] "" "* *************** *** 237,242 **** (define_insn "moddf3" [(set (match_operand:DF 0 "register_operand" "=f") ! (mod:DF (match_operand:DF 1 "register_operand" "f") ! (match_operand:DF 2 "fpu_rhs_operand" "fG")))] "" "* --- 237,242 ---- (define_insn "moddf3" [(set (match_operand:DF 0 "register_operand" "=f") ! (mod:DF (match_operand:DF 1 "register_operand" "f") ! (match_operand:DF 2 "fpu_rhs_operand" "fG")))] "" "* *************** *** 247,251 **** (define_insn "anddi3" ! [(set (match_operand:DI 0 "di_operand" "=r") (and:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] --- 247,251 ---- (define_insn "anddi3" ! [(set (match_operand:DI 0 "di_operand" "=&r") (and:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] *************** *** 258,263 **** (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "arm_rhs_operand" "rI")))] "" "* --- 258,263 ---- (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "arm_rhs_operand" "rI")))] "" "* *************** *** 267,272 **** (define_insn "andcbsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (match_operand:SI 1 "register_operand" "r") ! (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))))] "" "* --- 267,272 ---- (define_insn "andcbsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (match_operand:SI 1 "register_operand" "r") ! (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))))] "" "* *************** *** 275,279 **** (define_insn "iordi3" ! [(set (match_operand:DI 0 "di_operand" "=r") (ior:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] --- 275,279 ---- (define_insn "iordi3" ! [(set (match_operand:DI 0 "di_operand" "=&r") (ior:DI (match_operand:DI 1 "di_operand" "%r") (match_operand:DI 2 "di_operand" "r")))] *************** *** 286,291 **** (define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (ior:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "nonmemory_operand" "r,n")))] "" "* --- 286,291 ---- (define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (ior:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "nonmemory_operand" "r,n")))] "" "* *************** *** 303,308 **** (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (xor:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "nonmemory_operand" "r,n")))] "" "* --- 303,308 ---- (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (xor:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "nonmemory_operand" "r,n")))] "" "* *************** *** 314,318 **** return (output_multi_immediate (operands, \"eor\\t%0, %1, %2\", \"eor\\t%0, %0, %2\", ! 2, INTVAL (operands[2]))); } ") --- 314,318 ---- return (output_multi_immediate (operands, \"eor\\t%0, %1, %2\", \"eor\\t%0, %0, %2\", ! 2, INTVAL (operands[2]))); } ") *************** *** 322,327 **** (define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (ashift:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* --- 322,327 ---- (define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (ashift:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* *************** *** 331,336 **** (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* --- 331,336 ---- (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* *************** *** 343,348 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (lshift:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* --- 343,348 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (lshift:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* *************** *** 352,357 **** (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* --- 352,357 ---- (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r") ! (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "general_operand" "rn")))] "" "* *************** *** 363,368 **** (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "general_operand" "r,n")))] "" "* --- 363,368 ---- (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") ! (match_operand:SI 2 "general_operand" "r,n")))] "" "* *************** *** 373,377 **** case 1: if (INTVAL(operands[2]) > 31) ! operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32); return (arm_output_asm_insn (\"mov\\t%0, %1,ror%2\", operands)); } --- 373,377 ---- case 1: if (INTVAL(operands[2]) > 31) ! operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32); return (arm_output_asm_insn (\"mov\\t%0, %1,ror%2\", operands)); } *************** *** 381,386 **** (define_insn "negdi2" ! [(set (match_operand:DI 0 "di_operand" "=r") ! (neg:DI (match_operand:DI 1 "di_operand" "r")))] "" "* --- 381,386 ---- (define_insn "negdi2" ! [(set (match_operand:DI 0 "di_operand" "=&r") ! (neg:DI (match_operand:DI 1 "di_operand" "r")))] "" "* *************** *** 391,395 **** (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r") ! (neg:SI (match_operand:SI 1 "register_operand" "r")))] "" "* --- 391,395 ---- (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r") ! (neg:SI (match_operand:SI 1 "register_operand" "r")))] "" "* *************** *** 399,403 **** (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (neg:SF (match_operand:SF 1 "register_operand" "f")))] "" "* --- 399,403 ---- (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (neg:SF (match_operand:SF 1 "register_operand" "f")))] "" "* *************** *** 407,411 **** (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (neg:DF (match_operand:DF 1 "register_operand" "f")))] "" "* --- 407,411 ---- (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (neg:DF (match_operand:DF 1 "register_operand" "f")))] "" "* *************** *** 415,419 **** (define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (abs:SF (match_operand:SF 1 "register_operand" "f")))] "" "* --- 415,419 ---- (define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (abs:SF (match_operand:SF 1 "register_operand" "f")))] "" "* *************** *** 423,427 **** (define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (abs:DF (match_operand:DF 1 "register_operand" "f")))] "" "* --- 423,427 ---- (define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (abs:DF (match_operand:DF 1 "register_operand" "f")))] "" "* *************** *** 431,435 **** (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] "" "* --- 431,435 ---- (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] "" "* *************** *** 439,443 **** (define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] "" "* --- 439,443 ---- (define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] "" "* *************** *** 447,451 **** (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") ! (not:SI (match_operand:SI 1 "register_operand" "r")))] "" "* --- 447,451 ---- (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") ! (not:SI (match_operand:SI 1 "register_operand" "r")))] "" "* *************** *** 457,461 **** (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (float:SF (match_operand:SI 1 "register_operand" "r")))] "" "* --- 457,461 ---- (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (float:SF (match_operand:SI 1 "register_operand" "r")))] "" "* *************** *** 465,519 **** (define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (float:DF (match_operand:SI 1 "register_operand" "r")))] "" "* return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands)); ") - - ;; Truncation insns - - (define_insn "truncsiqi2" - [(set (match_operand:QI 0 "general_operand" "=mr") - (truncate:QI (match_operand:SI 1 "register_operand" "r")))] - "" - "* - if (GET_CODE (operands[0]) == MEM) - return (arm_output_asm_insn (\"strb\\t%1, %0\\t@ truncsiqi2\", operands)); - else - return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ truncsiqi2\", operands)); - ") - - (define_insn "trunchiqi2" - [(set (match_operand:QI 0 "general_operand" "=mr") - (truncate:QI (match_operand:HI 1 "register_operand" "r")))] - "" - "* - if (GET_CODE(operands[0]) == MEM) - return (arm_output_asm_insn (\"strb\\t%1, %0\\t@ trunchiqi2\", operands)); - else - return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ trunchiqi2\", operands)); - ") - - ;; Mode is changed to SI below ! (define_expand "truncsihi2" ! [(set (match_operand:SI 0 "register_operand" "") ! (ashift:SI (match_operand:HI 1 "register_operand" "") ! (const_int 16))) ! (set (match_dup 0) ! (ashiftrt:SI (match_dup 0) (const_int 16)))] ! "" ! " ! if (GET_CODE (operands[1]) == SUBREG) ! operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! SUBREG_WORD (operands[1])); ! else ! operands[1] = gen_rtx(SUBREG, SImode, operands[1], 0); ! ") (define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (float_truncate:SF ! (match_operand:DF 1 "register_operand" "f")))] "" "* --- 465,480 ---- (define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (float:DF (match_operand:SI 1 "register_operand" "r")))] "" "* return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands)); ") ! ;; Truncation insns (define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") ! (float_truncate:SF ! (match_operand:DF 1 "register_operand" "f")))] "" "* *************** *** 524,544 **** (define_expand "zero_extendhisi2" ! [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:HI 1 "register_operand" "") (const_int 16))) ! (set (match_dup 0) ! (lshiftrt:SI (match_dup 0) (const_int 16)))] "" " ! if (GET_CODE (operands[1]) == SUBREG) ! operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! SUBREG_WORD (operands[1])); ! else ! operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); ! ") (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") ! (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" --- 485,502 ---- (define_expand "zero_extendhisi2" ! [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "register_operand" "") (const_int 16))) ! (set (match_operand:SI 0 "register_operand" "") ! (lshiftrt:SI (match_dup 2) ! (const_int 16)))] "" " ! { operands[1] = gen_lowpart (SImode, operands[1]); ! operands[2] = gen_reg_rtx (SImode); }") (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") ! (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" *************** *** 549,553 **** (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] "" --- 507,511 ---- (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] "" *************** *** 562,614 **** ") - ;; Note that the ones starting from HImode come before those for QImode so - ;; that a constant operand will match HImode, not QImode. - (define_expand "extendhisi2" ! [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:HI 1 "register_operand" "") (const_int 16))) ! (set (match_dup 0) ! (ashiftrt:SI (match_dup 0) (const_int 16)))] "" " ! if (GET_CODE (operands[1]) == SUBREG) ! operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! SUBREG_WORD (operands[1])); ! else ! operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); ! ") ! ! ;; XXX Is this ever used? ! (define_insn "extendqihi2" ! [(set (match_operand:HI 0 "register_operand" "=r") ! (sign_extend:SI ! (match_operand:QI 1 "register_operand" "r")))] "" ! "* ! arm_output_asm_insn (\"mov\\t%0, %1, lsl#24\\t@ extendqihi\", operands); ! return (arm_output_asm_insn (\"mov\\t%0, %0, asr#24\", operands)); ! ") ! (define_expand "extendqisi2" ! [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:QI 1 "register_operand" "") (const_int 24))) ! (set (match_dup 0) ! (ashiftrt:SI (match_dup 0) (const_int 24)))] "" " ! if (GET_CODE (operands[1]) == SUBREG) ! operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! SUBREG_WORD(operands[1])); ! else ! operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); ! ") (define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "" "* --- 520,563 ---- ") (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); }") ! (define_expand "extendqihi2" ! [(set (match_dup 2) ! (ashift:SI (match_operand:QI 1 "register_operand" "") ! (const_int 24))) ! (set (match_operand:HI 0 "register_operand" "") ! (ashiftrt:SI (match_dup 2) ! (const_int 24)))] "" ! " ! { operands[0] = gen_lowpart (SImode, operands[0]); ! operands[1] = gen_lowpart (SImode, operands[1]); ! operands[2] = gen_reg_rtx (SImode); }") (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); }") (define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") ! (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "" "* *************** *** 678,682 **** (define_insn "movdi" [(set (match_operand:DI 0 "di_operand" "=r,r,r,o,r") ! (match_operand:DI 1 "di_operand" "r,n,o,r,F"))] "" "* --- 627,631 ---- (define_insn "movdi" [(set (match_operand:DI 0 "di_operand" "=r,r,r,o,r") ! (match_operand:DI 1 "di_operand" "r,n,o,r,F"))] "" "* *************** *** 686,690 **** (define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=r,r,r,m") ! (match_operand:SI 1 "general_operand" "r,n,m,r"))] "" "* --- 635,639 ---- (define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=r,r,r,m") ! (match_operand:SI 1 "general_operand" "r,n,m,r"))] "" "* *************** *** 697,704 **** case 2: if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF ! && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))) return (arm_output_llc (operands)); else ! return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands)); case 3: return (arm_output_asm_insn (\"str\\t%1, %0\", operands)); --- 646,653 ---- case 2: if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF ! && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))) return (arm_output_llc (operands)); else ! return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands)); case 3: return (arm_output_asm_insn (\"str\\t%1, %0\", operands)); *************** *** 738,815 **** (define_expand "restorehi" ! [(set (mem:QI (match_operand:SI 1 "address_operand" "")) ! (truncate:QI (match_operand:HI 0 "register_operand" ""))) ! (set (reg:HI 10) ! (ashiftrt:HI (match_dup 0) (const_int 8))) (set (mem:QI (plus:SI (match_dup 1) (const_int 1))) ! (truncate:QI (reg:HI 10)))] ! "" "") ;; Subroutine to store a half word from a register into memory. ;; Operand 0 is the source register (HImode) ! ;; Operand 1 is the destination address (SImode) ! ;; Operand 2 is a temporary (SImode). ! ;; Operand 3 is a temporary (SImode). ! ;; Operand 4 is a temporary (SImode). ! ;; Operand 5 is a local temporary (SImode). (define_expand "storehi" ! [;; compute the address into a register ! (set (match_operand:SI 2 "register_operand" "") ! (match_operand:SI 1 "address_operand" "")) ! ;; get the half word into a full word register ! (set (match_operand:SI 3 "register_operand" "") ! (match_dup 5)) ! ;; store the low byte ! (set (mem:QI (match_dup 2)) ! (truncate:QI (match_dup 3))) ;; extract the high byte ! (set (match_operand:SI 4 "register_operand" "") ! (ashiftrt:SI (match_dup 3) (const_int 8))) ;; store the high byte ! (set (mem:QI (plus (match_dup 2) (const_int 1))) ! (truncate:QI (match_dup 4)))] "" " ! if (GET_CODE(operands[0]) == SUBREG) ! operands[5] = gen_rtx(SUBREG, SImode, SUBREG_REG(operands[0]), ! SUBREG_WORD(operands[0])); ! else ! operands[5] = gen_rtx(SUBREG, SImode, operands[0], 0); ! ! ") ;; Subroutine to store a half word integer constant into memory. ;; Operand 0 is the constant ! ;; Operand 1 is the destination address (SImode) ! ;; Operand 2 is a temporary (SImode). ! ;; Operand 3 is a temporary (QImode). ! ;; Operand 4 is a temporary (QImode). ! ;; Operand 5 is a local CONST_INT. ! ;; Operand 6 is a local CONST_INT. (define_expand "storeinthi" ! [;; compute the address into a register ! (set (match_operand:SI 2 "register_operand" "") ! (match_operand:SI 1 "address_operand" "")) ! ;; load the low byte ! (set (match_operand:QI 3 "register_operand" "") ! (match_dup 5)) ! ;; store the low byte ! (set (mem:QI (match_dup 2)) ! (match_dup 3)) ! ;; load the high byte ! (set (match_operand:QI 4 "register_operand" "") ! (match_dup 6)) ;; store the high byte ! (set (mem:QI (plus (match_dup 2) (const_int 1))) ! (match_dup 4))] "" " { ! int value = INTVAL(operands[0]); ! operands[5] = gen_rtx(CONST_INT, VOIDmode, value & 255); ! operands[6] = gen_rtx(CONST_INT, VOIDmode,(value>>8) & 255); } ") --- 687,739 ---- (define_expand "restorehi" ! [(set (mem:QI (match_operand 1 "" "")) ! (match_dup 2)) ! (set (reg:SI 10) ! (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) (set (mem:QI (plus:SI (match_dup 1) (const_int 1))) ! (reg:QI 10))] ! "" ! " ! { ! operands[2] = gen_lowpart (QImode, operands[0]); ! operands[0] = gen_lowpart (SImode, operands[0]); ! }") ;; Subroutine to store a half word from a register into memory. ;; Operand 0 is the source register (HImode) ! ;; Operand 1 is the destination address in a register (SImode) (define_expand "storehi" ! [;; store the low byte ! (set (mem:QI (match_operand 1 "" "")) (match_dup 3)) ;; extract the high byte ! (set (match_dup 2) ! (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) ;; store the high byte ! (set (mem:QI (plus (match_dup 1) (const_int 1))) ! (subreg:QI (match_dup 2) 0))] ;explicit subreg safe "" " ! { operands[3] = gen_lowpart (QImode, operands[0]); ! operands[0] = gen_lowpart (SImode, operands[0]); ! operands[2] = gen_reg_rtx (SImode); }") ;; Subroutine to store a half word integer constant into memory. ;; Operand 0 is the constant ! ;; Operand 1 is the destination address in a register (SImode) (define_expand "storeinthi" ! [;; store the low byte ! (set (mem:QI (match_operand 1 "" "")) (match_operand 0 "" "")) ;; store the high byte ! (set (mem:QI (plus (match_dup 1) (const_int 1))) ! (match_dup 2))] "" " { ! int value = INTVAL (operands[0]); ! operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255)); ! operands[2] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255)); } ") *************** *** 817,821 **** (define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") ! (match_operand:HI 1 "general_operand" ""))] "" " --- 741,745 ---- (define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") ! (match_operand:HI 1 "general_operand" ""))] "" " *************** *** 834,853 **** if (GET_CODE (operands[0]) == MEM) { - if (GET_CODE (operands[1]) == MEM) - operands[1] = copy_to_reg (operands[1]); - if (GET_CODE (operands[1]) == CONST_INT) { ! insn = gen_storeinthi (operands[1], XEXP (operands[0], 0), ! gen_reg_rtx (SImode), ! gen_reg_rtx (QImode), ! gen_reg_rtx (QImode)); } else { ! insn = gen_storehi (operands[1], XEXP (operands[0], 0), ! gen_reg_rtx (SImode), ! gen_reg_rtx (SImode), ! gen_reg_rtx (SImode)); } } --- 758,770 ---- if (GET_CODE (operands[0]) == MEM) { if (GET_CODE (operands[1]) == CONST_INT) { ! insn = gen_storeinthi (operands[1], force_reg (SImode, XEXP (operands[0], 0))); } else { ! if (GET_CODE (operands[1]) == MEM) ! operands[1] = copy_to_reg (operands[1]); ! insn = gen_storehi (operands[1], force_reg (SImode, XEXP (operands[0], 0))); } } *************** *** 871,875 **** (define_insn "" [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") ! (match_operand:HI 1 "general_operand" "r,n,m,r"))] "" "* --- 788,792 ---- (define_insn "" [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") ! (match_operand:HI 1 "general_operand" "r,n,m,r"))] "" "* *************** *** 885,889 **** (define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=r,r,r,m") ! (match_operand:QI 1 "general_operand" "r,n,m,r"))] "" "* --- 802,806 ---- (define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=r,r,r,m") ! (match_operand:QI 1 "general_operand" "r,n,m,r"))] "" "* *************** *** 899,908 **** return (arm_output_asm_insn (\"strb\\t%1, %0\", operands)); } - ") (define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=f,f,m,f,r,r") ! (match_operand:SF 1 "general_operand" "fG,m,f,r,f,r"))] "" "* --- 816,824 ---- return (arm_output_asm_insn (\"strb\\t%1, %0\", operands)); } ") (define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=f,f,m,f,r,r") ! (match_operand:SF 1 "general_operand" "fG,m,f,r,f,r"))] "" "* *************** *** 928,932 **** (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=f,f,m,f,r,r") ! (match_operand:DF 1 "general_operand" "fG,m,f,r,f,r"))] "" "* --- 844,848 ---- (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=f,f,m,f,r,r") ! (match_operand:DF 1 "general_operand" "fG,m,f,r,f,r"))] "" "* *************** *** 946,950 **** (define_insn "cmpsi" [(set (cc0) ! (compare (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "arm_rhs_operand" "rI")))] "" --- 862,866 ---- (define_insn "cmpsi" [(set (cc0) ! (compare (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "arm_rhs_operand" "rI")))] "" *************** *** 962,967 **** (define_insn "" [(set (cc0) ! (compare (match_operand:SI 0 "register_operand" "r") ! (neg:SI (match_operand:SI 1 "arm_rhs_operand" "rI"))))] "" "* --- 878,883 ---- (define_insn "" [(set (cc0) ! (compare (match_operand:SI 0 "register_operand" "r") ! (neg:SI (match_operand:SI 1 "arm_rhs_operand" "rI"))))] "" "* *************** *** 971,975 **** (define_insn "cmpsf" [(set (cc0) ! (compare (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "fpu_rhs_operand" "fG")))] "" --- 887,891 ---- (define_insn "cmpsf" [(set (cc0) ! (compare (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "fpu_rhs_operand" "fG")))] "" *************** *** 980,984 **** (define_insn "cmpdf" [(set (cc0) ! (compare (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "fpu_rhs_operand" "fG")))] "" --- 896,900 ---- (define_insn "cmpdf" [(set (cc0) ! (compare (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "fpu_rhs_operand" "fG")))] "" *************** *** 991,997 **** (define_insn "beq" [(set (pc) ! (if_then_else (eq (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 907,913 ---- (define_insn "beq" [(set (pc) ! (if_then_else (eq (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1001,1007 **** (define_insn "bne" [(set (pc) ! (if_then_else (ne (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 917,923 ---- (define_insn "bne" [(set (pc) ! (if_then_else (ne (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1011,1017 **** (define_insn "bgt" [(set (pc) ! (if_then_else (gt (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 927,933 ---- (define_insn "bgt" [(set (pc) ! (if_then_else (gt (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1021,1027 **** (define_insn "ble" [(set (pc) ! (if_then_else (le (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 937,943 ---- (define_insn "ble" [(set (pc) ! (if_then_else (le (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1031,1037 **** (define_insn "bge" [(set (pc) ! (if_then_else (ge (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 947,953 ---- (define_insn "bge" [(set (pc) ! (if_then_else (ge (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1041,1047 **** (define_insn "blt" [(set (pc) ! (if_then_else (lt (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 957,963 ---- (define_insn "blt" [(set (pc) ! (if_then_else (lt (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1051,1057 **** (define_insn "bgtu" [(set (pc) ! (if_then_else (gtu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 967,973 ---- (define_insn "bgtu" [(set (pc) ! (if_then_else (gtu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1061,1067 **** (define_insn "bleu" [(set (pc) ! (if_then_else (leu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 977,983 ---- (define_insn "bleu" [(set (pc) ! (if_then_else (leu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1071,1077 **** (define_insn "bgeu" [(set (pc) ! (if_then_else (geu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 987,993 ---- (define_insn "bgeu" [(set (pc) ! (if_then_else (geu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1081,1087 **** (define_insn "bltu" [(set (pc) ! (if_then_else (ltu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* --- 997,1003 ---- (define_insn "bltu" [(set (pc) ! (if_then_else (ltu (cc0) (const_int 0)) ! (label_ref (match_operand 0 "" "")) ! (pc)))] "" "* *************** *** 1093,1099 **** (define_insn "" [(set (pc) ! (if_then_else (eq (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1009,1015 ---- (define_insn "" [(set (pc) ! (if_then_else (eq (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1103,1109 **** (define_insn "" [(set (pc) ! (if_then_else (ne (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1019,1025 ---- (define_insn "" [(set (pc) ! (if_then_else (ne (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1113,1119 **** (define_insn "" [(set (pc) ! (if_then_else (gt (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1029,1035 ---- (define_insn "" [(set (pc) ! (if_then_else (gt (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1123,1129 **** (define_insn "" [(set (pc) ! (if_then_else (le (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1039,1045 ---- (define_insn "" [(set (pc) ! (if_then_else (le (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1133,1139 **** (define_insn "" [(set (pc) ! (if_then_else (ge (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1049,1055 ---- (define_insn "" [(set (pc) ! (if_then_else (ge (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1143,1149 **** (define_insn "" [(set (pc) ! (if_then_else (lt (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1059,1065 ---- (define_insn "" [(set (pc) ! (if_then_else (lt (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1153,1159 **** (define_insn "" [(set (pc) ! (if_then_else (gtu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1069,1075 ---- (define_insn "" [(set (pc) ! (if_then_else (gtu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1163,1169 **** (define_insn "" [(set (pc) ! (if_then_else (leu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1079,1085 ---- (define_insn "" [(set (pc) ! (if_then_else (leu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1173,1179 **** (define_insn "" [(set (pc) ! (if_then_else (geu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1089,1095 ---- (define_insn "" [(set (pc) ! (if_then_else (geu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1183,1189 **** (define_insn "" [(set (pc) ! (if_then_else (ltu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* --- 1099,1105 ---- (define_insn "" [(set (pc) ! (if_then_else (ltu (cc0) (const_int 0)) ! (pc) ! (label_ref (match_operand 0 "" ""))))] "" "* *************** *** 1196,1200 **** (define_insn "jump" [(set (pc) ! (label_ref (match_operand 0 "" "")))] "" "* --- 1112,1116 ---- (define_insn "jump" [(set (pc) ! (label_ref (match_operand 0 "" "")))] "" "* *************** *** 1204,1208 **** (define_insn "call" [(call (match_operand 0 "memory_operand" "m") ! (match_operand 1 "general_operand" "g")) (clobber (reg:SI 14))] "" --- 1120,1124 ---- (define_insn "call" [(call (match_operand 0 "memory_operand" "m") ! (match_operand 1 "general_operand" "g")) (clobber (reg:SI 14))] "" *************** *** 1212,1218 **** (define_insn "call_value" ! [(set (match_operand 0 "" "rf") ! (call (match_operand 1 "memory_operand" "m") ! (match_operand 2 "general_operand" "g"))) (clobber (reg:SI 14))] "" --- 1128,1134 ---- (define_insn "call_value" ! [(set (match_operand 0 "" "=rf") ! (call (match_operand 1 "memory_operand" "m") ! (match_operand 2 "general_operand" "g"))) (clobber (reg:SI 14))] "" *************** *** 1226,1230 **** (define_insn "" [(call (mem:SI (match_operand:SI 0 "" "i")) ! (match_operand:SI 1 "general_operand" "g")) (clobber (reg:SI 14))] "GET_CODE (operands[0]) == SYMBOL_REF" --- 1142,1146 ---- (define_insn "" [(call (mem:SI (match_operand:SI 0 "" "i")) ! (match_operand:SI 1 "general_operand" "g")) (clobber (reg:SI 14))] "GET_CODE (operands[0]) == SYMBOL_REF" *************** *** 1235,1240 **** (define_insn "" [(set (match_operand 0 "register_operand" "=rf") ! (call (mem:SI (match_operand:SI 1 "" "i")) ! (match_operand:SI 2 "general_operand" "g"))) (clobber (reg:SI 14))] "GET_CODE(operands[1]) == SYMBOL_REF" --- 1151,1156 ---- (define_insn "" [(set (match_operand 0 "register_operand" "=rf") ! (call (mem:SI (match_operand:SI 1 "" "i")) ! (match_operand:SI 2 "general_operand" "g"))) (clobber (reg:SI 14))] "GET_CODE(operands[1]) == SYMBOL_REF" *************** *** 1245,1249 **** (define_insn "tablejump" [(set (pc) ! (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" --- 1161,1165 ---- (define_insn "tablejump" [(set (pc) ! (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" *************** *** 1254,1258 **** (define_insn "indirect_jump" [(set (pc) ! (match_operand:SI 0 "register_operand" "r"))] "" "* --- 1170,1174 ---- (define_insn "indirect_jump" [(set (pc) ! (match_operand:SI 0 "register_operand" "r"))] "" "* diff -rc2N gcc-2.2.2/config/att386.h gcc-2.3.1/config/att386.h *** gcc-2.2.2/config/att386.h Tue May 5 23:54:41 1992 --- gcc-2.3.1/config/att386.h Thu Jul 30 00:55:15 1992 *************** *** 67,70 **** --- 67,71 ---- #define ASM_NO_SKIP_IN_TEXT 1 + #undef BSS_SECTION_FUNCTION /* Override the definition from svr3.h. */ #define BSS_SECTION_FUNCTION \ void \ diff -rc2N gcc-2.2.2/config/bsd386.h gcc-2.3.1/config/bsd386.h *** gcc-2.2.2/config/bsd386.h Mon Dec 9 01:37:53 1991 --- gcc-2.3.1/config/bsd386.h Thu Oct 1 00:52:06 1992 *************** *** 98,103 **** /* This is how to output a reference to a user-level label named NAME. */ ! #define ASM_OUTPUT_LABELREF(FILE,NAME) \ ! fprintf (FILE, "_%s", NAME) /* Sequent has some changes in the format of DBX symbols. */ --- 98,106 ---- /* This is how to output a reference to a user-level label named NAME. */ ! #ifdef NO_UNDERSCORES ! #define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME) ! #else ! #define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "_%s", NAME) ! #endif /* not NO_UNDERSCORES */ /* Sequent has some changes in the format of DBX symbols. */ diff -rc2N gcc-2.2.2/config/convex.h gcc-2.3.1/config/convex.h *** gcc-2.2.2/config/convex.h Wed May 6 23:58:23 1992 --- gcc-2.3.1/config/convex.h Mon Oct 26 14:20:32 1992 *************** *** 70,74 **** #define TARGET_C34 (target_flags & 4) #define TARGET_C38 (target_flags & 010) ! #define TARGET_INDIRECTS (target_flags & 020) #define TARGET_ARGCOUNT (target_flags & 040) --- 70,74 ---- #define TARGET_C34 (target_flags & 4) #define TARGET_C38 (target_flags & 010) ! #define TARGET_INDIRECTS (1) #define TARGET_ARGCOUNT (target_flags & 040) *************** *** 86,90 **** { "c38", 012 }, \ { "noc1", -001 }, \ ! { "noc2", -022 }, \ { "argcount", 040 }, \ { "noargcount", -040 }, \ --- 86,90 ---- { "c38", 012 }, \ { "noc1", -001 }, \ ! { "noc2", -002 }, \ { "argcount", 040 }, \ { "noargcount", -040 }, \ *************** *** 400,404 **** args as part of the call template. We optionally omit the arg count word and let gcc combine the arg pops. */ ! #define RETURN_POPS_ARGS(FUNTYPE,SIZE) (TARGET_ARGCOUNT) /* Define how to find the value returned by a function. --- 400,404 ---- args as part of the call template. We optionally omit the arg count word and let gcc combine the arg pops. */ ! #define RETURN_POPS_ARGS(FUNTYPE, SIZE) (TARGET_ARGCOUNT ? (SIZE) : 0) /* Define how to find the value returned by a function. *************** *** 728,732 **** 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 --- 728,732 ---- 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 *************** *** 841,844 **** --- 841,850 ---- #define ASM_APP_OFF ";NO_APP\n" + + /* Output something following the gcc2_compiled tag to keep that label from + hiding a real function name for tools like adb and prof. */ + + #define ASM_IDENTIFY_GCC(FILE) \ + fprintf (FILE, "gcc2_compiled.:\n\tds.h 0\n"); /* Alignment with Convex's assembler goes like this: diff -rc2N gcc-2.2.2/config/convex.md gcc-2.3.1/config/convex.md *** gcc-2.2.2/config/convex.md Wed Feb 12 08:56:46 1992 --- gcc-2.3.1/config/convex.md Sun Oct 25 00:39:32 1992 *************** *** 295,299 **** (define_insn "movstrictsi" ! [(set (strict_low_part (match_operand:SI 0 "general_operand" "=g,r")) (match_operand:SI 1 "general_operand" "r,g"))] "" --- 295,299 ---- (define_insn "movstrictsi" ! [(set (strict_low_part (match_operand:SI 0 "general_operand" "+g,r")) (match_operand:SI 1 "general_operand" "r,g"))] "" *************** *** 715,719 **** (and:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "immediate_operand" "Fn")))] ! "GET_CODE (operands[2]) == CONST_INT || (GET_CODE (operands[2]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[2]) == -1)" --- 715,719 ---- (and:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "immediate_operand" "Fn")))] ! "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) || (GET_CODE (operands[2]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[2]) == -1)" *************** *** 754,758 **** (ior:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "immediate_operand" "Fn")))] ! "GET_CODE (operands[2]) == CONST_INT || (GET_CODE (operands[2]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[2]) == 0)" --- 754,758 ---- (ior:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "immediate_operand" "Fn")))] ! "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0) || (GET_CODE (operands[2]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[2]) == 0)" *************** *** 793,797 **** (xor:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "immediate_operand" "Fn")))] ! "GET_CODE (operands[2]) == CONST_INT || (GET_CODE (operands[2]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[2]) == 0)" --- 793,797 ---- (xor:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "immediate_operand" "Fn")))] ! "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0) || (GET_CODE (operands[2]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[2]) == 0)" *************** *** 1033,1039 **** { int rshift = INTVAL (operands[2]); ! operands[3] = ! force_reg (DImode, immed_double_const (1 << (63 - rshift), ! 1 << (31 - rshift), DImode)); } else --- 1033,1048 ---- { int rshift = INTVAL (operands[2]); ! if (rshift < 0) ! operands[3] = force_reg (DImode, immed_double_const (0, 0, DImode)); ! else if (rshift < 32) ! operands[3] = ! force_reg (DImode, ! immed_double_const (0, 1 << (31 - rshift), DImode)); ! else if (rshift < 64) ! operands[3] = ! force_reg (DImode, ! immed_double_const (1 << (63 - rshift), 0, DImode)); ! else ! operands[3] = force_reg (DImode, immed_double_const (0, 0, DImode)); } else *************** *** 1292,1296 **** (define_insn "call" [(call (match_operand:QI 0 "memory_operand" "m") ! (match_operand:SI 1 "general_operand" "g"))] "" "* return output_call (insn, operands[0], operands[1]);") --- 1301,1305 ---- (define_insn "call" [(call (match_operand:QI 0 "memory_operand" "m") ! (match_operand 1 "" "g"))] "" "* return output_call (insn, operands[0], operands[1]);") *************** *** 1299,1303 **** [(set (match_operand 0 "" "=g") (call (match_operand:QI 1 "memory_operand" "m") ! (match_operand:SI 2 "general_operand" "g")))] "" "* return output_call (insn, operands[1], operands[2]);") --- 1308,1312 ---- [(set (match_operand 0 "" "=g") (call (match_operand:QI 1 "memory_operand" "m") ! (match_operand 2 "" "g")))] "" "* return output_call (insn, operands[1], operands[2]);") diff -rc2N gcc-2.2.2/config/convex1.h gcc-2.3.1/config/convex1.h *** gcc-2.2.2/config/convex1.h Tue Dec 31 14:53:32 1991 --- gcc-2.3.1/config/convex1.h Tue Oct 13 21:17:52 1992 *************** *** 11,18 **** #define CPP_SPEC \ ! "%{mc2:-D__convex_c2__}%{!mc2:-D__convex_c1__}\ ! -D__NO_INLINE_MATH\ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long}\ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" --- 11,18 ---- #define CPP_SPEC \ ! "%{mc2:-D__convex_c2__}%{!mc2:-D__convex_c1__} \ ! -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" *************** *** 21,26 **** #define LIB_SPEC \ ! "%{mc2:-lC2}%{!mc2:-lC1}\ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" --- 21,26 ---- #define LIB_SPEC \ ! "%{mc2:-lC2}%{!mc2:-lC1} \ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}} \ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}} \ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" diff -rc2N gcc-2.2.2/config/convex2.h gcc-2.3.1/config/convex2.h *** gcc-2.2.2/config/convex2.h Tue Dec 31 14:53:29 1991 --- gcc-2.3.1/config/convex2.h Tue Oct 13 21:17:52 1992 *************** *** 11,18 **** #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__}\ ! -D__NO_INLINE_MATH\ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long}\ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" --- 11,18 ---- #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__} \ ! -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" *************** *** 21,26 **** #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2}\ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" --- 21,26 ---- #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2} \ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}} \ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}} \ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" diff -rc2N gcc-2.2.2/config/convex32.h gcc-2.3.1/config/convex32.h *** gcc-2.2.2/config/convex32.h Tue Dec 31 14:53:26 1991 --- gcc-2.3.1/config/convex32.h Tue Oct 13 21:17:53 1992 *************** *** 11,18 **** #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__}\ ! -D__NO_INLINE_MATH\ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long}\ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" --- 11,18 ---- #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__} \ ! -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" *************** *** 21,26 **** #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2}\ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" --- 21,26 ---- #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2} \ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}} \ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}} \ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" diff -rc2N gcc-2.2.2/config/convex34.h gcc-2.3.1/config/convex34.h *** gcc-2.2.2/config/convex34.h Tue Dec 31 14:53:23 1991 --- gcc-2.3.1/config/convex34.h Tue Oct 13 21:17:53 1992 *************** *** 11,18 **** #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__}\ ! -D__NO_INLINE_MATH\ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long}\ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" --- 11,18 ---- #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__} \ ! -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" *************** *** 21,26 **** #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2}\ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" --- 21,26 ---- #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2} \ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}} \ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}} \ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" diff -rc2N gcc-2.2.2/config/convex38.h gcc-2.3.1/config/convex38.h *** gcc-2.2.2/config/convex38.h Tue Dec 31 14:53:17 1991 --- gcc-2.3.1/config/convex38.h Tue Oct 13 21:17:53 1992 *************** *** 11,18 **** #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__}\ ! -D__NO_INLINE_MATH\ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long}\ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" --- 11,18 ---- #define CPP_SPEC \ ! "%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__} \ ! -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ %{!traditional:-D__stdc__ \ ! -D_LONGLONG -Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ %{!ansi:-D_POSIX_SOURCE -D_CONVEX_SOURCE}" *************** *** 21,26 **** #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2}\ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" --- 21,26 ---- #define LIB_SPEC \ ! "%{mc1:-lC1}%{!mc1:-lC2} \ ! %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}} \ ! %{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}} \ ! %{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}" diff -rc2N gcc-2.2.2/config/dec-gosf1.h gcc-2.3.1/config/dec-gosf1.h *** gcc-2.2.2/config/dec-gosf1.h --- gcc-2.3.1/config/dec-gosf1.h Fri Sep 11 13:29:29 1992 *************** *** 0 **** --- 1,24 ---- + /* Definitions of target machine for GNU compiler. + DECstation (OSF/1) version with stabs. + Copyright (C) 1992 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. */ + + /* Use stabs instead of ECOFF debug format. */ + #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + + #include "dec-osf1.h" diff -rc2N gcc-2.2.2/config/dec-osf1.h gcc-2.3.1/config/dec-osf1.h *** gcc-2.2.2/config/dec-osf1.h Thu Jun 11 00:54:12 1992 --- gcc-2.3.1/config/dec-osf1.h Wed Oct 7 09:49:14 1992 *************** *** 18,22 **** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - #define DECSTATION #define DEC_OSF1 --- 18,21 ---- *************** *** 24,26 **** --- 23,50 ---- -DMIPSEL -DR3000 -DSYSTYPE_BSD -D_SYSTYPE_BSD -Dbsd4_2 -Dhost_mips -Dmips -Dosf -Dunix" + #define LINK_SPEC "\ + %{G*} \ + %{!mgas: \ + %{EL} %{!EL: -EL} \ + %{EB: %e-EB not supported} \ + %{mips1} %{mips2} %{mips3} %{bestGnum} \ + %{shared} %{non_shared} %{!shared: %{!non_shared: -non_shared}}}" + #include "decstatn.h" + + /* Specify size_t, ptrdiff_t, and wchar_t types. */ + #undef SIZE_TYPE + #undef PTRDIFF_TYPE + #undef WCHAR_TYPE + #undef WCHAR_TYPE_SIZE + + #define SIZE_TYPE "long unsigned int" + #define PTRDIFF_TYPE "int" + #define WCHAR_TYPE "short unsigned int" + #define WCHAR_TYPE_SIZE SHORT_TYPE_SIZE + + /* turn off collect2 COFF support, since ldfcn now has elf declaration */ + #undef OBJECT_FORMAT_COFF + + #undef MACHINE_TYPE + #define MACHINE_TYPE "DECstation running DEC OSF/1" diff -rc2N gcc-2.2.2/config/decrose.h gcc-2.3.1/config/decrose.h *** gcc-2.2.2/config/decrose.h Thu Jun 11 00:54:42 1992 --- gcc-2.3.1/config/decrose.h Thu Oct 29 15:01:31 1992 *************** *** 1,4 **** ! /* Definitions of target machine for GNU compiler. DECstation (OSF/1 with OSF/rose) version. ! Copyright (C) 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,5 ---- ! /* Definitions of target machine for GNU compiler. ! DECstation (OSF/1 reference port with OSF/rose) version. ! Copyright (C) 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 26,29 **** --- 27,36 ---- #include "halfpic.h" + #define WORD_SWITCH_TAKES_ARG(STR) \ + (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ + || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ + || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ + || !strcmp (STR, "pic-names")) + #define CPP_PREDEFINES "-DOSF -DOSF1 -Dbsd4_2 -DMIPSEL -Dhost_mips -Dmips -Dunix -DR3000 -DSYSTYPE_BSD" *************** *** 41,44 **** --- 48,52 ---- %{G*}" + #ifndef CROSS_COMPILE #define ASM_FINAL_SPEC "\ %{mmips-as: %{!mno-mips-tfile: \ *************** *** 46,51 **** %{K: -I %b.o~} \ %{!K: %{save-temps: -I %b.o~}} \ ! %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %b.o} \ %{.s:%i} %{!.s:%g.s}}}" #define CPP_SPEC "\ --- 54,69 ---- %{K: -I %b.o~} \ %{!K: %{save-temps: -I %b.o~}} \ ! %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ ! %{.s:%i} %{!.s:%g.s}}}" ! ! #else /* CROSS_COMPILE */ ! #define ASM_FINAL_SPEC "\ ! %{mmips-as: %{mmips-tfile: \ ! \n mips-tfile %{v*: -v} %{d*} \ ! %{K: -I %b.o~} \ ! %{!K: %{save-temps: -I %b.o~}} \ ! %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ %{.s:%i} %{!.s:%g.s}}}" + #endif #define CPP_SPEC "\ *************** *** 74,78 **** #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}" ! #define MACHINE_TYPE "DECstation running OSF/1 with OSF/rose objects" #ifndef MD_EXEC_PREFIX --- 92,96 ---- #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}" ! #define MACHINE_TYPE "DECstation with OSF/rose objects" #ifndef MD_EXEC_PREFIX *************** *** 83,86 **** --- 101,116 ---- #define MD_STARTFILE_PREFIX "/usr/ccs/lib/" #endif + + /* Turn on -mpic-extern by default. */ + #define CC1_SPEC "\ + %{O*: %{!mno-gpOPT:%{!mno-gpopt: -mgpopt}}} \ + %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \ + %{G*} \ + %{pic-none: -mno-half-pic} \ + %{pic-lib: -mhalf-pic} \ + %{pic-extern: -mhalf-pic} \ + %{pic-calls: -mhalf-pic} \ + %{pic-names*: -mhalf-pic} \ + %{!pic-*: -mhalf-pic}" /* Specify size_t, ptrdiff_t, and wchar_t types. */ diff -rc2N gcc-2.2.2/config/decstatn.h gcc-2.3.1/config/decstatn.h *** gcc-2.2.2/config/decstatn.h Thu Jun 11 00:55:09 1992 --- gcc-2.3.1/config/decstatn.h Sat Oct 17 19:27:33 1992 *************** *** 25,28 **** --- 25,29 ---- #endif + #ifndef ASM_SPEC #define ASM_SPEC "\ %{!mgas: \ *************** *** 35,39 **** --- 36,42 ---- %{g} %{g0} %{g1} %{g2} %{g3} %{v} %{K}} \ %{G*}" + #endif + #ifndef CPP_SPEC #define CPP_SPEC "\ %{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ *************** *** 43,47 **** --- 46,52 ---- %{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \ %{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" + #endif + #ifndef LINK_SPEC #define LINK_SPEC "\ %{G*} \ *************** *** 51,63 **** --- 56,77 ---- %{mips1} %{mips2} %{mips3} \ %{bestGnum}}" + #endif + #ifndef LIB_SPEC #define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} -lc" + #endif + #ifndef STARTFILE_SPEC #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}" + #endif /* For compatibility with types.h. */ + #ifndef SIZE_TYPE #define SIZE_TYPE "unsigned int" + #endif + #ifndef MACHINE_TYPE #define MACHINE_TYPE "DECstation running ultrix" + #endif /* Use atexit for static constructors/destructors, instead of defining diff -rc2N gcc-2.2.2/config/dpx2.h gcc-2.3.1/config/dpx2.h *** gcc-2.2.2/config/dpx2.h Sat Jun 13 17:23:06 1992 --- gcc-2.3.1/config/dpx2.h Thu Jul 30 00:55:38 1992 *************** *** 1,6 **** /* * dpx2.h - Bull DPX/2 200 and 300 systems (m68k, SysVr3) - * - * $Id: dpx2.h,v 1.3 1992/05/21 08:04:22 rms Exp $ */ --- 1,4 ---- *************** *** 10,14 **** /* See m68k.h. 7 means 68020 with 68881. ! * We really have 68030, but this will get us going. */ #ifndef TARGET_DEFAULT --- 8,13 ---- /* See m68k.h. 7 means 68020 with 68881. ! * We really have 68030 and 68882, ! * but this will get us going. */ #ifndef TARGET_DEFAULT *************** *** 40,45 **** --- 39,55 ---- * no -ansi implies _SYSV */ + /* + * you can't get a DPX/2 without a 68882 but allow it + * to be ignored... + */ + #if 0 # define CPP_SPEC "%{ansi:-D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BULL_SOURCE}\ %{!ansi:-D_SYSV}" + #else + # define __HAVE_68881__ 1 + # define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ }\ + %{ansi:-D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BULL_SOURCE}\ + %{!ansi:-D_SYSV}" + #endif #undef ASM_LONG *************** *** 49,62 **** #undef DO_GLOBAL_CTORS_BODY /* don't use svr3.h version */ #undef DO_GLOBAL_DTORS_BODY - - #if 0 /* def DEBUG */ - /* - * find out where cc1 aborts - */ - #define abort() do { fprintf(stderr, "%s: aborting at line %d\n", \ - __FILE__, __LINE__); \ - kill(getpid(), 6); } while (0) - #endif /* * svr3.h says to use BSS_SECTION_FUNCTION --- 59,64 ---- #undef DO_GLOBAL_CTORS_BODY /* don't use svr3.h version */ #undef DO_GLOBAL_DTORS_BODY + #if 0 /* Should be no need now that svr3.h defines BSS_SECTION_FUNCTION. */ /* * svr3.h says to use BSS_SECTION_FUNCTION *************** *** 71,74 **** --- 73,77 ---- FINI_SECTION_FUNCTION #endif + #endif /* 0 */ #ifndef USE_GAS diff -rc2N gcc-2.2.2/config/dpx2.ifile gcc-2.3.1/config/dpx2.ifile *** gcc-2.2.2/config/dpx2.ifile --- gcc-2.3.1/config/dpx2.ifile Wed Sep 30 18:42:04 1992 *************** *** 0 **** --- 1,55 ---- + /* + * dpx2.ifile - for collectless G++ on Bull DPX/2 + * + * Peter Schauer + * + * Install this file as $prefix/gcc-lib/dpx2/VERSION/gcc.ifile + * and comment out the lines refering to COLLECT at the top + * of Makefile before building GCC. + * + * This file has been tested with gcc-2.2.2 on a DPX/2 340 + * running BOS 2.00.45, if it doesn't work for you, stick + * with collect. + * --sjg + */ + /* + * Ifile to link with memory configured at 0. + * BLOCK to an offset that leaves room for many headers ( the value + * here allows for a file header, an outheader, and up to 11 section + * headers on most systems. + * BIND to an address that excludes page 0 from being mapped. The value + * used for BLOCK should be or'd into this value. Here I'm setting BLOCK + * to 0x200 and BIND to ( 0x100000 | value_used_for(BLOCK) ) + * If you are using shared libraries, watch that you don't overlap the + * address ranges assigned for shared libs. + * + * GROUP BIND to a location in the next segment. Here, the only value + * that you should change (I think) is that within NEXT, which I've set + * to my hardware segment size. You can always use a larger size, but not + * a smaller one. + */ + SECTIONS + { + .text BIND(0x100200) BLOCK (0x200) : + { + /* plenty of room for headers */ + *(.init) + *(.text) + _vfork = _fork; /* I got tired of editing peoples sloppy code */ + *(.fini) + } + GROUP BIND( NEXT(0x100000) + (ADDR(.text) + (SIZEOF(.text)) % 0x1000)): + { + .data : { + ___CTOR_LIST__ = . ; + . += 4 ; /* leading NULL */ + *(.ctor) + . += 4 ; /* trailing NULL */ + ___DTOR_LIST__ = . ; + . += 4 ; /* leading NULL */ + *(.dtor) + . += 4 ; /* trailing NULL */ + } + .bss : { } + } + } diff -rc2N gcc-2.2.2/config/dpx2g.h gcc-2.3.1/config/dpx2g.h *** gcc-2.2.2/config/dpx2g.h Sat Jun 13 17:23:26 1992 --- gcc-2.3.1/config/dpx2g.h Wed Sep 30 18:42:08 1992 *************** *** 1,6 **** /* * dpx2g.h - Bull DPX/2 200 and 300 systems (m68k, SysVr3) with gas - * - * $Id: dpx2g.h,v 1.1 1992/03/27 21:26:48 rms Exp $ */ --- 1,4 ---- *************** *** 8,12 **** --- 6,48 ---- #include "dpx2.h" + #ifndef USE_COLLECT2 + /* We use set vectors for the constructors/destructors. */ + #undef ASM_OUTPUT_CONSTRUCTOR + #undef ASM_OUTPUT_DESTRUCTOR + + /* Although the gas we use can create .ctor and .dtor sections from N_SETT + stabs, it does not support section directives, so we need to have the loader + define the lists. + */ + #define CTOR_LISTS_DEFINED_EXTERNALLY + + /* similar to default, but allows for the table defined by ld with gcc.ifile. + nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0. + The old check is left in so that the same macro can be used if and when + a future version of gas does support section directives. */ + + #define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \ + if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \ + for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); \ + for (i = nptrs; i >= 1; i--) \ + __DTOR_LIST__[i] (); } + + #undef STARTFILE_SPEC + #define STARTFILE_SPEC \ + "%{!r:gcc.ifile%s}\ + %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}\ + huge.o%s" + + #else /* !USE_COLLECT2 */ + + #undef STARTFILE_SPEC + #define STARTFILE_SPEC \ + "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}\ + huge.o%s" + + #endif /* !USE_COLLECT2 */ + + /* GAS want's DBX debugging information. */ #undef SDB_DEBUGGING_INFO *************** *** 20,23 **** --- 56,63 ---- #undef EXTRA_SECTION_FUNCTIONS #undef EXTRA_SECTIONS + /* Gas understands dollars in labels. */ + #undef NO_DOLLAR_IN_LABEL + /* GAS does not understand .ident so don't output anything for #ident. */ + #undef ASM_OUTPUT_IDENT /* diff -rc2N gcc-2.2.2/config/elxsi.c gcc-2.3.1/config/elxsi.c *** gcc-2.2.2/config/elxsi.c --- gcc-2.3.1/config/elxsi.c Thu Oct 15 16:58:12 1992 *************** *** 0 **** --- 1,125 ---- + /* Subroutines for insn-output.c for GNU compiler. Elxsi version. + Copyright (C) 1987, 1992 Free Software Foundation, Inc + This port, done by Mike Stump in 1988, and is the first + 64 bit port of GNU CC. + Based upon the VAX port. + + 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 1, 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 + #include "rtl.h" + + extern char *reg_names[]; + rtx cmp_op0=0, cmp_op1=0; + + /* table of relations for compares and branches */ + char *cmp_tab[] = { + "gt", "gt", "eq", "eq", "ge", "ge", "lt", "lt", "ne", "ne", + "le", "le" }; + + /* type is the index into the above table */ + /* s is "" for signed, or "u" for unsigned */ + char *cmp_jmp(s, type, where) char *s; rtx where; { + rtx br_ops[3]; + char template[50]; + char *f = ""; + char *bits = "64"; + if (GET_MODE (cmp_op0) == SFmode) f = "f", bits = "32"; + if (GET_MODE (cmp_op0) == DFmode) f = "f"; + br_ops[0] = where; + br_ops[1] = cmp_op0; + br_ops[2] = cmp_op1; + if (cmp_op1) + sprintf(template, "%scmp%s.br.%s\t%%1,%%2:j%s\t%%l0", + f, s, bits, cmp_tab[type]); + else if (*f) + sprintf(template, "fcmp.br.%s\t%%1,=0:j%s\t%%l0", + bits, cmp_tab[type]); + else if (*s) /* can turn the below in to a jmp ... */ + sprintf(template, "cmpu.br.64\t%%1,=0:j%s\t%%l0", s, cmp_tab[type]); + else + sprintf(template, "jmp.%s\t%%1,%%l0", cmp_tab[type+1]); + output_asm_insn(template, br_ops); + return ""; + } + + char *cmp_set(s, type, reg) char *s, *type; rtx reg; { + rtx br_ops[3]; + char template[50]; + char *f = ""; + char *bits = "64"; + if (GET_MODE (cmp_op0) == SFmode) f = "f", bits = "32"; + else if (GET_MODE (cmp_op0) == DFmode) f = "f"; + else if (GET_MODE (cmp_op0) == SImode) bits = "32"; + else if (GET_MODE (cmp_op0) == HImode) bits = "16"; + else if (GET_MODE (cmp_op0) == QImode) bits = "8"; + br_ops[0] = reg; + br_ops[1] = cmp_op0; + br_ops[2] = cmp_op1; + if (cmp_op1) + sprintf(template, "%scmp%s.%s\t%%0,%%1,%%2:%s", + f, s, bits, type); + else + sprintf(template, "%scmp%s.%s\t%%0,%%1,=0:%s", + f, s, bits, type); + output_asm_insn(template, br_ops); + return ""; + } + + print_operand_address (file, addr) + FILE *file; + register rtx addr; + { + register rtx reg1, reg2, breg, ireg; + rtx offset; + + retry: + switch (GET_CODE (addr)) + { + + case MEM: + if (GET_CODE (XEXP (addr, 0)) == REG) + fprintf (file, "%s", reg_names[REGNO (addr)]); + else abort(); + break; + + case REG: + fprintf (file, "[%s]", reg_names[REGNO (addr)]); + break; + + case PLUS: + reg1 = 0; reg2 = 0; + ireg = 0; breg = 0; + offset = 0; + if (GET_CODE (XEXP (addr, 0)) == REG) + { + offset = XEXP (addr, 1); + addr = XEXP (addr, 0); + } + else if (GET_CODE (XEXP (addr, 1)) == REG) + { + offset = XEXP (addr, 0); + addr = XEXP (addr, 1); + } + fprintf (file, "[%s]", reg_names[REGNO (addr)]); + output_address (offset); + break; + + default: + output_addr_const (file, addr); + } + } diff -rc2N gcc-2.2.2/config/elxsi.h gcc-2.3.1/config/elxsi.h *** gcc-2.2.2/config/elxsi.h --- gcc-2.3.1/config/elxsi.h Thu Oct 15 16:58:05 1992 *************** *** 0 **** --- 1,976 ---- + /* Definitions of target machine for GNU compiler. Elxsi version. + Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. + This port, done by Mike Stump in 1988, and is the first + 64 bit port of GNU CC. + Based upon the VAX port. + + 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 1, 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. */ + + + /* Names to predefine in the preprocessor for this target machine. */ + + #define CPP_PREDEFINES "-Delxsi -Dunix" + + /* Print subsidiary information on the compiler version in use. */ + + #define TARGET_VERSION fprintf (stderr, " (elxsi)"); + + /* Run-time compilation parameters selecting different hardware subsets. */ + + extern int target_flags; + + /* Macros used in the machine description to test the flags. */ + + /* Nonzero if compiling code that Unix assembler can assemble. */ + #define TARGET_UNIX_ASM (target_flags & 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 \ + { {"unix", 1}, \ + {"embos", -1}, \ + { "", TARGET_DEFAULT}} + + /* Default target_flags if no switches specified. */ + + #ifndef TARGET_DEFAULT + #define TARGET_DEFAULT 1 + #endif + + /* 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 vax. */ + /* #define BITS_BIG_ENDIAN */ + + /* 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 numbered. */ + #define WORDS_BIG_ENDIAN 1 + + /* Number of bits in an addressible 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 64 + #define Rmode DImode + + #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 + + /* Width of a word, in units (bytes). */ + #define UNITS_PER_WORD 8 + + /* 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 + + /* Allocation boundary (in *bits*) for the code of a function. */ + #define FUNCTION_BOUNDARY 8 + + /* Alignment of field after `int : 0' in a structure. */ + #define EMPTY_FIELD_BOUNDARY 8 + + /* Every structure's size must be a multiple of this. */ + #define STRUCTURE_SIZE_BOUNDARY 32 + + /* 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 + + /* Define this if move instructions will actually fail to work + when given unaligned data. */ + #define STRICT_ALIGNMENT 0 + + /* 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 16 + + /* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + On the elxsi, these is the .r15 (aka .sp). */ + #define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + + /* 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. + On the vax, all registers are one word long. */ + #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) 1 + + /* 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) 1 + + /* 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 15 + + /* Base register for access to local variables of the function. */ + #define FRAME_POINTER_REGNUM 14 + + /* 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 + + #define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ + { int regno; \ + int offset = 0; \ + for( regno=0; regno < FIRST_PSEUDO_REGISTER; regno++ ) \ + if( regs_ever_live[regno] && !call_used_regs[regno] ) \ + offset += 8; \ + (DEPTH) = (offset + ((get_frame_size() + 3) & ~3) ); \ + (DEPTH) = 0; \ + } + + /* Base register for access to arguments of the function. */ + #define ARG_POINTER_REGNUM 14 + + /* Register in which static-chain is passed to a function. */ + #define STATIC_CHAIN_REGNUM 0 + + /* 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. */ + + /* The vax has only one kind of registers, so NO_REGS and ALL_REGS + are the only classes. */ + + 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" } + + /* 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, 0x07fff, 0xffff} + + /* 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 == 15 ? ALL_REGS : GENERAL_REGS) + + /* 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 + + /* 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' ? (VALUE) >=-16 && (VALUE) <=15 : 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) (CLASS) + + /* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ + /* On the vax, this is always the size of MODE in words, + since all registers are the same size. */ + #define CLASS_MAX_NREGS(CLASS, MODE) \ + ((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 -4 + + /* Offset of first parameter from the argument pointer register value. */ + #define FIRST_PARM_OFFSET(FNDECL) 4 + + /* Value is 1 if returning from a function call automatically + pops the arguments described by the number-of-args field in the call. + 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. + + On the Vax, the RET insn always pops all the args for any function. */ + + #define RETURN_POPS_ARGS(FUNTYPE,SIZE) (SIZE) + + /* 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. */ + + /* On the Vax the return value is in R0 regardless. */ + + #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. */ + + /* On the Vax the return value is in R0 regardless. */ + + #define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + + /* Define this if PCC uses the nonreentrant convention for returning + structure and union values. */ + + #define PCC_STATIC_STRUCT_RETURN + + /* 1 if N is a possible register number for a function value. + On the Vax, R0 is the only register thus used. */ + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + + /* 1 if N is a possible register number for function argument passing. + On the Vax, 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. + + On the vax, this is a single integer, which is a number of bytes + of arguments scanned so far. */ + + #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. + + On the vax, the offset starts at 0. */ + + #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,x) \ + ((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) != 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 vax all args are pushed. */ + + #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 + + /* 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) \ + { register int regno; \ + register int cnt = 0; \ + extern char call_used_regs[]; \ + /* the below two lines are a HACK, and should be deleted, but \ + for now are very much needed (1.35) */ \ + if (frame_pointer_needed) \ + regs_ever_live[14]=1, call_used_regs[14]=0; \ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + cnt+=8; \ + if ((SIZE)+cnt) \ + fprintf (FILE, "\tadd.64\t.sp,=%d\n", -(SIZE)-cnt); \ + cnt = 0; \ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + fprintf (FILE, "\tst.64\t.r%d,[.sp]%d\n", regno, (cnt+=8)-12); \ + if (frame_pointer_needed) \ + fprintf (FILE, "\tadd.64\t.r14,.sp,=%d\n", (SIZE)+cnt); \ + } + + /* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + + #define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "\tld.64\t.r0,.LP%d\n\tcall\tmcount\n", (LABELNO)); + + /* 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. */ + + #define FUNCTION_EPILOGUE(FILE, SIZE) \ + { register int regno; \ + register int cnt = 0; \ + extern char call_used_regs[]; \ + extern int current_function_calls_alloca; \ + /* this conditional is ONLY here because there is a BUG; \ + EXIT_IGNORE_STACK is ignored itself when the first part of \ + the condition is true! (atleast in version 1.35) */ \ + /* the 8*10 is for 64 bits of .r5 - .r14 */ \ + if (current_function_calls_alloca || (SIZE)>=(256-8*10)) { \ + /* use .r4 as a temporary! Ok for now.... */ \ + fprintf (FILE, "\tld.64\t.r4,.r14\n"); \ + for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + cnt+=8; \ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + fprintf (FILE, "\tld.64\t.r%d,[.r14]%d\n", regno, \ + -((cnt-=8) + 8)-4-(SIZE)); \ + fprintf (FILE, "\tld.64\t.sp,.r4\n\texit\t0\n"); \ + } else { \ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + fprintf (FILE, "\tld.64\t.r%d,[.sp]%d\n", regno, (cnt+=8)-12); \ + fprintf (FILE, "\texit\t%d\n", (SIZE)+cnt); \ + } } + + /* If the memory address ADDR is relative to the frame pointer, + correct it to be relative to the stack pointer instead. + This is for when we don't use a frame pointer. + ADDR should be a variable name. */ + + #define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \ + { int offset = -1; \ + rtx regs = stack_pointer_rtx; \ + if (ADDR == frame_pointer_rtx) \ + offset = 0; \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx \ + && GET_CODE (XEXP (ADDR, 0)) == CONST_INT) \ + offset = INTVAL (XEXP (ADDR, 0)); \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \ + && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \ + offset = INTVAL (XEXP (ADDR, 1)); \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \ + { rtx other_reg = XEXP (ADDR, 1); \ + offset = 0; \ + regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ + else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \ + { rtx other_reg = XEXP (ADDR, 0); \ + offset = 0; \ + regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ + if (offset >= 0) \ + { int regno; \ + extern char call_used_regs[]; \ + offset += 4; /* I don't know why??? */ \ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ + offset += 8; \ + ADDR = plus_constant (regs, offset + (DEPTH)); } } + + + /* Addressing modes, and classification of registers for them. */ + + /* #define HAVE_POST_INCREMENT */ + /* #define HAVE_POST_DECREMENT */ + + /* #define HAVE_PRE_DECREMENT */ + /* #define HAVE_PRE_INCREMENT */ + + /* 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_INDEX_P(regno) \ + ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0) + #define REGNO_OK_FOR_BASE_P(regno) \ + ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0) + + /* Maximum number of registers that can appear in a valid memory address. */ + + #define MAX_REGS_PER_ADDRESS 2 + + /* 1 if X is an rtx for a constant that is a valid address. */ + + #define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) + + /* 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) + + /* 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) 1 + /* 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 + + #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. + + CONSTANT_ADDRESS_P is actually machine-independent. */ + + #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ + { \ + if (GET_CODE (X) == REG) goto ADDR; \ + if (CONSTANT_ADDRESS_P (X)) goto ADDR; \ + if (GET_CODE (X) == PLUS) \ + { /* Handle [index]
represented with index-sum outermost */\ + if (GET_CODE (XEXP (X, 0)) == REG && \ + GET_CODE (XEXP (X, 1)) == CONST_INT) \ + goto ADDR; \ + if (GET_CODE (XEXP (X, 1)) == REG && \ + GET_CODE (XEXP (X, 0)) == 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. + + For the vax, nothing needs to be done. */ + + #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) + + + /* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ + #define CASE_VECTOR_MODE SImode + + /* Define this if the case 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 + + /* This is the kind of divide that is easiest to do in the general case. */ + #define EASY_DIV_EXPR TRUNC_DIV_EXPR + + /* Define this as 1 if `char' should by default be signed; else as 0. */ + #define DEFAULT_SIGNED_CHAR 1 + + /* 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 + + /* Max number of bytes we can move from memory to memory + in one reasonably fast instruction. */ + #define MOVE_MAX 8 + + /* 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 0 + + /* 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) 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 + + /* 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: \ + /* Constant zero is super cheap due to clr instruction. */ \ + if (RTX == const0_rtx) return 0; \ + if ((unsigned) INTVAL (RTX) < 077) return 1; \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 3; \ + case CONST_DOUBLE: \ + return 5; + + /* + * We can use the BSD C library routines for the gnulib calls that are + * still generated, since that's what they boil down to anyways. + */ + + /* #define UDIVSI3_LIBCALL "*udiv" */ + /* #define UMODSI3_LIBCALL "*urem" */ + + /* Check a `double' value for validity for a particular machine mode. */ + + /* note that it is very hard to accidently create a number that fits in a + double but not in a float, since their ranges are almost the same */ + #define CHECK_FLOAT_VALUE(mode, d) \ + if ((mode) == SFmode) \ + { \ + if ((d) > 1.7014117331926443e+38) \ + { error ("magnitude of constant too large for `float'"); \ + (d) = 1.7014117331926443e+38; } \ + else if ((d) < -1.7014117331926443e+38) \ + { error ("magnitude of constant too large for `float'"); \ + (d) = -1.7014117331926443e+38; } \ + else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \ + { warning ("`float' constant truncated to zero"); \ + (d) = 0.0; } \ + else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \ + { warning ("`float' constant truncated to zero"); \ + (d) = 0.0; } \ + } + + /* 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 NOTICE_UPDATE_CC(EXP, INSN) \ + CC_STATUS_INIT; + + + /* Control the assembler format that we output. */ + + /* Output the name of the file we are compiling. */ + #define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \ + fprintf(STREAM, "\t.file\t\"%s\"\n", NAME); + + /* Output at beginning of assembler file. */ + #define ASM_FILE_START(FILE) fprintf (FILE, ""); + + /* 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 "" + + /* Output before read-only data. */ + + #define TEXT_SECTION_ASM_OP "\t.inst" + + /* Output before writable data. */ + + #define DATA_SECTION_ASM_OP "\t.var" + + /* 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", ".sp"} + + /* This is BSD, so it wants DBX format. */ + + /* #define DBX_DEBUGGING_INFO */ + + /* How to renumber registers for dbx and gdb. + Vax needs no change in the numeration. */ + + #define DBX_REGISTER_NUMBER(REGNO) (REGNO) + + /* Do not break .stabs pseudos into continuations. */ + + #define DBX_CONTIN_LENGTH 0 + + /* This is the char to use for continuation (in case we need to turn + continuation back on). */ + + #define DBX_CONTIN_CHAR '?' + + /* Don't use the `xsfoo;' construct in DBX output; this system + doesn't support it. */ + + #define DBX_NO_XREFS + + /* 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.extdef\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. */ + + #define ASM_OUTPUT_LABELREF(FILE,NAME) \ + fprintf (FILE, "%s", NAME) + + /* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + + #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".%s%d:\n", 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'. */ + + #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, ".%s%d", PREFIX, NUM) + + /* This is how to output an assembler line defining a `double' constant. + It is .dfloat or .gfloat, depending. */ + + #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + { union {double d; int i[2]; } tem; \ + tem.d = (VALUE); \ + fprintf (FILE, "\t.data\t%d{32}, %d{32}\n", tem.i[0], tem.i[1]); } + + /* This is how to output an assembler line defining a `float' constant. */ + + #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + { union {float f; int i; } tem; \ + tem.f = (VALUE); \ + fprintf (FILE, "\t.data %d{32}\n", tem.i); } + + /* This is how to output an assembler line defining an `int' constant. */ + + #define ASM_OUTPUT_INT(FILE,VALUE) \ + ( \ + fprintf (FILE, "\t.data\t"), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "{32}\n")) + + #define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \ + { \ + fprintf (FILE, "\t.data\t"); \ + if (GET_CODE (VALUE) == CONST_DOUBLE) \ + { \ + fprintf (FILE, "%d", CONST_DOUBLE_HIGH (VALUE)); \ + fprintf (FILE, "{32}, "); \ + fprintf (FILE, "%d", CONST_DOUBLE_LOW (VALUE)); \ + fprintf (FILE, "{32}\n"); \ + } else if (GET_CODE (VALUE) == CONST_INT) \ + { \ + int val = INTVAL (VALUE); \ + fprintf (FILE, "%d", val < 0 ? -1 : 0); \ + fprintf (FILE, "{32}, "); \ + fprintf (FILE, "%d", val); \ + fprintf (FILE, "{32}\n"); \ + } else abort (); \ + } + + /* Likewise for `char' and `short' constants. */ + + #define ASM_OUTPUT_SHORT(FILE,VALUE) \ + ( fprintf (FILE, "\t.data\t"), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "{16}\n")) + + #define ASM_OUTPUT_CHAR(FILE,VALUE) \ + ( fprintf (FILE, "\t.data\t"), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "{8}\n")) + + /* This is how to output an assembler line for a numeric constant byte. */ + + #define ASM_OUTPUT_BYTE(FILE,VALUE) \ + fprintf (FILE, "\t.data\t%d{8}\n", (VALUE)) + + /* 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) \ + fprintf (FILE, "\tsubi.64\t4,.sp\n\tst.32\t%s,[.sp]\n", reg_names[REGNO]) + + /* 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) \ + fprintf (FILE, "\tld.32\t%s,[.sp]\n\taddi.64\t4,.sp\n", reg_names[REGNO]) + + /* This is how to output an element of a case-vector that is absolute. + (The Vax does not use such vectors, + but we must define this macro anyway.) */ + + #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\t.data .L%d{32}\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) \ + fprintf (FILE, "\t.data .L%d-.L%d{32}\n", VALUE, REL) + + /* 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!=0) fprintf (FILE, "\t.align\t%d\n", (LOG)); else 0 + + /* This is how to output an assembler line + that says to advance the location counter by SIZE bytes. */ + + #define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.space %d\n", (SIZE)) + + /* This says how to output an assembler line + to define a global common symbol. */ + + #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ + ( fputs (".comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d\n", (ROUNDED))) + + /* This says how to output an assembler line + to define a local common symbol. */ + + #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ + ( fputs (".bss ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%d,%d\n", (SIZE),(ROUNDED))) + + /* 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 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 + + /* Print an instruction operand X on file FILE. + CODE is the code from the %-spec that requested printing this operand; + if `%z3' was used to print operand 3, then CODE is 'z'. */ + + #define PRINT_OPERAND(FILE, X, CODE) \ + { \ + if (CODE == 'r' && GET_CODE (X) == MEM && GET_CODE (XEXP (X, 0)) == REG) \ + fprintf (FILE, "%s", reg_names[REGNO (XEXP (X, 0))]); \ + else if (GET_CODE (X) == REG) \ + fprintf (FILE, "%s", reg_names[REGNO (X)]); \ + else if (GET_CODE (X) == MEM) \ + output_address (XEXP (X, 0)); \ + else \ + { \ + /*debug_rtx(X);*/ \ + putc ('=', FILE); \ + output_addr_const (FILE, X); } \ + } + + /* 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) + + /* Functions used in the md file. */ + + extern char *cmp_set(); + extern char *cmp_jmp(); + + /* These are stubs, and have yet to bee written. */ + + #define TRAMPOLINE_SIZE 26 + #define TRAMPOLINE_TEMPLATE(FILE) + #define INITIALIZE_TRAMPOLINE(TRAMP,FNADDR,CXT) diff -rc2N gcc-2.2.2/config/elxsi.md gcc-2.3.1/config/elxsi.md *** gcc-2.2.2/config/elxsi.md --- gcc-2.3.1/config/elxsi.md Thu Oct 15 16:59:13 1992 *************** *** 0 **** --- 1,1440 ---- + ;;- Machine description for GNU compiler + ;;- Elxsi Version + ;; Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. + ;; This port done by Mike Stump in 1988, and is the first + ;; 64 bit port of GNU CC. + ;; Based upon the VAX port. + + ;; 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 1, 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. + + + ;;- Instruction patterns. When multiple patterns apply, + ;;- the first one in the file is chosen. + ;;- + ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. + ;;- + ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code + ;;- updates for most instructions. + + + (define_insn "" + [(set (reg:SI 15) + (plus:SI (reg:SI 15) + (match_operand:SI 0 "general_operand" "g")))] + "" + "add.64\\t.sp,%0") + + (define_insn "" + [(set (reg:SI 15) + (plus:SI (match_operand:SI 0 "general_operand" "g") + (reg:SI 15)))] + "" + "add.64\\t.sp,%0") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "r") + (plus:SI (reg:SI 15) + (match_operand:SI 1 "general_operand" "g")))] + "" + "ld.32\\t%0,.sp\;add.64\\t%0,%1") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "r") + (plus:SI (match_operand:SI 1 "general_operand" "g") + (reg:SI 15)))] + "" + "ld.32\\t%0,.sp\;add.64\\t%0,%1") + + (define_insn "" + [(set (reg:SI 15) + (minus:SI (reg:SI 15) + (match_operand:SI 0 "general_operand" "g")))] + "" + "sub.64\\t.sp,%0") + + (define_insn "" + [(set (reg:SI 15) + (match_operand:SI 0 "general_operand" "rm"))] + "" + "ld.32\\t.sp,%0") + + (define_insn "" + [(set (match_operand:SI 0 "general_operand" "m,r") + (reg:SI 15))] + "" + "* + if (which_alternative == 0) + return \"st.32\\t.sp,%0\"; + return \"ld.32\\t%0,.sp\"; + ") + + ; tstdi is first test insn so that it is the one to match + ; a constant argument. + + (define_insn "tstdi" + [(set (cc0) + (match_operand:DI 0 "register_operand" "r"))] + "" + "* + extern rtx cmp_op0, cmp_op1; + cmp_op0=operands[0]; cmp_op1=0; + return \";\\ttstdi\\t%0\"; + ") + + (define_insn "tstdf" + [(set (cc0) + (match_operand:DF 0 "register_operand" "r"))] + "" + "* + extern rtx cmp_op0, cmp_op1; + cmp_op0=operands[0]; cmp_op1=0; + return \";\\ttstdf\\t%0\"; + ") + + (define_insn "tstsf" + [(set (cc0) + (match_operand:SF 0 "register_operand" "r"))] + "" + "* + extern rtx cmp_op0, cmp_op1; + cmp_op0=operands[0]; cmp_op1=0; + return \";\\ttstsf\\t%0\"; + ") + + (define_insn "cmpdi" + [(set (cc0) + (compare (match_operand:DI 0 "register_operand" "r") + (match_operand:DI 1 "general_operand" "rm")))] + "" + "* + extern rtx cmp_op0, cmp_op1; + cmp_op0=operands[0]; cmp_op1=operands[1]; + return \";\\tcmpdi\\t%0,%1\"; + ") + + (define_insn "cmpdf" + [(set (cc0) + (compare (match_operand:DF 0 "register_operand" "r") + (match_operand:DF 1 "general_operand" "rm")))] + "" + "* + extern rtx cmp_op0, cmp_op1; + cmp_op0=operands[0]; cmp_op1=operands[1]; + return \";\\tcmpdf\\t%0,%1\"; + ") + + (define_insn "cmpsf" + [(set (cc0) + (compare (match_operand:SF 0 "register_operand" "r") + (match_operand:SF 1 "general_operand" "rm")))] + "" + "* + extern rtx cmp_op0, cmp_op1; + cmp_op0=operands[0]; cmp_op1=operands[1]; + return \";\\tcmpsf\\t%0,%1\"; + ") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (eq (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmp.64\\t%0,%1,%2:eq") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ne (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmp.64\\t%0,%1,%2:ne") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (le (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmp.64\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (leu (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmpu.64\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (lt (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmp.64\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ltu (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmpu.64\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (ge (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmp.64\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (geu (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmpu.64\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (gt (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmp.64\\t%0,%1,%2:gt") + + (define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (gtu (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "general_operand" "g")))] + "" + "cmpu.64\\t%0,%1,%2:gt") + + (define_insn "seq" + [(set (match_operand:DI 0 "register_operand" "=r") + (eq (cc0) (const_int 0)))] + "" + "* return cmp_set(\"\", \"eq\", operands[0]); ") + + (define_insn "sne" + [(set (match_operand:DI 0 "register_operand" "=r") + (ne (cc0) (const_int 0)))] + "" + "* return cmp_set(\"\", \"ne\", operands[0]); ") + + (define_insn "sle" + [(set (match_operand:DI 0 "register_operand" "=r") + (le (cc0) (const_int 0)))] + "" + "* return cmp_set(\"\", \"le\", operands[0]); ") + + (define_insn "sleu" + [(set (match_operand:DI 0 "register_operand" "=r") + (leu (cc0) (const_int 0)))] + "" + "* return cmp_set(\"u\", \"le\", operands[0]); ") + + (define_insn "slt" + [(set (match_operand:DI 0 "register_operand" "=r") + (lt (cc0) (const_int 0)))] + "" + "* return cmp_set(\"\", \"lt\", operands[0]); ") + + (define_insn "sltu" + [(set (match_operand:DI 0 "register_operand" "=r") + (ltu (cc0) (const_int 0)))] + "" + "* return cmp_set(\"u\", \"lt\", operands[0]); ") + + (define_insn "sge" + [(set (match_operand:DI 0 "register_operand" "=r") + (ge (cc0) (const_int 0)))] + "" + "* return cmp_set(\"\", \"ge\", operands[0]); ") + + (define_insn "sgeu" + [(set (match_operand:DI 0 "register_operand" "=r") + (geu (cc0) (const_int 0)))] + "" + "* return cmp_set(\"u\", \"ge\", operands[0]); ") + + (define_insn "sgt" + [(set (match_operand:DI 0 "register_operand" "=r") + (gt (cc0) (const_int 0)))] + "" + "* return cmp_set(\"\", \"gt\", operands[0]); ") + + (define_insn "sgtu" + [(set (match_operand:DI 0 "register_operand" "=r") + (gtu (cc0) (const_int 0)))] + "" + "* return cmp_set(\"u\", \"gt\", operands[0]); ") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmp.32\\t%0,%1,%2:eq") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (ne (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmp.32\\t%0,%1,%2:ne") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (le (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmp.32\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (leu (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmpu.32\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (lt (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmp.32\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (ltu (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmpu.32\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (ge (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmp.32\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (geu (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmpu.32\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (gt (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmp.32\\t%0,%1,%2:gt") + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (gtu (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "m")))] + "" + "cmpu.32\\t%0,%1,%2:gt") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (eq (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmp.16\\t%0,%1,%2:eq") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (ne (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmp.16\\t%0,%1,%2:ne") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (le (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmp.16\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (leu (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmpu.16\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (lt (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmp.16\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (ltu (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmpu.16\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (ge (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmp.16\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (geu (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmpu.16\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (gt (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmp.16\\t%0,%1,%2:gt") + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (gtu (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "general_operand" "m")))] + "" + "cmpu.16\\t%0,%1,%2:gt") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (eq (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmp.8\\t%0,%1,%2:eq") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (ne (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmp.8\\t%0,%1,%2:ne") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (le (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmp.8\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (leu (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmpu.8\\t%0,%1,%2:le") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (lt (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmp.8\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (ltu (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmpu.8\\t%0,%1,%2:lt") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (ge (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmp.8\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (geu (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmpu.8\\t%0,%1,%2:ge") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (gt (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmp.8\\t%0,%1,%2:gt") + + (define_insn "" + [(set (match_operand:QI 0 "register_operand" "=r") + (gtu (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "general_operand" "m")))] + "" + "cmpu.8\\t%0,%1,%2:gt") + + + + (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=r,m") + (match_operand:DF 1 "general_operand" "rm,r"))] + "" + "* + { + if (which_alternative == 0) + return \"ld.64\\t%0,%1\"; + return \"st.64\\t%1,%0\"; + }") + + (define_insn "movsf" + [(set (match_operand:SF 0 "general_operand" "=r,m") + (match_operand:SF 1 "general_operand" "rm,r"))] + "" + "* + { + if (which_alternative == 0) + return \"ld.32\\t%0,%1\"; + return \"st.32\\t%1,%0\"; + }") + + (define_insn "movdi" + [(set (match_operand:DI 0 "general_operand" "=r,m,rm") + (match_operand:DI 1 "general_operand" "g,r,I"))] + "" + "* + if (which_alternative == 0) + return \"ld.64\\t%0,%1\"; + else if (which_alternative == 1) + return \"st.64\\t%1,%0\"; + else + if (GET_CODE(operands[1])==CONST_INT) { + if (INTVAL(operands[1]) >= 0) + return \"sti.64\\t%c1,%0\"; + else + return \"stin.64\\t%n1,%0\"; + } + ") + + (define_insn "movsi" + [(set (match_operand:SI 0 "general_operand" "=r,m,r") + (match_operand:SI 1 "general_operand" "rm,rI,i"))] + "" + "* + if (which_alternative == 0) + return \"ld.32\\t%0,%1\"; + else if (which_alternative == 1) { + if (GET_CODE(operands[1])==CONST_INT) { + if (INTVAL(operands[1]) >= 0) + return \"sti.32\\t%c1,%0\"; + else + return \"stin.32\\t%n1,%0\"; + } + return \"st.32\\t%1,%0\"; + } else + return \"ld.64\\t%0,%1 ; I only want 32\"; + ") + + (define_insn "movhi" + [(set (match_operand:HI 0 "general_operand" "=r,m,r") + (match_operand:HI 1 "general_operand" "m,rI,ri"))] + "" + "* + { + if (which_alternative == 0) + return \"ld.16\\t%0,%1\"; + if (which_alternative == 2) + return \"ld.64\\t%0,%1\\t; I only want 16\"; + if (GET_CODE(operands[1])==CONST_INT) { + if (INTVAL(operands[1]) >= 0) + return \"sti.16\\t%c1,%0\"; + else + return \"stin.16\\t%n1,%0\"; + } + return \"st.16\\t%1,%0\"; + }") + + (define_insn "movqi" + [(set (match_operand:QI 0 "general_operand" "=r,m,r") + (match_operand:QI 1 "general_operand" "m,rI,ri"))] + "" + "* + { + if (which_alternative == 0) + return \"ld.8\\t%0,%1\"; + if (which_alternative == 2) + return \"ld.64\\t%0,%1\\t; I only want 8\"; + if (GET_CODE(operands[1])==CONST_INT) { + if (INTVAL(operands[1]) >= 0) + return \"sti.8\\t%c1,%0\"; + else + return \"stin.8\\t%n1,%0\"; + } + return \"st.8\\t%1,%0\"; + }") + + ;; Extension and truncation insns. + ;; Those for integer source operand + ;; are ordered widest source type first. + + (define_insn "truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=r") + (truncate:SF (match_operand:DF 1 "general_operand" "rm")))] + "" + "cvt.ds\\t%0,%1") + + (define_insn "truncdiqi2" + [(set (match_operand:QI 0 "general_operand" "=r,m,r") + (truncate:QI (match_operand:DI 1 "general_operand" "m,r,0")))] + "" + "* + { + if (which_alternative == 0) + return \"ld.8\\t%0,%1\"; + else if (which_alternative == 1) + return \"st.8\\t%1,%0\"; + return \"\"; + }") + + (define_insn "truncdihi2" + [(set (match_operand:HI 0 "general_operand" "=r,m,r") + (truncate:HI (match_operand:DI 1 "general_operand" "m,r,0")))] + "" + "* + { + if (which_alternative == 0) + return \"ld.16\\t%0,%1\"; + if (which_alternative == 1) + return \"st.16\\t%1,%0\"; + return \"\"; + }") + + (define_insn "truncdisi2" + [(set (match_operand:SI 0 "general_operand" "=r,m") + (truncate:SI (match_operand:DI 1 "general_operand" "rm,r")))] + "" + "* + { + if (which_alternative == 0) + return \"ld.32\\t%0,%1\"; + return \"st.32\\t%1,%0\"; + }") + + (define_insn "truncsiqi2" + [(set (match_operand:QI 0 "general_operand" "=r,m,r") + (truncate:QI (match_operand:SI 1 "general_operand" "m,r,0")))] + "" + "* + { + if (which_alternative == 0) + return \"ld.8\\t%0,%1\"; + if (which_alternative == 1) + return \"st.8\\t%1,%0\"; + return \"\"; + }") + + (define_insn "truncsihi2" + [(set (match_operand:HI 0 "general_operand" "=r,m,r") + (truncate:HI (match_operand:SI 1 "general_operand" "m,r,0")))] + "" + "* + { + if (which_alternative == 0) + return \"ld.16\\t%0,%1\"; + if (which_alternative == 1) + return \"st.16\\t%1,%0\"; + return \"\"; + }") + + (define_insn "trunchiqi2" + [(set (match_operand:QI 0 "general_operand" "=r,m,r") + (truncate:QI (match_operand:HI 1 "general_operand" "m,r,0")))] + "" + "* + { + if (which_alternative == 0) + return \"ld.8\\t%0,%1\"; + if (which_alternative == 1) + return \"st.8\\t%1,%0\"; + return \"\"; + }") + + (define_insn "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=r") + (sign_extend:DF (match_operand:SF 1 "general_operand" "rm")))] + "" + "cvt.sd\\t%0,%1") + + (define_insn "extendsidi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (match_operand:SI 1 "general_operand" "rm")))] + "" + "ld.32\\t%0,%1") + + (define_insn "extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:HI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ld.16\\t%0,%1\"; + return \"extract\\t%0,%1:bit 48,16\"; + ") + + (define_insn "extendhidi2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (sign_extend:DI (match_operand:HI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ld.16\\t%0,%1\"; + return \"extract\\t%0,%1:bit 48,16\"; + ") + + (define_insn "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (sign_extend:HI (match_operand:QI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ld.8\\t%0,%1\"; + return \"extract\\t%0,%1:bit 56,8\"; + ") + + (define_insn "extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:QI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ld.8\\t%0,%1\"; + return \"extract\\t%0,%1:bit 56,8\"; + ") + + (define_insn "extendqidi2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (sign_extend:DI (match_operand:QI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ld.8\\t%0,%1\"; + return \"extract\\t%0,%1:bit 56,8\"; + ") + + (define_insn "zero_extendsidi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))] + "" + "ldz.32\\t%0,%1") + + + (define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:HI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ldz.16\\t%0,%1\"; + return \"extractz\\t%0,%1:bit 48,16\"; + ") + + (define_insn "zero_extendhidi2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI (match_operand:HI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ldz.16\\t%0,%1\"; + return \"extractz\\t%0,%1:bit 48,16\"; + ") + + (define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (zero_extend:HI (match_operand:QI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ldz.8\\t%0,%1\"; + return \"extractz\\t%0,%1:bit 56,8\"; + ") + + (define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:QI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ldz.8\\t%0,%1\"; + return \"extractz\\t%0,%1:bit 56,8\"; + ") + + (define_insn "zero_extendqidi2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (zero_extend:DI (match_operand:QI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative==0) + return \"ldz.8\\t%0,%1\"; + return \"extractz\\t%0,%1:bit 56,8\"; + ") + + + + (define_insn "lshldi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (lshift:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "rn")))] + "" + "sll\\t%0,%1,%2") + + (define_insn "ashrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "rn")))] + "" + "sra\\t%0,%1,%2") + + (define_insn "lshrdi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "rn")))] + "" + "srl\\t%0,%1,%2") + + (define_insn "ashldi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (ashift:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:SI 2 "general_operand" "rn")))] + "" + "sla\\t%0,%1,%2") + + (define_insn "anddi3" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (and:DI (match_operand:DI 1 "general_operand" "%0,r") + (match_operand:DI 2 "general_operand" "g,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"and\\t%0,%2\"; + return \"and\\t%0,%1,%2\"; + ") + + (define_insn "iordi3" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (ior:DI (match_operand:DI 1 "general_operand" "%0,r") + (match_operand:DI 2 "general_operand" "g,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"or\\t%0,%2\"; + return \"or\\t%0,%1,%2\"; + ") + + (define_insn "xordi3" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (xor:DI (match_operand:DI 1 "general_operand" "%0,r") + (match_operand:DI 2 "general_operand" "g,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"xor\\t%0,%2\"; + return \"xor\\t%0,%1,%2\"; + ") + + (define_insn "one_cmpldi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (not:DI (match_operand:DI 1 "general_operand" "rm")))] + "" + "not\\t%0,%1") + + ;; gcc 2.1 does not widen ~si into ~di. + (define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:DI (match_operand:SI 1 "register_operand" "r")))] + "" + "not\\t%0,%1") + + (define_insn "negdi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (match_operand:DI 1 "general_operand" "rm")))] + "" + "neg.64\\t%0,%1") + + (define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (neg:SI (match_operand:SI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative == 0) + return \"neg.32\\t%0,%1\"; + return \"neg.64\\t%0,%1 ; I only want 32\"; + ") + + (define_insn "neghi2" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (neg:HI (match_operand:HI 1 "general_operand" "m,r")))] + "" + "* + if (which_alternative == 0) + return \"neg.16\\t%0,%1\"; + return \"neg.64\\t%0,%1 ; I only want 16\"; + ") + + (define_insn "adddf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (plus:DF (match_operand:DF 1 "general_operand" "%0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "fadd.64\\t%0,%2") + + (define_insn "addsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (plus:SF (match_operand:SF 1 "general_operand" "%0") + (match_operand:SF 2 "general_operand" "rm")))] + "" + "fadd.32\\t%0,%2") + + ;; There is also an addi.64 4,.r0'' optimization + (define_insn "adddi3" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (plus:DI (match_operand:DI 1 "general_operand" "%0,r") + (match_operand:DI 2 "general_operand" "g,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"add.64\\t%0,%2\"; + return \"add.64\\t%0,%1,%2\"; + ") + + (define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (plus:SI (match_operand:SI 1 "general_operand" "%0,r,0") + (match_operand:SI 2 "general_operand" "m,m,g")))] + "1 /*which_alternative != 1 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"add.32\\t%0,%2\"; + if (which_alternative == 1) + return \"add.32\\t%0,%1,%2\"; + return \"add.64\\t%0,%2 ; I only want 32\"; + ") + + (define_insn "addhi3" + [(set (match_operand:HI 0 "register_operand" "=r,r,r") + (plus:HI (match_operand:HI 1 "general_operand" "%0,r,0") + (match_operand:HI 2 "general_operand" "m,m,g")))] + "1 /*which_alternative != 1 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"add.16\\t%0,%2\"; + if (which_alternative == 1) + return \"add.16\\t%0,%1,%2\"; + return \"add.64\\t%0,%2 ; I only want 16\"; + ") + + (define_insn "subdf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (minus:DF (match_operand:DF 1 "general_operand" "0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "fsub.64\\t%0,%2") + + (define_insn "subsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (minus:SF (match_operand:SF 1 "general_operand" "0") + (match_operand:SF 2 "general_operand" "rm")))] + "" + "fsub.32\\t%0,%2") + + (define_insn "subdi3" + [(set (match_operand:DI 0 "register_operand" "=r,r,r") + (minus:DI (match_operand:DI 1 "general_operand" "0,g,r") + (match_operand:DI 2 "general_operand" "g,r,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"sub.64\\t%0,%2\"; + else if (which_alternative == 1) + return \"subr.64\\t%0,%2,%1\"; + else + return \"sub.64\\t%0,%1,%2\"; + ") + + (define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (minus:SI (match_operand:SI 1 "general_operand" "0,m,r,0") + (match_operand:SI 2 "general_operand" "m,r,m,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"sub.32\\t%0,%2\"; + else if (which_alternative == 1) + return \"subr.32\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"sub.32\\t%0,%1,%2\"; + else + return \"sub.64\\t%0,%2 ; I only want 32\"; + ") + + (define_insn "subhi3" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (minus:HI (match_operand:HI 1 "general_operand" "0,m,r,0") + (match_operand:HI 2 "general_operand" "m,r,m,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"sub.16\\t%0,%2\"; + else if (which_alternative == 1) + return \"subr.16\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"sub.16\\t%0,%1,%2\"; + else + return \"sub.64\\t%0,%2 ; I only want 16\"; + ") + + (define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (mult:DF (match_operand:DF 1 "general_operand" "%0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "fmul.64\\t%0,%2") + + (define_insn "mulsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (mult:SF (match_operand:SF 1 "general_operand" "%0") + (match_operand:SF 2 "general_operand" "rm")))] + "" + "fmul.32\\t%0,%2") + + (define_insn "muldi3" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (mult:DI (match_operand:DI 1 "general_operand" "%0,r") + (match_operand:DI 2 "general_operand" "g,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"mul.64\\t%0,%2\"; + return \"mul.64\\t%0,%1,%2\"; + ") + + (define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (mult:SI (match_operand:SI 1 "general_operand" "%0,r,0") + (match_operand:SI 2 "general_operand" "m,m,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"mul.32\\t%0,%2\"; + else if (which_alternative == 1) + return \"mul.32\\t%0,%1,%2\"; + else + return \"mul.64\\t%0,%2 ; I only want 32\"; + ") + + (define_insn "mulhi3" + [(set (match_operand:HI 0 "register_operand" "=r,r,r") + (mult:HI (match_operand:HI 1 "general_operand" "%0,r,0") + (match_operand:HI 2 "general_operand" "m,m,g")))] + "1 /*which_alternative == 0 || check356(operands[2])*/" + "* + if (which_alternative == 0) + return \"mul.16\\t%0,%2\"; + else if (which_alternative == 1) + return \"mul.16\\t%0,%1,%2\"; + else + return \"mul.64\\t%0,%2 ; I only want 16\"; + ") + + (define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (div:DF (match_operand:DF 1 "general_operand" "0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "fdiv.64\\t%0,%2") + + (define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (div:SF (match_operand:SF 1 "general_operand" "0") + (match_operand:SF 2 "general_operand" "rm")))] + "" + "fdiv.32\\t%0,%2") + + (define_insn "divdi3" + [(set (match_operand:DI 0 "register_operand" "=r,r,r") + (div:DI (match_operand:DI 1 "general_operand" "0,g,r") + (match_operand:DI 2 "general_operand" "g,r,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"div.64\\t%0,%2\"; + else if (which_alternative == 1) + return \"divr.64\\t%0,%2,%1\"; + else + return \"div.64\\t%0,%1,%2\"; + ") + + (define_insn "divsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (div:SI (match_operand:SI 1 "general_operand" "0,m,r,0") + (match_operand:SI 2 "general_operand" "m,r,m,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + /* We don't ignore high bits. */ + if (0) { + if (which_alternative == 0) + return \"div.32\\t%0,%2\"; + else if (which_alternative == 1) + return \"divr.32\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"div.32\\t%0,%1,%2\"; + else + return \"ld.32\\t%0,%0\;div.64\\t%0,%2 ; I only want 32\"; + } else { + if (which_alternative == 0) + return \"ld.32\\t%0,%0\;div.32\\t%0,%2\"; + else if (which_alternative == 1) + return \"ld.32\\t%2,%2\;divr.32\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"ld.32\\t%1,%1\;div.32\\t%0,%1,%2\"; + else + return \"ld.32\\t%0,%0\;div.64\\t%0,%2 ; I only want 32\"; + } + ") + + (define_insn "divhi3" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") + (div:HI (match_operand:HI 1 "general_operand" "0,m,r,0,0") + (match_operand:HI 2 "general_operand" "m,r,m,r,i")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"extract\\t%0,%0:bit 48,16\;div.16\\t%0,%2\"; + else if (which_alternative == 1) + return \"extract\\t%2,%2:bit 48,16\;divr.16\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"extract\\t%1,%1:bit 48,16\;div.16\\t%0,%1,%2\"; + else if (which_alternative == 3) + return \"extract\\t%0,%0:bit 48,16\;extract\\t%2,%2:bit 48,16\;div.64\\t%0,%2 ; I only want 16\"; + else + return \"extract\\t%0,%0:bit 48,16\;div.64\\t%0,%2 ; I only want 16\"; + ") + + (define_insn "modhi3" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") + (mod:HI (match_operand:HI 1 "general_operand" "0,m,r,0,0") + (match_operand:HI 2 "general_operand" "m,r,m,r,i")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"extract\\t%0,%0:bit 48,16\;rem.16\\t%0,%2\"; + else if (which_alternative == 1) + return \"extract\\t%2,%2:bit 48,16\;remr.16\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"extract\\t%1,%1:bit 48,16\;rem.16\\t%0,%1,%2\"; + else if (which_alternative == 3) + return \"extract\\t%0,%0:bit 48,16\;extract\\t%2,%2:bit 48,16\;rem.64\\t%0,%2 ; I only want 16\"; + else + return \"extract\\t%0,%0:bit 48,16\;rem.64\\t%0,%2 ; I only want 16\"; + ") + + (define_insn "moddi3" + [(set (match_operand:DI 0 "register_operand" "=r,r,r") + (mod:DI (match_operand:DI 1 "general_operand" "0,g,r") + (match_operand:DI 2 "general_operand" "g,r,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + if (which_alternative == 0) + return \"rem.64\\t%0,%2\"; + else if (which_alternative == 1) + return \"remr.64\\t%0,%2,%1\"; + else + return \"rem.64\\t%0,%1,%2\"; + ") + + (define_insn "modsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (mod:SI (match_operand:SI 1 "general_operand" "0,m,r,0") + (match_operand:SI 2 "general_operand" "m,r,m,g")))] + "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" + "* + /* There is a micro code bug with the below... */ + if (0) { + if (which_alternative == 0) + return \"rem.32\\t%0,%2\"; + else if (which_alternative == 1) + return \"remr.32\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"rem.32\\t%0,%1,%2\"; + else + return \"ld.32\\t%0,%0\;rem.64\\t%0,%2 ; I only want 32\"; + } else { + if (which_alternative == 0) + return \"ld.32\\t%0,%0\;rem.32\\t%0,%2\"; + else if (which_alternative == 1) + return \"ld.32\\t%2,%2\;remr.32\\t%0,%2,%1\"; + else if (which_alternative == 2) + return \"ld.32\\t%1,%1\;rem.32\\t%0,%1,%2\"; + else + return \"ld.32\\t%0,%0\;rem.64\\t%0,%2 ; I only want 32\"; + } + ") + + + (define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jmp\\t%l0") + + (define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "register_operand" "r"))] + "" + ;; Maybe %l0 is better, maybe we can relax register only. + "verify this before use ld.32\\t.r0,%0\;br.reg\\t.r0") + + (define_insn "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"\", 2, operands[0]); ") + + (define_insn "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"\", 8, operands[0]); ") + + (define_insn "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"\", 0, operands[0]); ") + + (define_insn "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"u\", 0, operands[0]); ") + + (define_insn "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"\", 6, operands[0]); ") + + (define_insn "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"u\", 6, operands[0]); ") + + (define_insn "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"\", 4, operands[0]); ") + + (define_insn "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"u\", 4, operands[0]); ") + + (define_insn "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"\", 10, operands[0]); ") + + (define_insn "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* return cmp_jmp(\"u\", 10, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"\", 8, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"\", 2, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"\", 10, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"u\", 10, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"\", 4, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"u\", 4, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"\", 6, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"u\", 6, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"\", 0, operands[0]); ") + + (define_insn "" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "* return cmp_jmp(\"u\", 0, operands[0]); ") + + ;; Note that operand 1 is total size of args, in bytes, + ;; and what the call insn wants is the number of words. + (define_insn "call" + [(call (match_operand:QI 0 "general_operand" "m") + (match_operand:QI 1 "general_operand" "g"))] + "" + "* + if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == REG) + if (REGNO (XEXP (operands[0], 0)) != 0) + return \"add.64\\t.sp,=-4\;ld.64\\t.r0,=.+11\;st.32\\t.r0,[.sp]\;br.reg\\t%r0\;add.64\\t.sp,=4\;add.64\\t.sp,%1\"; + else + return \"add.64\\t.sp,=-4\;ld.64\\t.r1,=.+11\;st.32\\t.r1,[.sp]\;br.reg\\t%r0\;add.64\\t.sp,=4\;add.64\\t.sp,%1\"; + else + return \"add.64\\t.sp,=-4\;call\\t%0\;add.64\\t.sp,=4\;add.64\\t.sp,%1\"; + ") + + (define_insn "call_value" + [(set (match_operand 0 "" "g") + (call (match_operand:QI 1 "general_operand" "m") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* + if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) == REG) + if (REGNO (XEXP (operands[1], 0)) != 0) + return \"add.64\\t.sp,=-4\;ld.64\\t.r0,=.+11\;st.32\\t.r0,[.sp]\;br.reg\\t%r1\;add.64\\t.sp,=4\;add.64\\t.sp,%2\"; + else + return \"add.64\\t.sp,=-4\;ld.64\\t.r1,=.+11\;st.32\\t.r1,[.sp]\;br.reg\\t%r1\;add.64\\t.sp,=4\;add.64\\t.sp,%2\"; + else + return \"add.64\\t.sp,=-4\;call\\t%1\;add.64\\t.sp,=4\;add.64\\t.sp,%2\"; + ") + + (define_insn "tablejump" + [(set (pc) (match_operand:SI 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "" + "br.reg\\t%0") + + (define_insn "nop" + [(const_int 0)] + "" + "nop") + + + + ;;- Local variables: + ;;- mode:emacs-lisp + ;;- comment-start: "!;;- " + ;;- eval: (set-syntax-table (copy-sequence (syntax-table))) + ;;- eval: (modify-syntax-entry ?[ "(]") + ;;- eval: (modify-syntax-entry ?] ")[") + ;;- eval: (modify-syntax-entry ?{ "(}") + ;;- eval: (modify-syntax-entry ?} "){") + ;;- End: diff -rc2N gcc-2.2.2/config/fx2800.h gcc-2.3.1/config/fx2800.h *** gcc-2.2.2/config/fx2800.h Wed Jun 10 00:47:20 1992 --- gcc-2.3.1/config/fx2800.h Fri Jul 10 19:17:53 1992 *************** *** 47,50 **** --- 47,51 ---- #define I860_STRICT_ABI_PROLOGUES + #define LINK_LIBGCC_SPECIAL 1 /* Most of the Alliant-specific definitions here are to get stab info that *************** *** 114,118 **** for (i=1;*dtyps[i];i++) \ for (decl = syms; decl; decl = TREE_CHAIN(decl)) \ ! if ((TREE_CODE (decl) == TYPE_DECL) && \ !strcmp(IDENTIFIER_POINTER(DECL_NAME(decl)), dtyps[i])) { \ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i; \ --- 115,119 ---- for (i=1;*dtyps[i];i++) \ for (decl = syms; decl; decl = TREE_CHAIN(decl)) \ ! if ((TREE_CODE (decl) == TYPE_DECL) && DECL_NAME(decl) && \ !strcmp(IDENTIFIER_POINTER(DECL_NAME(decl)), dtyps[i])) { \ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i; \ *************** *** 123,127 **** \ for (decl = syms; decl; decl = TREE_CHAIN(decl)) \ ! if ((TREE_CODE (decl) == TYPE_DECL) && \ !strcmp(IDENTIFIER_POINTER(DECL_NAME(decl)),"long int")) { \ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i; \ --- 124,128 ---- \ for (decl = syms; decl; decl = TREE_CHAIN(decl)) \ ! if ((TREE_CODE (decl) == TYPE_DECL) && DECL_NAME(decl) && \ !strcmp(IDENTIFIER_POINTER(DECL_NAME(decl)),"long int")) { \ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i; \ *************** *** 134,138 **** \ for (decl = syms; decl; decl = TREE_CHAIN(decl)) \ ! if ((TREE_CODE (decl) == TYPE_DECL) && !strcmp( \ IDENTIFIER_POINTER(DECL_NAME(decl)),"long unsigned int")) { \ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i; \ --- 135,139 ---- \ for (decl = syms; decl; decl = TREE_CHAIN(decl)) \ ! if ((TREE_CODE (decl) == TYPE_DECL) && DECL_NAME(decl) && !strcmp( \ IDENTIFIER_POINTER(DECL_NAME(decl)),"long unsigned int")) { \ TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = i; \ diff -rc2N gcc-2.2.2/config/gmicro.md gcc-2.3.1/config/gmicro.md *** gcc-2.2.2/config/gmicro.md Sat Mar 14 00:15:35 1992 --- gcc-2.3.1/config/gmicro.md Mon Jul 27 22:43:35 1992 *************** *** 1689,1693 **** (define_insn "negsf2" ! [(set (match_operand:SF 0 "general_operand" "f") (neg:SF (match_operand:SF 1 "general_operand" "fmF")))] "TARGET_FPU" --- 1689,1693 ---- (define_insn "negsf2" ! [(set (match_operand:SF 0 "general_operand" "=f") (neg:SF (match_operand:SF 1 "general_operand" "fmF")))] "TARGET_FPU" *************** *** 1696,1700 **** (define_insn "negdf2" ! [(set (match_operand:DF 0 "general_operand" "f") (neg:DF (match_operand:DF 1 "general_operand" "fmF")))] "TARGET_FPU" --- 1696,1700 ---- (define_insn "negdf2" ! [(set (match_operand:DF 0 "general_operand" "=f") (neg:DF (match_operand:DF 1 "general_operand" "fmF")))] "TARGET_FPU" *************** *** 1705,1709 **** (define_insn "abssf2" ! [(set (match_operand:SF 0 "general_operand" "f") (abs:SF (match_operand:SF 1 "general_operand" "fmF")))] "TARGET_FPU" --- 1705,1709 ---- (define_insn "abssf2" ! [(set (match_operand:SF 0 "general_operand" "=f") (abs:SF (match_operand:SF 1 "general_operand" "fmF")))] "TARGET_FPU" *************** *** 1711,1715 **** (define_insn "absdf2" ! [(set (match_operand:DF 0 "general_operand" "f") (abs:DF (match_operand:DF 1 "general_operand" "fmF")))] "TARGET_FPU" --- 1711,1715 ---- (define_insn "absdf2" ! [(set (match_operand:DF 0 "general_operand" "=f") (abs:DF (match_operand:DF 1 "general_operand" "fmF")))] "TARGET_FPU" *************** *** 2635,2639 **** (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) ! (set (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "r"))] "FPU_REG_P (operands[0]) && ! FPU_REG_P (operands[1])" --- 2635,2639 ---- (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) ! (set (match_operand:DF 0 "register_operand" "=f") (match_operand:DF 1 "register_operand" "r"))] "FPU_REG_P (operands[0]) && ! FPU_REG_P (operands[1])" diff -rc2N gcc-2.2.2/config/gmon-sol2.c gcc-2.3.1/config/gmon-sol2.c *** gcc-2.2.2/config/gmon-sol2.c --- gcc-2.3.1/config/gmon-sol2.c Mon Jul 27 22:54:08 1992 *************** *** 0 **** --- 1,399 ---- + /*- + * 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. + */ + + /* Mangled into a form that works on Sparc Solaris 2 by Mark Eichin + * for Cygnus Support, July 1992. + */ + + #ifndef lint + static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91"; + #endif /* not lint */ + + #include + + #ifdef DEBUG + #include + #endif + + #if 0 + #include "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 + 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 + + /* extern mcount() asm ("mcount"); */ + /*extern*/ char *minbrk /* asm ("minbrk") */; + + /* + * 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" + + 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 = 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 = 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 ); + } + + /* + * The Sparc stack frame is only held together by the frame pointers + * in the register windows. According to the SVR4 SPARC ABI + * Supplement, Low Level System Information/Operating System + * Interface/Software Trap Types, a type 3 trap will flush all of the + * register windows to the stack, which will make it possible to walk + * the frames and find the return addresses. + * However, it seems awfully expensive to incur a trap (system + * call) for every function call. It turns out that "call" simply puts + * the return address in %o7 expecting the "save" in the procedure to + * shift it into %i7; this means that before the "save" occurs, %o7 + * contains the address of the call to mcount, and %i7 still contains + * the caller above that. The asm mcount here simply saves those + * registers in argument registers and branches to internal_mcount, + * simulating a call with arguments. + * Kludges: + * 1) the branch to internal_mcount is hard coded; it should be + * possible to tell asm to use the assembler-name of a symbol. + * 2) in theory, the function calling mcount could have saved %i7 + * somewhere and reused the register; in practice, I *think* this will + * break longjmp (and maybe the debugger) but I'm not certain. (I take + * some comfort in the knowledge that it will break the native mcount + * as well.) + * 3) if builtin_return_address worked, this could be portable. + * However, it would really have to be optimized for arguments of 0 + * and 1 and do something like what we have here in order to avoid the + * trap per function call performance hit. + * 4) the atexit and monsetup calls prevent this from simply + * being a leaf routine that doesn't do a "save" (and would thus have + * access to %o7 and %i7 directly) but the call to write() at the end + * would have also prevented this. + * + * -- [eichin:19920702.1107EST] + */ + + /* i7 == last ret, -> frompcindex */ + /* o7 == current ret, -> selfpc */ + asm(".global mcount; mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount"); + + static internal_mcount(selfpc, frompcindex) + register char *selfpc; + register unsigned short *frompcindex; + { + register char *nextframe; + register struct tostruct *top; + register struct tostruct *prevtop; + register long toindex; + static char already_setup; + + /* + * find the return address for mcount, + * and the return address for mcount's caller. + */ + + if(!already_setup) { + extern etext(); + already_setup = 1; + monstartup(0, etext); + #ifdef USE_ONEXIT + on_exit(_mcleanup, 0); + #else + atexit(_mcleanup); + #endif + } + /* + * 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 -rc2N gcc-2.2.2/config/hp2bsd.h gcc-2.3.1/config/hp2bsd.h *** gcc-2.2.2/config/hp2bsd.h Sat Jun 13 17:24:30 1992 --- gcc-2.3.1/config/hp2bsd.h Wed Aug 12 03:23:27 1992 *************** *** 22,26 **** /* See m68k.h. 0 means 68000 with no 68881. */ ! #define TARGET_DEFAULT -0102 /* Define __HAVE_68881 in preprocessor only if -m68881 is specified. --- 22,26 ---- /* See m68k.h. 0 means 68000 with no 68881. */ ! #define TARGET_DEFAULT 0 /* Define __HAVE_68881 in preprocessor only if -m68881 is specified. diff -rc2N gcc-2.2.2/config/i386.c gcc-2.3.1/config/i386.c *** gcc-2.2.2/config/i386.c Fri May 15 13:11:23 1992 --- gcc-2.3.1/config/i386.c Sat Oct 31 03:59:37 1992 *************** *** 1,4 **** /* Subroutines for insn-output.c for Intel 80386. ! Copyright (C) 1988 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Subroutines for insn-output.c for Intel 80386. ! Copyright (C) 1988, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 36,40 **** constraint in REG_CLASS_FROM_LETTER will no longer work, and various asm statements that need 'S' for class SIREG will break. */ ! #error EXTRA_CONSTRAINT conflicts with S constraint letter #endif --- 36,42 ---- constraint in REG_CLASS_FROM_LETTER will no longer work, and various asm statements that need 'S' for class SIREG will break. */ ! error EXTRA_CONSTRAINT conflicts with S constraint letter ! /* The previous line used to be #error, but some compilers barf ! even if the conditional was untrue. */ #endif *************** *** 48,54 **** char *output_fp_cc0_set (); ! static char *hi_reg_name[] = HI_REGISTER_NAMES; ! static char *qi_reg_name[] = QI_REGISTER_NAMES; ! static char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES; /* Array of the smallest class containing reg number REGNO, indexed by --- 50,56 ---- char *output_fp_cc0_set (); ! char *hi_reg_name[] = HI_REGISTER_NAMES; ! char *qi_reg_name[] = QI_REGISTER_NAMES; ! char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES; /* Array of the smallest class containing reg number REGNO, indexed by *************** *** 99,103 **** xops[0] = src; xops[1] = AT_SP (Pmode); ! xops[2] = gen_rtx (CONST_INT, VOIDmode, GET_MODE_SIZE (GET_MODE (src))); xops[3] = stack_pointer_rtx; --- 101,105 ---- xops[0] = src; xops[1] = AT_SP (Pmode); ! xops[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (src))); xops[3] = stack_pointer_rtx; *************** *** 128,132 **** xops[0] = AT_SP (Pmode); xops[1] = stack_pointer_rtx; ! xops[2] = gen_rtx (CONST_INT, VOIDmode, GET_MODE_SIZE (GET_MODE (dest))); xops[3] = dest; --- 130,134 ---- xops[0] = AT_SP (Pmode); xops[1] = stack_pointer_rtx; ! xops[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (dest))); xops[3] = dest; *************** *** 222,231 **** if (n < 0) { ! xops[0] = gen_rtx (CONST_INT, VOIDmode, -n); output_asm_insn (AS2 (sub%L0,%0,%1), xops); } else if (n > 0) { ! xops[0] = gen_rtx (CONST_INT, VOIDmode, n); output_asm_insn (AS2 (add%L0,%0,%1), xops); } --- 224,233 ---- if (n < 0) { ! xops[0] = GEN_INT (-n); output_asm_insn (AS2 (sub%L0,%0,%1), xops); } else if (n > 0) { ! xops[0] = GEN_INT (n); output_asm_insn (AS2 (add%L0,%0,%1), xops); } *************** *** 242,245 **** --- 244,248 ---- rtx latehalf[2]; rtx addreg0 = 0, addreg1 = 0; + int dest_overlapped_low = 0; /* First classify both operands. */ *************** *** 351,354 **** --- 354,383 ---- operands[1] = latehalf[1]; + /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)), + if the upper part of reg N does not appear in the MEM, arrange to + emit the move late-half first. Otherwise, compute the MEM address + into the upper part of N and use that as a pointer to the memory + operand. */ + if (optype0 == REGOP + && (optype1 == OFFSOP || optype1 == MEMOP)) + { + if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) + && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) + { + /* If both halves of dest are used in the src memory address, + compute the address into latehalf of dest. */ + rtx xops[2]; + xops[0] = latehalf[0]; + xops[1] = XEXP (operands[1], 0); + output_asm_insn (AS2 (lea%L0,%a1,%0), xops); + operands[1] = gen_rtx (MEM, DImode, latehalf[0]); + latehalf[1] = adj_offsettable_operand (operands[1], 4); + } + else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))) + /* If the low half of dest is mentioned in the source memory + address, the arrange to emit the move late half first. */ + dest_overlapped_low = 1; + } + /* If one or both operands autodecrementing, do the two words, high-numbered first. */ *************** *** 361,365 **** if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP ! && REGNO (operands[0]) == REGNO (latehalf[1]))) { /* Make any unoffsettable addresses point at high-numbered word. */ --- 390,395 ---- if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP ! && REGNO (operands[0]) == REGNO (latehalf[1])) ! || dest_overlapped_low) { /* Make any unoffsettable addresses point at high-numbered word. */ *************** *** 448,452 **** u1.i[1] = CONST_DOUBLE_HIGH (operands[1]); u2.f = u1.d; ! operands[1] = gen_rtx (CONST_INT, VOIDmode, u2.i); } return singlemove_string (operands); --- 478,482 ---- u1.i[1] = CONST_DOUBLE_HIGH (operands[1]); u2.f = u1.d; ! operands[1] = GEN_INT (u2.i); } return singlemove_string (operands); *************** *** 580,584 **** base = legitimize_pic_address (XEXP (addr, 0), reg); ! addr = legitimize_pic_address (XEXP (addr, 1), base == reg ? 0 : reg); if (GET_CODE (addr) == CONST_INT) --- 610,615 ---- base = legitimize_pic_address (XEXP (addr, 0), reg); ! addr = legitimize_pic_address (XEXP (addr, 1), ! base == reg ? NULL_RTX : reg); if (GET_CODE (addr) == CONST_INT) *************** *** 627,631 **** xops[0] = stack_pointer_rtx; xops[1] = frame_pointer_rtx; ! xops[2] = gen_rtx (CONST_INT, VOIDmode, size); if (frame_pointer_needed) { --- 658,662 ---- xops[0] = stack_pointer_rtx; xops[1] = frame_pointer_rtx; ! xops[2] = GEN_INT (size); if (frame_pointer_needed) { *************** *** 789,793 **** /* If there is no frame pointer, we must still release the frame. */ ! xops[0] = gen_rtx (CONST_INT, VOIDmode, size); output_asm_insn (AS2 (add%L2,%0,%2), xops); } --- 820,824 ---- /* If there is no frame pointer, we must still release the frame. */ ! xops[0] = GEN_INT (size); output_asm_insn (AS2 (add%L2,%0,%2), xops); } *************** *** 795,799 **** if (current_function_pops_args && current_function_args_size) { ! xops[1] = gen_rtx (CONST_INT, VOIDmode, current_function_pops_args); /* i386 can only pop 32K bytes (maybe 64K? Is it signed?). If --- 826,830 ---- if (current_function_pops_args && current_function_args_size) { ! xops[1] = GEN_INT (current_function_pops_args); /* i386 can only pop 32K bytes (maybe 64K? Is it signed?). If *************** *** 920,962 **** } - /* Print the name of a register based on its machine mode and number. - If CODE is 'w', pretend the mode is HImode. - If CODE is 'b', pretend the mode is QImode. - If CODE is 'k', pretend the mode is SImode. - If CODE is 'h', pretend the reg is the `high' byte register. - If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */ - - #define PRINT_REG(X, CODE, FILE) \ - do { if (REGNO (X) == ARG_POINTER_REGNUM) \ - abort (); \ - fprintf (FILE, "%s", RP); \ - switch ((CODE == 'w' ? 2 \ - : CODE == 'b' ? 1 \ - : CODE == 'k' ? 4 \ - : CODE == 'y' ? 3 \ - : CODE == 'h' ? 0 \ - : GET_MODE_SIZE (GET_MODE (X)))) \ - { \ - case 3: \ - if (STACK_TOP_P (X)) \ - { \ - fputs ("st(0)", FILE); \ - break; \ - } \ - case 4: \ - case 8: \ - if (!FP_REG_P (X)) fputs ("e", FILE); \ - case 2: \ - fputs (hi_reg_name[REGNO (X)], FILE); \ - break; \ - case 1: \ - fputs (qi_reg_name[REGNO (X)], FILE); \ - break; \ - case 0: \ - fputs (qi_high_reg_name[REGNO (X)], FILE); \ - break; \ - } \ - } while (0) - /* Meaning of CODE: f -- float insn (print a CONST_DOUBLE as a float rather than in hex). --- 951,954 ---- *************** *** 1056,1060 **** default: ! abort (); } } --- 1048,1057 ---- default: ! { ! char str[50]; ! ! sprintf (str, "invalid operand code `%c'", code); ! output_operand_lossage (str); ! } } } *************** *** 1366,1373 **** { CC_STATUS_INIT; ! if (! stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); - - cc_status.flags |= CC_IN_80387; return; } --- 1363,1370 ---- { CC_STATUS_INIT; ! if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) ! cc_status.flags |= CC_IN_80387; ! else cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); return; } *************** *** 1656,1661 **** xops[1] = AT_SP (SImode); xops[2] = adj_offsettable_operand (xops[1], 2); ! xops[3] = gen_rtx (CONST_INT, VOIDmode, 4); ! xops[4] = gen_rtx (CONST_INT, VOIDmode, 0xc00); xops[5] = operands[2]; --- 1653,1658 ---- xops[1] = AT_SP (SImode); xops[2] = adj_offsettable_operand (xops[1], 2); ! xops[3] = GEN_INT (4); ! xops[4] = GEN_INT (0xc00); xops[5] = operands[2]; *************** *** 1798,1802 **** { case GT: ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45); output_asm_insn (AS2 (and%B0,%1,%h0), xops); /* je label */ --- 1795,1799 ---- { case GT: ! xops[1] = GEN_INT (0x45); output_asm_insn (AS2 (and%B0,%1,%h0), xops); /* je label */ *************** *** 1804,1809 **** case LT: ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45); ! xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x01); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); --- 1801,1806 ---- case LT: ! xops[1] = GEN_INT (0x45); ! xops[2] = GEN_INT (0x01); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); *************** *** 1812,1816 **** case GE: ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x05); output_asm_insn (AS2 (and%B0,%1,%h0), xops); /* je label */ --- 1809,1813 ---- case GE: ! xops[1] = GEN_INT (0x05); output_asm_insn (AS2 (and%B0,%1,%h0), xops); /* je label */ *************** *** 1818,1823 **** case LE: ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45); ! xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x40); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS1 (dec%B0,%h0), xops); --- 1815,1820 ---- case LE: ! xops[1] = GEN_INT (0x45); ! xops[2] = GEN_INT (0x40); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS1 (dec%B0,%h0), xops); *************** *** 1827,1832 **** case EQ: ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45); ! xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x40); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); --- 1824,1829 ---- case EQ: ! xops[1] = GEN_INT (0x45); ! xops[2] = GEN_INT (0x40); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); *************** *** 1835,1840 **** case NE: ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x44); ! xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x40); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS2 (xor%B0,%2,%h0), xops); --- 1832,1837 ---- case NE: ! xops[1] = GEN_INT (0x44); ! xops[2] = GEN_INT (0x40); output_asm_insn (AS2 (and%B0,%1,%h0), xops); output_asm_insn (AS2 (xor%B0,%2,%h0), xops); *************** *** 1851,2022 **** RET; } - - #ifdef HANDLE_PRAGMA - - /* When structure field packing is in effect, this variable is the - number of bits to use as the maximum alignment. When packing is not - in effect, this is zero. */ - - int maximum_field_alignment = 0; - - /* Handle a pragma directive. HANDLE_PRAGMA conspires to parse the - input following #pragma into tokens based on yylex. TOKEN is the - current token, and STRING is its printable form. */ - - void - handle_pragma_token (string, token) - char *string; - tree token; - { - static enum pragma_state - { - ps_start, - ps_done, - ps_bad, - ps_weak, - ps_name, - ps_equals, - ps_value, - ps_pack, - ps_left, - ps_align, - ps_right - } state = ps_start, type; - static char *name; - static char *value; - static int align; - - if (string == 0) - { - if (type == ps_pack) - { - if (state == ps_right) - maximum_field_alignment = align * 8; - else - warning ("ignoring malformed #pragma pack( [ 1 | 2 | 4 ] )"); - } - #ifdef WEAK_ASM_OP - else if (type == ps_weak) - { - if (state == ps_name || state == ps_value) - { - fprintf (asm_out_file, "\t%s\t", WEAK_ASM_OP); - ASM_OUTPUT_LABELREF (asm_out_file, name); - fputc ('\n', asm_out_file); - if (state == ps_value) - { - fprintf (asm_out_file, "\t%s\t", SET_ASM_OP); - ASM_OUTPUT_LABELREF (asm_out_file, name); - fputc (',', asm_out_file); - ASM_OUTPUT_LABELREF (asm_out_file, value); - fputc ('\n', asm_out_file); - } - } - else if (! (state == ps_done || state == ps_start)) - warning ("ignoring malformed #pragma weak symbol [=value]"); - } - #endif /* WEAK_ASM_OP */ - - type = state = ps_start; - return; - } - - switch (state) - { - case ps_start: - if (token && TREE_CODE (token) == IDENTIFIER_NODE) - { - if (strcmp (IDENTIFIER_POINTER (token), "pack") == 0) - type = state = ps_pack; - #ifdef WEAK_ASM_OP - else if (strcmp (IDENTIFIER_POINTER (token), "weak") == 0) - type = state = ps_weak; - #endif - else - type = state = ps_done; - } - else - type = state = ps_done; - break; - - #ifdef WEAK_ASM_OP - case ps_weak: - if (token && TREE_CODE (token) == IDENTIFIER_NODE) - { - name = IDENTIFIER_POINTER (token); - state = ps_name; - } - else - state = ps_bad; - break; - - case ps_name: - state = (strcmp (string, "=") ? ps_bad : ps_equals); - break; - - case ps_equals: - if (token && TREE_CODE (token) == IDENTIFIER_NODE) - { - value = IDENTIFIER_POINTER (token); - state = ps_value; - } - else - state = ps_bad; - break; - - case ps_value: - state = ps_bad; - break; - #endif /* WEAK_ASM_OP */ - - case ps_pack: - if (strcmp (string, "(") == 0) - state = ps_left; - else - state = ps_bad; - break; - - case ps_left: - if (token && TREE_CODE (token) == INTEGER_CST - && TREE_INT_CST_HIGH (token) == 0) - switch (TREE_INT_CST_LOW (token)) - { - case 1: - case 2: - case 4: - align = TREE_INT_CST_LOW (token); - state = ps_align; - break; - - default: - state = ps_bad; - } - else if (! token && strcmp (string, ")") == 0) - { - align = 0; - state = ps_right; - } - else - state = ps_bad; - break; - - case ps_align: - if (strcmp (string, ")") == 0) - state = ps_right; - else - state = ps_bad; - break; - - case ps_right: - state = ps_bad; - break; - - case ps_bad: - case ps_done: - break; - - default: - abort (); - } - } - #endif /* HANDLE_PRAGMA */ --- 1848,1849 ---- diff -rc2N gcc-2.2.2/config/i386.h gcc-2.3.1/config/i386.h *** gcc-2.2.2/config/i386.h Sun May 3 22:40:28 1992 --- gcc-2.3.1/config/i386.h Mon Oct 12 09:10:04 1992 *************** *** 38,41 **** --- 38,55 ---- #define I386 1 + /* Stubs for half-pic support if not OSF/1 reference platform. */ + + #ifndef HALF_PIC_P + #define HALF_PIC_P() 0 + #define HALF_PIC_NUMBER_PTRS 0 + #define HALF_PIC_NUMBER_REFS 0 + #define HALF_PIC_ENCODE(DECL) + #define HALF_PIC_DECLARE(NAME) + #define HALF_PIC_INIT() error ("half-pic init called on systems that don't support it.") + #define HALF_PIC_ADDRESS_P(X) 0 + #define HALF_PIC_PTR(X) X + #define HALF_PIC_FINISH(STREAM) + #endif + /* Run-time compilation parameters selecting different hardware subsets. */ *************** *** 44,47 **** --- 58,66 ---- /* Macros used in the machine description to test the flags. */ + /* configure can arrage to make this 2, to force a 486. */ + #ifndef TARGET_CPU_DEFAULT + #define TARGET_CPU_DEFAULT 0 + #endif + /* Compile 80387 insns for floating point (not library calls). */ #define TARGET_80387 (target_flags & 1) *************** *** 67,70 **** --- 86,94 ---- #define TARGET_IEEE_FP (target_flags & 0100) + /* Functions that return a floating point value may return that value + in the 387 FPU or in 386 integer registers. If set, this flag causes + the 387 to be used, which is compatible with most calling conventions. */ + #define TARGET_FLOAT_RETURNS_IN_80387 (target_flags & 0200) + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, *************** *** 75,91 **** #define TARGET_SWITCHES \ { { "80387", 1}, \ { "soft-float", -1}, \ { "486", 2}, \ ! { "no486", -2}, \ { "386", -2}, \ { "rtd", 8}, \ ! { "nortd", -8}, \ { "regparm", 020}, \ ! { "noregparm", -020}, \ { "svr3-shlib", 040}, \ ! { "nosvr3-shlib", -040}, \ { "ieee-fp", 0100}, \ ! { "noieee-fp", -0100}, \ ! { "", TARGET_DEFAULT}} /* target machine storage layout */ --- 99,124 ---- #define TARGET_SWITCHES \ { { "80387", 1}, \ + { "no-80387", -1}, \ { "soft-float", -1}, \ + { "no-soft-float", 1}, \ { "486", 2}, \ ! { "no-486", -2}, \ { "386", -2}, \ { "rtd", 8}, \ ! { "no-rtd", -8}, \ { "regparm", 020}, \ ! { "no-regparm", -020}, \ { "svr3-shlib", 040}, \ ! { "no-svr3-shlib", -040}, \ { "ieee-fp", 0100}, \ ! { "no-ieee-fp", -0100}, \ ! { "fp-ret-in-387", 0200}, \ ! { "no-fp-ret-in-387", -0200}, \ ! SUBTARGET_SWITCHES \ ! { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} ! ! /* This is meant to be redefined in the host dependent files */ ! #define SUBTARGET_SWITCHES ! /* target machine storage layout */ *************** *** 213,216 **** --- 246,258 ---- call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \ } \ + if (! TARGET_80387 && ! TARGET_FLOAT_RETURNS_IN_80387) \ + { \ + int i; \ + HARD_REG_SET x; \ + COPY_HARD_REG_SET (x, reg_class_contents[(int)FLOAT_REGS]); \ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \ + if (TEST_HARD_REG_BIT (x, i)) \ + fixed_regs[i] = call_used_regs[i] = 1; \ + } \ } *************** *** 420,433 **** #define REG_CLASS_FROM_LETTER(C) \ ! ((C) == 'r' ? GENERAL_REGS : \ ! (C) == 'q' ? Q_REGS : \ ! (C) == 'f' ? FLOAT_REGS : \ ! (C) == 't' ? FP_TOP_REG : \ ! (C) == 'u' ? FP_SECOND_REG : \ ! (C) == 'a' ? AREG : \ ! (C) == 'b' ? BREG : \ ! (C) == 'c' ? CREG : \ ! (C) == 'd' ? DREG : \ ! (C) == 'D' ? DIREG : \ (C) == 'S' ? SIREG : NO_REGS) --- 462,481 ---- #define REG_CLASS_FROM_LETTER(C) \ ! ((C) == 'r' ? GENERAL_REGS : \ ! (C) == 'q' ? Q_REGS : \ ! (C) == 'f' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 \ ! ? FLOAT_REGS \ ! : NO_REGS) : \ ! (C) == 't' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 \ ! ? FP_TOP_REG \ ! : NO_REGS) : \ ! (C) == 'u' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 \ ! ? FP_SECOND_REG \ ! : NO_REGS) : \ ! (C) == 'a' ? AREG : \ ! (C) == 'b' ? BREG : \ ! (C) == 'c' ? CREG : \ ! (C) == 'd' ? DREG : \ ! (C) == 'D' ? DIREG : \ (C) == 'S' ? SIREG : NO_REGS) *************** *** 550,553 **** --- 598,605 ---- : (aggregate_value_p (FUNTYPE)) ? GET_MODE_SIZE (Pmode) : 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 0. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ gen_rtx (REG, TYPE_MODE (VALTYPE), \ *************** *** 700,713 **** mov #FUNCTION,eax jmp @eax */ ! #define TRAMPOLINE_TEMPLATE(FILE) \ ! { \ ! ASM_OUTPUT_CHAR (FILE, gen_rtx (CONST_INT, VOIDmode, 0xb9)); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_CHAR (FILE, gen_rtx (CONST_INT, VOIDmode, 0xb8)); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_CHAR (FILE, gen_rtx (CONST_INT, VOIDmode, 0xff)); \ ! ASM_OUTPUT_CHAR (FILE, gen_rtx (CONST_INT, VOIDmode, 0xe0)); \ } --- 752,765 ---- mov #FUNCTION,eax jmp @eax */ ! #define TRAMPOLINE_TEMPLATE(FILE) \ ! { \ ! ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb9)); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb8)); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_SHORT (FILE, const0_rtx); \ ! ASM_OUTPUT_CHAR (FILE, GEN_INT (0xff)); \ ! ASM_OUTPUT_CHAR (FILE, GEN_INT (0xe0)); \ } *************** *** 974,978 **** { register rtx temp = gen_reg_rtx (Pmode); \ register rtx val = force_operand (XEXP (X, 1), temp); \ ! if (val != temp) emit_move_insn (temp, val, 0); \ XEXP (X, 1) = temp; \ goto WIN; } \ --- 1026,1030 ---- { register rtx temp = gen_reg_rtx (Pmode); \ register rtx val = force_operand (XEXP (X, 1), temp); \ ! if (val != temp) emit_move_insn (temp, val); \ XEXP (X, 1) = temp; \ goto WIN; } \ *************** *** 980,984 **** { register rtx temp = gen_reg_rtx (Pmode); \ register rtx val = force_operand (XEXP (X, 0), temp); \ ! if (val != temp) emit_move_insn (temp, val, 0); \ XEXP (X, 0) = temp; \ goto WIN; }}} --- 1032,1036 ---- { register rtx temp = gen_reg_rtx (Pmode); \ register rtx val = force_operand (XEXP (X, 0), temp); \ ! if (val != temp) emit_move_insn (temp, val); \ XEXP (X, 0) = temp; \ goto WIN; }}} *************** *** 1171,1175 **** VOIDmode should be used in all other cases. */ ! #define SELECT_CC_MODE(OP,X) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ && ((OP) == EQ || (OP) == NE) ? CCFPEQmode : CCmode) --- 1223,1227 ---- VOIDmode should be used in all other cases. */ ! #define SELECT_CC_MODE(OP,X,Y) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ && ((OP) == EQ || (OP) == NE) ? CCFPEQmode : CCmode) *************** *** 1229,1234 **** For float regs, the stack top is sometimes referred to as "%st(0)" ! instead of just "%st". PRINT_REG in i386.c handles with with the ! "y" code. */ #define HI_REGISTER_NAMES \ --- 1281,1285 ---- For float regs, the stack top is sometimes referred to as "%st(0)" ! instead of just "%st". PRINT_REG handles this with the "y" code. */ #define HI_REGISTER_NAMES \ *************** *** 1384,1388 **** #define TARGET_FF 014 #define TARGET_CR 015 ! /* 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. --- 1435,1439 ---- #define TARGET_FF 014 #define TARGET_CR 015 ! /* 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. *************** *** 1403,1412 **** ((CODE) == '*') #define PRINT_OPERAND(FILE, X, CODE) \ print_operand (FILE, X, CODE) - #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ print_operand_address (FILE, ADDR) /* Output the prefix for an immediate operand, or for an offset operand. */ --- 1454,1532 ---- ((CODE) == '*') + /* Print the name of a register based on its machine mode and number. + If CODE is 'w', pretend the mode is HImode. + If CODE is 'b', pretend the mode is QImode. + If CODE is 'k', pretend the mode is SImode. + If CODE is 'h', pretend the reg is the `high' byte register. + If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */ + + extern char *hi_reg_name[]; + extern char *qi_reg_name[]; + extern char *qi_high_reg_name[]; + + #define PRINT_REG(X, CODE, FILE) \ + do { if (REGNO (X) == ARG_POINTER_REGNUM) \ + abort (); \ + fprintf (FILE, "%s", RP); \ + switch ((CODE == 'w' ? 2 \ + : CODE == 'b' ? 1 \ + : CODE == 'k' ? 4 \ + : CODE == 'y' ? 3 \ + : CODE == 'h' ? 0 \ + : GET_MODE_SIZE (GET_MODE (X)))) \ + { \ + case 3: \ + if (STACK_TOP_P (X)) \ + { \ + fputs ("st(0)", FILE); \ + break; \ + } \ + case 4: \ + case 8: \ + if (! FP_REG_P (X)) fputs ("e", FILE); \ + case 2: \ + fputs (hi_reg_name[REGNO (X)], FILE); \ + break; \ + case 1: \ + fputs (qi_reg_name[REGNO (X)], FILE); \ + break; \ + case 0: \ + fputs (qi_high_reg_name[REGNO (X)], FILE); \ + break; \ + } \ + } while (0) + #define PRINT_OPERAND(FILE, X, CODE) \ print_operand (FILE, X, CODE) #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ print_operand_address (FILE, ADDR) + + /* Print the name of a register for based on its machine mode and number. + This macro is used to print debugging output. + This macro is different from PRINT_REG in that it may be used in + programs that are not linked with aux-output.o. */ + + #define DEBUG_PRINT_REG(X, CODE, FILE) \ + do { static char *hi_name[] = HI_REGISTER_NAMES; \ + static char *qi_name[] = QI_REGISTER_NAMES; \ + fprintf (FILE, "%s", RP); \ + if (REGNO (X) == ARG_POINTER_REGNUM) \ + { fputs ("argp", FILE); break; } \ + if (STACK_TOP_P (X)) \ + { fputs ("st(0)", FILE); break; } \ + switch (GET_MODE_SIZE (GET_MODE (X))) \ + { \ + case 8: \ + case 4: \ + if (! FP_REG_P (X)) fputs ("e", FILE); \ + case 2: \ + fputs (hi_name[REGNO (X)], FILE); \ + break; \ + case 1: \ + fputs (qi_name[REGNO (X)], FILE); \ + break; \ + } \ + } while (0) /* Output the prefix for an immediate operand, or for an offset operand. */ diff -rc2N gcc-2.2.2/config/i386.md gcc-2.3.1/config/i386.md *** gcc-2.2.2/config/i386.md Wed May 27 13:53:14 1992 --- gcc-2.3.1/config/i386.md Sun Oct 25 15:31:05 1992 *************** *** 53,57 **** ;; of the scas opcode will be the same as the mode of this operand. ;; operand 2 is the known alignment of operand 0. ! ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". --- 53,60 ---- ;; of the scas opcode will be the same as the mode of this operand. ;; operand 2 is the known alignment of operand 0. ! ;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT. ! ;; operand 0 is the argument for `sin'. ! ;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. ! ;; operand 0 is the argument for `cos'. ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". *************** *** 428,432 **** if (GET_CODE (operands[1]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) ! && ! NON_QI_REG_P (operands[0])) { /* We may set the sign bit spuriously. */ --- 431,435 ---- if (GET_CODE (operands[1]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) ! && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) { /* We may set the sign bit spuriously. */ *************** *** 441,446 **** { cc_status.flags |= CC_NOT_NEGATIVE; ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[1]) >> 8); if (QI_REG_P (operands[0])) --- 444,448 ---- { cc_status.flags |= CC_NOT_NEGATIVE; ! operands[1] = GEN_INT (INTVAL (operands[1]) >> 8); if (QI_REG_P (operands[0])) *************** *** 457,463 **** { cc_status.flags |= CC_NOT_NEGATIVE; ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[1]) >> 16); ! operands[0] = adj_offsettable_operand (operands[0], 2); return AS2 (test%B0,%1,%b0); --- 459,463 ---- { cc_status.flags |= CC_NOT_NEGATIVE; ! operands[1] = GEN_INT (INTVAL (operands[1]) >> 16); operands[0] = adj_offsettable_operand (operands[0], 2); return AS2 (test%B0,%1,%b0); *************** *** 467,473 **** && (INTVAL (operands[1]) & ~0xff000000) == 0) { ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (operands[1]) >> 24) & 0xff); ! operands[0] = adj_offsettable_operand (operands[0], 3); return AS2 (test%B0,%1,%b0); --- 467,471 ---- && (INTVAL (operands[1]) & ~0xff000000) == 0) { ! operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff); operands[0] = adj_offsettable_operand (operands[0], 3); return AS2 (test%B0,%1,%b0); *************** *** 490,494 **** if (GET_CODE (operands[1]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) ! && ! NON_QI_REG_P (operands[0])) { if ((INTVAL (operands[1]) & 0xff00) == 0) --- 488,492 ---- if (GET_CODE (operands[1]) == CONST_INT && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) ! && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) { if ((INTVAL (operands[1]) & 0xff00) == 0) *************** *** 496,501 **** /* ??? This might not be necessary. */ if (INTVAL (operands[1]) & 0xffff0000) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[1]) & 0xff); /* We may set the sign bit spuriously. */ --- 494,498 ---- /* ??? This might not be necessary. */ if (INTVAL (operands[1]) & 0xffff0000) ! operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); /* We may set the sign bit spuriously. */ *************** *** 506,511 **** if ((INTVAL (operands[1]) & 0xff) == 0) { ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (operands[1]) >> 8) & 0xff); if (QI_REG_P (operands[0])) --- 503,507 ---- if ((INTVAL (operands[1]) & 0xff) == 0) { ! operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff); if (QI_REG_P (operands[0])) *************** *** 761,765 **** xops[0] = AT_SP (SFmode); ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 4); xops[2] = stack_pointer_rtx; --- 757,761 ---- xops[0] = AT_SP (SFmode); ! xops[1] = GEN_INT (4); xops[2] = stack_pointer_rtx; *************** *** 842,846 **** xops[0] = AT_SP (SFmode); ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 8); xops[2] = stack_pointer_rtx; --- 838,842 ---- xops[0] = AT_SP (SFmode); ! xops[1] = GEN_INT (8); xops[2] = stack_pointer_rtx; *************** *** 937,941 **** (define_insn "movdi" ! [(set (match_operand:DI 0 "general_operand" "=&r,rm") (match_operand:DI 1 "general_operand" "m,riF"))] "" --- 933,937 ---- (define_insn "movdi" ! [(set (match_operand:DI 0 "general_operand" "=r,rm") (match_operand:DI 1 "general_operand" "m,riF"))] "" *************** *** 963,967 **** rtx xops[2]; xops[0] = operands[0]; ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xffff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; --- 959,963 ---- rtx xops[2]; xops[0] = operands[0]; ! xops[1] = GEN_INT (0xffff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; *************** *** 987,991 **** rtx xops[2]; xops[0] = operands[0]; ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; --- 983,987 ---- rtx xops[2]; xops[0] = operands[0]; ! xops[1] = GEN_INT (0xff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; *************** *** 1011,1015 **** rtx xops[2]; xops[0] = operands[0]; ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 0xff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; --- 1007,1011 ---- rtx xops[2]; xops[0] = operands[0]; ! xops[1] = GEN_INT (0xff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; *************** *** 1385,1390 **** { CC_STATUS_INIT; ! operands[1] = SET_SRC (PATTERN (insn)); ! return AS2 (lea%L0,%a1,%0); } --- 1381,1398 ---- { CC_STATUS_INIT; ! ! if (operands[2] == stack_pointer_rtx) ! { ! rtx temp; ! ! temp = operands[1]; ! operands[1] = operands[2]; ! operands[2] = temp; ! } ! if (operands[2] != stack_pointer_rtx) ! { ! operands[1] = SET_SRC (PATTERN (insn)); ! return AS2 (lea%L0,%a1,%0); ! } } *************** *** 1811,1816 **** } ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) & 0xff); return AS2 (and%B0,%2,%b0); } --- 1819,1823 ---- } ! operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); return AS2 (and%B0,%2,%b0); } *************** *** 1826,1831 **** } ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) >> 8); return AS2 (and%B0,%2,%h0); } --- 1833,1837 ---- } ! operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); return AS2 (and%B0,%2,%h0); } *************** *** 1852,1856 **** { /* Can we ignore the upper byte? */ ! if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff00) == 0xff00) { --- 1858,1862 ---- { /* Can we ignore the upper byte? */ ! if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & 0xff00) == 0xff00) { *************** *** 1863,1868 **** } ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) & 0xff); return AS2 (and%B0,%2,%b0); } --- 1869,1873 ---- } ! operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); return AS2 (and%B0,%2,%b0); } *************** *** 1880,1885 **** } ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (operands[2]) >> 8) & 0xff); return AS2 (and%B0,%2,%h0); } --- 1885,1889 ---- } ! operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); return AS2 (and%B0,%2,%h0); } *************** *** 1933,1937 **** && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { ! if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff) == 0) { CC_STATUS_INIT; --- 1937,1942 ---- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { ! if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) ! && (INTVAL (operands[2]) & ~0xff) == 0) { CC_STATUS_INIT; *************** *** 1946,1951 **** { CC_STATUS_INIT; ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) >> 8); if (INTVAL (operands[2]) == 0xff) --- 1951,1955 ---- { CC_STATUS_INIT; ! operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); if (INTVAL (operands[2]) == 0xff) *************** *** 1970,1980 **** { /* Can we ignore the upper byte? */ ! if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff00) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) & 0xffff0000) ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) --- 1974,1983 ---- { /* Can we ignore the upper byte? */ ! if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & 0xff00) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) & 0xffff0000) ! operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) *************** *** 1990,1995 **** { CC_STATUS_INIT; ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (operands[2]) >> 8) & 0xff); if (INTVAL (operands[2]) == 0xff) --- 1993,1997 ---- { CC_STATUS_INIT; ! operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); if (INTVAL (operands[2]) == 0xff) *************** *** 2023,2027 **** && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { ! if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff) == 0) { CC_STATUS_INIT; --- 2025,2030 ---- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { ! if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) ! && (INTVAL (operands[2]) & ~0xff) == 0) { CC_STATUS_INIT; *************** *** 2036,2041 **** { CC_STATUS_INIT; ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) >> 8); if (INTVAL (operands[2]) == 0xff) --- 2039,2043 ---- { CC_STATUS_INIT; ! operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); if (INTVAL (operands[2]) == 0xff) *************** *** 2060,2070 **** { /* Can we ignore the upper byte? */ ! if (! NON_QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff00) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) & 0xffff0000) ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) --- 2062,2071 ---- { /* Can we ignore the upper byte? */ ! if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) && (INTVAL (operands[2]) & 0xff00) == 0) { CC_STATUS_INIT; if (INTVAL (operands[2]) & 0xffff0000) ! operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); if (INTVAL (operands[2]) == 0xff) *************** *** 2080,2085 **** { CC_STATUS_INIT; ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (operands[2]) >> 8) & 0xff); if (INTVAL (operands[2]) == 0xff) --- 2081,2085 ---- { CC_STATUS_INIT; ! operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); if (INTVAL (operands[2]) == 0xff) *************** *** 2181,2185 **** [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] ! "TARGET_80387" "fsqrt") --- 2181,2185 ---- [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsqrt") *************** *** 2187,2191 **** [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] ! "TARGET_80387" "fsqrt") --- 2187,2191 ---- [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsqrt") *************** *** 2194,2199 **** (sqrt:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] ! "TARGET_80387" "fsqrt") ;;- one complement instructions --- 2194,2237 ---- (sqrt:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] ! "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" "fsqrt") + + (define_insn "sindf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] + "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "fsin") + + (define_insn "sinsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] + "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "fsin") + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(float_extend:DF + (match_operand:SF 1 "register_operand" "0"))] 1))] + "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "fsin") + + (define_insn "cosdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] + "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "fcos") + + (define_insn "cossf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] + "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "fcos") + + (define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(float_extend:DF + (match_operand:SF 1 "register_operand" "0"))] 2))] + "TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math)" + "fcos") ;;- one complement instructions *************** *** 2286,2291 **** if (INTVAL (xops[0]) > 32) { ! xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xops[0]) - 32); ! output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */ } --- 2324,2328 ---- if (INTVAL (xops[0]) > 32) { ! xops[0] = GEN_INT (INTVAL (xops[0]) - 32); output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */ } *************** *** 2324,2328 **** output_asm_insn (AS2 (sal%L2,%0,%2), xops); ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); --- 2361,2365 ---- output_asm_insn (AS2 (sal%L2,%0,%2), xops); ! xops[1] = GEN_INT (7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); *************** *** 2355,2361 **** { CC_STATUS_INIT; operands[1] = gen_rtx (MULT, SImode, operands[1], ! gen_rtx (CONST_INT, VOIDmode, ! 1 << INTVAL (operands[2]))); return AS2 (lea%L0,%a1,%0); } --- 2392,2403 ---- { CC_STATUS_INIT; + + if (operands[1] == stack_pointer_rtx) + { + output_asm_insn (AS2 (mov%L0,%1,%0), operands); + operands[1] = operands[0]; + } operands[1] = gen_rtx (MULT, SImode, operands[1], ! GEN_INT (1 << INTVAL (operands[2]))); return AS2 (lea%L0,%a1,%0); } *************** *** 2444,2448 **** if (INTVAL (xops[0]) > 31) { ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 31); output_asm_insn (AS2 (mov%L2,%3,%2), xops); output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ --- 2486,2490 ---- if (INTVAL (xops[0]) > 31) { ! xops[1] = GEN_INT (31); output_asm_insn (AS2 (mov%L2,%3,%2), xops); output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ *************** *** 2450,2456 **** if (INTVAL (xops[0]) > 32) { ! xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xops[0]) - 32); ! ! output_asm_insn (AS2 (sar%2,%0,%2), xops); /* Remaining shift */ } } --- 2492,2497 ---- if (INTVAL (xops[0]) > 32) { ! xops[0] = GEN_INT (INTVAL (xops[0]) - 32); ! output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */ } } *************** *** 2489,2493 **** output_asm_insn (AS2 (sar%L3,%0,%3), xops); ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); --- 2530,2534 ---- output_asm_insn (AS2 (sar%L3,%0,%3), xops); ! xops[1] = GEN_INT (7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); *************** *** 2586,2592 **** if (INTVAL (xops[0]) > 32) { ! xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xops[0]) - 32); ! ! output_asm_insn (AS2 (shr%2,%0,%2), xops); /* Remaining shift */ } } --- 2627,2632 ---- if (INTVAL (xops[0]) > 32) { ! xops[0] = GEN_INT (INTVAL (xops[0]) - 32); ! output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */ } } *************** *** 2625,2629 **** output_asm_insn (AS2 (shr%L3,%0,%3), xops); ! xops[1] = gen_rtx (CONST_INT, VOIDmode, 7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); --- 2665,2669 ---- output_asm_insn (AS2 (shr%L3,%0,%3), xops); ! xops[1] = GEN_INT (7); /* shift count & 1 */ output_asm_insn (AS2 (shr%B0,%1,%0), xops); *************** *** 2771,2779 **** { unsigned int mask = (1 << INTVAL (operands[1])) - 1; ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! ~(mask << INTVAL (operands[2]))); output_asm_insn (AS2 (and%L0,%1,%0), operands); ! operands[3] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[3]) << INTVAL (operands[2])); output_asm_insn (AS2 (or%L0,%3,%0), operands); } --- 2811,2817 ---- { unsigned int mask = (1 << INTVAL (operands[1])) - 1; ! operands[1] = GEN_INT (~(mask << INTVAL (operands[2]))); output_asm_insn (AS2 (and%L0,%1,%0), operands); ! operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2])); output_asm_insn (AS2 (or%L0,%3,%0), operands); } *************** *** 2784,2789 **** output_asm_insn (AS2 (ror%L0,%2,%0), operands); output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! BITS_PER_WORD - INTVAL (operands[1]) - INTVAL (operands[2])); if (INTVAL (operands[2])) --- 2822,2826 ---- output_asm_insn (AS2 (ror%L0,%2,%0), operands); output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); ! operands[2] = GEN_INT (BITS_PER_WORD - INTVAL (operands[1]) - INTVAL (operands[2])); if (INTVAL (operands[2])) *************** *** 2901,2904 **** --- 2938,3004 ---- ;; constraint. + ;; ??? All bets are off if operand 0 is a volatile MEM reference. + + (define_insn "" + [(set (cc0) (zero_extract (match_operand 0 "general_operand" "rm") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "const_int_operand" "n")))] + "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT + && GET_MODE_SIZE (GET_MODE (operands[0])) <= 4 + && (GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0]))" + "* + { + unsigned int mask; + + mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); + operands[1] = GEN_INT (mask); + + if (! REG_P (operands[0]) || QI_REG_P (operands[0])) + { + /* We may set the sign bit spuriously. */ + + if ((mask & ~0xff) == 0) + { + cc_status.flags |= CC_NOT_NEGATIVE; + return AS2 (test%B0,%1,%b0); + } + + if ((mask & ~0xff00) == 0) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = GEN_INT (mask >> 8); + + if (QI_REG_P (operands[0])) + return AS2 (test%B0,%1,%h0); + else + { + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (test%B0,%1,%b0); + } + } + + if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = GEN_INT (mask >> 16); + operands[0] = adj_offsettable_operand (operands[0], 2); + return AS2 (test%B0,%1,%b0); + } + + if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0) + { + cc_status.flags |= CC_NOT_NEGATIVE; + operands[1] = GEN_INT (mask >> 24); + operands[0] = adj_offsettable_operand (operands[0], 3); + return AS2 (test%B0,%1,%b0); + } + } + + if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) + return AS2 (test%L0,%1,%0); + + return AS2 (test%L1,%0,%1); + }") + (define_insn "" [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") *************** *** 2917,2923 **** ;; generates cc0. Generate an equality comparison if `seq' or `sne'. (define_expand "seq" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (eq:QI (cc0) (const_int 0)))] "" --- 3017,3027 ---- ;; generates cc0. Generate an equality comparison if `seq' or `sne'. + ;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may + ;; not have any input reloads. A MEM write might need an input reload + ;; for the address of the MEM. So don't allow MEM as the SET_DEST. + (define_expand "seq" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (eq:QI (cc0) (const_int 0)))] "" *************** *** 2932,2936 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (eq:QI (cc0) (const_int 0)))] "" --- 3036,3040 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (eq:QI (cc0) (const_int 0)))] "" *************** *** 2945,2949 **** (define_expand "sne" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (ne:QI (cc0) (const_int 0)))] "" --- 3049,3053 ---- (define_expand "sne" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (ne:QI (cc0) (const_int 0)))] "" *************** *** 2958,2962 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (ne:QI (cc0) (const_int 0)))] "" --- 3062,3066 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (ne:QI (cc0) (const_int 0)))] "" *************** *** 2972,2976 **** (define_expand "sgt" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (gt:QI (cc0) (const_int 0)))] "" --- 3076,3080 ---- (define_expand "sgt" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (gt:QI (cc0) (const_int 0)))] "" *************** *** 2978,2982 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (gt:QI (cc0) (const_int 0)))] "" --- 3082,3086 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (gt:QI (cc0) (const_int 0)))] "" *************** *** 2986,2995 **** return AS1 (sete,%0); ! OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0); }") (define_expand "sgtu" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (gtu:QI (cc0) (const_int 0)))] "" --- 3090,3099 ---- return AS1 (sete,%0); ! OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR); }") (define_expand "sgtu" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (gtu:QI (cc0) (const_int 0)))] "" *************** *** 2997,3001 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (gtu:QI (cc0) (const_int 0)))] "" --- 3101,3105 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (gtu:QI (cc0) (const_int 0)))] "" *************** *** 3004,3008 **** (define_expand "slt" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (lt:QI (cc0) (const_int 0)))] "" --- 3108,3112 ---- (define_expand "slt" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (lt:QI (cc0) (const_int 0)))] "" *************** *** 3010,3014 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (lt:QI (cc0) (const_int 0)))] "" --- 3114,3118 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (lt:QI (cc0) (const_int 0)))] "" *************** *** 3023,3027 **** (define_expand "sltu" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (ltu:QI (cc0) (const_int 0)))] "" --- 3127,3131 ---- (define_expand "sltu" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (ltu:QI (cc0) (const_int 0)))] "" *************** *** 3029,3033 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (ltu:QI (cc0) (const_int 0)))] "" --- 3133,3137 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (ltu:QI (cc0) (const_int 0)))] "" *************** *** 3036,3040 **** (define_expand "sge" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (ge:QI (cc0) (const_int 0)))] "" --- 3140,3144 ---- (define_expand "sge" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (ge:QI (cc0) (const_int 0)))] "" *************** *** 3042,3046 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (ge:QI (cc0) (const_int 0)))] "" --- 3146,3150 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (ge:QI (cc0) (const_int 0)))] "" *************** *** 3055,3059 **** (define_expand "sgeu" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (geu:QI (cc0) (const_int 0)))] "" --- 3159,3163 ---- (define_expand "sgeu" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (geu:QI (cc0) (const_int 0)))] "" *************** *** 3061,3065 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (geu:QI (cc0) (const_int 0)))] "" --- 3165,3169 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (geu:QI (cc0) (const_int 0)))] "" *************** *** 3068,3072 **** (define_expand "sle" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (le:QI (cc0) (const_int 0)))] "" --- 3172,3176 ---- (define_expand "sle" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (le:QI (cc0) (const_int 0)))] "" *************** *** 3074,3078 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (le:QI (cc0) (const_int 0)))] "" --- 3178,3182 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (le:QI (cc0) (const_int 0)))] "" *************** *** 3082,3091 **** return AS1 (setb,%0); ! OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0); }") (define_expand "sleu" [(match_dup 1) ! (set (match_operand:QI 0 "general_operand" "") (leu:QI (cc0) (const_int 0)))] "" --- 3186,3195 ---- return AS1 (setb,%0); ! OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR); }") (define_expand "sleu" [(match_dup 1) ! (set (match_operand:QI 0 "register_operand" "") (leu:QI (cc0) (const_int 0)))] "" *************** *** 3093,3097 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=qm") (leu:QI (cc0) (const_int 0)))] "" --- 3197,3201 ---- (define_insn "" ! [(set (match_operand:QI 0 "register_operand" "=q") (leu:QI (cc0) (const_int 0)))] "" *************** *** 3190,3194 **** return AS1 (je,%l0); ! OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0); }") --- 3294,3298 ---- return AS1 (je,%l0); ! OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); }") *************** *** 3322,3326 **** return AS1 (jb,%l0); ! OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0); }") --- 3426,3430 ---- return AS1 (jb,%l0); ! OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); }") *************** *** 3388,3392 **** return AS1 (jne,%l0); ! OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0); }") --- 3492,3496 ---- return AS1 (jne,%l0); ! OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); }") *************** *** 3460,3464 **** return AS1 (jae,%l0); ! OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0); }") --- 3564,3568 ---- return AS1 (jae,%l0); ! OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); }") *************** *** 3606,3611 **** --- 3710,3722 ---- " { + rtx addr; + if (flag_pic) current_function_uses_pic_offset_table = 1; + + /* With half-pic, force the address into a register. */ + addr = XEXP (operands[0], 0); + if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) + XEXP (operands[0], 0) = force_reg (Pmode, addr); }") *************** *** 3633,3637 **** (set (reg:SI 7) (plus:SI (reg:SI 7) (match_operand:SI 3 "immediate_operand" "i")))] ! "" "call %P0") --- 3744,3748 ---- (set (reg:SI 7) (plus:SI (reg:SI 7) (match_operand:SI 3 "immediate_operand" "i")))] ! "!HALF_PIC_P ()" "call %P0") *************** *** 3643,3648 **** --- 3754,3766 ---- " { + rtx addr; + if (flag_pic) current_function_uses_pic_offset_table = 1; + + /* With half-pic, force the address into a register. */ + addr = XEXP (operands[0], 0); + if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) + XEXP (operands[0], 0) = force_reg (Pmode, addr); }") *************** *** 3668,3672 **** (match_operand:SI 1 "general_operand" "g"))] ;; Operand 1 not used on the i386. ! "" "call %P0") --- 3786,3790 ---- (match_operand:SI 1 "general_operand" "g"))] ;; Operand 1 not used on the i386. ! "!HALF_PIC_P ()" "call %P0") *************** *** 3684,3689 **** --- 3802,3814 ---- " { + rtx addr; + if (flag_pic) current_function_uses_pic_offset_table = 1; + + /* With half-pic, force the address into a register. */ + addr = XEXP (operands[1], 0); + if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) + XEXP (operands[1], 0) = force_reg (Pmode, addr); }") *************** *** 3715,3719 **** (set (reg:SI 7) (plus:SI (reg:SI 7) (match_operand:SI 4 "immediate_operand" "i")))] ! "" "call %P1") --- 3840,3844 ---- (set (reg:SI 7) (plus:SI (reg:SI 7) (match_operand:SI 4 "immediate_operand" "i")))] ! "!HALF_PIC_P ()" "call %P1") *************** *** 3726,3731 **** --- 3851,3863 ---- " { + rtx addr; + if (flag_pic) current_function_uses_pic_offset_table = 1; + + /* With half-pic, force the address into a register. */ + addr = XEXP (operands[1], 0); + if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) + XEXP (operands[1], 0) = force_reg (Pmode, addr); }") *************** *** 3755,3759 **** (match_operand:SI 2 "general_operand" "g")))] ;; Operand 2 not used on the i386. ! "" "call %P1") --- 3887,3891 ---- (match_operand:SI 2 "general_operand" "g")))] ;; Operand 2 not used on the i386. ! "!HALF_PIC_P ()" "call %P1") *************** *** 3777,3794 **** (define_expand "movstrsi" ! [(parallel [(set (mem:BLK (match_operand:BLK 0 "address_operand" "")) ! (mem:BLK (match_operand:BLK 1 "address_operand" ""))) (use (match_operand:SI 2 "const_int_operand" "")) (use (match_operand:SI 3 "const_int_operand" "")) (clobber (match_scratch:SI 4 "")) ! (clobber (match_dup 0)) ! (clobber (match_dup 1))])] "" " { if (GET_CODE (operands[2]) != CONST_INT) FAIL; ! operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); ! operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); }") --- 3909,3935 ---- (define_expand "movstrsi" ! [(parallel [(set (match_operand:BLK 0 "memory_operand" "") ! (match_operand:BLK 1 "memory_operand" "")) (use (match_operand:SI 2 "const_int_operand" "")) (use (match_operand:SI 3 "const_int_operand" "")) (clobber (match_scratch:SI 4 "")) ! (clobber (match_dup 5)) ! (clobber (match_dup 6))])] "" " { + rtx addr0, addr1; + if (GET_CODE (operands[2]) != CONST_INT) FAIL; ! ! addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); ! addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); ! ! operands[5] = addr0; ! operands[6] = addr1; ! ! operands[0] = gen_rtx (MEM, BLKmode, addr0); ! operands[1] = gen_rtx (MEM, BLKmode, addr1); }") *************** *** 3810,3818 **** rtx xops[2]; if (GET_CODE (operands[2]) == CONST_INT) { if (INTVAL (operands[2]) & ~0x03) { ! xops[0] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) >> 2); xops[1] = operands[4]; --- 3951,3960 ---- rtx xops[2]; + output_asm_insn (\"cld\", operands); if (GET_CODE (operands[2]) == CONST_INT) { if (INTVAL (operands[2]) & ~0x03) { ! xops[0] = GEN_INT (INTVAL (operands[2]) >> 2); xops[1] = operands[4]; *************** *** 3835,3853 **** (define_expand "cmpstrsi" ! [(parallel [(set (match_operand:QI 0 "general_operand" "") ! (compare:CC ! (mem:BLK (match_operand:BLK 1 "address_operand" "")) ! (mem:BLK (match_operand:BLK 2 "address_operand" "")))) (use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 4 "immediate_operand" "")) ! (clobber (match_dup 1)) ! (clobber (match_dup 2)) (clobber (match_dup 3))])] "" " { ! operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); ! operands[2] = copy_to_mode_reg (SImode, XEXP (operands[2], 0)); operands[3] = copy_to_mode_reg (SImode, operands[3]); }") --- 3977,4003 ---- (define_expand "cmpstrsi" ! [(parallel [(set (match_operand:SI 0 "general_operand" "") ! (compare:CC (match_operand:BLK 1 "general_operand" "") ! (match_operand:BLK 2 "general_operand" ""))) (use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 4 "immediate_operand" "")) ! (clobber (match_dup 5)) ! (clobber (match_dup 6)) (clobber (match_dup 3))])] "" " { ! rtx addr1, addr2; ! ! addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); ! addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); operands[3] = copy_to_mode_reg (SImode, operands[3]); + + operands[5] = addr1; + operands[6] = addr2; + + operands[1] = gen_rtx (MEM, BLKmode, addr1); + operands[2] = gen_rtx (MEM, BLKmode, addr2); + }") *************** *** 3864,3868 **** (define_insn "" ! [(set (match_operand:QI 0 "general_operand" "=&q") (compare:CC (mem:BLK (match_operand:SI 1 "address_operand" "S")) (mem:BLK (match_operand:SI 2 "address_operand" "D")))) --- 4014,4018 ---- (define_insn "" ! [(set (match_operand:SI 0 "general_operand" "=&r") (compare:CC (mem:BLK (match_operand:SI 1 "address_operand" "S")) (mem:BLK (match_operand:SI 2 "address_operand" "D")))) *************** *** 3875,3883 **** "* { ! rtx xops[3], label; label = gen_label_rtx (); ! output_asm_insn (AS2 (xor%B0,%0,%0), operands); output_asm_insn (\"repz\;cmps%B2\", operands); output_asm_insn (\"je %l0\", &label); --- 4025,4034 ---- "* { ! rtx xops[4], label; label = gen_label_rtx (); ! output_asm_insn (\"cld\", operands); ! output_asm_insn (AS2 (xor%L0,%0,%0), operands); output_asm_insn (\"repz\;cmps%B2\", operands); output_asm_insn (\"je %l0\", &label); *************** *** 3888,3894 **** xops[2] = gen_rtx (MEM, QImode, gen_rtx (PLUS, SImode, operands[2], constm1_rtx)); ! output_asm_insn (AS2 (mov%B0,%1,%b0), xops); ! output_asm_insn (AS2 (sub%B0,%2,%b0), xops); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); RET; --- 4039,4048 ---- xops[2] = gen_rtx (MEM, QImode, gen_rtx (PLUS, SImode, operands[2], constm1_rtx)); + xops[3] = operands[3]; + + output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops); + output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops); ! output_asm_insn (AS2 (sub%L0,%3,%0), xops); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); RET; *************** *** 3909,3915 **** --- 4063,4072 ---- rtx xops[2]; + cc_status.flags |= CC_NOT_SIGNED; + xops[0] = gen_rtx (REG, QImode, 0); xops[1] = CONST0_RTX (QImode); + output_asm_insn (\"cld\", operands); output_asm_insn (AS2 (test%B0,%1,%0), xops); return \"repz\;cmps%B2\"; *************** *** 4073,4076 **** --- 4230,4234 ---- xops[0] = operands[0]; xops[1] = constm1_rtx; + output_asm_insn (\"cld\", operands); output_asm_insn (AS2 (mov%L0,%1,%0), xops); return \"repnz\;scas%B2\"; diff -rc2N gcc-2.2.2/config/i386bsd.h gcc-2.3.1/config/i386bsd.h *** gcc-2.2.2/config/i386bsd.h Sat Mar 21 15:49:31 1992 --- gcc-2.3.1/config/i386bsd.h Wed Oct 28 18:01:46 1992 *************** *** 3,7 **** #undef CPP_PREDEFINES ! #define CPP_PREDEFINES "-Dunix -Di386" /* Specify extra dir to search for include files. */ --- 3,7 ---- #undef CPP_PREDEFINES ! #define CPP_PREDEFINES "-Dunix -Di386 -D____386BSD____" /* Specify extra dir to search for include files. */ diff -rc2N gcc-2.2.2/config/i386gas.h gcc-2.3.1/config/i386gas.h *** gcc-2.2.2/config/i386gas.h Mon May 25 16:10:20 1992 --- gcc-2.3.1/config/i386gas.h Thu Oct 29 20:15:41 1992 *************** *** 22,25 **** --- 22,31 ---- #include "i386.h" + + #ifndef YES_UNDERSCORES + /* Define this now, because bsd386.h tests it. */ + #define NO_UNDERSCORES + #endif + /* Use the bsd assembler syntax. */ /* we need to do this because gas is really a bsd style assembler, *************** *** 44,54 **** #undef DBX_CONTIN_LENGTH ! /* By default, target has a 80387. */ ! #define TARGET_DEFAULT 1 /* Specify predefined symbols in preprocessor. */ #define CPP_PREDEFINES "-Dunix -Di386" /* Allow #sccs in preprocessor. */ --- 50,61 ---- #undef DBX_CONTIN_LENGTH ! /* Ask for COFF symbols. */ ! #define SDB_DEBUGGING_INFO /* Specify predefined symbols in preprocessor. */ #define CPP_PREDEFINES "-Dunix -Di386" + #define CPP_SPEC "%{posix:-D_POSIX_SOURCE}" /* Allow #sccs in preprocessor. */ *************** *** 60,71 **** #define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME); - /* We do not want to output SDB debugging information. */ - - #undef SDB_DEBUGGING_INFO - - /* We want to output DBX debugging information. */ - - #define DBX_DEBUGGING_INFO - /* Implicit library calls should use memcpy, not bcopy, etc. */ --- 67,70 ---- *************** *** 94,111 **** fprintf ((FILE), "\t.align 2,0x90\n"); /* Use log of 4 as arg. */ - /* Machines that use the AT&T assembler syntax - also return floating point values in an FP register. */ - /* 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 VALUE_REGNO(MODE) \ - (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0) - - /* 1 if N is a possible register number for a function value. */ - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) - #undef ASM_FILE_START #define ASM_FILE_START(FILE) \ --- 93,96 ---- *************** *** 150,151 **** --- 135,158 ---- /* Print opcodes the way that GAS expects them. */ #define GAS_MNEMONICS 1 + + #ifdef NO_UNDERSCORES /* If user-symbols don't have underscores, + then it must take more than `L' to identify + a label that should be ignored. */ + + /* This is how to store into the string BUF + the symbol_ref name of an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. + This is suitable for output with `assemble_name'. */ + + #undef ASM_GENERATE_INTERNAL_LABEL + #define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \ + sprintf ((BUF), ".%s%d", (PREFIX), (NUMBER)) + + /* This is how to output an internal numbered label where + PREFIX is the class of label and NUM is the number within the class. */ + + #undef ASM_OUTPUT_INTERNAL_LABEL + #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM) + + #endif /* NO_UNDERSCORES */ diff -rc2N gcc-2.2.2/config/i386gstabs.h gcc-2.3.1/config/i386gstabs.h *** gcc-2.2.2/config/i386gstabs.h --- gcc-2.3.1/config/i386gstabs.h Wed Oct 28 04:30:36 1992 *************** *** 0 **** --- 1,9 ---- + #include "i386gas.h" + + /* We do not want to output SDB debugging information. */ + + #undef SDB_DEBUGGING_INFO + + /* We want to output DBX debugging information. */ + + #define DBX_DEBUGGING_INFO diff -rc2N gcc-2.2.2/config/i386isc.h gcc-2.3.1/config/i386isc.h *** gcc-2.2.2/config/i386isc.h Fri Mar 13 14:58:13 1992 --- gcc-2.3.1/config/i386isc.h Tue Jul 21 18:57:41 1992 *************** *** 7,40 **** #include "i386v.h" ! /* Use crt1.o, not crt0.o, as a startup file, and crtn.o as a closing file. */ ! #undef STARTFILE_SPEC ! #define STARTFILE_SPEC \ ! "%{!shlib:%{posix:%{pg:mcrtp1.o%s}%{!pg:%{p:mcrtp1.o%s}%{!p:crtp1.o%s}}}\ ! %{!posix:%{pg:mcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}\ ! %{p:-L/lib/libp} %{pg:-L/lib/libp}}}\ ! %{shlib:%{posix:crtp1.o%s}%{!posix:crt1.o%s}} crtbegin.o%s" ! ! #define ENDFILE_SPEC "crtend.o%s crtn.o%s" ! ! /* Library spec */ ! #undef LIB_SPEC ! #define LIB_SPEC "%{posix:-lcposix} %{shlib:-lc_s} -lc -lg" ! ! #if 0 ! /* This is apparently not true: ISC versions up to 3.0,at least, use ! the standard calling sequence in which the called function pops the ! extra arg. */ ! /* caller has to pop the extra argument passed to functions that return ! structures. */ ! ! #undef RETURN_POPS_ARGS ! #define RETURN_POPS_ARGS(FUNTYPE,SIZE) \ ! (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ ! : (TARGET_RTD \ ! && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ ! || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ ! == void_type_node))) ? (SIZE) \ ! : 0) ! /* On other 386 systems, the last line looks like this: ! : (aggregate_value_p (FUNTYPE)) ? GET_MODE_SIZE (Pmode) : 0) */ ! #endif --- 7,10 ---- #include "i386v.h" ! /* But with a few changes. */ ! #include "isc.h" diff -rc2N gcc-2.2.2/config/i386iscgas.h gcc-2.3.1/config/i386iscgas.h *** gcc-2.2.2/config/i386iscgas.h --- gcc-2.3.1/config/i386iscgas.h Mon Jul 27 22:32:25 1992 *************** *** 0 **** --- 1,39 ---- + /* Definitions for Intel 386 running Interactive Unix System V, + producing stabs-in-coff output (using a slightly modified gas). + Specifically, this is for recent versions that support POSIX; + for version 2.0.2, use configuration option i386-sysv instead. */ + + /* Underscores are not used on ISC systems (probably not on any COFF + system), despite the comments in i386gas.h. If this is not defined, + enquire (for example) will fail to link. --karl@cs.umb.edu */ + #define NO_UNDERSCORES + + /* Mostly like other gas-using systems. */ + #include "i386gas.h" + + /* But with ISC-specific additions. */ + #include "isc.h" + + + /* Because we don't include `svr3.h', we haven't yet defined SIZE_TYPE + and PTRDIFF_TYPE. ISC's definitions don't match GCC's defaults, so: */ + + #undef SIZE_TYPE + #define SIZE_TYPE "unsigned int" + + #undef PTRDIFF_TYPE + #define PTRDIFF_TYPE "int" + + + /* But we can't use crtbegin.o and crtend.o, because gas 1.38.1 doesn't + grok .section. The definitions here are otherwise identical to those + in isc.h. */ + #undef STARTFILE_SPEC + #define STARTFILE_SPEC \ + "%{!shlib:%{posix:%{pg:mcrtp1.o%s}%{!pg:%{p:mcrtp1.o%s}%{!p:crtp1.o%s}}}\ + %{!posix:%{pg:mcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}\ + %{p:-L/lib/libp} %{pg:-L/lib/libp}}}\ + %{shlib:%{posix:crtp1.o%s}%{!posix:crt1.o%s}}" + + #undef ENDFILE_SPEC + #define ENDFILE_SPEC "crtn.o%s" diff -rc2N gcc-2.2.2/config/i386linux.h gcc-2.3.1/config/i386linux.h *** gcc-2.2.2/config/i386linux.h --- gcc-2.3.1/config/i386linux.h Thu Oct 29 05:40:29 1992 *************** *** 0 **** --- 1,84 ---- + /* Definitions for Intel 386 running Linux + * Copyright (C) 1992 Free Software Foundation, Inc. + * + * Written by H.J. Lu (hlu@eecs.wsu.edu) + * + * Linux is a POSIX.1 compatible UNIX clone for i386, which uses GNU + * stuffs as the native stuffs. + */ + + #if 0 /* The FSF has fixed the known bugs. But ....... */ + + /* Linux has a hacked gas 1.38.1, which can handle repz, repnz + * and fildll. + */ + + #define GOOD_GAS + + #endif + + /* This is tested by i386gas.h. */ + #define YES_UNDERSCORES + + #include "i386gas.h" + + /* Specify predefined symbols in preprocessor. */ + + #undef CPP_PREDEFINES + #define CPP_PREDEFINES "-Dunix -Di386 -Dlinux" + + #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 HAVE_ATEXIT + #define HAVE_ATEXIT + + /* 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 + + #undef LIB_SPEC + #define LIB_SPEC "%{g*:-lg} %{!g*:%{!p:%{!pg:-lc}}%{p:-lgmon -lc_p}%{pg:-lgmon -lc_p}}" + + + #undef STARTFILE_SPEC + #undef GPLUSPLUS_INCLUDE_DIR + + #ifdef CROSS_COMPILE + + /* + * For cross-compile, we just need to search `$(tooldir)/lib' + */ + + #define STARTFILE_SPEC \ + "%{g*:crt0.o%s} %{!g*:%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s %{!static:%{nojump:-nojump}} %{static:-static}}}} -L"TOOLDIR"/lib" + + /* + *The cross-compile uses this. + */ + #define GPLUSPLUS_INCLUDE_DIR TOOLDIR"/g++-include" + + #else + + #define STARTFILE_SPEC \ + "%{g*:crt0.o%s} %{!g*:%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s %{!static:%{nojump:-nojump}} %{static:-static}}}}" + + /* + *The native Linux system uses this. + */ + #define GPLUSPLUS_INCLUDE_DIR "/usr/g++-include" + + #endif diff -rc2N gcc-2.2.2/config/i386mach.h gcc-2.3.1/config/i386mach.h *** gcc-2.2.2/config/i386mach.h Sun Mar 15 00:18:49 1992 --- gcc-2.3.1/config/i386mach.h Tue Sep 22 23:39:35 1992 *************** *** 7,10 **** --- 7,13 ---- /* Specify extra dir to search for include files. */ #define SYSTEM_INCLUDE_DIR "/usr/mach/include" + + /* Make stddef.h agree with types.h. */ + #define SIZE_TYPE "long int" /* Defines to be able to build libgcc.a with GCC. */ *************** *** 61,73 **** auto unsigned short nstatus; \ auto int ret; \ \ &ostatus; /* guarantee these land in memory */ \ &nstatus; \ &ret; \ \ asm volatile ("fnstcw %0" : "=m" (ostatus)); \ nstatus = ostatus | 0x0c00; \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (nstatus)); \ ! asm volatile ("fldl %0" : /* no outputs */ : "m" (a)); \ asm volatile ("fistpl %0" : "=m" (ret)); \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (ostatus)); \ --- 64,79 ---- auto unsigned short nstatus; \ auto int ret; \ + auto double tmp; \ \ &ostatus; /* guarantee these land in memory */ \ &nstatus; \ &ret; \ + &tmp; \ \ asm volatile ("fnstcw %0" : "=m" (ostatus)); \ nstatus = ostatus | 0x0c00; \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (nstatus)); \ ! tmp = a; \ ! asm volatile ("fldl %0" : /* no outputs */ : "m" (tmp)); \ asm volatile ("fistpl %0" : "=m" (ret)); \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (ostatus)); \ diff -rc2N gcc-2.2.2/config/i386rose.h gcc-2.3.1/config/i386rose.h *** gcc-2.2.2/config/i386rose.h Thu May 7 17:17:13 1992 --- gcc-2.3.1/config/i386rose.h Thu Oct 29 15:01:30 1992 *************** *** 1,4 **** /* Definitions of target machine for GNU compiler. ! Encore Multimax (OSF/1 with OSF/rose) version. Copyright (C) 1991 Free Software Foundation, Inc. --- 1,4 ---- /* Definitions of target machine for GNU compiler. ! Intel 386 (OSF/1 with OSF/rose) version. Copyright (C) 1991 Free Software Foundation, Inc. *************** *** 19,44 **** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "halfpic.h" ! #include "i386gas.h" #define OSF_OS ! /* Use a more friendly abort which prints internal compiler error, ! rather than just dumping core. */ ! ! #ifndef abort ! #define abort fancy_abort ! #endif ! ! #define MASK_HALF_PIC 0x00000100 /* Mask for half-pic code */ ! #define TARGET_HALF_PIC (target_flags & MASK_HALF_PIC) ! #ifdef SUBTARGET_SWITCHES ! #undef SUBTARGET_SWITCHES ! #endif #define SUBTARGET_SWITCHES \ ! { "half-pic", MASK_HALF_PIC}, \ ! { "no-half-pic", -MASK_HALF_PIC}, ! /* Prefix that appears before all global/static identifiers, except for temporary labels. */ --- 19,50 ---- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Put leading underscores in front of names. */ + #define YES_UNDERSCORES + #include "halfpic.h" ! #include "i386gstabs.h" #define OSF_OS ! #undef WORD_SWITCH_TAKES_ARG ! #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ ! || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ ! || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ ! || !strcmp (STR, "pic-names")) ! ! #define MASK_HALF_PIC 0x40000000 /* Mask for half-pic code */ ! #define MASK_HALF_PIC_DEBUG 0x20000000 /* Debug flag */ ! ! #define TARGET_HALF_PIC (target_flags & MASK_HALF_PIC) ! #define TARGET_DEBUG (target_flags & MASK_HALF_PIC_DEBUG) ! #define HALF_PIC_DEBUG TARGET_DEBUG ! #undef SUBTARGET_SWITCHES #define SUBTARGET_SWITCHES \ ! { "half-pic", MASK_HALF_PIC}, \ ! { "no-half-pic", -MASK_HALF_PIC}, \ ! { "debugb", MASK_HALF_PIC_DEBUG}, ! /* Prefix that appears before all global/static identifiers, except for temporary labels. */ *************** *** 52,63 **** /* Change default predefines. */ ! #ifdef CPP_PREDEFINES ! #undef CPP_PREDEFINES ! #endif #define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Di386" - #ifdef CPP_SPEC #undef CPP_SPEC - #endif #define CPP_SPEC "\ %{.S: -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ --- 58,65 ---- /* Change default predefines. */ ! #undef CPP_PREDEFINES #define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Di386" #undef CPP_SPEC #define CPP_SPEC "\ %{.S: -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ *************** *** 68,125 **** %{!.S: -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" ! #ifdef CC1_SPEC #undef CC1_SPEC ! #endif ! #define CC1_SPEC \ ! "%{pic-none: -mno-half-pic} \ ! %{pic-lib: -mhalf-pic} \ ! %{pic-extern: -mhalf-pic} \ ! %{pic-calls: -mhalf-pic}" ! #ifdef ASM_SPEC ! #undef ASM_SPEC ! #endif #define ASM_SPEC "" - #ifdef LINK_SPEC #undef LINK_SPEC - #endif #define LINK_SPEC "%{v*: -v} \ %{!noshrlib: %{pic-none: -noshrlib} %{!pic-none: -warn_nopic}} \ %{nostdlib} %{noshrlib} %{glue}" - #ifdef LIB_SPEC #undef LIB_SPEC - #endif - #define LIB_SPEC "-lc" - #ifdef LIBG_SPEC #undef LIBG_SPEC ! #endif ! #define LIBG_SPEC "" - #ifdef STARTFILE_SPEC #undef STARTFILE_SPEC - #endif #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}" ! #ifdef MACHINE_TYPE ! #undef MACHINE_TYPE ! #endif ! #define MACHINE_TYPE ((!TARGET_486) ? "80386 running OSF/1 with OSF/rose objects" : \ ! "80486 running OSF/1 with OSF/rose objects") ! #ifdef MD_EXEC_PREFIX #undef MD_EXEC_PREFIX - #endif #define MD_EXEC_PREFIX "/usr/ccs/gcc/" - #ifdef MD_STARTFILE_PREFIX #undef MD_STARTFILE_PREFIX - #endif #define MD_STARTFILE_PREFIX "/usr/ccs/lib/" /* Tell final.c we don't need a label passed to mcount. */ #define NO_PROFILE_DATA --- 70,126 ---- %{!.S: -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" ! /* Turn on -mpic-extern by default. */ #undef CC1_SPEC ! #define CC1_SPEC "\ ! %{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \ ! %{pic-none: -mno-half-pic} \ ! %{pic-lib: -mhalf-pic} \ ! %{pic-extern: -mhalf-pic} \ ! %{pic-calls: -mhalf-pic} \ ! %{pic-names*: -mhalf-pic} \ ! %{!pic-*: -mhalf-pic}" ! #undef ASM_SPEC #define ASM_SPEC "" #undef LINK_SPEC #define LINK_SPEC "%{v*: -v} \ %{!noshrlib: %{pic-none: -noshrlib} %{!pic-none: -warn_nopic}} \ %{nostdlib} %{noshrlib} %{glue}" #undef LIB_SPEC #define LIB_SPEC "-lc" #undef LIBG_SPEC ! #define LIBG_SPEC "" #undef STARTFILE_SPEC #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}" ! #undef TARGET_VERSION_INTERNAL ! #undef TARGET_VERSION ! #define I386_VERSION " 80386, OSF/rose objects" ! #define TARGET_VERSION_INTERNAL(STREAM) fputs (I386_VERSION, STREAM) ! #define TARGET_VERSION TARGET_VERSION_INTERNAL (stderr) ! #undef MD_EXEC_PREFIX #define MD_EXEC_PREFIX "/usr/ccs/gcc/" #undef MD_STARTFILE_PREFIX #define MD_STARTFILE_PREFIX "/usr/ccs/lib/" + /* Specify size_t, ptrdiff_t, and wchar_t types. */ + #undef SIZE_TYPE + #undef PTRDIFF_TYPE + #undef WCHAR_TYPE + #undef WCHAR_TYPE_SIZE + + #define SIZE_TYPE "long unsigned int" + #define PTRDIFF_TYPE "int" + #define WCHAR_TYPE "unsigned int" + #define WCHAR_TYPE_SIZE BITS_PER_WORD + /* Tell final.c we don't need a label passed to mcount. */ #define NO_PROFILE_DATA *************** *** 140,163 **** #define OPTIMIZATION_OPTIONS(LEVEL) \ { \ ! flag_gnu_linker = FALSE; \ ! \ ! if (LEVEL) \ ! { \ ! flag_omit_frame_pointer = TRUE; \ ! flag_thread_jumps = TRUE; \ ! } \ ! \ ! if (LEVEL >= 2) \ ! { \ ! flag_strength_reduce = TRUE; \ ! flag_cse_follow_jumps = TRUE; \ ! flag_expensive_optimizations = TRUE; \ ! flag_rerun_cse_after_loop = TRUE; \ ! } \ \ if (LEVEL >= 3) \ ! { \ ! flag_inline_functions = TRUE; \ ! } \ } --- 141,148 ---- #define OPTIMIZATION_OPTIONS(LEVEL) \ { \ ! flag_gnu_linker = FALSE; \ \ if (LEVEL >= 3) \ ! flag_inline_functions = TRUE; \ } *************** *** 172,181 **** addition to `const_int' and `const_double' expressions. */ ! #ifdef CONSTANT_ADDRESS_P ! #undef CONSTANT_ADDRESS_P ! #endif #define CONSTANT_ADDRESS_P(X) \ (CONSTANT_P (X) && (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (X))) /* Define this macro if references to a symbol must be treated differently depending on something about the variable or --- 157,219 ---- addition to `const_int' and `const_double' expressions. */ ! #undef CONSTANT_ADDRESS_P #define CONSTANT_ADDRESS_P(X) \ (CONSTANT_P (X) && (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (X))) + /* Nonzero if the constant value X is a legitimate general operand. + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ + + #undef LEGITIMATE_CONSTANT_P + #define LEGITIMATE_CONSTANT_P(X) \ + (!HALF_PIC_P () \ + || GET_CODE (X) == CONST_DOUBLE \ + || GET_CODE (X) == CONST_INT \ + || !HALF_PIC_ADDRESS_P (X)) + + /* 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. */ + + #undef GO_IF_LEGITIMATE_ADDRESS + #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ + { \ + if (CONSTANT_P (X)) \ + { \ + if (! HALF_PIC_P () || ! HALF_PIC_ADDRESS_P (X)) \ + goto ADDR; \ + } \ + else \ + { \ + GO_IF_INDEXING (X, ADDR); \ + \ + if (GET_CODE (X) == PLUS) \ + { \ + rtx x1 = XEXP (X, 1); \ + \ + if (CONSTANT_P (x1)) \ + { \ + if (! HALF_PIC_P () || ! HALF_PIC_ADDRESS_P (x1)) \ + { \ + rtx x0 = XEXP (X, 0); \ + GO_IF_INDEXING (x0, ADDR); \ + } \ + } \ + } \ + } \ + } + + /* 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. */ + + #define OVERRIDE_OPTIONS \ + { \ + if (TARGET_HALF_PIC) \ + half_pic_init (); \ + } + /* Define this macro if references to a symbol must be treated differently depending on something about the variable or *************** *** 202,208 **** `PRINT_OPERAND_ADDRESS'. */ ! #ifdef ENCODE_SECTION_INFO ! #undef ENCODE_SECTION_INFO ! #endif #define ENCODE_SECTION_INFO(DECL) \ do \ --- 240,244 ---- `PRINT_OPERAND_ADDRESS'. */ ! #undef ENCODE_SECTION_INFO #define ENCODE_SECTION_INFO(DECL) \ do \ *************** *** 214,217 **** --- 250,286 ---- + /* Given a decl node or constant node, choose the section to output it in + and select that section. */ + + #undef SELECT_RTX_SECTION + #define SELECT_RTX_SECTION(MODE, RTX) \ + do \ + { \ + if (MODE == Pmode && HALF_PIC_P () && HALF_PIC_ADDRESS_P (RTX)) \ + data_section (); \ + else \ + readonly_data_section (); \ + } \ + while (0) + + #undef SELECT_SECTION + #define SELECT_SECTION(DECL,RELOC) \ + { \ + if (TREE_CODE (DECL) == STRING_CST) \ + { \ + if (flag_writable_strings) \ + data_section (); \ + else \ + readonly_data_section (); \ + } \ + else if (TREE_CODE (DECL) != VAR_DECL) \ + readonly_data_section (); \ + else if (!TREE_READONLY (DECL)) \ + data_section (); \ + else \ + readonly_data_section (); \ + } + + /* A C statement (sans semicolon) to output to the stdio stream STREAM any text necessary for declaring the name NAME of an *************** *** 224,230 **** in the usual manner as a label (by means of `ASM_OUTPUT_LABEL'). */ ! #ifdef ASM_DECLARE_OBJECT_NAME ! #undef ASM_DECLARE_OBJECT_NAME ! #endif #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \ do \ --- 293,297 ---- in the usual manner as a label (by means of `ASM_OUTPUT_LABEL'). */ ! #undef ASM_DECLARE_OBJECT_NAME #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \ do \ *************** *** 245,248 **** --- 312,324 ---- while (0) + /* This says what to print at the end of the assembly file */ + #define ASM_FILE_END(STREAM) \ + do \ + { \ + if (HALF_PIC_P ()) \ + HALF_PIC_FINISH (STREAM); \ + } \ + while (0) + /* Tell collect that the object format is OSF/rose. */ #define OBJECT_FORMAT_ROSE *************** *** 267,293 **** /* This is how to output an assembler line defining a `double' constant. */ ! #ifdef ASM_OUTPUT_DOUBLE ! #undef ASM_OUTPUT_DOUBLE #endif - #define ASM_OUTPUT_DOUBLE(STREAM,VALUE) \ - { \ - union { double d; long l[2]; } u2; \ - u2.d = VALUE; \ - fprintf (STREAM, "\t.long\t0x%08lx\t\t# %.20g\n\t.long\t0x%08lx\n", \ - u2.l[0], u2.d, u2.l[1]); \ - } /* This is how to output an assembler line defining a `float' constant. */ ! #ifdef ASM_OUTPUT_FLOAT ! #undef ASM_OUTPUT_FLOAT #endif - #define ASM_OUTPUT_FLOAT(STREAM,VALUE) \ - { \ - union { float f; long l; } u2; \ - u2.f = VALUE; \ - fprintf (STREAM, "\t.long\t0x%08lx\t\t# %.12g\n", u2.l, u2.f); \ - } /* Generate calls to memcpy, etc., not bcopy, etc. */ #define TARGET_MEM_FUNCTIONS --- 343,387 ---- /* This is how to output an assembler line defining a `double' constant. */ ! #undef ASM_OUTPUT_DOUBLE ! ! #ifndef CROSS_COMPILE ! #define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \ ! do \ ! { \ ! long value_long[2]; \ ! REAL_VALUE_TO_TARGET_DOUBLE (VALUE, value_long); \ ! \ ! fprintf (STREAM, "\t.long\t0x%08lx\t\t# %.20g\n\t.long\t0x%08lx\n", \ ! value_long[0], VALUE, value_long[1]); \ ! } \ ! while (0) ! ! #else ! #define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \ ! fprintf (STREAM, "\t.double\t%.20g\n", VALUE) #endif /* This is how to output an assembler line defining a `float' constant. */ ! #undef ASM_OUTPUT_FLOAT ! ! #ifndef CROSS_COMPILE ! #define ASM_OUTPUT_FLOAT(STREAM, VALUE) \ ! do \ ! { \ ! long value_long; \ ! REAL_VALUE_TO_TARGET_SINGLE (VALUE, value_long); \ ! \ ! fprintf (STREAM, "\t.long\t0x%08lx\t\t# %.12g (float)\n", \ ! value_long, VALUE); \ ! } \ ! while (0) ! ! #else ! #define ASM_OUTPUT_FLOAT(STREAM, VALUE) \ ! fprintf (STREAM, "\t.float\t%.12g\n", VALUE) #endif + /* Generate calls to memcpy, etc., not bcopy, etc. */ #define TARGET_MEM_FUNCTIONS *************** *** 297,300 **** --- 391,398 ---- /* Defines to be able to build libgcc.a with GCC. */ + /* It might seem that these are not important, since gcc 2 will never + call libgcc for these functions. But programs might be linked with + code compiled by gcc 1, and then these will be used. */ + #define perform_udivsi3(a,b) \ { \ *************** *** 344,356 **** auto unsigned short nstatus; \ auto int ret; \ \ &ostatus; /* guarantee these land in memory */ \ &nstatus; \ &ret; \ \ asm volatile ("fnstcw %0" : "=m" (ostatus)); \ nstatus = ostatus | 0x0c00; \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (nstatus)); \ ! asm volatile ("fldl %0" : /* no outputs */ : "m" (a)); \ asm volatile ("fistpl %0" : "=m" (ret)); \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (ostatus)); \ --- 442,457 ---- auto unsigned short nstatus; \ auto int ret; \ + auto double tmp; \ \ &ostatus; /* guarantee these land in memory */ \ &nstatus; \ &ret; \ + &tmp; \ \ asm volatile ("fnstcw %0" : "=m" (ostatus)); \ nstatus = ostatus | 0x0c00; \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (nstatus)); \ ! tmp = a; \ ! asm volatile ("fldl %0" : /* no outputs */ : "m" (tmp)); \ asm volatile ("fistpl %0" : "=m" (ret)); \ asm volatile ("fldcw %0" : /* no outputs */ : "m" (ostatus)); \ diff -rc2N gcc-2.2.2/config/i386sco.h gcc-2.3.1/config/i386sco.h *** gcc-2.2.2/config/i386sco.h Wed May 27 22:34:40 1992 --- gcc-2.3.1/config/i386sco.h Sat Oct 10 05:26:55 1992 *************** *** 6,9 **** --- 6,20 ---- #include "i386v.h" + /* By default, target has a 80387, uses IEEE compatible arithmetic, + and returns float values in the 387, ie, + (TARGET_80387 | TARGET_FLOAT_RETURNS_IN_80387) + + SCO's software emulation of a 387 fails to handle the `fucomp' + opcode. fucomp is only used when generating IEEE compliant code. + So don't make TARGET_IEEE_FP default for SCO. */ + + #undef TARGET_DEFAULT + #define TARGET_DEFAULT 0201 + /* Use crt1.o as a startup file and crtn.o as a closing file. */ diff -rc2N gcc-2.2.2/config/i386sun.h gcc-2.3.1/config/i386sun.h *** gcc-2.2.2/config/i386sun.h Thu Feb 27 07:50:32 1992 --- gcc-2.3.1/config/i386sun.h Mon Aug 31 00:06:08 1992 *************** *** 25,32 **** #include "sun386.h" - /* By default, target has a 80387. */ - - #define TARGET_DEFAULT 1 - /* Use crt0.o as a startup file. */ --- 25,28 ---- *************** *** 39,43 **** #undef LINK_SPEC ! #define LINK_SPEC "%{!e*:-e _start} -dc -dp %{static:-Bstatic}" /* Extra switches to give the assembler. */ --- 35,40 ---- #undef LINK_SPEC ! #define LINK_SPEC \ ! "%{!nostdlib:%{!r*:%{!e*:-e _start}}} -dc -dp %{static:-Bstatic}" /* Extra switches to give the assembler. */ *************** *** 49,52 **** --- 46,53 ---- #define CPP_PREDEFINES "-Dunix -Di386 -Dsun386 -Dsun" + /* Define size_t for built-in functions. */ + + #define SIZE_TYPE "int" + /* Allow #sccs in preprocessor. */ *************** *** 72,87 **** #define PCC_BITFIELD_TYPE_MATTERS 1 - - /* 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 VALUE_REGNO(MODE) \ - (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0) - - /* 1 if N is a possible register number for a function value. */ - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) /* This is partly guess. */ --- 73,76 ---- diff -rc2N gcc-2.2.2/config/i386v.h gcc-2.3.1/config/i386v.h *** gcc-2.2.2/config/i386v.h Sat Mar 28 23:50:08 1992 --- gcc-2.3.1/config/i386v.h Mon Aug 31 00:06:09 1992 *************** *** 30,37 **** #include "att386.h" - /* By default, target has a 80387. */ - - #define TARGET_DEFAULT 1 - /* Use crt1.o as a startup file and crtn.o as a closing file. */ --- 30,33 ---- *************** *** 59,84 **** #define ASM_FILE_START_1(FILE) - /* Machines that use the AT&T assembler syntax - also return floating point values in an FP register. */ - /* 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 VALUE_REGNO(MODE) \ - (((MODE) == SFmode || (MODE) == DFmode) ? FIRST_FLOAT_REG : 0) - - /* 1 if N is a possible register number for a function value. */ - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) - - #if 0 /* This symbol is expected to exist only on BSD, - and besides, it describes the host rather than the target. - It certainly does not belong here. */ - #ifndef MAXPATHLEN - #define MAXPATHLEN 1024 - #endif - #endif - /* longjmp may fail to restore the registers if called from the same function that called setjmp. To compensate, the compiler avoids --- 55,58 ---- diff -rc2N gcc-2.2.2/config/i386v4.h gcc-2.3.1/config/i386v4.h *** gcc-2.2.2/config/i386v4.h Thu May 28 14:41:14 1992 --- gcc-2.3.1/config/i386v4.h Fri Oct 2 22:30:59 1992 *************** *** 23,49 **** #include "att386.h" /* Use the i386 AT&T assembler syntax */ #include "svr4.h" /* Definitions common to all SVR4 targets */ - #include "real.h" #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (i386 System V Release 4)"); - /* By default, target has a 80387. */ - - #define TARGET_DEFAULT 1 - - /* Machines that use the AT&T assembler syntax - also return floating point values in an FP register. */ - /* 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 VALUE_REGNO(MODE) \ - (((MODE) == SFmode || (MODE) == DFmode) ? FIRST_FLOAT_REG : 0) - - /* 1 if N is a possible register number for a function value. */ - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) - /* The svr4 ABI for the i386 says that records and unions are returned in memory. */ --- 23,30 ---- *************** *** 126,130 **** 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 compatability with. The verison of x86/svr4 SDB I have at the moment does (partially) --- 107,111 ---- 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 verison of x86/svr4 SDB I have at the moment does (partially) *************** *** 174,178 **** : (n) == 7 ? 4 \ : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ ! : (abort (), 0)) /* The routine used to output sequences of byte values. We use a special --- 155,159 ---- : (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 *************** *** 255,284 **** #define PCC_BITFIELD_TYPE_MATTERS (maximum_field_alignment == 0) ! /* Code to handle #pragma directives. The interface is a bit messy, ! but there's no simpler way to do this while still using yylex. */ ! #define HANDLE_PRAGMA(FILE) \ ! do { \ ! while (c == ' ' || c == '\t') \ ! c = getc (FILE); \ ! if (c == '\n' || c == EOF) \ ! { \ ! handle_pragma_token (0, 0); \ ! return c; \ ! } \ ! ungetc (c, FILE); \ ! switch (yylex ()) \ ! { \ ! case IDENTIFIER: \ ! case TYPENAME: \ ! case STRING: \ ! case CONSTANT: \ ! handle_pragma_token (token_buffer, yylval.ttype); \ ! break; \ ! default: \ ! handle_pragma_token (token_buffer, 0); \ ! } \ ! if (nextchar >= 0) \ ! c = nextchar, nextchar = -1; \ ! else \ ! c = getc (FILE); \ ! } while (1) --- 236,239 ---- #define PCC_BITFIELD_TYPE_MATTERS (maximum_field_alignment == 0) ! /* Handle #pragma pack and sometimes #pragma weak. */ ! #define HANDLE_SYSV_PRAGMA diff -rc2N gcc-2.2.2/config/i860.c gcc-2.3.1/config/i860.c *** gcc-2.2.2/config/i860.c Sat Jun 13 17:49:04 1992 --- gcc-2.3.1/config/i860.c Thu Jul 23 02:08:19 1992 *************** *** 352,494 **** } } - - /* Nonzero only if this *really* is a single insn operand. */ - int - strict_single_insn_op_p (op, mode) - rtx op; - enum machine_mode mode; - { - if (mode == VOIDmode) - mode = GET_MODE (op); - - switch (GET_CODE (op)) - { - case CC0: - return 1; - - case CONST_INT: - if (SMALL_INT (op)) - return 1; - /* We can put this set insn into delay slot, because this is one - insn; `orh'. */ - if ((INTVAL (op) & 0xffff) == 0) - return 1; - return 0; - - case SYMBOL_REF: - return 0; - - case REG: - #if 0 - /* This loses when moving an freg to a general reg. */ - return HARD_REGNO_NREGS (REGNO (op), mode) == 1; - #endif - return (mode != DFmode && mode != DImode); - - case MEM: - if (! CONSTANT_ADDRESS_P (XEXP (op, 0))) - return (mode != DFmode && mode != DImode); - return 0; - - /* We never need to negate or complement constants. */ - case NEG: - return (mode != DFmode); - case NOT: - case ZERO_EXTEND: - return 1; - - case PLUS: - case MINUS: - /* Detect cases that require multiple instructions. */ - if (CONSTANT_P (XEXP (op, 1)) - && !(GET_CODE (XEXP (op, 1)) == CONST_INT - && SMALL_INT (XEXP (op, 1)))) - return 0; - case EQ: - case NE: - case LT: - case GT: - case LE: - case GE: - case LTU: - case GTU: - case LEU: - case GEU: - return 1; - - case AND: - if (GET_CODE (XEXP (op, 1)) == NOT) - { - rtx arg = XEXP (XEXP (op, 1), 0); - if (CONSTANT_P (arg) - && !(GET_CODE (arg) == CONST_INT - && (SMALL_INT (arg) - || INTVAL (arg) & 0xffff == 0))) - return 0; - } - case IOR: - case XOR: - /* Both small and round numbers take one instruction; - others take two. */ - if (CONSTANT_P (XEXP (op, 1)) - && !(GET_CODE (XEXP (op, 1)) == CONST_INT - && (SMALL_INT (XEXP (op, 1)) - || INTVAL (XEXP (op, 1)) & 0xffff == 0))) - return 0; - - case LSHIFT: - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - return 1; - - case SUBREG: - if (SUBREG_WORD (op) != 0) - return 0; - return strict_single_insn_op_p (SUBREG_REG (op), mode); - - case SIGN_EXTEND: - if (GET_CODE (XEXP (op, 0)) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0))) - return 1; - return 0; - - /* Not doing floating point, since they probably - take longer than the branch slot they might fill. */ - case FLOAT_EXTEND: - case FLOAT_TRUNCATE: - case FLOAT: - case FIX: - case UNSIGNED_FLOAT: - case UNSIGNED_FIX: - return 0; - - default: - return 0; - } - } - - /* Return truth value of whether OP is a relational operator. */ - int - relop (op, mode) - rtx op; - enum machine_mode mode; - { - switch (GET_CODE (op)) - { - case EQ: - case NE: - case GT: - case GE: - case LT: - case LE: - case GTU: - case GEU: - case LTU: - case LEU: - return 1; - } - return 0; - } /* Return non-zero only if OP is a register of mode MODE, --- 352,355 ---- diff -rc2N gcc-2.2.2/config/i860.h gcc-2.3.1/config/i860.h *** gcc-2.2.2/config/i860.h Sun Jun 14 18:15:12 1992 --- gcc-2.3.1/config/i860.h Sun Oct 18 04:37:09 1992 *************** *** 76,79 **** --- 76,85 ---- numbered. */ /* For the i860 this goes with BYTES_BIG_ENDIAN. */ + /* NOTE: GCC probably cannot support a big-endian i860 + because GCC fundamentally assumes that the order of words + in memory as the same as the order in registers. + That's not true for the big-endian i860. + The big-endian i860 isn't important enough to + justify the trouble of changing this assumption. */ #define WORDS_BIG_ENDIAN 0 *************** *** 202,206 **** #define HARD_REGNO_MODE_OK(REGNO, MODE) \ (((REGNO) < 32) \ ! || ((MODE) == VOIDmode) \ || REGNO_MODE_ALIGNED (REGNO, MODE)) --- 208,212 ---- #define HARD_REGNO_MODE_OK(REGNO, MODE) \ (((REGNO) < 32) \ ! || (MODE) == VOIDmode || (MODE) == BLKmode \ || REGNO_MODE_ALIGNED (REGNO, MODE)) *************** *** 1056,1061 **** labels a jump table. */ ! #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ ! fprintf (FILE, "\t.align\t4\n.%s%d:\n", PREFIX, NUM) /* Output at the end of a jump table. */ --- 1062,1070 ---- labels a jump table. */ ! #undef ASM_OUTPUT_CASE_LABEL ! #define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \ ! do { ASM_OUTPUT_ALIGN ((FILE), 2); \ ! ASM_OUTPUT_INTERNAL_LABEL ((FILE), PREFIX, NUM); \ ! } while (0) /* Output at the end of a jump table. */ *************** *** 1278,1301 **** output_address (XEXP (X, 0)); \ else if ((CODE) == 'L') \ ! if (GET_CODE (X) == MEM) \ ! PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_LOW_PART); \ ! else \ ! PRINT_OPERAND_PART (FILE, X, OPERAND_LOW_PART); \ else if ((CODE) == 'H') \ ! if (GET_CODE (X) == MEM) \ ! PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_HIGH_PART); \ ! else \ ! PRINT_OPERAND_PART (FILE, X, OPERAND_HIGH_PART); \ else if ((CODE) == 'h') \ ! if (GET_CODE (X) == MEM) \ ! PRINT_OPERAND_PART (FILE, XEXP (X, 0), \ ! const_int_operand (XEXP (X, 0)) \ ! ? OPERAND_HIGH_PART \ ! : OPERAND_HIGH_ADJ_PART); \ ! else \ ! PRINT_OPERAND_PART (FILE, X, \ ! const_int_operand (X) \ ! ? OPERAND_HIGH_PART \ ! : OPERAND_HIGH_ADJ_PART); \ else if (GET_CODE (X) == MEM) \ output_address (XEXP (X, 0)); \ --- 1287,1310 ---- output_address (XEXP (X, 0)); \ else if ((CODE) == 'L') \ ! { \ ! if (GET_CODE (X) == MEM) \ ! PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_LOW_PART); \ ! else \ ! PRINT_OPERAND_PART (FILE, X, OPERAND_LOW_PART); \ ! } \ else if ((CODE) == 'H') \ ! { \ ! if (GET_CODE (X) == MEM) \ ! PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_HIGH_PART); \ ! else \ ! PRINT_OPERAND_PART (FILE, X, OPERAND_HIGH_PART); \ ! } \ else if ((CODE) == 'h') \ ! { \ ! if (GET_CODE (X) == MEM) \ ! PRINT_OPERAND_PART (FILE, XEXP (X, 0), OPERAND_HIGH_ADJ_PART); \ ! else \ ! PRINT_OPERAND_PART (FILE, X, OPERAND_HIGH_ADJ_PART); \ ! } \ else if (GET_CODE (X) == MEM) \ output_address (XEXP (X, 0)); \ diff -rc2N gcc-2.2.2/config/i860.md gcc-2.3.1/config/i860.md *** gcc-2.2.2/config/i860.md Sat Jun 13 17:49:54 1992 --- gcc-2.3.1/config/i860.md Fri Sep 4 23:20:52 1992 *************** *** 498,576 **** ;; Simple BTE/BTNE compare-and-branch insns made by combining. (define_insn "" [(set (pc) - (if_then_else (eq (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "bte_operand" "rK")) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bte %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "bte_operand" "rK")) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "btne %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "bte_operand" "rK")) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "btne %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "bte_operand" "rK")) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "bte %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:HI 0 "register_operand" "r") - (match_operand:HI 1 "bte_operand" "rK")) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bte %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:HI 0 "register_operand" "r") - (match_operand:HI 1 "bte_operand" "rK")) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "btne %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:HI 0 "register_operand" "r") - (match_operand:HI 1 "bte_operand" "rK")) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "btne %1,%0,%2") - - (define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:HI 0 "register_operand" "r") - (match_operand:HI 1 "bte_operand" "rK")) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "bte %1,%0,%2") - - (define_insn "" - [(set (pc) (if_then_else (eq (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "bte_operand" "rK")) --- 498,506 ---- ;; Simple BTE/BTNE compare-and-branch insns made by combining. + ;; Note that it is wrong to add similar patterns for QI or HImode + ;; because bte/btne always compare the whole register. (define_insn "" [(set (pc) (if_then_else (eq (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "bte_operand" "rK")) *************** *** 1770,1773 **** --- 1700,1735 ---- " { + if (WORDS_BIG_ENDIAN) + emit_insn (gen_mulsi3_big (operands[0], operands[1], operands[2])); + else + emit_insn (gen_mulsi3_little (operands[0], operands[1], operands[2])); + DONE; + }") + + (define_expand "mulsi3_little" + [(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" "")) + (set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" "")) + (clobber (match_dup 3)) + (set (subreg:SI (match_dup 3) 0) + (mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0))) + (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))] + "! WORDS_BIG_ENDIAN" + " + { + operands[3] = gen_reg_rtx (DImode); + operands[4] = gen_reg_rtx (DImode); + operands[5] = gen_reg_rtx (DImode); + }") + + (define_expand "mulsi3_big" + [(set (subreg:SI (match_dup 4) 1) (match_operand:SI 1 "general_operand" "")) + (set (subreg:SI (match_dup 5) 1) (match_operand:SI 2 "general_operand" "")) + (clobber (match_dup 3)) + (set (subreg:SI (match_dup 3) 1) + (mult:SI (subreg:SI (match_dup 4) 1) (subreg:SI (match_dup 5) 1))) + (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 1))] + "WORDS_BIG_ENDIAN" + " + { operands[3] = gen_reg_rtx (DImode); operands[4] = gen_reg_rtx (DImode); *************** *** 1779,1783 **** (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 0) (subreg:SI (match_operand:DI 2 "register_operand" "f") 0)))] ! "" "fmlow.dd %2,%1,%0") --- 1741,1752 ---- (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 0) (subreg:SI (match_operand:DI 2 "register_operand" "f") 0)))] ! "! WORDS_BIG_ENDIAN" ! "fmlow.dd %2,%1,%0") ! ! (define_insn "" ! [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 1) ! (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 1) ! (subreg:SI (match_operand:DI 2 "register_operand" "f") 1)))] ! "WORDS_BIG_ENDIAN" "fmlow.dd %2,%1,%0") diff -rc2N gcc-2.2.2/config/i860b.h gcc-2.3.1/config/i860b.h *** gcc-2.2.2/config/i860b.h Sat Jun 13 17:50:04 1992 --- gcc-2.3.1/config/i860b.h Fri Jul 3 16:34:09 1992 *************** *** 1,4 **** --- 1,7 ---- #include "i860.h" + #undef TARGET_VERSION + #define TARGET_VERSION fprintf (stderr, " (i860, BSD)") + /* BSD UN*X systems use BSD STABS debugging info. */ diff -rc2N gcc-2.2.2/config/i860mach.h gcc-2.3.1/config/i860mach.h *** gcc-2.2.2/config/i860mach.h --- gcc-2.3.1/config/i860mach.h Thu Jul 30 00:02:41 1992 *************** *** 0 **** --- 1,12 ---- + /* Configuration for an i860 running Mach as the target machine. */ + + #include "i860.h" + + #undef TARGET_VERSION + #define TARGET_VERSION fprintf (stderr, " (i860 Mach3.x)"); + + #undef CPP_PREDEFINES + #define CPP_PREDEFINES "-Dunix -Di860 -DMACH" + + /* Specify extra dir to search for include files. */ + #define SYSTEM_INCLUDE_DIR "/usr/mach/include" diff -rc2N gcc-2.2.2/config/i860v3.h gcc-2.3.1/config/i860v3.h *** gcc-2.2.2/config/i860v3.h Sat Jun 13 17:50:32 1992 --- gcc-2.3.1/config/i860v3.h Thu Jul 30 00:54:53 1992 *************** *** 23,29 **** #include "svr3.h" /* Provide a set of pre-definitions and pre-assertions appropriate for the i860 running svr3. */ ! #define CPP_PREDEFINES "-Di860 -Dunix -DSVR3" /* Use crt1.o as a startup file and crtn.o as a closing file. */ --- 23,32 ---- #include "svr3.h" + #undef TARGET_VERSION + #define TARGET_VERSION fprintf (stderr, " (i860, System V Release 3)") + /* Provide a set of pre-definitions and pre-assertions appropriate for the i860 running svr3. */ ! #define CPP_PREDEFINES "-Di860 -Dunix -D__svr3__" /* Use crt1.o as a startup file and crtn.o as a closing file. */ *************** *** 157,159 **** --- 160,163 ---- /* Enable the `const' section that svr3.h defines how to use. */ + #undef USE_CONST_SECTION #define USE_CONST_SECTION 1 diff -rc2N gcc-2.2.2/config/i960.c gcc-2.3.1/config/i960.c *** gcc-2.2.2/config/i960.c Sat Jun 13 19:00:15 1992 --- gcc-2.3.1/config/i960.c Thu Oct 22 15:15:54 1992 *************** *** 58,66 **** enum insn_types i960_last_insn_type; - /* Where to save/restore register 14 to/from before/after a procedure call - when it holds an argument block pointer. */ - - static rtx g14_save_reg; - /* The leaf-procedure return register. Set only if this is a leaf routine. */ --- 58,61 ---- *************** *** 434,438 **** { rtx cc_reg; ! enum machine_mode ccmode = SELECT_CC_MODE (code, x); enum machine_mode mode = GET_MODE (x) == VOIDmode ? GET_MODE (y) : GET_MODE (x); --- 429,433 ---- { rtx cc_reg; ! enum machine_mode ccmode = SELECT_CC_MODE (code, x, y); enum machine_mode mode = GET_MODE (x) == VOIDmode ? GET_MODE (y) : GET_MODE (x); *************** *** 494,498 **** return 6; ! abort (); } if (GET_CODE (x) == MULT) --- 489,495 ---- return 6; ! /* This is an invalid address. The return value doesn't matter, but ! for convenience we make this more expensive than anything else. */ ! return 12; } if (GET_CODE (x) == MULT) *************** *** 596,600 **** else if (mode == DImode) { ! rtx upperhalf, lowerhalf; char *string; --- 593,597 ---- else if (mode == DImode) { ! rtx upperhalf, lowerhalf, xoperands[2]; char *string; *************** *** 619,625 **** /* Output the upper half with a recursive call. */ ! string = i960_output_ldconst (gen_rtx (REG, SImode, REGNO (dst) + 1), ! upperhalf); ! output_asm_insn (string); /* The lower word is emitted as normally. */ } --- 616,623 ---- /* Output the upper half with a recursive call. */ ! xoperands[0] = gen_rtx (REG, SImode, REGNO (dst) + 1); ! xoperands[1] = upperhalf; ! output_asm_insn (i960_output_ldconst (xoperands[0], xoperands[1]), ! xoperands); /* The lower word is emitted as normally. */ } *************** *** 627,637 **** { #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! union { long l; float f; } flt; ! flt.f = (float) *((double *) &CONST_DOUBLE_LOW (src)); output_asm_insn ("# ldconst %1,%0",operands); operands[0] = gen_rtx (REG, SImode, REGNO (dst)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, flt.l); output_asm_insn (i960_output_ldconst (operands[0], operands[1]), operands); --- 625,637 ---- { #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! REAL_VALUE_TYPE d; ! long value; ! REAL_VALUE_FROM_CONST_DOUBLE (d, src); ! REAL_VALUE_TO_TARGET_SINGLE (d, value); output_asm_insn ("# ldconst %1,%0",operands); operands[0] = gen_rtx (REG, SImode, REGNO (dst)); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, value); output_asm_insn (i960_output_ldconst (operands[0], operands[1]), operands); *************** *** 734,738 **** /* Determine if there is an opportunity for a bypass optimization. ! Bypass suceeds on the 960K* if the destination of the previous instruction is the second operand of the current instruction. Bypass always succeeds on the C*. --- 734,738 ---- /* Determine if there is an opportunity for a bypass optimization. ! Bypass succeeds on the 960K* if the destination of the previous instruction is the second operand of the current instruction. Bypass always succeeds on the C*. *************** *** 1186,1201 **** char * ! i960_output_call_insn (target, argsize_rtx, insn) ! register rtx target, argsize_rtx, insn; { - int non_indirect; int argsize = INTVAL (argsize_rtx); rtx nexti = next_real_insn (insn); ! rtx operands[1]; operands[0] = target; ! non_indirect = ((GET_CODE (target) == MEM) ! && (GET_CODE (XEXP (target, 0)) == SYMBOL_REF)); /* Nexti could be zero if the called routine is volatile. */ --- 1186,1212 ---- char * ! i960_output_call_insn (target, argsize_rtx, arg_pointer, scratch_reg, insn) ! register rtx target, argsize_rtx, arg_pointer, scratch_reg, insn; { int argsize = INTVAL (argsize_rtx); rtx nexti = next_real_insn (insn); ! rtx operands[3]; operands[0] = target; + operands[1] = arg_pointer; + operands[2] = scratch_reg; ! if (current_function_args_size != 0) ! output_asm_insn ("mov g14,%2", operands); ! ! if (argsize > 48) ! output_asm_insn ("lda %a1,g14", operands); ! else if (current_function_args_size != 0) ! output_asm_insn ("mov 0,g14", operands); ! ! /* The code used to assume that calls to SYMBOL_REFs could not be more ! than 24 bits away (b vs bx, callj vs callx). This is not true. This ! feature is now implemented by relaxing in the GNU linker. It can convert ! bx to b if in range, and callx to calls/call/balx/bal as appropriate. */ /* Nexti could be zero if the called routine is volatile. */ *************** *** 1206,1215 **** if (nexti && no_labels_between_p (insn, nexti)) delete_insn (nexti); ! output_asm_insn (non_indirect ? "b %0" : "bx %0", ! operands); return "# notreached"; } ! output_asm_insn (non_indirect ? "callj %0" : "callx %0", operands); return ""; } --- 1217,1229 ---- if (nexti && no_labels_between_p (insn, nexti)) delete_insn (nexti); ! output_asm_insn ("bx %0", operands); return "# notreached"; } ! output_asm_insn ("callx %0", operands); ! ! if (current_function_args_size != 0) ! output_asm_insn ("mov %2,g14", operands); ! return ""; } *************** *** 1967,1994 **** return ret; } - - /* Return the rtx for the register representing the return value, or 0 - if the return value must be passed through the stack. */ - - rtx - i960_function_value (type) - tree type; - { - int mode = TYPE_MODE (type); - - if (mode == BLKmode) - { - unsigned int size = int_size_in_bytes (type); - - if (size <= 16) - mode = mode_for_size (i960_object_bytes_bitalign (size), MODE_INT, 0); - } - - if (mode == BLKmode || mode == VOIDmode) - /* Tell stmt.c and expr.c to pass in address */ - return 0; - else - return gen_rtx (REG, mode, 0); - } /* Floating-point support. */ --- 1981,1984 ---- *************** *** 2040,2044 **** tree tsize; { ! int size, align; if (TREE_CODE (tsize) != INTEGER_CST) --- 2030,2034 ---- tree tsize; { ! int size, byte_size, align; if (TREE_CODE (tsize) != INTEGER_CST) *************** *** 2046,2050 **** size = TREE_INT_CST_LOW (tsize); ! align = i960_object_bytes_bitalign (size / BITS_PER_UNIT); /* Handle #pragma align. */ --- 2036,2041 ---- size = TREE_INT_CST_LOW (tsize); ! byte_size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; ! align = i960_object_bytes_bitalign (byte_size); /* Handle #pragma align. */ *************** *** 2065,2078 **** tree tsize; { if (TREE_CODE (tsize) != INTEGER_CST) return align; ! align = i960_object_bytes_bitalign (TREE_INT_CST_LOW (tsize) ! / BITS_PER_UNIT); return align; } /* Do any needed setup for a varargs function. For the i960, we must ! create a register paramter block if one doesn't exist, and then copy all register parameters to memory. */ --- 2056,2071 ---- tree tsize; { + int byte_size; + if (TREE_CODE (tsize) != INTEGER_CST) return align; ! byte_size = (TREE_INT_CST_LOW (tsize) + BITS_PER_UNIT - 1) / BITS_PER_UNIT; ! align = i960_object_bytes_bitalign (byte_size); return align; } /* Do any needed setup for a varargs function. For the i960, we must ! create a register parameter block if one doesn't exist, and then copy all register parameters to memory. */ *************** *** 2180,2257 **** return LOCAL_OR_GLOBAL_REGS; - } - - /* Emit the code necessary for a procedure call. Return value is needed - after the call if target is non-zero. */ - - void - i960_expand_call (first_operand, second_operand, target) - rtx first_operand, second_operand, target; - { - /* Used to ensure that g14_save_reg is initialized once and only once - for each function if it is needed. */ - static char *this_function_name = 0; - int frob_g14 = 0; - - if (this_function_name != current_function_name) - { - rtx seq, first; - struct sequence_stack *seq_stack; - - this_function_name = current_function_name; - - /* If the current function has an argument block, then save g14 into - a pseudo at the top of the function and restore it after this - function call. If the current function has no argument block, - then g14 is zero before and after the call. */ - - if (current_function_args_size != 0) - { - start_sequence (); - seq_stack = sequence_stack; - while (seq_stack->next) - seq_stack = seq_stack->next; - first = seq_stack->first; - g14_save_reg = copy_to_reg (arg_pointer_rtx); - seq = gen_sequence (); - end_sequence (); - emit_insn_after (seq, first); - } - } - - if (current_function_args_size != 0) - frob_g14 = 1; - - if (GET_CODE (second_operand) != CONST_INT || INTVAL (second_operand) > 48) - { - /* Calling a function needing an argument block. */ - emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx, - virtual_outgoing_args_rtx)); - } - else - { - /* Calling a normal function -- only set to zero if we know our g14 - is nonzero. */ - if (frob_g14) - emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx, const0_rtx)); - } - - if (target) - emit_call_insn (gen_rtx (SET, VOIDmode, target, - gen_rtx (CALL, VOIDmode, first_operand, - second_operand))); - else - emit_call_insn (gen_rtx (CALL, VOIDmode, first_operand, second_operand)); - - if (frob_g14) - emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx, g14_save_reg)); - else if (GET_CODE (second_operand) != CONST_INT - || INTVAL (second_operand) > 48) - { - /* Calling a function needing an argument block. It will have set - reg14 back to zero before returning, so we must emit a clobber here - to tell cse that g14 has changed. */ - emit_insn (gen_rtx (CLOBBER, VOIDmode, arg_pointer_rtx)); - } } --- 2173,2176 ---- diff -rc2N gcc-2.2.2/config/i960.h gcc-2.3.1/config/i960.h *** gcc-2.2.2/config/i960.h Sat Jun 13 19:00:37 1992 --- gcc-2.3.1/config/i960.h Thu Oct 22 15:15:47 1992 *************** *** 85,93 **** %{mka:-lfpg}%{msa:-lfpg}%{mca:-lfpg}%{mcf:-lfpg} -lgnu}" - /* These compiler options take an argument. */ - #define WORD_SWITCH_TAKES_ARG(STR) \ - (!strcmp (STR, "Tdata") || !strcmp (STR, "include") \ - || !strcmp (STR, "imacros") || !strcmp (STR, "Ttext")) - /* Omit frame pointer at -O2. Inline functions at -O3. */ #define OPTIMIZATION_OPTIONS(LEVEL) \ --- 85,88 ---- *************** *** 293,302 **** target_flags |= TARGET_FLAG_CLEAN_LINKAGE; \ } \ - /* ??? Function inlining is not supported, because the i960 \ - calling convention requires the caller to manage the arg \ - pointer in a wierd fashion. This is ordinarily done by \ - expand_call, but this is never called when inlining \ - functions, and no replacement for it exists. */ \ - flag_no_inline = 1; \ i960_initialize (); \ } --- 288,291 ---- *************** *** 827,832 **** otherwise, FUNC is 0. */ ! extern struct rtx_def *i960_function_value (); ! #define FUNCTION_VALUE(TYPE, FUNC) i960_function_value (TYPE) /* Force objects larger than 16 bytes to be returned in memory, since we --- 816,821 ---- otherwise, FUNC is 0. */ ! #define FUNCTION_VALUE(TYPE, FUNC) \ ! gen_rtx (REG, TYPE_MODE (TYPE), 0) /* Force objects larger than 16 bytes to be returned in memory, since we *************** *** 1106,1110 **** PLUS, MINUS, or NEG. CCmode should be used when no special processing is needed. */ ! #define SELECT_CC_MODE(OP,X) select_cc_mode (OP, X) /* A function address in a call instruction is a byte address --- 1095,1099 ---- PLUS, MINUS, or NEG. CCmode should be used when no special processing is needed. */ ! #define SELECT_CC_MODE(OP,X,Y) select_cc_mode (OP, X,Y) /* A function address in a call instruction is a byte address diff -rc2N gcc-2.2.2/config/i960.md gcc-2.3.1/config/i960.md *** gcc-2.2.2/config/i960.md Sat Jun 13 19:00:59 1992 --- gcc-2.3.1/config/i960.md Tue Oct 20 17:07:20 1992 *************** *** 23,26 **** --- 23,33 ---- ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. + ;; There are very few (4) 'f' registers, they can't be loaded/stored from/to + ;; memory, and some instructions explicitly require them, so we get better + ;; code by discouraging psuedo-registers from being allocated to them. + ;; However, we do want to allow all patterns which can store to them to + ;; include them in their constraints, so we always use '*f' in a destination + ;; constraint except when 'f' is the only alternative. + ;; Insn attributes which describe the i960. *************** *** 49,53 **** ;; (define_function_unit {name} {num-units} {n-users} {test} ! ;; {ready-delay} {busy-delay} [{conflict-list}]) ;; The integer ALU --- 56,60 ---- ;; (define_function_unit {name} {num-units} {n-users} {test} ! ;; {ready-delay} {issue-delay} [{conflict-list}]) ;; The integer ALU *************** *** 527,531 **** ;; Normal move instructions. ! ;; This code is based on the sparc machine desciption. (define_expand "movsi" --- 534,538 ---- ;; Normal move instructions. ! ;; This code is based on the sparc machine description. (define_expand "movsi" *************** *** 774,779 **** ;; The store case can not be separate. See comment above. (define_insn "" ! [(set (match_operand:DI 0 "general_operand" "=d,d,d,m") ! (match_operand:DI 1 "general_operand" "dI,i,m,dJ"))] "current_function_args_size == 0 && (register_operand (operands[0], DImode) --- 781,786 ---- ;; The store case can not be separate. See comment above. (define_insn "" ! [(set (match_operand:DI 0 "general_operand" "=d,d,d,m,o") ! (match_operand:DI 1 "general_operand" "dI,i,m,d,J"))] "current_function_args_size == 0 && (register_operand (operands[0], DImode) *************** *** 791,800 **** return \"ldl %1,%0\"; case 3: - if (operands[1] == const0_rtx) - return \"st g14,%0\;st g14,4(%0)\"; return \"stl %1,%0\"; } }" ! [(set_attr "type" "move,load,load,store")]) ;; The store case can not be separate. See comment above. --- 798,808 ---- return \"ldl %1,%0\"; case 3: return \"stl %1,%0\"; + case 4: + operands[1] = adj_offsettable_operand (operands[0], 4); + return \"st g14,%0\;st g14,%1\"; } }" ! [(set_attr "type" "move,load,load,store,store")]) ;; The store case can not be separate. See comment above. *************** *** 833,838 **** ;; The store case can not be separate. See comment above. (define_insn "" ! [(set (match_operand:TI 0 "general_operand" "=d,d,d,m") ! (match_operand:TI 1 "general_operand" "dI,i,m,dJ"))] "current_function_args_size == 0 && (register_operand (operands[0], TImode) --- 841,846 ---- ;; The store case can not be separate. See comment above. (define_insn "" ! [(set (match_operand:TI 0 "general_operand" "=d,d,d,m,o") ! (match_operand:TI 1 "general_operand" "dI,i,m,d,J"))] "current_function_args_size == 0 && (register_operand (operands[0], TImode) *************** *** 850,859 **** return \"ldq %1,%0\"; case 3: - if (operands[1] == const0_rtx) - return \"st g14,%0\;st g14,4(%0)\;st g14,8(%0)\;st g14,12(%0)\"; return \"stq %1,%0\"; } }" ! [(set_attr "type" "move,load,load,store")]) ;; The store case can not be separate. See comment above. --- 858,870 ---- return \"ldq %1,%0\"; case 3: return \"stq %1,%0\"; + case 4: + operands[1] = adj_offsettable_operand (operands[0], 4); + operands[2] = adj_offsettable_operand (operands[0], 8); + operands[3] = adj_offsettable_operand (operands[0], 12); + return \"st g14,%0\;st g14,%1\;st g14,%2\;st g14,%3\"; } }" ! [(set_attr "type" "move,load,load,store,store")]) ;; The store case can not be separate. See comment above. *************** *** 946,951 **** (define_insn "" ! [(set (match_operand:DF 0 "general_operand" "=r,f,d,d,m") ! (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,dG"))] "current_function_args_size == 0 && (register_operand (operands[0], DFmode) --- 957,962 ---- (define_insn "" ! [(set (match_operand:DF 0 "general_operand" "=r,*f,d,d,m,o") ! (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d,G"))] "current_function_args_size == 0 && (register_operand (operands[0], DFmode) *************** *** 968,980 **** return \"ldl %1,%0\"; case 4: - if (operands[1] == CONST0_RTX (DFmode)) - return \"st g14,%0\;st g14,4(%0)\"; return \"stl %1,%0\"; } }" ! [(set_attr "type" "move,move,load,fpload,fpstore")]) (define_insn "" ! [(set (match_operand:DF 0 "general_operand" "=r,f,d,d,m") (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "current_function_args_size != 0 --- 979,992 ---- return \"ldl %1,%0\"; case 4: return \"stl %1,%0\"; + case 5: + operands[1] = adj_offsettable_operand (operands[0], 4); + return \"st g14,%0\;st g14,%1\"; } }" ! [(set_attr "type" "move,move,load,fpload,fpstore,fpstore")]) (define_insn "" ! [(set (match_operand:DF 0 "general_operand" "=r,*f,d,d,m") (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "current_function_args_size != 0 *************** *** 1013,1017 **** (define_insn "" ! [(set (match_operand:SF 0 "general_operand" "=r,f,d,d,m") (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,dG"))] "current_function_args_size == 0 --- 1025,1029 ---- (define_insn "" ! [(set (match_operand:SF 0 "general_operand" "=r,*f,d,d,m") (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,dG"))] "current_function_args_size == 0 *************** *** 1043,1047 **** (define_insn "" ! [(set (match_operand:SF 0 "general_operand" "=r,f,d,d,m") (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "current_function_args_size != 0 --- 1055,1059 ---- (define_insn "" ! [(set (match_operand:SF 0 "general_operand" "=r,*f,d,d,m") (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "current_function_args_size != 0 *************** *** 1308,1312 **** (define_insn "extendsfdf2" ! [(set (match_operand:DF 0 "register_operand" "=f,d") (float_extend:DF (match_operand:SF 1 "fp_arith_operand" "dGH,fGH")))] "TARGET_NUMERICS" --- 1320,1324 ---- (define_insn "extendsfdf2" ! [(set (match_operand:DF 0 "register_operand" "=*f,d") (float_extend:DF (match_operand:SF 1 "fp_arith_operand" "dGH,fGH")))] "TARGET_NUMERICS" *************** *** 1334,1338 **** (define_insn "floatsisf2" ! [(set (match_operand:SF 0 "register_operand" "=df") (float:SF (match_operand:SI 1 "register_operand" "d")))] "TARGET_NUMERICS" --- 1346,1350 ---- (define_insn "floatsisf2" ! [(set (match_operand:SF 0 "register_operand" "=d*f") (float:SF (match_operand:SI 1 "register_operand" "d")))] "TARGET_NUMERICS" *************** *** 1693,1697 **** (define_insn "adddf3" ! [(set (match_operand:DF 0 "register_operand" "=d") (plus:DF (match_operand:DF 1 "fp_arith_operand" "%rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] --- 1705,1709 ---- (define_insn "adddf3" ! [(set (match_operand:DF 0 "register_operand" "=d*f") (plus:DF (match_operand:DF 1 "fp_arith_operand" "%rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] *************** *** 1701,1705 **** (define_insn "addsf3" ! [(set (match_operand:SF 0 "register_operand" "=d") (plus:SF (match_operand:SF 1 "fp_arith_operand" "%rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] --- 1713,1717 ---- (define_insn "addsf3" ! [(set (match_operand:SF 0 "register_operand" "=d*f") (plus:SF (match_operand:SF 1 "fp_arith_operand" "%rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] *************** *** 1710,1714 **** (define_insn "subdf3" ! [(set (match_operand:DF 0 "register_operand" "=d") (minus:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] --- 1722,1726 ---- (define_insn "subdf3" ! [(set (match_operand:DF 0 "register_operand" "=d*f") (minus:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] *************** *** 1718,1722 **** (define_insn "subsf3" ! [(set (match_operand:SF 0 "register_operand" "=d") (minus:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] --- 1730,1734 ---- (define_insn "subsf3" ! [(set (match_operand:SF 0 "register_operand" "=d*f") (minus:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] *************** *** 1727,1731 **** (define_insn "muldf3" ! [(set (match_operand:DF 0 "register_operand" "=d") (mult:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] --- 1739,1743 ---- (define_insn "muldf3" ! [(set (match_operand:DF 0 "register_operand" "=d*f") (mult:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] *************** *** 1735,1739 **** (define_insn "mulsf3" ! [(set (match_operand:SF 0 "register_operand" "=d") (mult:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] --- 1747,1751 ---- (define_insn "mulsf3" ! [(set (match_operand:SF 0 "register_operand" "=d*f") (mult:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] *************** *** 1744,1748 **** (define_insn "divdf3" ! [(set (match_operand:DF 0 "register_operand" "=d") (div:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] --- 1756,1760 ---- (define_insn "divdf3" ! [(set (match_operand:DF 0 "register_operand" "=d*f") (div:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] *************** *** 1752,1756 **** (define_insn "divsf3" ! [(set (match_operand:SF 0 "register_operand" "=d") (div:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] --- 1764,1768 ---- (define_insn "divsf3" ! [(set (match_operand:SF 0 "register_operand" "=d*f") (div:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] *************** *** 1760,1764 **** (define_insn "negdf2" ! [(set (match_operand:DF 0 "register_operand" "=d,f") (neg:DF (match_operand:DF 1 "register_operand" "d,r")))] "" --- 1772,1776 ---- (define_insn "negdf2" ! [(set (match_operand:DF 0 "register_operand" "=d,d*f") (neg:DF (match_operand:DF 1 "register_operand" "d,r")))] "" *************** *** 1776,1780 **** (define_insn "negsf2" ! [(set (match_operand:SF 0 "register_operand" "=d,f") (neg:SF (match_operand:SF 1 "register_operand" "d,r")))] "" --- 1788,1792 ---- (define_insn "negsf2" ! [(set (match_operand:SF 0 "register_operand" "=d,d*f") (neg:SF (match_operand:SF 1 "register_operand" "d,r")))] "" *************** *** 1789,1793 **** (define_insn "absdf2" ! [(set (match_operand:DF 0 "register_operand" "=df") (abs:DF (match_operand:DF 1 "register_operand" "df")))] "" --- 1801,1805 ---- (define_insn "absdf2" ! [(set (match_operand:DF 0 "register_operand" "=d*f") (abs:DF (match_operand:DF 1 "register_operand" "df")))] "" *************** *** 1815,1819 **** (define_insn "abssf2" ! [(set (match_operand:SF 0 "register_operand" "=df") (abs:SF (match_operand:SF 1 "register_operand" "df")))] "" --- 1827,1831 ---- (define_insn "abssf2" ! [(set (match_operand:SF 0 "register_operand" "=d*f") (abs:SF (match_operand:SF 1 "register_operand" "df")))] "" *************** *** 1857,1862 **** (define_insn "" ! [(set (match_operand:TF 0 "general_operand" "=r,f,d,d,m") ! (match_operand:TF 1 "fpmove_src_operand" "r,GH,F,m,dG"))] "current_function_args_size == 0 && (register_operand (operands[0], TFmode) --- 1869,1874 ---- (define_insn "" ! [(set (match_operand:TF 0 "general_operand" "=r,*f,d,d,m,o") ! (match_operand:TF 1 "fpmove_src_operand" "r,GH,F,m,d,G"))] "current_function_args_size == 0 && (register_operand (operands[0], TFmode) *************** *** 1879,1891 **** return \"ldq %1,%0\"; case 4: - if (operands[1] == CONST0_RTX (TFmode)) - return \"st g14,%0\;st g14,4(%0)\;st g14,8(%0)\;st g14,12(%0)\"; return \"stq %1,%0\"; } }" ! [(set_attr "type" "move,move,load,fpload,fpstore")]) (define_insn "" ! [(set (match_operand:TF 0 "general_operand" "=r,f,d,d,m") (match_operand:TF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "current_function_args_size != 0 --- 1891,1906 ---- return \"ldq %1,%0\"; case 4: return \"stq %1,%0\"; + case 5: + operands[1] = adj_offsettable_operand (operands[0], 4); + operands[2] = adj_offsettable_operand (operands[0], 8); + operands[3] = adj_offsettable_operand (operands[0], 12); + return \"st g14,%0\;st g14,%1\;st g14,%2\;st g14,%3\"; } }" ! [(set_attr "type" "move,move,load,fpload,fpstore,fpstore")]) (define_insn "" ! [(set (match_operand:TF 0 "general_operand" "=r,*f,d,d,m") (match_operand:TF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "current_function_args_size != 0 *************** *** 1914,1918 **** (define_insn "extendsftf2" ! [(set (match_operand:TF 0 "register_operand" "=f,d") (float_extend:TF (match_operand:SF 1 "register_operand" "d,f")))] --- 1929,1933 ---- (define_insn "extendsftf2" ! [(set (match_operand:TF 0 "register_operand" "=*f,d") (float_extend:TF (match_operand:SF 1 "register_operand" "d,f")))] *************** *** 1924,1928 **** (define_insn "extenddftf2" ! [(set (match_operand:TF 0 "register_operand" "=f,d") (float_extend:TF (match_operand:DF 1 "register_operand" "d,f")))] --- 1939,1943 ---- (define_insn "extenddftf2" ! [(set (match_operand:TF 0 "register_operand" "=*f,d") (float_extend:TF (match_operand:DF 1 "register_operand" "d,f")))] *************** *** 2052,2058 **** (define_insn "indirect_jump" ! [(set (pc) (match_operand:SI 0 "register_operand" "r"))] "" ! "b* %0" [(set_attr "type" "branch")]) --- 2067,2073 ---- (define_insn "indirect_jump" ! [(set (pc) (match_operand:SI 0 "address_operand" "p"))] "" ! "bx %a0" [(set_attr "type" "branch")]) *************** *** 2067,2084 **** (define_expand "call" ! [(call (match_operand:SI 0 "general_operand" "") ! (match_operand:SI 1 "immediate_operand" ""))] "" " { ! i960_expand_call (operand0, operand1, 0); DONE; }") ! (define_insn "" [(call (match_operand:SI 0 "general_operand" "g") ! (match_operand:SI 1 "immediate_operand" "i"))] "" ! "* return i960_output_call_insn (operands[0], operands[1], insn);" [(set_attr "type" "call")]) --- 2082,2103 ---- (define_expand "call" ! [(call (match_operand:SI 0 "general_operand" "g") ! (match_operand:SI 1 "immediate_operand" "i"))] "" " { ! emit_insn (gen_call_internal (operands[0], operands[1], ! virtual_outgoing_args_rtx)); DONE; }") ! (define_insn "call_internal" [(call (match_operand:SI 0 "general_operand" "g") ! (match_operand:SI 1 "immediate_operand" "i")) ! (use (match_operand:SI 2 "address_operand" "p")) ! (clobber (match_scratch:SI 3 "=&d"))] "" ! "* return i960_output_call_insn (operands[0], operands[1], operands[2], ! operands[3], insn);" [(set_attr "type" "call")]) *************** *** 2090,2103 **** " { ! i960_expand_call (operand1, operand2, operand0); DONE; }") ! (define_insn "" [(set (match_operand 0 "register_operand" "=d") (call (match_operand:SI 1 "general_operand" "g") ! (match_operand:SI 2 "immediate_operand" "i")))] "" ! "* return i960_output_call_insn (operands[1], operands[2], insn);" [(set_attr "type" "call")]) --- 2109,2126 ---- " { ! emit_insn (gen_call_value_internal (operands[0], operands[1], operands[2], ! virtual_outgoing_args_rtx)); DONE; }") ! (define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=d") (call (match_operand:SI 1 "general_operand" "g") ! (match_operand:SI 2 "immediate_operand" "i"))) ! (use (match_operand:SI 3 "address_operand" "p")) ! (clobber (match_scratch:SI 4 "=&d"))] "" ! "* return i960_output_call_insn (operands[1], operands[2], operands[3], ! operands[4], insn);" [(set_attr "type" "call")]) diff -rc2N gcc-2.2.2/config/iris.h gcc-2.3.1/config/iris.h *** gcc-2.2.2/config/iris.h Thu Jun 11 00:51:18 1992 --- gcc-2.3.1/config/iris.h Wed Aug 26 14:31:58 1992 *************** *** 53,57 **** %{G*} \ %{!mgas: %{mips1} %{mips2} %{mips3} \ ! %{bestGnum}}" /* Always use 1 for .file number. I [meissner@osf.org] wonder why --- 53,57 ---- %{G*} \ %{!mgas: %{mips1} %{mips2} %{mips3} \ ! %{bestGnum} %{shared} %{non_shared}}" /* Always use 1 for .file number. I [meissner@osf.org] wonder why diff -rc2N gcc-2.2.2/config/iris4g.h gcc-2.3.1/config/iris4g.h *** gcc-2.2.2/config/iris4g.h --- gcc-2.3.1/config/iris4g.h Fri Sep 11 07:37:06 1992 *************** *** 0 **** --- 1,23 ---- + /* Definitions of target machine for GNU compiler. Iris version 4. + Copyright (C) 1991 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. */ + + /* Use stabs instead of ECOFF debug format. */ + #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + + #include "iris4.h" diff -rc2N gcc-2.2.2/config/isc.h gcc-2.3.1/config/isc.h *** gcc-2.2.2/config/isc.h --- gcc-2.3.1/config/isc.h Mon Jul 27 22:54:24 1992 *************** *** 0 **** --- 1,46 ---- + /* Assembler-independent definitions for an Intel 386 running + Interactive Unix System V. Specifically, this is for recent versions + that support POSIX. */ + + /* Use crt1.o, not crt0.o, as a startup file, and crtn.o as a closing file. */ + #undef STARTFILE_SPEC + #define STARTFILE_SPEC \ + "%{!shlib:%{posix:%{pg:mcrtp1.o%s}%{!pg:%{p:mcrtp1.o%s}%{!p:crtp1.o%s}}}\ + %{!posix:%{pg:mcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}\ + %{p:-L/lib/libp} %{pg:-L/lib/libp}}}\ + %{shlib:%{posix:crtp1.o%s}%{!posix:crt1.o%s}} crtbegin.o%s" + + #define ENDFILE_SPEC "crtend.o%s crtn.o%s" + + /* Library spec */ + #undef LIB_SPEC + #define LIB_SPEC "%{posix:-lcposix} %{shlib:-lc_s} -lc -lg" + + /* ISC 2.2 uses `char' for `wchar_t'. */ + #undef WCHAR_TYPE + #define WCHAR_TYPE "char" + + #undef WCHAR_TYPE_SIZE + #define WCHAR_TYPE_SIZE BITS_PER_UNIT + + #if 0 + /* This is apparently not true: ISC versions up to 3.0, at least, use + the standard calling sequence in which the called function pops the + extra arg. */ + /* caller has to pop the extra argument passed to functions that return + structures. */ + + #undef RETURN_POPS_ARGS + #define RETURN_POPS_ARGS(FUNTYPE,SIZE) \ + (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + : (TARGET_RTD \ + && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ + == void_type_node))) ? (SIZE) \ + : 0) + /* On other 386 systems, the last line looks like this: + : (aggregate_value_p (FUNTYPE)) ? GET_MODE_SIZE (Pmode) : 0) */ + #endif + + /* Handle #pragma pack and #pragma weak. */ + #define HANDLE_SYSV_PRAGMA diff -rc2N gcc-2.2.2/config/isi.h gcc-2.3.1/config/isi.h *** gcc-2.2.2/config/isi.h Sat Jun 13 17:26:31 1992 --- gcc-2.3.1/config/isi.h Sun Jul 12 16:30:00 1992 *************** *** 21,35 **** #include "m68k.h" - /* Without STRUCTURE_SIZE_BOUNDARY, we can't ensure that structures are - aligned such that we can correctly extract bitfields from them. - Someone should check whether the usual compiler on this machine - provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY. */ - /* Alternative solutions are (1) define PCC_BITFIELD_TYPE_MATTERS, - if that fits what the usual compiler does, - or disable the -m68000 and -mnobitfield options. */ - #error This doesn't define STRUCTURE_SIZE_BOUNDARY - /* See m68k.h. 7 means 68020 with 68881. */ - #ifndef TARGET_DEFAULT #define TARGET_DEFAULT 7 --- 21,25 ---- *************** *** 44,48 **** /* If the 68881 is used, link must load libmc.a instead of libc.a */ ! #define LIB_SPEC "%{g:-lg} %{msoft-float:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}%{!msoft-float:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}} %{g:-lg}" #else --- 34,40 ---- /* If the 68881 is used, link must load libmc.a instead of libc.a */ ! #define LIB_SPEC "%{msoft-float:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}} \ ! %{!msoft-float:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}} \ ! %{g:-lg}" #else *************** *** 54,58 **** /* If the 68881 is used, link must load libmc.a instead of libc.a */ ! #define LIB_SPEC "%{g:-lg} %{!m68881:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}%{m68881:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}}" #endif --- 46,52 ---- /* If the 68881 is used, link must load libmc.a instead of libc.a */ ! #define LIB_SPEC "%{!m68881:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}} \ ! %{m68881:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}} \ ! %{g:-lg}" #endif *************** *** 71,74 **** --- 65,72 ---- #undef FUNCTION_VALUE_REGNO_P #undef ASM_FILE_START + + /* Every structure or union's size must be a multiple of 2 bytes. */ + + #define STRUCTURE_SIZE_BOUNDARY 16 /* If TARGET_68881, return SF and DF values in f0 instead of d0. */ diff -rc2N gcc-2.2.2/config/m68k.c gcc-2.3.1/config/m68k.c *** gcc-2.2.2/config/m68k.c Wed Jun 10 00:41:20 1992 --- gcc-2.3.1/config/m68k.c Thu Oct 29 20:00:58 1992 *************** *** 45,48 **** --- 45,52 ---- #endif /* defined SUPPORT_SUN_FPA */ + /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END, + if SGS_SWITCH_TABLE. */ + int switch_table_difference_label_flag; + static rtx find_addr_reg (); rtx legitimize_pic_address (); *************** *** 177,180 **** --- 181,189 ---- num_saved_regs--; } + + #if NEED_PROBE + fprintf (stream, "\ttstl sp@(%d)\n", NEED_PROBE - num_saved_regs * 4); + #endif + if (num_saved_regs <= 2) { *************** *** 1247,1254 **** rtx x; { - union {double d; int i[2];} u; register double d; ! /* fmovecr must be emulated on the 68040, so it shoudn't be used at all. */ if (TARGET_68040) return 0; --- 1256,1262 ---- rtx x; { register double d; ! /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */ if (TARGET_68040) return 0; *************** *** 1259,1270 **** #endif ! #ifdef HOST_WORDS_BIG_ENDIAN ! u.i[0] = CONST_DOUBLE_LOW (x); ! u.i[1] = CONST_DOUBLE_HIGH (x); ! #else ! u.i[0] = CONST_DOUBLE_HIGH (x); ! u.i[1] = CONST_DOUBLE_LOW (x); ! #endif ! d = u.d; if (d == 0) --- 1267,1271 ---- #endif ! REAL_VALUE_FROM_CONST_DOUBLE (d, x); if (d == 0) *************** *** 1298,1302 **** rtx x; { - union {double d; int i[2];} u; register double d, d1; int i; --- 1299,1302 ---- *************** *** 1307,1318 **** #endif ! #ifdef HOST_WORDS_BIG_ENDIAN ! u.i[0] = CONST_DOUBLE_LOW (x); ! u.i[1] = CONST_DOUBLE_HIGH (x); ! #else ! u.i[0] = CONST_DOUBLE_HIGH (x); ! u.i[1] = CONST_DOUBLE_LOW (x); ! #endif ! d = u.d; if (! (d > 0)) --- 1307,1311 ---- #endif ! REAL_VALUE_FROM_CONST_DOUBLE (d, x); if (! (d > 0)) *************** *** 1358,1362 **** rtx x; { - union {double d; int i[2];} u; register double d; --- 1351,1354 ---- *************** *** 1366,1374 **** #endif - u.i[0] = CONST_DOUBLE_LOW (x); - u.i[1] = CONST_DOUBLE_HIGH (x); - d = u.d; - if (d == 0.0) return 0x200; /* 0 once 0x1ff is anded with it */ --- 1358,1363 ---- #endif + REAL_VALUE_FROM_CONST_DOUBLE (d, x); if (d == 0.0) return 0x200; /* 0 once 0x1ff is anded with it */ *************** *** 1611,1625 **** else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) { ! union { double d; int i[2]; } u; union { float f; int i; } u1; ! PRINT_OPERAND_EXTRACT_FLOAT (op); ! u1.f = u.d; PRINT_OPERAND_PRINT_FLOAT (letter, file); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode) { ! union { double d; int i[2]; } u; ! PRINT_OPERAND_EXTRACT_FLOAT (op); ! ASM_OUTPUT_DOUBLE_OPERAND (file, u.d); } else --- 1600,1614 ---- else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode) { ! double d; union { float f; int i; } u1; ! REAL_VALUE_FROM_CONST_DOUBLE (d, op); ! u1.f = d; PRINT_OPERAND_PRINT_FLOAT (letter, file); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode) { ! double d; ! REAL_VALUE_FROM_CONST_DOUBLE (d, op); ! ASM_OUTPUT_DOUBLE_OPERAND (file, d); } else *************** *** 1783,1787 **** } if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF ! && ! (flag_pic && ireg == pic_offset_table_rtx)) { int scale = 1; --- 1772,1776 ---- } if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF ! && ! (flag_pic && ireg == pic_offset_table_rtx)) { int scale = 1; *************** *** 1799,1803 **** reg_names[REGNO (XEXP (ireg, 0))]); #else ! asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.w", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), --- 1788,1792 ---- reg_names[REGNO (XEXP (ireg, 0))]); #else ! asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), *************** *** 1819,1823 **** reg_names[REGNO (ireg)]); #else ! asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), --- 1808,1812 ---- reg_names[REGNO (ireg)]); #else ! asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), *************** *** 1843,1847 **** } if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF ! && ! (flag_pic && breg == pic_offset_table_rtx)) { #ifdef MOTOROLA --- 1832,1836 ---- } if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF ! && ! (flag_pic && breg == pic_offset_table_rtx)) { #ifdef MOTOROLA *************** *** 1851,1855 **** reg_names[REGNO (breg)]); #else ! asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), --- 1840,1844 ---- reg_names[REGNO (breg)]); #else ! asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), *************** *** 1881,1887 **** output_addr_const (file, addr); if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) ! fprintf (file, ":w"); if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) ! fprintf (file, ":l"); } fprintf (file, "(%s", reg_names[REGNO (breg)]); --- 1870,1876 ---- output_addr_const (file, addr); if ((flag_pic == 1) && (breg == pic_offset_table_rtx)) ! fprintf (file, ".w"); if ((flag_pic == 2) && (breg == pic_offset_table_rtx)) ! fprintf (file, ".l"); } fprintf (file, "(%s", reg_names[REGNO (breg)]); *************** *** 1938,1942 **** } else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF ! && ! (flag_pic && reg1 == pic_offset_table_rtx)) { #ifdef MOTOROLA --- 1927,1931 ---- } else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF ! && ! (flag_pic && reg1 == pic_offset_table_rtx)) { #ifdef MOTOROLA *************** *** 1946,1950 **** reg_names[REGNO (reg1)]); #else ! asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l)", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), --- 1935,1939 ---- reg_names[REGNO (reg1)]); #else ! asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)", CODE_LABEL_NUMBER (XEXP (addr, 0)), CODE_LABEL_NUMBER (XEXP (addr, 0)), diff -rc2N gcc-2.2.2/config/m68k.h gcc-2.3.1/config/m68k.h *** gcc-2.2.2/config/m68k.h Wed Jun 10 00:42:15 1992 --- gcc-2.3.1/config/m68k.h Thu Oct 22 03:12:03 1992 *************** *** 82,93 **** #define TARGET_SKY (target_flags & 0200) ! /* Optimize for 68040. The 68040 will execute all 68030 and 68881/2 instructions, but some of them must be emulated in software by the OS. When TARGET_68040 is turned on, these instructions won't be used. This code will still run on a 68030 and 68881/2. */ ! #define TARGET_68040 (target_flags & 0400) ! /* Support 68040 fp instructions. */ #define TARGET_68040_ONLY (target_flags & 01000) --- 82,94 ---- #define TARGET_SKY (target_flags & 0200) ! /* Optimize for 68040, but still allow execution on 68020 ! (-m68020-40 or -m68040). The 68040 will execute all 68030 and 68881/2 instructions, but some of them must be emulated in software by the OS. When TARGET_68040 is turned on, these instructions won't be used. This code will still run on a 68030 and 68881/2. */ ! #define TARGET_68040 (target_flags & 01400) ! /* Use the 68040-only fp instructions (-m68040). */ #define TARGET_68040_ONLY (target_flags & 01000) *************** *** 115,122 **** { "sky", 0200}, \ { "nosky", -0200}, \ ! { "68040", 0407}, \ { "68030", -01400}, \ { "68030", 7}, \ ! { "68040-only", 01000}, \ { "", TARGET_DEFAULT}} /* TARGET_DEFAULT is defined in sun*.h and isi.h, etc. */ --- 116,123 ---- { "sky", 0200}, \ { "nosky", -0200}, \ ! { "68020-40", 0407}, \ { "68030", -01400}, \ { "68030", 7}, \ ! { "68040", 01007}, \ { "", TARGET_DEFAULT}} /* TARGET_DEFAULT is defined in sun*.h and isi.h, etc. */ *************** *** 1128,1133 **** { if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; } ! #define GO_IF_INDEXABLE_BASE(X, ADDR) \ ! { if (GET_CODE (X) == LABEL_REF) goto ADDR; \ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; } --- 1129,1141 ---- { if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; } ! /* Only labels on dispatch tables are valid for indexing from. */ ! #define GO_IF_INDEXABLE_BASE(X, ADDR) \ ! { rtx temp; \ ! if (GET_CODE (X) == LABEL_REF \ ! && (temp = next_nonnote_insn (XEXP (X, 0))) != 0 \ ! && GET_CODE (temp) == JUMP_INSN \ ! && (GET_CODE (PATTERN (temp)) == ADDR_VEC \ ! || GET_CODE (PATTERN (temp)) == ADDR_DIFF_VEC)) \ ! goto ADDR; \ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; } diff -rc2N gcc-2.2.2/config/m68k.md gcc-2.3.1/config/m68k.md *** gcc-2.2.2/config/m68k.md Wed Jun 10 00:43:59 1992 --- gcc-2.3.1/config/m68k.md Mon Sep 28 09:37:59 1992 *************** *** 657,662 **** ;This is never used. ;(define_insn "swapsi" ! ; [(set (match_operand:SI 0 "general_operand" "r") ! ; (match_operand:SI 1 "general_operand" "r")) ; (set (match_dup 1) (match_dup 0))] ; "" --- 657,662 ---- ;This is never used. ;(define_insn "swapsi" ! ; [(set (match_operand:SI 0 "general_operand" "+r") ! ; (match_operand:SI 1 "general_operand" "+r")) ; (set (match_dup 1) (match_dup 0))] ; "" *************** *** 2538,2545 **** --- 2538,2552 ---- "* { + #ifdef FSGLMUL_USE_S if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) return (TARGET_68040_ONLY + ? \"fsmul%.s %2,%0\" + : \"fsglmul%.s %2,%0\"); + #else + if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) + return (TARGET_68040_ONLY ? \"fsmul%.x %2,%0\" : \"fsglmul%.x %2,%0\"); + #endif return (TARGET_68040_ONLY ? \"fsmul%.s %f2,%0\" *************** *** 3625,3629 **** ; (define_insn "" ! [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "o") (match_operand:SI 1 "immediate_operand" "i") (match_operand:SI 2 "immediate_operand" "i")) --- 3632,3636 ---- ; (define_insn "" ! [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o") (match_operand:SI 1 "immediate_operand" "i") (match_operand:SI 2 "immediate_operand" "i")) *************** *** 4730,4734 **** operands[0] = gen_rtx (PLUS, SImode, stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode, NEED_PROBE)); ! return \"tstl %0\"; }") --- 4737,4741 ---- operands[0] = gen_rtx (PLUS, SImode, stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode, NEED_PROBE)); ! return \"tstl %a0\"; }") *************** *** 4746,4758 **** (define_insn "indirect_jump" ! [(set (pc) (match_operand:SI 0 "register_operand" "a"))] "" ! "* ! #ifdef MOTOROLA ! return \"jmp (%0)\"; ! #else ! return \"jmp %0@\"; ! #endif ! ") ;; This should not be used unless the add/sub insns can't be. --- 4753,4759 ---- (define_insn "indirect_jump" ! [(set (pc) (match_operand:SI 0 "address_operand" "p"))] "" ! "jmp %a0") ;; This should not be used unless the add/sub insns can't be. *************** *** 4771,4775 **** (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) ! (set (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "ad"))] "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" --- 4772,4776 ---- (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) ! (set (match_operand:DF 0 "register_operand" "=f") (match_operand:DF 1 "register_operand" "ad"))] "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" diff -rc2N gcc-2.2.2/config/m68ksgs.h gcc-2.3.1/config/m68ksgs.h *** gcc-2.2.2/config/m68ksgs.h Sat Jun 13 17:26:26 1992 --- gcc-2.3.1/config/m68ksgs.h Tue Jul 21 17:49:29 1992 *************** *** 201,204 **** --- 201,213 ---- #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T syntax)"); + /* Use proper assembler syntax for these macros. */ + #undef ASM_OUTPUT_REG_PUSH + #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ + asm_fprintf (FILE, "\t%Omove.l %s,-(%Rsp)\n", reg_names[REGNO]) + + #undef ASM_OUTPUT_REG_POP + #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ + asm_fprintf (FILE, "\t%Omove.l (%Rsp)+,%s\n", reg_names[REGNO]) + #undef PRINT_OPERAND_PRINT_FLOAT #define PRINT_OPERAND_PRINT_FLOAT(CODE,FILE) \ *************** *** 377,383 **** example, can identify that it is the start of a switch table. */ #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ ! fprintf ((FILE), "\t%s &%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); \ ! ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); /* At end of a switch table, define LDnnn iff the symbol LInnn was defined. --- 386,397 ---- example, can identify that it is the start of a switch table. */ + #define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ + fprintf ((FILE), "\t%s &%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); + #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ ! do { \ ! ASM_OUTPUT_BEFORE_CASE_LABEL((FILE),(PREFIX),(NUM),(TABLE)); \ ! ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); \ ! } while (0) /* At end of a switch table, define LDnnn iff the symbol LInnn was defined. diff -rc2N gcc-2.2.2/config/m68kv4.h gcc-2.3.1/config/m68kv4.h *** gcc-2.2.2/config/m68kv4.h Sat Jun 13 17:27:17 1992 --- gcc-2.3.1/config/m68kv4.h Sun Jul 12 17:14:58 1992 *************** *** 182,183 **** --- 182,233 ---- #undef BIGGEST_ALIGNMENT #define BIGGEST_ALIGNMENT 64 + + /* SVR4 m68k assembler is bitching on the `comm i,1,1' which askes for + 1 byte alignment. Don't generate alignment for COMMON seems to be + safer until we the assembler is fixed. */ + #undef ASM_OUTPUT_ALIGNED_COMMON + /* Same problem with this one. */ + #undef ASM_OUTPUT_ALIGNED_LOCAL + + /* The `string' directive on m68k svr4 does not handle string with + escape char (ie., `\') right. Use normal way to output ASCII bytes + seems to be safer. */ + #undef ASM_OUTPUT_ASCII + #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \ + { \ + register int sp = 0, lp = 0, ch; \ + fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \ + do { \ + ch = (PTR)[sp]; \ + if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \ + { \ + fprintf ((FILE), "'%c", ch); \ + } \ + else \ + { \ + fprintf ((FILE), "0x%x", ch); \ + } \ + if (++sp < (LEN)) \ + { \ + if ((sp % 10) == 0) \ + { \ + fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \ + } \ + else \ + { \ + putc (',', (FILE)); \ + } \ + } \ + } while (sp < (LEN)); \ + putc ('\n', (FILE)); \ + } + + /* SVR4 m68k assembler is bitching on the syntax `2.b'. Change + it back to use the "LLDnnn-LLnnn" format. */ + + #undef ASM_OUTPUT_CASE_END + #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \ + if (RTX_INTEGRATED_P (TABLE)) \ + asm_fprintf (FILE, "\t%s %LLD%d,%LL%d\n",\ + SET_ASM_OP, (NUM), (NUM)) + diff -rc2N gcc-2.2.2/config/m88k-move.sh gcc-2.3.1/config/m88k-move.sh *** gcc-2.2.2/config/m88k-move.sh Sat Jun 13 17:19:28 1992 --- gcc-2.3.1/config/m88k-move.sh Wed Oct 7 16:17:51 1992 *************** *** 4,8 **** # you might try using GNU's bash. # ! #ident "@(#) m88k-move.sh 3-Jan-92" # # This file provided by Data General, February 1990. --- 4,8 ---- # you might try using GNU's bash. # ! #ident "@(#) m88k-move.sh 1-Sep-92" # # This file provided by Data General, February 1990. *************** *** 32,35 **** --- 32,36 ---- #.Revision History # + # 1-Sep-92 Stan Cox Added moveDI96x, moveDI41x through moveDI47x. # 2-Jan-92 Tom Wood Renamed files to comply with SVR3 14 char limit. # 26-Oct-90 Tom Wood Delete movstr.h; moved to out-m88k.c. *************** *** 62,65 **** --- 63,67 ---- awk_flag="-F:"; awk_begin="BEGIN { " + ps=""; us="_"; tf="x"; la="@L"; fb="8"; nt=""; do_file() { echo " file $1"; *************** *** 68,73 **** while [ $# -gt 0 ] ; do case $1 in ! -no-tdesc) awk_begin="$awk_begin no_tdesc=1;";; -abi) awk_begin="$awk_begin abi=1;" do_file() { echo ' version "03.00"'; --- 70,77 ---- while [ $# -gt 0 ] ; do case $1 in ! -no-tdesc) awk_begin="$awk_begin no_tdesc=1;" ! nt=";";; -abi) awk_begin="$awk_begin abi=1;" + ps="#"; us=""; tf="a"; la=".L"; fb="16"; do_file() { echo ' version "03.00"'; *************** *** 100,106 **** awk $awk_flag "$awk_begin"' if (abi) { ! ps="#"; us=""; tf="a"; } else { ! ps=""; us="_"; tf="x"; } } --- 104,110 ---- awk $awk_flag "$awk_begin"' if (abi) { ! ps="#"; us=""; tf="a"; la=".L"; fb=16; } else { ! ps=""; us="_"; tf="x"; la="@L"; fb=8; } } *************** *** 111,116 **** printf "; The following was calculated using awk.\n"; printf "\ttext\n"; ! printf "\talign\t16\n"; ! printf "loop%s%d:\n", mode, count * align; printf "\taddu\t%sr3,%sr3,%d\n", ps, ps, count * align; printf "\taddu\t%sr2,%sr2,%d\n", ps, ps, count * align; --- 115,120 ---- printf "; The following was calculated using awk.\n"; printf "\ttext\n"; ! printf "\talign\t%d\n", fb; ! printf "%sloop%s%d:\n", la, mode, count * align; printf "\taddu\t%sr3,%sr3,%d\n", ps, ps, count * align; printf "\taddu\t%sr2,%sr2,%d\n", ps, ps, count * align; *************** *** 128,132 **** } else if (r == 2) { printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; ! printf "\tbcnd.n\t%sgt0,%sr6,loop%s%d\n", ps, ps, mode, count * align; printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; printf "\tjmp.n\t%sr1\n", ps; --- 132,136 ---- } else if (r == 2) { printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; ! printf "\tbcnd.n\t%sgt0,%sr6,%sloop%s%d\n", ps, ps, la, mode, count * align; printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; printf "\tjmp.n\t%sr1\n", ps; *************** *** 137,150 **** } if (!no_tdesc) { ! printf "end%s%d:\n", mode, count * align; printf "\tsection\t.tdesc,\"%s\"\n", tf; ! printf "\tword\t0x42\n"; ! printf "\tword\t1\n"; ! printf "\tword\tloop%s%d\n", mode, count * align; ! printf "\tword\tend%s%d\n", mode, count * align; ! printf "\tword\t0x0100001f\n"; ! printf "\tword\t0\n"; ! printf "\tword\t1\n"; ! printf "\tword\t0\n"; printf "\ttext\n"; } --- 141,149 ---- } if (!no_tdesc) { ! printf "%send%s%d:\n", la, mode, count * align; printf "\tsection\t.tdesc,\"%s\"\n", tf; ! printf "\tword\t0x42,1,%sloop%s%d", la, mode, count * align; ! printf ",%send%s%d\n", la, mode, count * align; ! printf "\tword\t0x0100001f,0,1,0\n"; printf "\ttext\n"; } *************** *** 176,182 **** awk $awk_flag "$awk_begin"' if (abi) { ! ps="#"; us=""; tf="a"; } else { ! ps=""; us="_"; tf="x"; } } --- 175,181 ---- awk $awk_flag "$awk_begin"' if (abi) { ! ps="#"; us=""; tf="a"; la=".L"; fb=16; } else { ! ps=""; us="_"; tf="x"; la="@L"; fb=8; } } *************** *** 184,190 **** mode = $1; suffix = $2; align = $3; bytes = $4; ld = align; st = 0; count = bytes / align; printf "; The following was calculated using awk.\n"; printf "\ttext\n"; ! printf "\talign\t16\n"; for (r = count; r >= 1; r--) { evenp = r % 2; --- 183,190 ---- mode = $1; suffix = $2; align = $3; bytes = $4; ld = align; st = 0; count = bytes / align; + reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; printf "; The following was calculated using awk.\n"; printf "\ttext\n"; ! printf "\talign\t%d\n", fb; for (r = count; r >= 1; r--) { evenp = r % 2; *************** *** 197,215 **** printf "\tjmp.n\t%sr1\n", ps; else ! printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; ! printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; ld += align; st += align; } if (!no_tdesc) { ! printf "end%s%dx:\n", mode, count * align; printf "\tsection\t.tdesc,\"%s\"\n", tf; ! printf "\tword\t0x42\n"; ! printf "\tword\t1\n"; ! printf "\tword\t__%smovstr%s%dx%d\n", us, mode, count * align, count * align; ! printf "\tword\tend%s%dx\n", mode, count * align; ! printf "\tword\t0x0100001f\n"; ! printf "\tword\t0\n"; ! printf "\tword\t1\n"; ! printf "\tword\t0\n"; printf "\ttext\n"; } --- 197,210 ---- printf "\tjmp.n\t%sr1\n", ps; else ! printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, reg[evenp], ps, ld; ! printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, reg[1-evenp], ps, st; ld += align; st += align; } if (!no_tdesc) { ! printf "%send%s%dx:\n", la, mode, count * align; printf "\tsection\t.tdesc,\"%s\"\n", tf; ! printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, count * align, count * align; ! printf ",%send%s%dx\n", la, mode, count * align; ! printf "\tword\t0x0100001f,0,1,0\n"; printf "\ttext\n"; } *************** *** 225,228 **** --- 220,225 ---- (do_file '"movstrSI96x.s"'; echo 'SI::4:96' | gen_movstrX0) > moveSI96x.asm + (do_file '"movstrDI96x.s"'; + echo 'DI:.d:8:96' | gen_movstrX0) > moveDI96x.asm #.Implementation_continued[=----------------------------------------------- *************** *** 236,257 **** awk $awk_flag "$awk_begin"' if (abi) { ! ps="#"; us=""; tf="a"; } else { ! ps=""; us="_"; tf="x"; } } NR == 1 && NF == 4 { mode = $1; rem = $2; most = $3; count = $4; ! suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; prev = align = most; ld = align; st = 0; total = count - rem - most; evenp = int(total/align) % 2; printf "; The following was calculated using awk.\n"; printf "\ttext\n"; ! printf "\talign\t16\n"; for (bytes = total; bytes >= 0; bytes -= align) { if (bytes < align) { ! if (bytes >= 2) align = 2; else align = 1; } --- 233,256 ---- awk $awk_flag "$awk_begin"' if (abi) { ! ps="#"; us=""; tf="a"; la=".L"; fb=16; } else { ! ps=""; us="_"; tf="x"; la="@L"; fb=8; } } NR == 1 && NF == 4 { mode = $1; rem = $2; most = $3; count = $4; ! suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; suffix[8] = ".d"; prev = align = most; ld = align; st = 0; total = count - rem - most; evenp = int(total/align) % 2; + reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; printf "; The following was calculated using awk.\n"; printf "\ttext\n"; ! printf "\talign\t%d\n", fb; for (bytes = total; bytes >= 0; bytes -= align) { if (bytes < align) { ! if (bytes >= 4) align = 4; ! else if (bytes >= 2) align = 2; else align = 1; } *************** *** 264,286 **** printf "\tjmp.n\t%sr1\n", ps; else ! printf "\tld%s\t%sr%d,%sr3,%d\n", suffix[align], ps, 4 + evenp, ps, ld; ! printf "\tst%s\t%sr%d,%sr2,%d\n", suffix[prev], ps, 5 - evenp, ps, st; ld += align; st += prev; prev = align; ! if (evenp) ! evenp = 0; ! else ! evenp = 1; } if (!no_tdesc) { ! printf "end%s%dx:\n", mode, total + most; printf "\tsection\t.tdesc,\"%s\"\n", tf; ! printf "\tword\t0x42\n"; ! printf "\tword\t1\n"; ! printf "\tword\t__%smovstr%s%dx%d\n", us, mode, total + most, total + most; ! printf "\tword\tend%s%dx\n", mode, total + most; ! printf "\tword\t0x0100001f\n"; ! printf "\tword\t0\n"; ! printf "\tword\t1\n"; ! printf "\tword\t0\n"; printf "\ttext\n"; } --- 263,277 ---- printf "\tjmp.n\t%sr1\n", ps; else ! printf "\tld%s\t%sr%d,%sr3,%d\n", suffix[align], ps, reg[evenp], ps, ld; ! printf "\tst%s\t%sr%d,%sr2,%d\n", suffix[prev], ps, reg[1-evenp], ps, st; ld += align; st += prev; prev = align; ! evenp = 1 - evenp; } if (!no_tdesc) { ! printf "%send%s%dx:\n", la, mode, total + most; printf "\tsection\t.tdesc,\"%s\"\n", tf; ! printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, total + most, total + most; ! printf ",%send%s%dx\n", la, mode, total + most; ! printf "\tword\t0x0100001f,0,1,0\n"; printf "\ttext\n"; } *************** *** 290,293 **** --- 281,299 ---- } + (do_file '"movstrDI47x.s"'; + echo 'DI:1:8:48' | gen_movstrXr) > moveDI47x.asm + (do_file '"movstrDI46x.s"'; + echo 'DI:2:8:48' | gen_movstrXr) > moveDI46x.asm + (do_file '"movstrDI45x.s"'; + echo 'DI:3:8:48' | gen_movstrXr) > moveDI45x.asm + (do_file '"movstrDI44x.s"'; + echo 'DI:4:8:48' | gen_movstrXr) > moveDI44x.asm + (do_file '"movstrDI43x.s"'; + echo 'DI:5:8:48' | gen_movstrXr) > moveDI43x.asm + (do_file '"movstrDI42x.s"'; + echo 'DI:6:8:48' | gen_movstrXr) > moveDI42x.asm + (do_file '"movstrDI41x.s"'; + echo 'DI:7:8:48' | gen_movstrXr) > moveDI41x.asm + (do_file '"movstrSI47x.s"'; echo 'SI:1:4:48' | gen_movstrXr) > moveSI47x.asm *************** *** 296,299 **** --- 302,306 ---- (do_file '"movstrSI45x.s"'; echo 'SI:3:4:48' | gen_movstrXr) > moveSI45x.asm + (do_file '"movstrHI15x.s"'; echo 'HI:1:2:16' | gen_movstrXr) > moveHI15x.asm diff -rc2N gcc-2.2.2/config/m88k.c gcc-2.3.1/config/m88k.c *** gcc-2.2.2/config/m88k.c Sat Jun 13 17:15:07 1992 --- gcc-2.3.1/config/m88k.c Thu Oct 29 05:47:44 1992 *************** *** 26,29 **** --- 26,30 ---- #include + #include "assert.h" #include "config.h" #include "rtl.h" *************** *** 47,55 **** extern FILE *asm_out_file; ! static char out_sccs_id[] = "@(#)m88k.c 2.1.11.11 29 May 1992 11:12:23"; static char tm_sccs_id [] = TM_SCCS_ID; char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */ char *m88k_short_data; int m88k_gp_threshold; --- 48,58 ---- extern FILE *asm_out_file; ! static char out_sccs_id[] = "@(#)m88k.c 2.2.14.4 10/29/92 05:37:46"; static char tm_sccs_id [] = TM_SCCS_ID; char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */ char *m88k_short_data; + char *m88k_version; + char m88k_volatile_code; int m88k_gp_threshold; *************** *** 59,62 **** --- 62,66 ---- int m88k_stack_size = 0; /* size of allocated stack (including frame) */ int m88k_case_index; + int m88k_version_0300; /* Version is at least 03.00 */ rtx m88k_compare_reg; /* cmp output pseudo register */ *************** *** 94,97 **** --- 98,123 ---- } + /* Return the bit number in a compare word corresponding to CONDITION. */ + + int + condition_value (condition) + rtx condition; + { + switch (GET_CODE (condition)) + { + case EQ: return 2; + case NE: return 3; + case GT: return 4; + case LE: return 5; + case LT: return 6; + case GE: return 7; + case GTU: return 8; + case LEU: return 9; + case LTU: return 10; + case GEU: return 11; + default: abort (); + } + } + int integer_ok_for_set (value) *************** *** 186,195 **** Return 1 if we have written out everything that needs to be done to do the move. Otherwise, return 0 and the caller will emit the move ! normally. */ int ! emit_move_sequence (operands, mode) rtx *operands; enum machine_mode mode; { register rtx operand0 = operands[0]; --- 212,225 ---- Return 1 if we have written out everything that needs to be done to do the move. Otherwise, return 0 and the caller will emit the move ! normally. ! ! SCRATCH if non zero can be used as a scratch register for the move ! operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */ int ! emit_move_sequence (operands, mode, scratch) rtx *operands; enum machine_mode mode; + rtx scratch; { register rtx operand0 = operands[0]; *************** *** 233,240 **** { rtx temp = ((reload_in_progress || reload_completed) ! ? operand0 : gen_reg_rtx (Pmode)); operands[1] = legitimize_address (flag_pic && symbolic_address_p (operand1), ! operand1, temp); if (mode != SImode) operands[1] = gen_rtx (SUBREG, mode, operands[1], 0); --- 263,270 ---- { rtx temp = ((reload_in_progress || reload_completed) ! ? operand0 : 0); operands[1] = legitimize_address (flag_pic && symbolic_address_p (operand1), ! operand1, temp, scratch); if (mode != SImode) operands[1] = gen_rtx (SUBREG, mode, operands[1], 0); *************** *** 246,277 **** } ! /* Return a legitimate reference for ORIG (either an address or a MEM) using ! the register REG. If PIC and the address is already position-independent, ! use ORIG. */ struct rtx_def * ! legitimize_address (pic, orig, reg) int pic; rtx orig; rtx reg; { rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig); rtx new = orig; ! rtx temp; if (pic) { ! if (GET_CODE (addr) == SYMBOL_REF ! || GET_CODE (addr) == LABEL_REF) { ! if (reg == 0) abort (); if (flag_pic == 2) { emit_insn (gen_rtx (SET, VOIDmode, ! reg, gen_rtx (HIGH, SImode, addr))); emit_insn (gen_rtx (SET, VOIDmode, ! reg, gen_rtx (LO_SUM, SImode, reg, addr))); ! addr = reg; } new = gen_rtx (MEM, Pmode, --- 276,323 ---- } ! /* Return a legitimate reference for ORIG (either an address or a MEM) ! using the register REG. If PIC and the address is already ! position-independent, use ORIG. Newly generated position-independent ! addresses go into a reg. This is REG if non zero, otherwise we ! allocate register(s) as necessary. If this is called during reload, ! and we need a second temp register, then we use SCRATCH, which is ! provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */ struct rtx_def * ! legitimize_address (pic, orig, reg, scratch) int pic; rtx orig; rtx reg; + rtx scratch; { rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig); rtx new = orig; ! rtx temp, insn; if (pic) { ! if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) { ! if (reg == 0) ! { ! if (reload_in_progress || reload_completed) ! abort (); ! else ! reg = gen_reg_rtx (Pmode); ! } if (flag_pic == 2) { + /* If not during reload, allocate another temp reg here for + loading in the address, so that these instructions can be + optimized properly. */ + temp = ((reload_in_progress || reload_completed) + ? reg : gen_reg_rtx (Pmode)); + emit_insn (gen_rtx (SET, VOIDmode, ! temp, gen_rtx (HIGH, SImode, addr))); emit_insn (gen_rtx (SET, VOIDmode, ! temp, gen_rtx (LO_SUM, SImode, temp, addr))); ! addr = temp; } new = gen_rtx (MEM, Pmode, *************** *** 280,290 **** current_function_uses_pic_offset_table = 1; RTX_UNCHANGING_P (new) = 1; ! { ! rtx insn = emit_move_insn (reg, new); ! /* Put a REG_EQUAL note on this insn, so that it can be optimized ! by loop. */ ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig, ! REG_NOTES (insn)); ! } new = reg; } --- 326,334 ---- current_function_uses_pic_offset_table = 1; RTX_UNCHANGING_P (new) = 1; ! insn = emit_move_insn (reg, new); ! /* Put a REG_EQUAL note on this insn, so that it can be optimized ! by loop. */ ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig, ! REG_NOTES (insn)); new = reg; } *************** *** 298,313 **** if (reg == 0) ! abort (); if (GET_CODE (XEXP (addr, 0)) != PLUS) abort (); ! base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg); addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1), ! base == reg ? 0 : reg); if (GET_CODE (addr) == CONST_INT) ! new = plus_constant_for_output (base, INTVAL (addr)); ! else ! new = gen_rtx (PLUS, SImode, base, addr); /* Should we set special REG_NOTEs here? */ } --- 342,378 ---- if (reg == 0) ! { ! if (reload_in_progress || reload_completed) ! abort (); ! else ! reg = gen_reg_rtx (Pmode); ! } if (GET_CODE (XEXP (addr, 0)) != PLUS) abort (); ! base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0); addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1), ! base == reg ? 0 : reg, 0); if (GET_CODE (addr) == CONST_INT) ! { ! if (SMALL_INT (addr)) ! return plus_constant_for_output (base, INTVAL (addr)); ! else if (! reload_in_progress && ! reload_completed) ! addr = force_reg (Pmode, addr); ! /* We can't create any new registers during reload, so use the ! SCRATCH reg provided by the reload_insi pattern. */ ! else if (scratch) ! { ! emit_move_insn (scratch, addr); ! addr = scratch; ! } ! else ! /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS ! macro needs to be adjusted so that a scratch reg is provided ! for this address. */ ! abort (); ! } ! new = gen_rtx (PLUS, SImode, base, addr); /* Should we set special REG_NOTEs here? */ } *************** *** 315,318 **** --- 380,391 ---- else if (! SHORT_ADDRESS_P (addr, temp)) { + if (reg == 0) + { + if (reload_in_progress || reload_completed) + abort (); + else + reg = gen_reg_rtx (Pmode); + } + emit_insn (gen_rtx (SET, VOIDmode, reg, gen_rtx (HIGH, SImode, addr))); *************** *** 345,364 **** #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */ #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */ #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11, __movstrSI46x46 .. __movstrSI46x10, __movstrSI45x45 .. __movstrSI45x9 */ ! #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */ ! ! /* Break even points where memcpy will do just as well. */ ! #define MOVSTR_QI_LIMIT 13 ! #define MOVSTR_HI_LIMIT 38 ! #define MOVSTR_SI_LIMIT MOVSTR_SI ! ! static enum machine_mode mode_from_bytes[] = ! {VOIDmode, QImode, HImode, VOIDmode, SImode}; ! static int max_from_bytes[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI}; ! static int all_from_bytes[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI}; ! static int best_from_bytes[] = ! {0, MOVSTR_QI_LIMIT, MOVSTR_HI_LIMIT, 0, MOVSTR_SI_LIMIT}; static void block_move_loop (); --- 418,472 ---- #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */ #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */ + #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */ + #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */ #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11, __movstrSI46x46 .. __movstrSI46x10, __movstrSI45x45 .. __movstrSI45x9 */ ! #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23, ! __movstrDI46x46 .. __movstrDI46x22, ! __movstrDI45x45 .. __movstrDI45x21, ! __movstrDI44x44 .. __movstrDI44x20, ! __movstrDI43x43 .. __movstrDI43x19, ! __movstrDI42x42 .. __movstrDI42x18, ! __movstrDI41x41 .. __movstrDI41x17 */ ! ! /* Limits for using the non-looping movstr functions. For the m88100 ! processor, we assume the source and destination are word aligned. ! The QImode and HImode limits are the break even points where memcpy ! does just as well and beyond which memcpy does better. For the ! m88110, we tend to assume double word alignment, but also analyze ! the word aligned cases. The analysis is complicated because memcpy ! may use the cache control instructions for better performance. */ ! ! #define MOVSTR_QI_LIMIT_88100 13 ! #define MOVSTR_HI_LIMIT_88100 38 ! #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI ! #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI ! ! #define MOVSTR_QI_LIMIT_88000 16 ! #define MOVSTR_HI_LIMIT_88000 38 ! #define MOVSTR_SI_LIMIT_88000 72 ! #define MOVSTR_DI_LIMIT_88000 72 ! ! #define MOVSTR_QI_LIMIT_88110 16 ! #define MOVSTR_HI_LIMIT_88110 38 ! #define MOVSTR_SI_LIMIT_88110 72 ! #define MOVSTR_DI_LIMIT_88110 72 ! ! static enum machine_mode mode_from_align[] = ! {VOIDmode, QImode, HImode, VOIDmode, SImode, ! VOIDmode, VOIDmode, VOIDmode, DImode}; ! static int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI, ! 0, 0, 0, MOVSTR_DI}; ! static int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0, MOVSTR_ODD_SI, ! 0, 0, 0, MOVSTR_ODD_DI}; ! ! static int best_from_align[3][9] = ! {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100, ! 0, 0, 0, MOVSTR_DI_LIMIT_88100, ! 0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110, ! 0, 0, 0, MOVSTR_DI_LIMIT_88110, ! 0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000, ! 0, 0, 0, MOVSTR_DI_LIMIT_88000}; static void block_move_loop (); *************** *** 382,385 **** --- 490,498 ---- int constp = (GET_CODE (operands[2]) == CONST_INT); int bytes = (constp ? INTVAL (operands[2]) : 0); + int target = (int) m88k_cpu; + + assert (CPU_M88100 == 0); + assert (CPU_M88110 == 1); + assert (CPU_M88000 == 2); if (constp && bytes <= 0) *************** *** 387,391 **** /* Determine machine mode to do move with. */ ! if (align > 4) align = 4; else if (align <= 0 || align == 3) --- 500,504 ---- /* Determine machine mode to do move with. */ ! if (align > 4 && !TARGET_88110) align = 4; else if (align <= 0 || align == 3) *************** *** 396,404 **** bytes, align, 0); ! else if (constp && bytes <= best_from_bytes[align]) block_move_no_loop (operands[0], dest_mem, operands[1], src_mem, bytes, align); ! else if (constp && align == 4) block_move_loop (operands[0], dest_mem, operands[1], src_mem, bytes, align); --- 509,517 ---- bytes, align, 0); ! else if (constp && bytes <= best_from_align[target][align]) block_move_no_loop (operands[0], dest_mem, operands[1], src_mem, bytes, align); ! else if (constp && align == 4 && TARGET_88100) block_move_loop (operands[0], dest_mem, operands[1], src_mem, bytes, align); *************** *** 464,468 **** remainder = size - count * MOVSTR_LOOP - units * align; ! mode = mode_from_bytes[align]; sprintf (entry, "__movstr%s%dn%d", GET_MODE_NAME (mode), MOVSTR_LOOP, units * align); --- 577,581 ---- remainder = size - count * MOVSTR_LOOP - units * align; ! mode = mode_from_align[align]; sprintf (entry, "__movstr%s%dn%d", GET_MODE_NAME (mode), MOVSTR_LOOP, units * align); *************** *** 480,484 **** MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); ! emit_insn (gen_call_block_move_loop (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), dest, src, offset_rtx, value_rtx, --- 593,597 ---- MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); ! emit_insn (gen_call_movstrsi_loop (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), dest, src, offset_rtx, value_rtx, *************** *** 503,511 **** int align; { ! enum machine_mode mode = mode_from_bytes[align]; int units = size / align; int remainder = size - units * align; int most; ! int evenp; rtx offset_rtx; rtx value_rtx; --- 616,624 ---- int align; { ! enum machine_mode mode = mode_from_align[align]; int units = size / align; int remainder = size - units * align; int most; ! int value_reg; rtx offset_rtx; rtx value_rtx; *************** *** 513,524 **** tree entry_name; ! if (remainder && size <= all_from_bytes[align]) { ! most = all_from_bytes[align] - (align - remainder); remainder = 0; } else { ! most = max_from_bytes[align]; } --- 626,637 ---- tree entry_name; ! if (remainder && size <= all_from_align[align]) { ! most = all_from_align[align] - (align - remainder); remainder = 0; } else { ! most = max_from_align[align]; } *************** *** 537,546 **** MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); ! evenp = ((most - (size - remainder)) / align) & 1; emit_insn (gen_call_block_move (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), dest, src, offset_rtx, value_rtx, ! gen_rtx (REG, GET_MODE (value_rtx), (evenp ? 4 : 5)))); if (remainder) --- 650,660 ---- MEM_IN_STRUCT_P (value_rtx) = MEM_IN_STRUCT_P (src_mem); ! value_reg = ((((most - (size - remainder)) / align) & 1) == 0 ! ? (align == 8 ? 6 : 5) : 4); emit_insn (gen_call_block_move (gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (entry_name)), dest, src, offset_rtx, value_rtx, ! gen_rtx (REG, GET_MODE (value_rtx), value_reg))); if (remainder) *************** *** 577,581 **** it is known to be the same mode as the first. */ amount[0] = amount[1] = align; ! mode[0] = mode_from_bytes[align]; temp[0] = gen_reg_rtx (mode[0]); if (size >= 2 * align) --- 691,695 ---- it is known to be the same mode as the first. */ amount[0] = amount[1] = align; ! mode[0] = mode_from_align[align]; temp[0] = gen_reg_rtx (mode[0]); if (size >= 2 * align) *************** *** 596,601 **** if (size < amount[next]) { ! amount[next] = (size >= 2 ? 2 : 1); ! mode[next] = mode_from_bytes[amount[next]]; temp[next] = gen_reg_rtx (mode[next]); } --- 710,715 ---- if (size < amount[next]) { ! amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1)); ! mode[next] = mode_from_align[amount[next]]; temp[next] = gen_reg_rtx (mode[next]); } *************** *** 770,773 **** --- 884,893 ---- operands); + #ifdef USE_GAS + last = (delta < 0 + ? "subu %#r1,%#r1,.-%l0+4" + : "addu %#r1,%#r1,%l0-.-4"); + operands[0] = dest; + #else operands[0] = gen_label_rtx (); operands[1] = gen_label_rtx (); *************** *** 789,792 **** --- 909,913 ---- sb_high = gen_rtx (EXPR_LIST, VOIDmode, high, sb_high); sb_low = gen_rtx (EXPR_LIST, VOIDmode, low, sb_low); + #endif /* Don't USE_GAS */ return last; *************** *** 844,851 **** if (GET_CODE (insnt) == JUMP_INSN) break; ! else if (GET_CODE (insnt) == SEQUENCE ! && GET_CODE (XVECEXP (insnt, 0, 0)) == JUMP_INSN) { ! insnt = XVECEXP (insnt, 0, 0); break; } --- 965,973 ---- if (GET_CODE (insnt) == JUMP_INSN) break; ! else if (GET_CODE (insnt) == INSN ! && GET_CODE (PATTERN (insnt)) == SEQUENCE ! && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN) { ! insnt = XVECEXP (PATTERN (insnt), 0, 0); break; } *************** *** 864,871 **** if (GET_CODE (insnj) == JUMP_INSN) break; ! else if (GET_CODE (insnj) == SEQUENCE ! && GET_CODE (XVECEXP (insnj, 0, 0)) == JUMP_INSN) { ! insnj = XVECEXP (insnj, 0, 0); break; } --- 986,994 ---- if (GET_CODE (insnj) == JUMP_INSN) break; ! else if (GET_CODE (insnj) == INSN ! && GET_CODE (PATTERN (insnj)) == SEQUENCE ! && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN) { ! insnj = XVECEXP (PATTERN (insnj), 0, 0); break; } *************** *** 876,880 **** && GET_CODE (SET_SRC (PATTERN (insnj))) == REG && REGNO (SET_SRC (PATTERN (insnj))) == 1))) ! insnt = 0; /* Predict to not return. */ --- 999,1003 ---- && GET_CODE (SET_SRC (PATTERN (insnj))) == REG && REGNO (SET_SRC (PATTERN (insnj))) == 1))) ! insnj = 0; /* Predict to not return. */ *************** *** 904,908 **** /* EQ tests are usually false and NE tests are usually true. Also, most quantities are positive, so we can make the appropriate guesses ! about signed comparisons against zero. Consider unsigned comparsions to be a range check and assume quantities to be in range. */ switch (GET_CODE (condition)) --- 1027,1031 ---- /* EQ tests are usually false and NE tests are usually true. Also, most quantities are positive, so we can make the appropriate guesses ! about signed comparisons against zero. Consider unsigned comparisons to be a range check and assume quantities to be in range. */ switch (GET_CODE (condition)) *************** *** 1403,1406 **** --- 1526,1530 ---- { int i; + int in_escape = 0; register int num = 0; *************** *** 1416,1442 **** num = 0; } ! if (c == '\"' || c == '\\') { putc ('\\', file); ! num++; } ! ! if (c >= ' ' && c < 0177) { putc (c, file); num++; } else { fprintf (file, "\\%03o", c); num += 4; ! /* After an octal-escape, if a digit follows, ! terminate one string constant and start another. ! The Vax assembler fails to stop reading the escape ! after three digits, so this is the only way we ! can get it to parse the data properly. */ ! if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9') ! num = max + 1; /* next pass will start a new string */ } } --- 1540,1582 ---- num = 0; } ! if (c == '\"' || c == '\\') { + escape: putc ('\\', file); ! putc (c, file); ! num += 2; ! in_escape = 0; } ! else if (in_escape && c >= '0' && c <= '9') { + /* If a digit follows an octal-escape, the Vax assembler fails + to stop reading the escape after three digits. Continue to + output the values as an octal-escape until a non-digit is + found. */ + fprintf (file, "\\%03o", c); + num += 4; + } + else if (c >= ' ' && c < 0177) + { putc (c, file); num++; + in_escape = 0; } else { + switch (c) + { + /* Some assemblers can't handle \a, \v, or \?. */ + case '\t': c = 't'; goto escape; + case '\f': c = 'f'; goto escape; + case '\b': c = 'b'; goto escape; + case '\r': c = 'r'; goto escape; + case '\n': c = 'n'; goto escape; + } + fprintf (file, "\\%03o", c); num += 4; ! in_escape = 1; } } *************** *** 1453,1549 **** ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number); } - - /* Handle a pragma directive. HANDLE_PRAGMA conspires to parse the input - following #pragma into tokens based on yylex. */ - - void - m88k_handle_pragma_token (string, token) - char *string; - tree token; - { - static enum pragma_state - { - ps_start, - ps_done, - ps_bad, - ps_weak, - ps_name, - ps_equals, - ps_value - } state; - static char *name; - static char *value; - - if (HANDLE_PRAGMA_WEAK) - { - if (string == 0) - { - if (state == ps_name || state == ps_value) - { - fprintf (asm_out_file, "\t%s\t ", WEAK_ASM_OP); - ASM_OUTPUT_LABELREF (asm_out_file, name); - fputc ('\n', asm_out_file); - if (state == ps_value) - { - fprintf (asm_out_file, "\t%s\t ", SET_ASM_OP); - ASM_OUTPUT_LABELREF (asm_out_file, name); - fputc (',', asm_out_file); - ASM_OUTPUT_LABELREF (asm_out_file, value); - fputc ('\n', asm_out_file); - } - } - else if (! (state == ps_done || state == ps_start)) - warning ("ignoring malformed #pragma weak symbol [=value]"); - state = ps_start; - } - else - switch (state) - { - case ps_start: - if (token - && TREE_CODE (token) == IDENTIFIER_NODE - && !strcmp (IDENTIFIER_POINTER (token), "weak")) - state = ps_weak; - else - state = ps_done; - break; - - case ps_weak: - if (token - && TREE_CODE (token) == IDENTIFIER_NODE) - { - name = IDENTIFIER_POINTER (token); - state = ps_name; - } - else - state = ps_bad; - break; - - case ps_name: - state = (strcmp (string, "=") ? ps_bad : ps_equals); - break; - - case ps_equals: - if (token - && TREE_CODE (token) == IDENTIFIER_NODE) - { - value = IDENTIFIER_POINTER (token); - state = ps_value; - } - else - state = ps_bad; - break; - - case ps_value: - state = ps_bad; - case ps_bad: - case ps_done: - break; - - default: - abort (); - } - } - } /* Generate the assembly code for function entry. --- 1593,1596 ---- *************** *** 1620,1625 **** */ ! static void output_reg_adjust (); static void preserve_registers (); static void output_tdesc (); --- 1667,1673 ---- */ ! static void emit_add (); static void preserve_registers (); + static void emit_ldst (); static void output_tdesc (); *************** *** 1630,1633 **** --- 1678,1683 ---- static int frame_size; static int variable_args_p; + static int epilogue_marked; + static int prologue_marked; extern char call_used_regs[]; *************** *** 1756,1763 **** } ! /* Return true if this function is known to have a null epilogue. */ int ! null_epilogue () { if (! reload_completed) --- 1806,1813 ---- } ! /* Return true if this function is known to have a null prologue. */ int ! null_prologue () { if (! reload_completed) *************** *** 1771,1865 **** } - /* Determine the number of instructions needed for the function epilogue. */ - - #define MAX_EPILOGUE_DELAY_INSNS 4 - - static char epilogue_dead_regs[FIRST_PSEUDO_REGISTER]; - - delay_slots_for_epilogue () - { - register int insns = save_regs[1] + save_regs[FRAME_POINTER_REGNUM]; - register int regs = nregs - insns; - - if (regs > 3) - insns += 1 + (regs & 1); - else if (nregs == 4) - /* This is a special cases of ld/ld/ld.d which has no start-up delay. */ - return 0; - - if (insns) - { - bzero ((char *) &epilogue_dead_regs[0], sizeof (epilogue_dead_regs)); - epilogue_dead_regs[1] = save_regs[1]; - epilogue_dead_regs[STACK_POINTER_REGNUM] = frame_pointer_needed; - epilogue_dead_regs[TEMP_REGNUM] = ! ADD_INTVAL (m88k_fp_offset); - } - - return insns; - } - - /* Return 1 if X is safe to use as an epilogue insn. */ - - int - ok_for_epilogue_p (x) - rtx x; - { - register char *fmt; - register int i, j; - - switch (GET_CODE (x)) - { - case REG: - for (i = REGNO (x), j = i + HARD_REGNO_NREGS (i, GET_MODE (x)); - i < j; - i++) - if (epilogue_dead_regs[i]) - return 0; - - case CONST_INT: - case CONST_DOUBLE: - case CONST: - case PC: - case CC0: - case LABEL_REF: - case SYMBOL_REF: - case CODE_LABEL: - return 1; - } - - fmt = GET_RTX_FORMAT (GET_CODE (x)); - for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (!ok_for_epilogue_p (XEXP (x, i))) - return 0; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (!ok_for_epilogue_p (XVECEXP (x, i, j))) - return 0; - } - } - return 1; - } - - int - eligible_for_epilogue_delay (insn) - rtx insn; - { - switch (get_attr_type (insn)) - { - case TYPE_STORE: - case TYPE_LOADA: - case TYPE_ARITH: - case TYPE_MARITH: - return ok_for_epilogue_p (PATTERN (insn)); - default: - return 0; - } - } - /* Determine if the current function has any references to the arg pointer. This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL. --- 1821,1824 ---- *************** *** 1893,1916 **** void ! m88k_output_prologue (stream, size) FILE *stream; int size; { ! int old_fp_offset = m88k_fp_offset; ! int old_stack_size = m88k_stack_size; ! m88k_layout_frame (); ! #if (MONITOR_GCC & 0x8) /* Watch for suspicious register elimination changes. */ ! if (frame_laid_out > 1) { ! if (old_fp_offset != m88k_fp_offset) ! warning ("Internal gcc error: FP offset has changed by %d bytes", ! m88k_fp_offset - old_fp_offset); ! if (old_stack_size != m88k_stack_size) ! warning ("Internal gcc error: stack size has changed by %d bytes", ! m88k_stack_size - old_stack_size); } ! #endif ! frame_laid_out = 0; if (TARGET_OPTIMIZE_ARG_AREA --- 1852,1889 ---- void ! m88k_begin_prologue (stream, size) FILE *stream; int size; { ! m88k_prologue_done = 1; /* it's ok now to put out ln directives */ ! } ! void ! m88k_end_prologue (stream) ! FILE *stream; ! { ! if (TARGET_OCS_DEBUG_INFO && !prologue_marked) { ! PUT_OCS_FUNCTION_START (stream); ! prologue_marked = 1; ! ! /* If we've already passed the start of the epilogue, say that ! it starts here. This marks the function as having a null body, ! but at a point where the return address is in a known location. ! ! Originally, I thought this couldn't happen, but the pic prologue ! for leaf functions ends with the instruction that restores the ! return address from the temporary register. If the temporary ! register is never used, that instruction can float all the way ! to the end of the function. */ ! if (epilogue_marked) ! PUT_OCS_FUNCTION_END (stream); } ! } ! ! void ! m88k_expand_prologue () ! { ! m88k_layout_frame (); if (TARGET_OPTIMIZE_ARG_AREA *************** *** 1919,1923 **** { /* The incoming argument area is used for stack space if it is not ! used (or if -mno-use-arg-area is given). */ if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0) m88k_stack_size = 0; --- 1892,1896 ---- { /* The incoming argument area is used for stack space if it is not ! used (or if -mno-optimize-arg-area is given). */ if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0) m88k_stack_size = 0; *************** *** 1925,1965 **** if (m88k_stack_size) ! output_reg_adjust (stream, 31, 31, -m88k_stack_size, 0); if (nregs || nxregs) ! preserve_registers (stream, m88k_fp_offset + 4, 1); if (frame_pointer_needed) ! output_reg_adjust (stream, 30, 31, m88k_fp_offset, 0); ! ! if (TARGET_OCS_DEBUG_INFO) ! PUT_OCS_FUNCTION_START (stream); if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]) { ! char label[256]; if (! save_regs[1]) ! fprintf (stream, "\tor\t %s,%s,0\n", ! reg_names[TEMP_REGNUM], reg_names[1]); ! ASM_GENERATE_INTERNAL_LABEL (label, "Lab", m88k_function_number); ! fprintf (stream, "\tbsr.n\t %s\n", &label[1]); ! fprintf (stream, "\tor.u\t %s,%s,%shi16(%s#abdiff)\n", ! reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[0], ! m88k_pound_sign, &label[1]); ! ASM_OUTPUT_INTERNAL_LABEL (stream, "Lab", m88k_function_number); ! fprintf (stream, "\tor\t %s,%s,%slo16(%s#abdiff)\n", ! reg_names[PIC_OFFSET_TABLE_REGNUM], ! reg_names[PIC_OFFSET_TABLE_REGNUM], ! m88k_pound_sign, &label[1]); ! fprintf (stream, "\taddu\t %s,%s,%s\n", ! reg_names[PIC_OFFSET_TABLE_REGNUM], ! reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[1]); if (! save_regs[1]) ! fprintf (stream, "\tor\t %s,%s,0\n", ! reg_names[1], reg_names[TEMP_REGNUM]); } ! ! m88k_prologue_done = 1; /* it's ok now to put out ln directives */ } --- 1898,1929 ---- if (m88k_stack_size) ! emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size); if (nregs || nxregs) ! preserve_registers (m88k_fp_offset + 4, 1); if (frame_pointer_needed) ! emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset); if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]) { ! rtx return_reg = gen_rtx (REG, SImode, 1); ! rtx label = gen_label_rtx (); ! rtx temp_reg; if (! save_regs[1]) ! { ! temp_reg = gen_rtx (REG, SImode, TEMP_REGNUM); ! emit_move_insn (temp_reg, return_reg); ! } ! emit_insn (gen_locate1 (pic_offset_table_rtx, label)); ! emit_insn (gen_locate2 (pic_offset_table_rtx, label)); ! emit_insn (gen_addsi3 (pic_offset_table_rtx, ! pic_offset_table_rtx, return_reg)); if (! save_regs[1]) ! emit_move_insn (return_reg, temp_reg); } ! if (profile_flag || profile_block_flag) ! emit_insn (gen_blockage ()); } *************** *** 1973,2009 **** void ! m88k_output_epilogue (stream, size) FILE *stream; int size; { rtx insn = get_last_insn (); - #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */ - fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n", - size, m88k_fp_offset, m88k_stack_size); - #endif - - output_short_branch_defs (stream); ! if (TARGET_OCS_DEBUG_INFO) PUT_OCS_FUNCTION_END (stream); ! /* If the last insn was a BARRIER, we don't have to write any code. */ if (GET_CODE (insn) == NOTE) insn = prev_nonnote_insn (insn); ! if (insn && GET_CODE (insn) == BARRIER) ! { ! if (current_function_epilogue_delay_list) ! abort (); ! } ! else ! { ! if (frame_pointer_needed) ! output_reg_adjust (stream, 31, 30, -m88k_fp_offset, 0); ! ! if (nregs || nxregs) ! preserve_registers (stream, m88k_fp_offset + 4, 0); ! output_reg_adjust (stream, 31, 31, m88k_stack_size, 1); ! } fprintf (stream, "\n"); --- 1937,1968 ---- void ! m88k_begin_epilogue (stream) ! FILE *stream; ! { ! if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked) ! { ! PUT_OCS_FUNCTION_END (stream); ! } ! epilogue_marked = 1; ! } ! ! void ! m88k_end_epilogue (stream, size) FILE *stream; int size; { rtx insn = get_last_insn (); ! if (TARGET_OCS_DEBUG_INFO && !epilogue_marked) PUT_OCS_FUNCTION_END (stream); ! /* If the last insn isn't a BARRIER, we must write a return insn. This ! should only happen if the function has no prologe and no body. */ if (GET_CODE (insn) == NOTE) insn = prev_nonnote_insn (insn); ! if (insn == 0 || GET_CODE (insn) != BARRIER) ! fprintf (stream, "\tjmp\t %s\n", reg_names[1]); ! output_short_branch_defs (stream); fprintf (stream, "\n"); *************** *** 2015,2081 **** m88k_prologue_done = 0; /* don't put out ln directives */ variable_args_p = 0; /* has variable args */ } - - /* Output code to STREAM to set DSTREG to SRCREG + AMOUNT. Issue - a return instruction and use it's delay slot based on RETURN_P. */ ! static void ! output_reg_adjust (stream, dstreg, srcreg, amount, return_p) ! FILE *stream; ! int dstreg, srcreg, amount, return_p; { ! char *opname; ! char incr[256]; ! if (amount < 0) ! { ! opname = "subu"; ! amount = -amount; ! } ! else ! opname = "addu"; ! if (amount == 0 && dstreg == srcreg) ! { ! if (return_p) ! fprintf (stream, "\tjmp\t %s\n", reg_names[1]); ! return; ! } ! else if (SMALL_INTVAL (amount)) ! sprintf (incr, "\t%s\t %s,%s,%d", opname, ! reg_names[dstreg], reg_names[srcreg], amount); ! else ! { ! rtx operands[2]; ! operands[0] = gen_rtx (REG, SImode, TEMP_REGNUM); ! operands[1] = gen_rtx (CONST_INT, VOIDmode, amount); ! output_asm_insn (output_load_const_int (SImode, operands), ! operands); ! sprintf (incr, "\t%s\t %s,%s,%s", opname, ! reg_names[dstreg], reg_names[srcreg], reg_names[TEMP_REGNUM]); ! } ! if (!return_p) ! fprintf (stream, "%s\n", incr); ! else if (flag_delayed_branch) ! fprintf (stream, "\tjmp.n\t %s\n%s\n", reg_names[1], incr); ! else ! fprintf (stream, "%s\n\tjmp\t %s\n", incr, reg_names[1]); } /* Save/restore the preserve registers. base is the highest offset from r31 at which a register is stored. store_p is true if stores are to ! be done; otherwise loads. When loading, output the epilogue delay ! insns. */ static void ! preserve_registers (stream, base, store_p) ! FILE *stream; int base; int store_p; { int regno, offset; - char *fmt = (store_p ? "\tst%s\t %s,%s,%d\n" : "\tld%s\t %s,%s,%d\n"); struct mem_op { int regno; --- 1974,2029 ---- m88k_prologue_done = 0; /* don't put out ln directives */ variable_args_p = 0; /* has variable args */ + frame_laid_out = 0; + epilogue_marked = 0; + prologue_marked = 0; } ! void ! m88k_expand_epilogue () { ! #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */ ! fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n", ! size, m88k_fp_offset, m88k_stack_size); ! #endif ! if (frame_pointer_needed) ! emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset); ! if (nregs || nxregs) ! preserve_registers (m88k_fp_offset + 4, 0); ! if (m88k_stack_size) ! emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size); ! } ! ! /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or ! epilogue. */ ! static void ! emit_add (dstreg, srcreg, amount) ! rtx dstreg; ! rtx srcreg; ! int amount; ! { ! rtx incr = gen_rtx (CONST_INT, VOIDmode, abs (amount)); ! if (! ADD_INTVAL (amount)) ! { ! rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM); ! emit_move_insn (temp, incr); ! incr = temp; ! } ! emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr)); } /* Save/restore the preserve registers. base is the highest offset from r31 at which a register is stored. store_p is true if stores are to ! be done; otherwise loads. */ static void ! preserve_registers (base, store_p) int base; int store_p; { int regno, offset; struct mem_op { int regno; *************** *** 2096,2100 **** if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM]) offset -= 4; ! fprintf (stream, fmt, "", reg_names[1], reg_names[31], offset); offset -= 4; base = offset; --- 2044,2048 ---- if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM]) offset -= 4; ! emit_ldst (store_p, 1, SImode, offset); offset -= 4; base = offset; *************** *** 2157,2225 **** mo_ptr->regno = 0; - /* Output the delay insns interleaved with the memory operations. */ - if (! store_p && current_function_epilogue_delay_list) - { - rtx delay_insns = current_function_epilogue_delay_list; - rtx insn; - - /* The first delay insn goes after the restore of r1. */ - if (save_regs[1]) - { - final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1); - delay_insns = XEXP (delay_insns, 1); - } - - while (delay_insns) - { - /* Find a memory operation that doesn't conflict with this insn. */ - for (mo_ptr = mem_op; mo_ptr->regno != 0; mo_ptr++) - { - if (mo_ptr->nregs) - { - int nregs = (mo_ptr->regno < FIRST_EXTENDED_REGISTER - ? mo_ptr->nregs : 1); - rtx ok_insns = delay_insns; - int i; - - for (i = 0; i < nregs; i++) - epilogue_dead_regs[mo_ptr->regno + i] = 1; - - while (ok_insns) - { - insn = XEXP (ok_insns, 0); - ok_insns = XEXP (ok_insns, 1); - - if (! ok_for_epilogue_p (PATTERN (insn))) - { - for (i = 0; i < nregs; i++) - epilogue_dead_regs[mo_ptr->regno + i] = 0; - insn = 0; - break; /* foreach delay insn */ - } - } - if (insn) - { - fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "", - reg_names[mo_ptr->regno], reg_names[31], - mo_ptr->offset); - mo_ptr->nregs = 0; - break; /* foreach memory operation */ - } - } - } - final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1); - delay_insns = XEXP (delay_insns, 1); - } - } - /* Output the memory operations. */ for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++) { if (mo_ptr->nregs) ! fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "", ! reg_names[mo_ptr->regno], reg_names[31], mo_ptr->offset); } } /* Convert the address expression REG to a CFA offset. */ --- 2105,2134 ---- mo_ptr->regno = 0; /* Output the memory operations. */ for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++) { if (mo_ptr->nregs) ! emit_ldst (store_p, mo_ptr->regno, ! (mo_ptr->nregs > 1 ? DImode : SImode), ! mo_ptr->offset); } } + static void + emit_ldst (store_p, regno, mode, offset) + int store_p; + int regno; + enum machine_mode mode; + int offset; + { + rtx reg = gen_rtx (REG, mode, regno); + rtx mem = gen_rtx (MEM, mode, plus_constant (stack_pointer_rtx, offset)); + + if (store_p) + emit_move_insn (mem, reg); + else + emit_move_insn (reg, mem); + } + /* Convert the address expression REG to a CFA offset. */ *************** *** 2349,2353 **** text_section (); } ! /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. NAME is the mcount function name --- 2258,2262 ---- text_section (); } ! /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. NAME is the mcount function name *************** *** 2366,2369 **** --- 2275,2280 ---- char *temp = (savep ? reg_names[2] : reg_names[10]); + /* Remember to update FUNCTION_PROFILER_LENGTH. */ + if (savep) { *************** *** 2425,2428 **** --- 2336,2341 ---- char label[256]; + /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */ + ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 0); ASM_GENERATE_INTERNAL_LABEL (label, "LPY", labelno); *************** *** 2464,2467 **** --- 2377,2382 ---- char block[256]; + /* Remember to update BLOCK_PROFILER_LENGTH. */ + ASM_GENERATE_INTERNAL_LABEL (block, "LPBX", 2); *************** *** 2726,2729 **** --- 2641,2683 ---- case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */ fputs (m88k_pound_sign, file); return; + + case 'V': /* Output a serializing instruction as needed if the operand + (assumed to be a MEM) is a volatile load. */ + case 'v': /* ditto for a volatile store. */ + if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE) + { + /* The m88110 implements two FIFO queues, one for loads and + one for stores. These queues mean that loads complete in + their issue order as do stores. An interaction between the + history buffer and the store reservation station ensures + that a store will not bypass load. Finally, a load will not + bypass store, but only when they reference the same address. + + To avoid this reordering (a load bypassing a store) for + volatile references, a serializing instruction is output. + We choose the fldcr instruction as it does not serialize on + the m88100 so that -m88000 code will not be degraded. + + The mechanism below is completed by having CC_STATUS_INIT set + the code to the unknown value. */ + + static rtx last_addr = 0; + if (code == 'V' /* Only need to serialize before a load. */ + && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */ + && !(m88k_volatile_code == 'v' + && GET_CODE (XEXP (x, 0)) == LO_SUM + && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr))) + fprintf (file, + #ifdef AS_BUG_FLDCR + "fldcr\t %s,%scr63\n\t", + #else + "fldcr\t %s,%sfcr63\n\t", + #endif + reg_names[0], m88k_pound_sign); + m88k_volatile_code = code; + last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM + ? XEXP (XEXP (x, 0), 1) : 0); + } + return; case 'X': /* print the upper 16 bits... */ diff -rc2N gcc-2.2.2/config/m88k.h gcc-2.3.1/config/m88k.h *** gcc-2.2.2/config/m88k.h Sat Jun 13 17:16:45 1992 --- gcc-2.3.1/config/m88k.h Wed Oct 28 15:23:32 1992 *************** *** 84,87 **** --- 84,89 ---- extern char *m88k_pound_sign; extern char *m88k_short_data; + extern char *m88k_version; + extern char m88k_volatile_code; extern int m88k_gp_threshold; *************** *** 91,94 **** --- 93,97 ---- extern int m88k_stack_size; extern int m88k_case_index; + extern int m88k_version_0300; extern struct rtx_def *m88k_compare_reg; *************** *** 98,111 **** extern enum attr_cpu m88k_cpu; ! extern int null_epilogue (); extern int integer_ok_for_set (); extern int m88k_debugger_offset (); - extern void m88k_handle_pragma_token (); extern void emit_bcnd (); extern void expand_block_move (); extern void m88k_layout_frame (); ! extern void m88k_output_prologue (); ! extern void m88k_output_epilogue (); extern void output_function_profiler (); extern void output_function_block_profiler (); --- 101,117 ---- extern enum attr_cpu m88k_cpu; ! extern int null_prologue (); extern int integer_ok_for_set (); extern int m88k_debugger_offset (); extern void emit_bcnd (); extern void expand_block_move (); extern void m88k_layout_frame (); ! extern void m88k_expand_prologue (); ! extern void m88k_begin_prologue (); ! extern void m88k_end_prologue (); ! extern void m88k_expand_epilogue (); ! extern void m88k_begin_epilogue (); ! extern void m88k_end_epilogue (); extern void output_function_profiler (); extern void output_function_block_profiler (); *************** *** 186,189 **** --- 192,201 ---- } while (0) + /* If -m88100 is in effect, add -D__m88100__; similarly for -m88110. + Here, the CPU_DEFAULT is assumed to be -m88100. */ + #undef CPP_SPEC + #define CPP_SPEC "%{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \ + %{!m88000:%{!m88110:-D__m88100__}}" + /* LIB_SPEC, LINK_SPEC, and STARTFILE_SPEC defined in svr3.h. ASM_SPEC, ASM_FINAL_SPEC, LIB_SPEC, LINK_SPEC, and STARTFILE_SPEC redefined *************** *** 204,210 **** Redefined in m88kv4.h, and m88kluna.h. */ #define VERSION_INFO1 "88open OCS/BCS, " ! #define VERSION_INFO2 "29 May 1992" #define VERSION_STRING version_string ! #define TM_SCCS_ID "@(#)m88k.h 2.1.11.11 29 May 1992 13:20:31" /* Run-time compilation parameters selecting different hardware subsets. */ --- 216,222 ---- Redefined in m88kv4.h, and m88kluna.h. */ #define VERSION_INFO1 "88open OCS/BCS, " ! #define VERSION_INFO2 "10/21/92" #define VERSION_STRING version_string ! #define TM_SCCS_ID "@(#)m88k.h 2.2.14.1 10/21/92 23:03:03" /* Run-time compilation parameters selecting different hardware subsets. */ *************** *** 221,225 **** #define MASK_OCS_FRAME_POSITION 0x00000008 /* Debug frame = CFA, not r30 */ #define MASK_SVR4 0x00000010 /* Target is AT&T System V.4 */ - #define MASK_VERSION_0300 0x00000020 /* Use version 03.00 syntax */ #define MASK_NO_UNDERSCORES 0x00000040 /* Don't emit a leading `_' */ #define MASK_BIG_PIC 0x00000080 /* PIC with large got-rel's -fPIC */ --- 233,236 ---- *************** *** 231,238 **** --- 242,252 ---- #define MASK_WARN_PASS_STRUCT 0x00002000 /* Warn about passed structs */ #define MASK_OPTIMIZE_ARG_AREA 0x00004000 /* Save stack space */ + #define MASK_SERIALIZE_VOLATILE 0x00008000 /* Serialize volatile refs */ + #define MASK_NO_SERIALIZE_VOLATILE 0x00010000 /* Don't serialize */ #define MASK_88000 (MASK_88100 | MASK_88110) #define MASK_EITHER_LARGE_SHIFT (MASK_TRAP_LARGE_SHIFT | \ MASK_HANDLE_LARGE_SHIFT) + #define MASK_SERIALIZE (MASK_SERIALIZE_VOLATILE | MASK_NO_SERIALIZE_VOLATILE) #define TARGET_88100 ((target_flags & MASK_88000) == MASK_88100) *************** *** 243,247 **** #define TARGET_OCS_FRAME_POSITION (target_flags & MASK_OCS_FRAME_POSITION) #define TARGET_SVR4 (target_flags & MASK_SVR4) - #define TARGET_VERSION_0300 (target_flags & MASK_VERSION_0300) #define TARGET_NO_UNDERSCORES (target_flags & MASK_NO_UNDERSCORES) #define TARGET_BIG_PIC (target_flags & MASK_BIG_PIC) --- 257,260 ---- *************** *** 253,256 **** --- 266,270 ---- #define TARGET_WARN_PASS_STRUCT (target_flags & MASK_WARN_PASS_STRUCT) #define TARGET_OPTIMIZE_ARG_AREA (target_flags & MASK_OPTIMIZE_ARG_AREA) + #define TARGET_SERIALIZE_VOLATILE (target_flags & MASK_SERIALIZE_VOLATILE) #define TARGET_EITHER_LARGE_SHIFT (target_flags & MASK_EITHER_LARGE_SHIFT) *************** *** 271,275 **** { "svr4", MASK_SVR4 }, \ { "svr3", -MASK_SVR4 }, \ - { "version-03.00", MASK_VERSION_0300 }, \ { "no-underscores", MASK_NO_UNDERSCORES }, \ { "big-pic", MASK_BIG_PIC }, \ --- 285,288 ---- *************** *** 283,286 **** --- 296,301 ---- { "optimize-arg-area", MASK_OPTIMIZE_ARG_AREA }, \ { "no-optimize-arg-area", -MASK_OPTIMIZE_ARG_AREA }, \ + { "serialize-volatile", MASK_SERIALIZE_VOLATILE }, \ + { "no-serialize-volatile", MASK_NO_SERIALIZE_VOLATILE }, \ SUBTARGET_SWITCHES \ /* Default switches */ \ *************** *** 293,297 **** /* Macro to define table for command options with values. */ ! #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } /* Do any checking or such that is needed after processing the -m switches. */ --- 308,313 ---- /* Macro to define table for command options with values. */ ! #define TARGET_OPTIONS { { "short-data-", &m88k_short_data }, \ ! { "version-", &m88k_version } } /* Do any checking or such that is needed after processing the -m switches. */ *************** *** 307,310 **** --- 323,332 ---- : (TARGET_88100 ? CPU_M88100 : CPU_M88110)); \ \ + if (! TARGET_88100 && (target_flags & MASK_SERIALIZE) == 0) \ + target_flags |= MASK_SERIALIZE_VOLATILE; \ + \ + if ((target_flags & MASK_NO_SERIALIZE_VOLATILE) != 0) \ + target_flags &= ~MASK_SERIALIZE_VOLATILE; \ + \ if (TARGET_BIG_PIC) \ flag_pic = 2; \ *************** *** 313,316 **** --- 335,341 ---- error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");\ \ + m88k_version_0300 = (m88k_version != 0 \ + && strcmp (m88k_version, "03.00") >= 0); \ + \ if (VERSION_0300_SYNTAX) \ { \ *************** *** 318,323 **** --- 343,356 ---- reg_names[i]--; \ m88k_pound_sign = "#"; \ + if (m88k_version == 0) \ + m88k_version = "03.00"; \ + else if (strcmp (m88k_version, "03.00") < 0) \ + error ("Specified assembler version (%s) is less that 03.00", \ + m88k_version); \ } \ \ + m88k_version_0300 = (m88k_version != 0 \ + && strcmp (m88k_version, "03.00") >= 0); \ + \ if (m88k_short_data) \ { \ *************** *** 389,409 **** #define STACK_BOUNDARY 128 ! /* Allocation boundary (in *bits*) for the code of a function. ! Pack code tightly when compiling crtstuff.c. */ ! #define FUNCTION_BOUNDARY (flag_inhibit_size_directive ? 32 : 128) /* No data type wants to be aligned rounder than this. */ #define BIGGEST_ALIGNMENT 64 ! /* Make strings word-aligned so strcpy from constants will be faster. */ #define CONSTANT_ALIGNMENT(EXP, ALIGN) \ ! (TREE_CODE (EXP) == STRING_CST \ ! && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (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) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) /* Alignment of field after `int : 0' in a structure. --- 422,449 ---- #define STACK_BOUNDARY 128 ! /* Allocation boundary (in *bits*) for the code of a function. On the ! m88100, it is desirable to align to a cache line. However, SVR3 targets ! only provided 8 byte alignment. The m88110 cache is small, so align ! to an 8 byte boundary. Pack code tightly when compiling crtstuff.c. */ ! #define FUNCTION_BOUNDARY (flag_inhibit_size_directive ? 32 : \ ! (TARGET_88100 && TARGET_SVR4 ? 128 : 64)) /* No data type wants to be aligned rounder than this. */ #define BIGGEST_ALIGNMENT 64 ! /* The best alignment to use in cases where we have a choice. */ ! #define FASTEST_ALIGNMENT (TARGET_88100 ? 32 : 64) ! ! /* Make strings 4/8 byte 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 4/8 byte 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)) /* Alignment of field after `int : 0' in a structure. *************** *** 453,457 **** -waste if only used once ! floating point caluclations -probably a waste unless we have run out of general purpose registers --- 493,497 ---- -waste if only used once ! floating point calculations -probably a waste unless we have run out of general purpose registers *************** *** 504,509 **** yet implemented. ! The explaination of why the preserved register is not used is as follows, ! I believe. The registers are being allocated in order. Tieing is not done so efficiently, so when it comes time to do the first allocation, there are no registers left to use without spilling except extended --- 544,549 ---- yet implemented. ! The explanation of why the preserved register is not used is as follows, ! I believe. The registers are being allocated in order. Tying is not done so efficiently, so when it comes time to do the first allocation, there are no registers left to use without spilling except extended *************** *** 557,561 **** Extended Register File (XRF): Reg 32 = x0 Always equal to zero ! Reg 33-53 = x1-x21 Tempory registers (Caller Save) Reg 54-61 = x22-x29 Preserver registers (Callee Save) Reg 62-63 = x30-x31 Reserved for future ABI use. --- 597,601 ---- Extended Register File (XRF): Reg 32 = x0 Always equal to zero ! Reg 33-53 = x1-x21 Temporary registers (Caller Save) Reg 54-61 = x22-x29 Preserver registers (Callee Save) Reg 62-63 = x30-x31 Reserved for future ABI use. *************** *** 801,804 **** --- 841,854 ---- (CONSTANT_P(X) && (CLASS == XRF_REGS) ? NO_REGS : (CLASS)) + /* Return the register class of a scratch register needed to load IN + into a register of class CLASS in MODE. On the m88k, when PIC, we + need a temporary when loading some addresses into a register. */ + #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ + ((flag_pic \ + && GET_CODE (IN) == CONST \ + && GET_CODE (XEXP (IN, 0)) == PLUS \ + && GET_CODE (XEXP (XEXP (IN, 0), 0)) == CONST_INT \ + && ! SMALL_INT (XEXP (XEXP (IN, 0), 1))) ? GENERAL_REGS : NO_REGS) + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ *************** *** 1040,1044 **** /* Generate the assembly code for function entry. */ ! #define FUNCTION_PROLOGUE(FILE, SIZE) m88k_output_prologue(FILE, SIZE) /* Output assembler code to FILE to increment profiler label # LABELNO --- 1090,1097 ---- /* Generate the assembly code for function entry. */ ! #define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE) ! ! /* Perform special actions at the point where the prologue ends. */ ! #define FUNCTION_END_PROLOGUE(FILE) m88k_end_prologue(FILE) /* Output assembler code to FILE to increment profiler label # LABELNO *************** *** 1048,1051 **** --- 1101,1107 ---- output_function_profiler (FILE, LABELNO, "mcount", 1) + /* Maximum length in instructions of the code output by FUNCTION_PROFILER. */ + #define FUNCTION_PROFILER_LENGTH (5+3+1+5) + /* Output assembler code to FILE to initialize basic-block profiling for the current module. LABELNO is unique to each instance. */ *************** *** 1053,1060 **** --- 1109,1123 ---- output_function_block_profiler (FILE, LABELNO) + /* Maximum length in instructions of the code output by + FUNCTION_BLOCK_PROFILER. */ + #define FUNCTION_BLOCK_PROFILER_LENGTH (3+5+2+5) + /* Output assembler code to FILE to increment the count associated with the basic block number BLOCKNO. */ #define BLOCK_PROFILER(FILE, BLOCKNO) output_block_profiler (FILE, BLOCKNO) + /* Maximum length in instructions of the code output by BLOCK_PROFILER. */ + #define BLOCK_PROFILER_LENGTH 4 + /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in *************** *** 1064,1077 **** /* Generate the assembly code for function exit. */ ! #define FUNCTION_EPILOGUE(FILE, SIZE) m88k_output_epilogue(FILE, SIZE) ! /* Define the number of delay slots needed for the function epilogue. ! These are used for scheduling the function epilogue and depend on ! what the epilogue looks like. */ ! #define DELAY_SLOTS_FOR_EPILOGUE delay_slots_for_epilogue () ! ! /* Define whether INSN can be placed in delay slot N for the epilogue. */ ! #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \ ! eligible_for_epilogue_delay (INSN) /* Value should be nonzero if functions must have frame pointers. --- 1127,1134 ---- /* Generate the assembly code for function exit. */ ! #define FUNCTION_EPILOGUE(FILE, SIZE) m88k_end_epilogue(FILE, SIZE) ! /* Perform special actions at the point where the epilogue begins. */ ! #define FUNCTION_BEGIN_EPILOGUE(FILE) m88k_begin_epilogue(FILE) /* Value should be nonzero if functions must have frame pointers. *************** *** 1336,1340 **** if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \ || GET_CODE (X) == LABEL_REF) \ ! (X) = legitimize_address (flag_pic, X, gen_reg_rtx (Pmode)); \ if (memory_address_p (MODE, X)) \ goto WIN; } --- 1393,1397 ---- if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \ || GET_CODE (X) == LABEL_REF) \ ! (X) = legitimize_address (flag_pic, X, 0, 0); \ if (memory_address_p (MODE, X)) \ goto WIN; } *************** *** 1405,1408 **** --- 1462,1474 ---- /* #define CASE_DROPS_THROUGH */ + /* Define this to be the smallest number of different values for which it + is best to use a jump-table instead of a tree of conditional branches. + The default is 4 for machines with a casesi instruction and 5 otherwise. + The best 88110 number is around 7, though the exact number isn't yet + known. A third alternative for the 88110 is to use a binary tree of + bb1 instructions on bits 2/1/0 if the range is dense. This may not + win very much though. */ + #define CASE_VALUES_THRESHOLD (TARGET_88100 ? 4 : 7) + /* Specify the tree operation to be used to convert reals to integers. */ #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR *************** *** 1420,1451 **** #define SCCS_DIRECTIVE ! /* Code to handle #pragma directives. The interface is a bit messy, ! but there's no simpler way to do this while still using yylex. */ ! #define HANDLE_PRAGMA(FILE) \ ! do { \ ! while (c == ' ' || c == '\t') \ ! c = getc (FILE); \ ! if (c == '\n' || c == EOF) \ ! { \ ! m88k_handle_pragma_token (0, 0); \ ! return c; \ ! } \ ! ungetc (c, FILE); \ ! switch (yylex ()) \ ! { \ ! case IDENTIFIER: \ ! case TYPENAME: \ ! case STRING: \ ! case CONSTANT: \ ! m88k_handle_pragma_token (token_buffer, yylval.ttype); \ ! break; \ ! default: \ ! m88k_handle_pragma_token (token_buffer, 0); \ ! } \ ! if (nextchar >= 0) \ ! c = nextchar, nextchar = -1; \ ! else \ ! c = getc (FILE); \ ! } while (1) /* Tell when to handle #pragma weak. This is only done for V.4. */ --- 1486,1491 ---- #define SCCS_DIRECTIVE ! /* Handle #pragma pack and sometimes #pragma weak. */ ! #define HANDLE_SYSV_PRAGMA /* Tell when to handle #pragma weak. This is only done for V.4. */ *************** *** 1454,1458 **** /* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */ ! #define MOVE_MAX 64 /* Define if normal loads of shorter-than-word items from memory clears --- 1494,1498 ---- /* Max number of bytes we can move from memory to memory in one reasonably fast instruction. */ ! #define MOVE_MAX 8 /* Define if normal loads of shorter-than-word items from memory clears *************** *** 1497,1504 **** #define FUNCTION_MODE SImode ! /* A barrier will be aligned so account for the possible expansion. */ ! #define ADJUST_INSN_LENGTH(INSN, LENGTH) \ ! if (GET_CODE (INSN) == BARRIER) \ ! LENGTH += 1; /* Compute the cost of computing a constant rtl expression RTX --- 1537,1572 ---- #define FUNCTION_MODE SImode ! /* A barrier will be aligned so account for the possible expansion. ! A volatile load may be preceeded by a serializing instruction. ! Account for profiling code output at NOTE_INSN_PROLOGUE_END. ! Account for block profiling code at basic block boundaries. */ ! #define ADJUST_INSN_LENGTH(RTX, LENGTH) \ ! if (GET_CODE (RTX) == BARRIER \ ! || (TARGET_SERIALIZE_VOLATILE \ ! && GET_CODE (RTX) == INSN \ ! && GET_CODE (PATTERN (RTX)) == SET \ ! && ((GET_CODE (SET_SRC (PATTERN (RTX))) == MEM \ ! && MEM_VOLATILE_P (SET_SRC (PATTERN (RTX))))))) \ ! LENGTH += 1; \ ! else if (GET_CODE (RTX) == NOTE \ ! && NOTE_LINE_NUMBER (RTX) == NOTE_INSN_PROLOGUE_END) \ ! { \ ! if (profile_block_flag) \ ! LENGTH += FUNCTION_BLOCK_PROFILER_LENGTH; \ ! if (profile_flag) \ ! LENGTH += (FUNCTION_PROFILER_LENGTH + REG_PUSH_LENGTH \ ! + REG_POP_LENGTH); \ ! } \ ! else if (profile_block_flag \ ! && (GET_CODE (RTX) == CODE_LABEL \ ! || GET_CODE (RTX) == JUMP_INSN \ ! || (GET_CODE (RTX) == INSN \ ! && GET_CODE (PATTERN (RTX)) == SEQUENCE \ ! && GET_CODE (XVECEXP (PATTERN (RTX), 0, 0)) == JUMP_INSN)))\ ! LENGTH += BLOCK_PROFILER_LENGTH; ! ! /* Track the state of the last volatile memory reference. Clear the ! state with CC_STATUS_INIT for now. */ ! #define CC_STATUS_INIT m88k_volatile_code = '\0' /* Compute the cost of computing a constant rtl expression RTX *************** *** 1567,1570 **** --- 1635,1655 ---- #define BRANCH_COST (TARGET_88100 ? 1 : 2) + /* A C statement (sans semicolon) to update the integer variable COST + based on the relationship between INSN that is dependent on + DEP_INSN through the dependence LINK. The default is to make no + adjustment to COST. On the m88k, ignore the cost of anti- and + output-dependencies. On the m88100, a store can issue two cycles + before the value (not the address) has finished computing. */ + #define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ + do { \ + if (REG_NOTE_KIND (LINK) != 0) \ + (COST) = 0; /* Anti or output dependence. */ \ + else if (! TARGET_88100 \ + && recog_memoized (INSN) >= 0 \ + && get_attr_type (INSN) == TYPE_STORE \ + && SET_SRC (PATTERN (INSN)) == SET_DEST (PATTERN (DEP_INSN))) \ + (COST) -= 4; /* 88110 store reservation station. */ \ + } while (0) + /* Define this to be nonzero if the character `$' should be allowed by default in identifier names. */ *************** *** 1595,1598 **** --- 1680,1685 ---- #undef SKIP_ASM_OP #undef COMMON_ASM_OP + #undef ALIGN_ASM_OP + #undef IDENT_ASM_OP /* These are used in varasm.c as well. */ *************** *** 1695,1700 **** #define ASM_FIRST_LINE(FILE) \ do { \ ! if (VERSION_0300_SYNTAX) \ ! fprintf (FILE, "\t%s\t \"03.00\"\n", VERSION_ASM_OP); \ } while (0) --- 1782,1787 ---- #define ASM_FIRST_LINE(FILE) \ do { \ ! if (m88k_version) \ ! fprintf (FILE, "\t%s\t \"%s\"\n", VERSION_ASM_OP, m88k_version); \ } while (0) *************** *** 1766,1769 **** --- 1853,1864 ---- "#x24"+1,"#x25"+1,"#x26"+1,"#x27"+1,"#x28"+1,"#x29"+1,"#x30"+1,"#x31"+1} + /* Define additional names for use in asm clobbers and asm declarations. + + We define the fake Condition Code register as an alias for reg 0 (which + is our `condition code' register), so that condition codes can easily + be clobbered by an asm. The carry bit in the PSR is now used. */ + + #define ADDITIONAL_REGISTER_NAMES {"psr", 0, "cc", 0} + /* How to renumber registers for dbx and gdb. */ #define DBX_REGISTER_NUMBER(REGNO) (REGNO) *************** *** 1961,1964 **** --- 2056,2072 ---- output_ascii (FILE, ASCII_DATA_ASM_OP, 48, P, SIZE) + /* Override svr4.h. Change to the readonly data section for a table of + addresses. final_scan_insn changes back to the text section. */ + #undef ASM_OUTPUT_CASE_LABEL + #define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \ + do { \ + if (! CASE_VECTOR_INSNS) \ + { \ + readonly_data_section (); \ + ASM_OUTPUT_ALIGN (FILE, 2); \ + } \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ + } while (0) + /* Epilogue for case labels. This jump instruction is called by casesi to transfer to the appropriate branch instruction within the table. *************** *** 1998,2005 **** fprintf (FILE, "\t%s\t %d\n", ALIGN_ASM_OP, 1<<(LOG)) ! /* Align the text address to half a cache boundary when it can only be ! reached by jumping. Pack code tightly when compiling crtstuff.c. */ #define ASM_OUTPUT_ALIGN_CODE(FILE) \ ! ASM_OUTPUT_ALIGN (FILE, (flag_inhibit_size_directive ? 2 : 3)) /* Override svr[34].h. */ --- 2106,2115 ---- fprintf (FILE, "\t%s\t %d\n", ALIGN_ASM_OP, 1<<(LOG)) ! /* On the m88100, align the text address to half a cache boundary when it ! can only be reached by jumping. Pack code tightly when compiling ! crtstuff.c. */ #define ASM_OUTPUT_ALIGN_CODE(FILE) \ ! ASM_OUTPUT_ALIGN (FILE, \ ! (TARGET_88100 && !flag_inhibit_size_directive ? 3 : 2)) /* Override svr[34].h. */ *************** *** 2049,2052 **** --- 2159,2165 ---- reg_names[STACK_POINTER_REGNUM]) + /* Length in instructions of the code output by ASM_OUTPUT_REG_PUSH. */ + #define REG_PUSH_LENGTH 2 + /* This is how to output an insn to pop a register from the stack. */ #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ *************** *** 2058,2061 **** --- 2171,2177 ---- (STACK_BOUNDARY / BITS_PER_UNIT)) + /* Length in instructions of the code output by ASM_OUTPUT_REG_POP. */ + #define REG_POP_LENGTH 2 + /* Define the parentheses used to group arithmetic operations in assembler code. */ *************** *** 2285,2289 **** #define USE_CONST_SECTION DECLARE_ASM_NAME ! #if defined(CTORS_SECTION_FUNCTION) /* SVR4 */ #define EXTRA_SECTIONS in_const, in_tdesc, in_sdata, in_ctors, in_dtors --- 2401,2405 ---- #define USE_CONST_SECTION DECLARE_ASM_NAME ! #if defined(USING_SVR4_H) #define EXTRA_SECTIONS in_const, in_tdesc, in_sdata, in_ctors, in_dtors *************** *** 2291,2299 **** #define FINI_SECTION_FUNCTION ! #elif defined(FINI_SECTION_FUNCTION) /* SVR3 */ ! #define EXTRA_SECTIONS in_const, in_tdesc, in_sdata, in_init, in_fini ! #define CTORS_SECTION_FUNCTION ! #define DTORS_SECTION_FUNCTION #else /* m88kluna or other not based on svr[34].h. */ --- 2407,2415 ---- #define FINI_SECTION_FUNCTION ! #else ! #if defined(USING_SVR3_H) ! #define EXTRA_SECTIONS in_const, in_tdesc, in_sdata, in_ctors, in_dtors, \ ! in_init, in_fini #else /* m88kluna or other not based on svr[34].h. */ *************** *** 2312,2316 **** #define FINI_SECTION_FUNCTION ! #endif /* CTORS_SECTION_FUNCTION */ #undef EXTRA_SECTION_FUNCTIONS --- 2428,2433 ---- #define FINI_SECTION_FUNCTION ! #endif /* USING_SVR3_H */ ! #endif /* USING_SVR4_H */ #undef EXTRA_SECTION_FUNCTIONS *************** *** 2343,2348 **** FINI_SECTION_FUNCTION - #undef READONLY_DATA_SECTION - /* A C statement or statements to switch to the appropriate section for output of DECL. DECL is either a `VAR_DECL' node --- 2460,2463 ---- *************** *** 2377,2380 **** --- 2492,2500 ---- const_section (); \ } + + /* Jump tables consist of branch instructions and should be output in + the text section. When we use a table of addresses, we explicitly + change to the readonly data section. */ + #define JUMP_TABLES_IN_TEXT_SECTION 1 /* Define this macro if references to a symbol must be treated differently diff -rc2N gcc-2.2.2/config/m88k.md gcc-2.3.1/config/m88k.md *** gcc-2.2.2/config/m88k.md Sat Jun 13 17:17:55 1992 --- gcc-2.3.1/config/m88k.md Mon Oct 19 16:59:16 1992 *************** *** 29,33 **** [(match_operand:SI 0 "" "")] "" ! "{ static char sccs_id[] = \"@(#)m88k.md 2.1.11.6 29 May 1992 10:55:49\"; FAIL; }") --- 29,33 ---- [(match_operand:SI 0 "" "")] "" ! "{ static char sccs_id[] = \"@(#)m88k.md 2.2.13.5 10/19/92 10:13:13\"; FAIL; }") *************** *** 35,39 **** ; Target CPU. ! (define_attr "cpu" "m88000,m88100,m88110" (const (symbol_ref "m88k_cpu"))) --- 35,39 ---- ; Target CPU. ! (define_attr "cpu" "m88100,m88110,m88000" (const (symbol_ref "m88k_cpu"))) *************** *** 42,68 **** ; ; "branch,jump,call, ; flow-control instructions ! ; load,store,loada, ; data unit instructions ; spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv, ; FPU add instructions ; spmul,dpmul,imul, ; FPU multiply instructions ; arith,bit,mov ; integer unit instructions ! ; marith,mbit,mfp,weird" ; multi-word instructions ; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. (define_attr "type" ! "branch,jump,call,load,store,loada,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,bit,mov,marith,mbit,mfp,weird" (const_string "arith")) - ; Convenience attributes. - (define_attr "unit" "bit,memory,multiply,divide,fpadd,other" - (cond [(eq_attr "type" "bit,mbit") (const_string "bit") - (eq_attr "type" "load,store") (const_string "memory") - (eq_attr "type" "spmul,dpmul,imul") (const_string "multiply") - (eq_attr "type" "spdiv,dpdiv,idiv") (const_string "divide") - (eq_attr "type" "spadd,dpadd,spcmp,dpcmp,mfp") (const_string "fpadd")] - (const_string "other"))) - (define_attr "fpu" "yes,no" (if_then_else ! (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv,mfp") (const_string "yes") (const_string "no"))) --- 42,59 ---- ; ; "branch,jump,call, ; flow-control instructions ! ; load,store,loadd,loada, ; data unit instructions ; spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv, ; FPU add instructions ; spmul,dpmul,imul, ; FPU multiply instructions ; arith,bit,mov ; integer unit instructions ! ; marith,weird" ; multi-word instructions ; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. (define_attr "type" ! "branch,jump,call,load,store,loadd,loada,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,bit,mov,marith,weird" (const_string "arith")) (define_attr "fpu" "yes,no" (if_then_else ! (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv") (const_string "yes") (const_string "no"))) *************** *** 70,74 **** ; are safe. (define_attr "length" "" ! (cond [(eq_attr "type" "marith,mbit,mfp") (const_int 2)] (const_int 1))) --- 61,65 ---- ; are safe. (define_attr "length" "" ! (cond [(eq_attr "type" "marith") (const_int 2)] (const_int 1))) *************** *** 89,94 **** [(and (and ! (eq_attr "type" "!branch,jump,call,marith,mbit,mfp,weird") ; required. ! (eq_attr "type" "!load")) ; issue as-soon-as-possible. (eq_attr "fpu" "no")) ; issue as-soon-as-possible. (eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1) --- 80,85 ---- [(and (and ! (eq_attr "type" "!branch,jump,call,marith,weird") ; required. ! (eq_attr "type" "!load,loadd")) ; issue as-soon-as-possible. (eq_attr "fpu" "no")) ; issue as-soon-as-possible. (eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1) *************** *** 98,102 **** (define_delay (eq_attr "type" "call") ! [(eq_attr "type" "!branch,call,marith,mbit,mfp,weird") ; required. (nil) (nil)]) --- 89,93 ---- (define_delay (eq_attr "type" "call") ! [(eq_attr "type" "!branch,call,marith,weird") ; required. (nil) (nil)]) *************** *** 140,164 **** ; ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY ! ; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST]) ! ! ;(define_function_unit "decode" 1 1 (const_int 1) 0 1) ! ; Describing the alu is currently not useful. ;(define_function_unit "alu" 1 0 (eq_attr "type" ! ; "!store,marith,mbit,mfp,weird") 1 0) ! ;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,mbit,weird") 2 0) (define_function_unit "alu" 1 0 ! (and (eq_attr "type" "loada,arith,bit,mov") (eq_attr "cpu" "!m88100")) 2 0) (define_function_unit "alu" 1 0 ! (and (eq_attr "type" "marith,mbit,weird") (eq_attr "cpu" "!m88100")) 4 0) ! (define_function_unit "memory" 1 3 ! (and (eq_attr "type" "load") (eq_attr "cpu" "m88100")) 3 2) ! (define_function_unit "memory" 1 3 ! (and (eq_attr "type" "load") (eq_attr "cpu" "!m88100")) 4 2) ! ; The fp1 and fplast descriptions currently have no effect. ! ;(define_function_unit "fp1" 1 1 (eq_attr "fpu" "yes") 1 2) ; The times are adjusted to include fp1 and fplast, but then are further --- 131,160 ---- ; ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY ! ; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) ! ; Describing the '100 alu is currently not useful. ;(define_function_unit "alu" 1 0 (eq_attr "type" ! ; "!store,marith,weird") 1 0) ! ;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0) (define_function_unit "alu" 1 0 ! (and (eq_attr "type" "loada,arith,mov") (eq_attr "cpu" "!m88100")) 2 0) (define_function_unit "alu" 1 0 ! (and (eq_attr "type" "marith,weird") (eq_attr "cpu" "!m88100")) 4 0) ! (define_function_unit "bit" 1 0 ! (and (eq_attr "type" "bit") (eq_attr "cpu" "!m88100")) 2 2) ! (define_function_unit "mem100" 1 0 ! (and (eq_attr "type" "store,loada") (eq_attr "cpu" "m88100")) 1 0) ! (define_function_unit "mem100" 1 0 ! (and (eq_attr "type" "load") (eq_attr "cpu" "m88100")) 3 0) ! (define_function_unit "mem100" 1 0 ! (and (eq_attr "type" "loadd") (eq_attr "cpu" "m88100")) 3 2) ! ! (define_function_unit "mem110" 1 0 ! (and (eq_attr "type" "load,loadd") (eq_attr "cpu" "!m88100")) 3 2) ! (define_function_unit "mem110" 1 0 ! (and (eq_attr "type" "store") (eq_attr "cpu" "!m88100")) 1 2) ; The times are adjusted to include fp1 and fplast, but then are further *************** *** 166,213 **** ; is the total latency. A range denotes a group of instructions and/or ; conditions (the extra clock of fplast time with some sequences). ! (define_function_unit "fpmul" 1 4 ! (and (eq_attr "type" "spmul") (eq_attr "cpu" "m88100")) 4 2) ; 6-8 ! (define_function_unit "fpmul" 1 4 ! (and (eq_attr "type" "dpmul,mfp") (eq_attr "cpu" "m88100")) 7 2) ; 9-10 ! (define_function_unit "fpmul" 1 4 ! (and (eq_attr "type" "imul") (eq_attr "cpu" "m88100")) 3 2) ; 4 ! ! (define_function_unit "fpmul" 1 4 ! (and (eq_attr "type" "imul,spmul,dpmul,mfp") ! (eq_attr "cpu" "!m88100")) 6 2) ; 3 ! ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "spadd,spcmp") (eq_attr "cpu" "m88100")) 3 2) ; 5-6 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "dpadd,dpcmp") (eq_attr "cpu" "m88100")) 4 2) ; 6-7 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "spdiv") (eq_attr "cpu" "m88100")) 30 2) ; 30-31 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "m88100")) 60 2) ; 60-61 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "idiv") (eq_attr "cpu" "m88100")) 38 2) ; 38 ! ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "spadd,dpadd") (eq_attr "cpu" "!m88100")) 6 2) ; 3 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "spcmp,dpcmp") (eq_attr "cpu" "!m88100")) 2 2) ; 3 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "spdiv") (eq_attr "cpu" "!m88100")) 26 2) ; 13 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "!m88100")) 46 2) ; 23 ! (define_function_unit "fpadd" 1 3 ! (and (eq_attr "type" "idiv") (eq_attr "cpu" "!m88100")) 36 2) ; 18 ! ! ;(define_function_unit "fplast" 1 1 (eq_attr "fpu" "yes") 1 2) ! ! ; Describing writeback contention is currently not useful. ! ;(define_function_unit "writeback" 1 1 ! ; (eq_attr "type" "!store,branch,jump,call") 0 1) ! ! ; Describing stores is currently not useful. The suggestion here is that the ! ; function unit ordering has already been established (writeback is last) and ! ; that store insns use the units in an unusual order. ! ;(define_function_unit "writeback" 1 1 (eq_attr "type" "store") 0 1) ! ;(define_function_unit "memory" 1 3 (eq_attr "type" "store") 1 2) ;; This rich set of complex patterns are mostly due to Torbjorn Granlund --- 162,323 ---- ; is the total latency. A range denotes a group of instructions and/or ; conditions (the extra clock of fplast time with some sequences). ! ! (define_function_unit "fpmul100" 1 0 ! (and (eq_attr "type" "spmul") (eq_attr "cpu" "m88100")) 4 0) ; 6-8 ! (define_function_unit "fpmul100" 1 0 ! (and (eq_attr "type" "dpmul") (eq_attr "cpu" "m88100")) 7 0) ; 9-10 ! (define_function_unit "fpmul100" 1 0 ! (and (eq_attr "type" "imul") (eq_attr "cpu" "m88100")) 3 0) ; 4 ! ! (define_function_unit "fpmul110" 1 0 ! (and (eq_attr "type" "imul,spmul,dpmul") ! (eq_attr "cpu" "!m88100")) 5 2) ; 3 ! ! (define_function_unit "fpadd100" 1 5 ! (and (eq_attr "type" "spadd,spcmp") (eq_attr "cpu" "m88100")) 3 0) ; 5-6 ! (define_function_unit "fpadd100" 1 5 ! (and (eq_attr "type" "dpadd,dpcmp") (eq_attr "cpu" "m88100")) 4 0) ; 6-7 ! ! (define_function_unit "fpadd110" 1 0 ! (and (eq_attr "type" "spadd,dpadd") (eq_attr "cpu" "!m88100")) 5 2) ; 3 ! (define_function_unit "fpadd110" 1 0 ! (and (eq_attr "type" "spcmp,dpcmp") (eq_attr "cpu" "!m88100")) 2 2) ; 1 ! ! (define_function_unit "fpadd100" 1 5 ! (and (eq_attr "type" "spdiv") (eq_attr "cpu" "m88100")) 30 0) ; 30-31 ! (define_function_unit "fpadd100" 1 5 ! (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "m88100")) 60 0) ; 60-61 ! (define_function_unit "fpadd100" 1 5 ! (and (eq_attr "type" "idiv") (eq_attr "cpu" "m88100")) 38 0) ; 38 ! ! (define_function_unit "div" 1 1 ! (and (eq_attr "type" "spdiv") (eq_attr "cpu" "!m88100")) 25 2) ; 13 ! (define_function_unit "div" 1 1 ! (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "!m88100")) 45 2) ; 23 ! (define_function_unit "div" 1 1 ! (and (eq_attr "type" "idiv") (eq_attr "cpu" "!m88100")) 35 2) ; 18 ! ! ;; Superoptimizer sequences ! ! ;; geu+: { r = ((unsigned_word) v0 >= (unsigned_word) v1) + v2; } ! ;; subu.co r5,r2,r3 ! ;; addu.cio r6,r4,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (minus:SI (match_operand:SI 1 "register_operand" "r") ! (geu:SI (match_operand:SI 2 "register_operand" "r") ! (match_operand:SI 3 "register_operand" "r"))))] ! "" ! [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) ! (set (match_dup 0) ! (plus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 0)))] ! "") ! ! ;; leu+: { r = ((unsigned_word) v0 <= (unsigned_word) v1) + v2; } ! ;; subu.co r5,r3,r2 ! ;; addu.cio r6,r4,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (minus:SI (match_operand:SI 1 "register_operand" "r") ! (leu:SI (match_operand:SI 3 "register_operand" "r") ! (match_operand:SI 2 "register_operand" "r"))))] ! "" ! [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) ! (set (match_dup 0) ! (plus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 0)))] ! "") ! ! ;; eq0+: { r = (v0 == 0) + v1; } ! ;; subu.co r4,r0,r2 ! ;; addu.cio r5,r3,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (minus:SI (match_operand:SI 1 "register_operand" "r") ! (eq:SI (match_operand:SI 2 "register_operand" "r") ! (const_int 0))))] ! "" ! [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1)) ! (set (match_dup 0) ! (plus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 0)))] ! "") ! ! ;; ltu-: { r = v2 - ((unsigned_word) v0 < (unsigned_word) v1); } ! ;; subu.co r5,r2,r3 ! ;; subu.cio r6,r4,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (plus:SI (ltu:SI (match_operand:SI 2 "register_operand" "r") ! (match_operand:SI 3 "register_operand" "r")) ! (match_operand:SI 1 "register_operand" "r")))] ! "" ! [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) ! (set (match_dup 0) ! (minus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 1)))] ! "") ! ! ;; gtu-: { r = v2 - ((unsigned_word) v0 > (unsigned_word) v1); } ! ;; subu.co r5,r3,r2 ! ;; subu.cio r6,r4,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (plus:SI (gtu:SI (match_operand:SI 3 "register_operand" "r") ! (match_operand:SI 2 "register_operand" "r")) ! (match_operand:SI 1 "register_operand" "r")))] ! "" ! [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1)) ! (set (match_dup 0) ! (minus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 1)))] ! "") ! ! ;; ne0-: { r = v1 - (v0 != 0); } ! ;; subu.co r4,r0,r2 ! ;; subu.cio r5,r3,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (plus:SI (ne:SI (match_operand:SI 2 "register_operand" "r") ! (const_int 0)) ! (match_operand:SI 1 "register_operand" "r")))] ! "" ! [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1)) ! (set (match_dup 0) ! (minus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 1)))] ! "") ! ! ;; ges0-: { r = v1 - ((signed_word) v0 >= 0); } ! ;; addu.co r4,r2,r2 ! ;; subu.cio r5,r3,r0 ! ! (define_split ! [(set (match_operand:SI 0 "register_operand" "=r") ! (minus:SI (match_operand:SI 1 "register_operand" "r") ! (xor:SI (lshiftrt:SI ! (match_operand:SI 2 "register_operand" "r") ! (const_int 31)) ! (const_int 1))))] ! "" ! [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 2)] 0)) ! (set (match_dup 0) ! (minus:SI (match_dup 1) ! (unspec:SI [(const_int 0) ! (reg:CC 0)] 1)))] ! "") ;; This rich set of complex patterns are mostly due to Torbjorn Granlund *************** *** 220,254 **** ;; special needs to be done here. - ;; (a << int1) >> int2 optimizations into a single extract. - ;; These patterns need to occur before the normal shift patterns - - (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "")) - (match_operand:SI 3 "int5_operand" "")))] - "INTVAL (operands [2]) <= INTVAL (operands [3])" - "* - { - operands[4] = gen_rtx (CONST_INT, SImode, - INTVAL (operands[3]) - INTVAL (operands[2])); - return \"ext %0,%1,%w3<%4>\"; /* <(%3-%2)> */ - }" - [(set_attr "type" "bit")]) - - (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "")) - (match_operand:SI 3 "int5_operand" "")))] - "INTVAL (operands [2]) <= INTVAL (operands [3])" - "* - { - operands[4] = gen_rtx (CONST_INT, SImode, - INTVAL (operands[3]) - INTVAL (operands[2])); - return \"extu %0,%1,%w3<%4>\"; /* <(%3-%2)> */ - }" - [(set_attr "type" "bit")]) - ;; Optimize possible cases of the set instruction. --- 330,333 ---- *************** *** 314,317 **** --- 393,667 ---- [(set_attr "type" "marith")]) ; arith,bit,marith. length is 1 or 2. + ;; Improve logical operations on compare words + ;; + ;; We define all logical operations on CCmode values to preserve the pairwise + ;; relationship of the compare bits. This allows a future branch prediction + ;; pass the degree of freedom needed to change and/bb0-le into or/bb1-gt. + ;; + ;; Opportunities arise when conditional expressions using && and || are made + ;; unconditional. When these are used to branch, the sequence is + ;; cmp/cmp/extu/extu/{and,or}/bcnd-{eq0,ne0}. When these are used to create + ;; a value, the sequence is cmp/cmp/extu/extu/{and,or} for 1 or 0 or + ;; cmp/cmp/ext/ext/{and,or} for -1 or 0. + ;; + ;; When the extracted conditions are the same, the define_split patterns + ;; below change extu/extu/{and,or} into {and,or}/extu. If the reversed + ;; conditions match, one compare word can be complimented, resulting in + ;; {and.c,or.c}/extu. These changes are done for ext/ext/{and,or} as well. + ;; If the conditions don't line up, one can be rotated. To keep the pairwise + ;; relationship, it may be necessary to both rotate and compliment. Rotating + ;; makes branching cheaper, but doesn't help (or hurt) creating a value, so + ;; we don't do this for ext/ext/{and,or}. + ;; + ;; These changes result in the sequence extu/bcnd-{eq0,ne0} which is combined + ;; into an alternate form of bb0 and bb1. + + (define_split + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (neg:SI + (match_operator 1 "relop" + [(match_operand:CC 2 "register_operand" "%r") + (const_int 0)])) + (neg:SI + (match_operator 3 "relop" + [(match_operand:CC 4 "register_operand" "r") + (const_int 0)])))) + (clobber (match_operand:SI 5 "register_operand" "=r"))] + "" + [(set (match_dup 5) + (ior:CC (match_dup 4) + (match_dup 2))) + (set (match_dup 0) + (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))] + "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0); + if (GET_CODE (operands[1]) == GET_CODE (operands[3])) + ; /* The conditions match. */ + else if (GET_CODE (operands[1]) + == reverse_condition (GET_CODE (operands[3]))) + /* Reverse the condition by complimenting the compare word. */ + operands[4] = gen_rtx (NOT, CCmode, operands[4]); + else + { + /* Make the condition pairs line up by rotating the compare word. */ + int cv1 = condition_value (operands[1]); + int cv2 = condition_value (operands[3]); + + operands[4] = gen_rtx (ROTATE, CCmode, operands[4], + gen_rtx (CONST_INT, VOIDmode, + ((cv2 & ~1) - (cv1 & ~1)) & 0x1f)); + /* Reverse the condition if needed. */ + if ((cv1 & 1) != (cv2 & 1)) + operands[4] = gen_rtx (NOT, CCmode, operands[4]); + }") + + (define_split + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_operator 1 "relop" + [(match_operand:CC 2 "register_operand" "%r") + (const_int 0)]) + (match_operator 3 "relop" + [(match_operand:CC 4 "register_operand" "r") + (const_int 0)]))) + (clobber (match_operand:SI 5 "register_operand" "=r"))] + "GET_CODE (operands[1]) == GET_CODE (operands[3]) + || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))" + [(set (match_dup 5) + (ior:CC (match_dup 4) + (match_dup 2))) + (set (match_dup 0) + (match_op_dup 1 [(match_dup 5) (const_int 0)]))] + "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0); + /* Reverse the condition by complimenting the compare word. */ + if (GET_CODE (operands[1]) != GET_CODE (operands[3])) + operands[4] = gen_rtx (NOT, CCmode, operands[4]);") + + (define_split + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (neg:SI + (match_operator 1 "relop" + [(match_operand:CC 2 "register_operand" "%r") + (const_int 0)])) + (neg:SI + (match_operator 3 "relop" + [(match_operand:CC 4 "register_operand" "r") + (const_int 0)])))) + (clobber (match_operand:SI 5 "register_operand" "=r"))] + "" + [(set (match_dup 5) + (and:CC (match_dup 4) + (match_dup 2))) + (set (match_dup 0) + (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))] + "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0); + if (GET_CODE (operands[1]) == GET_CODE (operands[3])) + ; /* The conditions match. */ + else if (GET_CODE (operands[1]) + == reverse_condition (GET_CODE (operands[3]))) + /* Reverse the condition by complimenting the compare word. */ + operands[4] = gen_rtx (NOT, CCmode, operands[4]); + else + { + /* Make the condition pairs line up by rotating the compare word. */ + int cv1 = condition_value (operands[1]); + int cv2 = condition_value (operands[3]); + + operands[4] = gen_rtx (ROTATE, CCmode, operands[4], + gen_rtx (CONST_INT, VOIDmode, + ((cv2 & ~1) - (cv1 & ~1)) & 0x1f)); + /* Reverse the condition if needed. */ + if ((cv1 & 1) != (cv2 & 1)) + operands[4] = gen_rtx (NOT, CCmode, operands[4]); + }") + + (define_split + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (match_operator 1 "relop" + [(match_operand:CC 2 "register_operand" "%r") + (const_int 0)]) + (match_operator 3 "relop" + [(match_operand:CC 4 "register_operand" "r") + (const_int 0)]))) + (clobber (match_operand:SI 5 "register_operand" "=r"))] + "GET_CODE (operands[1]) == GET_CODE (operands[3]) + || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))" + [(set (match_dup 5) + (and:CC (match_dup 4) + (match_dup 2))) + (set (match_dup 0) + (match_op_dup 1 [(match_dup 5) (const_int 0)]))] + "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0); + /* Reverse the condition by complimenting the compare word. */ + if (GET_CODE (operands[1]) != GET_CODE (operands[3])) + operands[4] = gen_rtx (NOT, CCmode, operands[4]);") + + ;; Logical operations on compare words. + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (and:CC (not:CC (match_operand:CC 1 "register_operand" "r")) + (match_operand:CC 2 "register_operand" "r")))] + "" + "and.c %0,%2,%1") + + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (and:CC (match_operand:CC 1 "register_operand" "%r") + (match_operand:CC 2 "register_operand" "r")))] + "" + "and %0,%1,%2") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (ior:CC (not:CC (match_operand:CC 1 "register_operand" "r")) + (match_operand:CC 2 "register_operand" "r")))] + "" + "or.c %0,%2,%1") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (ior:CC (match_operand:CC 1 "register_operand" "%r") + (match_operand:CC 2 "register_operand" "r")))] + "" + "or %0,%1,%2") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" "")))] + "" + "rot %0,%1,%2" + [(set_attr "type" "bit")]) + + ;; rotate/and[.c] and rotate/ior[.c] + + (define_split + [(set (match_operand:CC 0 "register_operand" "=r") + (ior:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" "")) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_operand:CC 4 "register_operand" "=r"))] + "" + [(set (match_dup 4) + (rotate:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (ior:CC (match_dup 4) (match_dup 3)))] + "") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (ior:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" "")) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_scratch:CC 4 "=r"))] + "" + "#") + + (define_split + [(set (match_operand:CC 0 "register_operand" "=r") + (ior:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" ""))) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_operand:CC 4 "register_operand" "=r"))] + "" + [(set (match_dup 4) + (rotate:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (ior:CC (not:CC (match_dup 4)) (match_dup 3)))] + "") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (ior:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" ""))) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_scratch:CC 4 "=r"))] + "" + "#") + + (define_split + [(set (match_operand:CC 0 "register_operand" "=r") + (and:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" "")) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_operand:CC 4 "register_operand" "=r"))] + "" + [(set (match_dup 4) + (rotate:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (and:CC (match_dup 4) (match_dup 3)))] + "") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (and:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" "")) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_scratch:CC 4 "=r"))] + "" + "#") + + (define_split + [(set (match_operand:CC 0 "register_operand" "=r") + (and:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" ""))) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_operand:CC 4 "register_operand" "=r"))] + "" + [(set (match_dup 4) + (rotate:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (and:CC (not:CC (match_dup 4)) (match_dup 3)))] + "") + + (define_insn "" + [(set (match_operand:CC 0 "register_operand" "=r") + (and:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r") + (match_operand:CC 2 "int5_operand" ""))) + (match_operand:CC 3 "register_operand" "r"))) + (clobber (match_scratch:CC 4 "=r"))] + "" + "#") + ;; Recognize bcnd instructions for integer values. This is distinguished ;; from a conditional branch instruction (below) with SImode instead of *************** *** 1009,1012 **** --- 1359,1407 ---- }" [(set_attr "type" "branch")]) + + ;; Branch conditional on scc values. These arise from manipulations on + ;; compare words above. + + (define_insn "" + [(set (pc) + (if_then_else + (ne (match_operator 0 "relop" + [(match_operand:CC 1 "register_operand" "r") + (const_int 0)]) + (const_int 0)) + (match_operand 2 "pc_or_label_ref" "") + (match_operand 3 "pc_or_label_ref" "")))] + "" + "bb1%. %R3%C0,%1,%P2%P3" + [(set_attr "type" "branch")]) + + (define_insn "" + [(set (pc) + (if_then_else + (eq (match_operator 0 "relop" + [(match_operand:CC 1 "register_operand" "r") + (const_int 0)]) + (const_int 0)) + (match_operand 2 "pc_or_label_ref" "") + (match_operand 3 "pc_or_label_ref" "")))] + "" + "bb0%. %R3%C0,%1,%P2%P3" + [(set_attr "type" "branch")]) + + (define_insn "locate1" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (unspec:SI [(label_ref (match_operand 1 "" ""))] 0)))] + "" + "or.u %0,%#r0,%#hi16(%1#abdiff)") + + (define_insn "locate2" + [(parallel [(set (reg:SI 1) (pc)) + (set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_dup 0) + (unspec:SI + [(label_ref (match_operand 1 "" ""))] 0)))])] + "" + "bsr.n %1\;or %0,%0,%#lo16(%1#abdiff)\\n%1:" + [(set_attr "length" "2")]) ;; SImode move instructions *************** *** 1018,1023 **** " { ! if (emit_move_sequence (operands, SImode)) DONE; }") --- 1413,1433 ---- " { ! if (emit_move_sequence (operands, SImode, 0)) ! DONE; ! }") ! ! (define_expand "reload_insi" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (match_operand:SI 1 "general_operand" "")) ! (clobber (match_operand:SI 2 "register_operand" "=&r"))] ! "" ! " ! { ! if (emit_move_sequence (operands, SImode, operands[2])) DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; }") *************** *** 1030,1035 **** "@ or %0,%#r0,%1 ! ld %0,%1 ! st %r1,%0 subu %0,%#r0,%n1 set %0,%#r0,%s1 --- 1440,1445 ---- "@ or %0,%#r0,%1 ! %V1ld %0,%1 ! %v0st %r1,%0 subu %0,%#r0,%n1 set %0,%#r0,%s1 *************** *** 1037,1042 **** mov.s %0,%1 mov %0,%1 ! ld %0,%1 ! st %1,%0" [(set_attr "type" "arith,load,store,arith,bit,mov,mov,mov,load,store")]) --- 1447,1452 ---- mov.s %0,%1 mov %0,%1 ! %V1ld %0,%1 ! %v0st %1,%0" [(set_attr "type" "arith,load,store,arith,bit,mov,mov,mov,load,store")]) *************** *** 1075,1079 **** " { ! if (emit_move_sequence (operands, HImode)) DONE; }") --- 1485,1489 ---- " { ! if (emit_move_sequence (operands, HImode, 0)) DONE; }") *************** *** 1087,1092 **** "@ or %0,%#r0,%h1 ! ld.hu %0,%1 ! st.h %r1,%0 subu %0,%#r0,%H1" [(set_attr "type" "arith,load,store,arith")]) --- 1497,1502 ---- "@ or %0,%#r0,%h1 ! %V1ld.hu %0,%1 ! %v0st.h %r1,%0 subu %0,%#r0,%H1" [(set_attr "type" "arith,load,store,arith")]) *************** *** 1107,1111 **** " { ! if (emit_move_sequence (operands, QImode)) DONE; }") --- 1517,1521 ---- " { ! if (emit_move_sequence (operands, QImode, 0)) DONE; }") *************** *** 1119,1124 **** "@ or %0,%#r0,%q1 ! ld.bu %0,%1 ! st.b %r1,%0 subu %r0,%#r0,%Q1" [(set_attr "type" "arith,load,store,arith")]) --- 1529,1534 ---- "@ or %0,%#r0,%q1 ! %V1ld.bu %0,%1 ! %v0st.b %r1,%0 subu %r0,%#r0,%Q1" [(set_attr "type" "arith,load,store,arith")]) *************** *** 1139,1143 **** " { ! if (emit_move_sequence (operands, DImode)) DONE; }") --- 1549,1553 ---- " { ! if (emit_move_sequence (operands, DImode, 0)) DONE; }") *************** *** 1158,1169 **** "@ or %0,%#r0,%1\;or %d0,%#r0,%d1 ! ld.d %0,%1 ! st.d %1,%0 mov.d %0,%1 mov.d %0,%1 mov %0,%1 ! ld.d %0,%1 ! st.d %1,%0" ! [(set_attr "type" "marith,load,store,mov,mov,mov,load,store")]) (define_insn "" --- 1568,1579 ---- "@ or %0,%#r0,%1\;or %d0,%#r0,%d1 ! %V1ld.d %0,%1 ! %v0st.d %1,%0 mov.d %0,%1 mov.d %0,%1 mov %0,%1 ! %V1ld.d %0,%1 ! %v0st.d %1,%0" ! [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")]) (define_insn "" *************** *** 1190,1194 **** " { ! if (emit_move_sequence (operands, DFmode)) DONE; }") --- 1600,1604 ---- " { ! if (emit_move_sequence (operands, DFmode, 0)) DONE; }") *************** *** 1212,1216 **** ; case 1: ; operands[1] = adj_offsettable_operand (operands[0], 4); ! ; return \"st %#r0,%0\;st %#r0,%1\"; ; } ;}") --- 1622,1626 ---- ; case 1: ; operands[1] = adj_offsettable_operand (operands[0], 4); ! ; return \"%v0st %#r0,%0\;st %#r0,%1\"; ; } ;}") *************** *** 1231,1242 **** "@ or %0,%#r0,%1\;or %d0,%#r0,%d1 ! ld.d %0,%1 ! st.d %1,%0 mov.d %0,%1 mov.d %0,%1 mov %0,%1 ! ld.d %0,%1 ! st.d %1,%0" ! [(set_attr "type" "marith,load,store,mov,mov,mov,load,store")]) (define_insn "" --- 1641,1652 ---- "@ or %0,%#r0,%1\;or %d0,%#r0,%d1 ! %V1ld.d %0,%1 ! %v0st.d %1,%0 mov.d %0,%1 mov.d %0,%1 mov %0,%1 ! %V1ld.d %0,%1 ! %v0st.d %1,%0" ! [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")]) (define_insn "" *************** *** 1263,1267 **** " { ! if (emit_move_sequence (operands, SFmode)) DONE; }") --- 1673,1677 ---- " { ! if (emit_move_sequence (operands, SFmode, 0)) DONE; }") *************** *** 1283,1293 **** "@ or %0,%#r0,%1 ! ld %0,%1 ! st %r1,%0 mov.s %0,%1 mov.s %0,%1 mov %0,%1 ! ld %0,%1 ! st %r1,%0" [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")]) --- 1693,1703 ---- "@ or %0,%#r0,%1 ! %V1ld %0,%1 ! %v0st %r1,%0 mov.s %0,%1 mov.s %0,%1 mov %0,%1 ! %V1ld %0,%1 ! %v0st %r1,%0" [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")]) *************** *** 1309,1314 **** (define_expand "movstrsi" ! [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) ! (mem:BLK (match_operand:BLK 1 "general_operand" ""))) (use (match_operand:SI 2 "arith32_operand" "")) (use (match_operand:SI 3 "immediate_operand" ""))])] --- 1719,1724 ---- (define_expand "movstrsi" ! [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) ! (mem:BLK (match_operand:BLK 1 "" ""))) (use (match_operand:SI 2 "arith32_operand" "")) (use (match_operand:SI 3 "immediate_operand" ""))])] *************** *** 1333,1369 **** (define_expand "call_block_move" ! [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r") ! (match_operand:SI 3 "immediate_operand" "i"))) ! (set (match_operand 5 "register_operand" "r") ! (match_operand 4 "memory_operand" "m")) ! (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r") (match_dup 3))) (use (reg:SI 2)) (use (reg:SI 3)) (use (match_dup 5)) ! (parallel [(call (mem:SI (match_operand 0 "" "")) ! (const_int 0)) (clobber (reg:SI 1))])] "" "") ! ;; Call a looping block move library function (e.g. __movstrSI64n68). ;; operands 0-5 as in the non-looping interface ;; operand 6 is the loop count ! (define_expand "call_block_move_loop" ! [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r") ! (match_operand:SI 3 "immediate_operand" "i"))) ! (set (match_operand:SI 5 "register_operand" "r") ! (match_operand:SI 4 "memory_operand" "m")) ! (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r") (match_dup 3))) ! (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "i")) (use (reg:SI 2)) (use (reg:SI 3)) (use (match_dup 5)) (use (reg:SI 6)) ! (parallel [(call (mem:SI (match_operand 0 "" "")) ! (const_int 0)) (clobber (reg:SI 1))])] "" --- 1743,1781 ---- (define_expand "call_block_move" ! [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "") ! (match_operand:SI 3 "immediate_operand" ""))) ! (set (match_operand 5 "register_operand" "") ! (match_operand 4 "memory_operand" "")) ! (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "") (match_dup 3))) (use (reg:SI 2)) (use (reg:SI 3)) (use (match_dup 5)) ! (parallel [(set (reg:DI 2) ! (call (mem:SI (match_operand 0 "" "")) ! (const_int 0))) (clobber (reg:SI 1))])] "" "") ! ;; Call an SImode looping block move library function (e.g. __movstrSI64n68). ;; operands 0-5 as in the non-looping interface ;; operand 6 is the loop count ! (define_expand "call_movstrsi_loop" ! [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "") ! (match_operand:SI 3 "immediate_operand" ""))) ! (set (match_operand:SI 5 "register_operand" "") ! (match_operand:SI 4 "memory_operand" "")) ! (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "") (match_dup 3))) ! (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "")) (use (reg:SI 2)) (use (reg:SI 3)) (use (match_dup 5)) (use (reg:SI 6)) ! (parallel [(set (reg:DI 2) ! (call (mem:SI (match_operand 0 "" "")) ! (const_int 0))) (clobber (reg:SI 1))])] "" *************** *** 1381,1385 **** && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); }") --- 1793,1797 ---- && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], 0, 0); }") *************** *** 1391,1395 **** mask %0,%1,0xffff or %0,%#r0,%h1 ! ld.hu %0,%1" [(set_attr "type" "arith,arith,load")]) --- 1803,1807 ---- mask %0,%1,0xffff or %0,%#r0,%h1 ! %V1ld.hu %0,%1" [(set_attr "type" "arith,arith,load")]) *************** *** 1403,1407 **** && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); }") --- 1815,1819 ---- && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], 0, 0); }") *************** *** 1413,1417 **** mask %0,%1,0xff or %0,%#r0,%q1 ! ld.bu %0,%1" [(set_attr "type" "arith,arith,load")]) --- 1825,1829 ---- mask %0,%1,0xff or %0,%#r0,%q1 ! %V1ld.bu %0,%1" [(set_attr "type" "arith,arith,load")]) *************** *** 1426,1430 **** { operands[1] ! = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); emit_insn (gen_rtx (SET, VOIDmode, operands[0], gen_rtx (ZERO_EXTEND, SImode, operands[1]))); --- 1838,1842 ---- { operands[1] ! = legitimize_address (flag_pic, operands[1], 0, 0); emit_insn (gen_rtx (SET, VOIDmode, operands[0], gen_rtx (ZERO_EXTEND, SImode, operands[1]))); *************** *** 1440,1444 **** mask %0,%1,0xff or %0,%#r0,%q1 ! ld.bu %0,%1" [(set_attr "type" "arith,arith,load")]) --- 1852,1856 ---- mask %0,%1,0xff or %0,%#r0,%q1 ! %V1ld.bu %0,%1" [(set_attr "type" "arith,arith,load")]) *************** *** 1463,1467 **** && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); }") --- 1875,1879 ---- && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], 0, 0); }") *************** *** 1474,1478 **** or %0,%#r0,%h1 subu %0,%#r0,%H1 ! ld.h %0,%1" [(set_attr "type" "bit,arith,arith,load")]) --- 1886,1890 ---- or %0,%#r0,%h1 subu %0,%#r0,%H1 ! %V1ld.h %0,%1" [(set_attr "type" "bit,arith,arith,load")]) *************** *** 1486,1490 **** && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); }") --- 1898,1902 ---- && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], 0, 0); }") *************** *** 1497,1501 **** or %0,%#r0,%q1 subu %0,%#r0,%Q1 ! ld.b %0,%1" [(set_attr "type" "bit,arith,arith,load")]) --- 1909,1913 ---- or %0,%#r0,%q1 subu %0,%#r0,%Q1 ! %V1ld.b %0,%1" [(set_attr "type" "bit,arith,arith,load")]) *************** *** 1509,1513 **** && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); }") --- 1921,1925 ---- && symbolic_address_p (XEXP (operands[1], 0))) operands[1] ! = legitimize_address (flag_pic, operands[1], 0, 0); }") *************** *** 1520,1524 **** or %0,%#r0,%q1 subu %0,%#r0,%Q1 ! ld.b %0,%1" [(set_attr "type" "bit,arith,arith,load")]) --- 1932,1936 ---- or %0,%#r0,%q1 subu %0,%#r0,%Q1 ! %V1ld.b %0,%1" [(set_attr "type" "bit,arith,arith,load")]) *************** *** 1612,1641 **** subu %0,%1,%n2") - ;; In unusual contexts, an add of a large value is generated (case statements - ;; for example). In these contexts, it is sufficient to accept only those - ;; cases where the two registers are different. - - (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,&r") - (plus:SI (match_operand:SI 1 "arith32_operand" "%r,r") - (match_operand:SI 2 "arith32_operand" "r,!n")))] - "" - "* - { - rtx xoperands[10]; - - if (which_alternative == 0) - return \"addu %0,%1,%2\"; - - xoperands[0] = operands[0]; - xoperands[1] = operands[2]; - output_asm_insn (output_load_const_int (SImode, xoperands), - xoperands); - - return \"addu %0,%1,%0\"; - }" - [(set_attr "type" "arith,marith") - (set_attr "length" "1,3")]) ; may be 2 or 3. - ;; patterns for mixed mode floating point. ;; Do not define patterns that utilize mixed mode arithmetic that result --- 2024,2027 ---- *************** *** 1698,1702 **** (plus:DI (match_operand:DI 1 "register_operand" "r") (zero_extend:DI ! (match_operand:SI 2 "register_operand" "r"))))] "" "addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0" --- 2084,2089 ---- (plus:DI (match_operand:DI 1 "register_operand" "r") (zero_extend:DI ! (match_operand:SI 2 "register_operand" "r")))) ! (clobber (reg:CC 0))] "" "addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0" *************** *** 1707,1711 **** (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! (match_operand:DI 2 "register_operand" "r")))] "" "addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2" --- 2094,2099 ---- (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! (match_operand:DI 2 "register_operand" "r"))) ! (clobber (reg:CC 0))] "" "addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2" *************** *** 1715,1722 **** [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%r") ! (match_operand:DI 2 "register_operand" "r")))] "" "addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2" [(set_attr "type" "marith")]) ;;- subtract instructions --- 2103,2137 ---- [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%r") ! (match_operand:DI 2 "register_operand" "r"))) ! (clobber (reg:CC 0))] "" "addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2" [(set_attr "type" "marith")]) + + ;; Add with carry insns. + + (define_insn "" + [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") + (match_operand:SI 2 "reg_or_0_operand" "rO"))) + (set (reg:CC 0) + (unspec:CC [(match_dup 1) (match_dup 2)] 0))])] + "" + "addu.co %r0,%r1,%r2") + + (define_insn "" + [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO") + (match_operand:SI 1 "reg_or_0_operand" "rO")] + 0))] + "" + "addu.co %#r0,%r0,%r1") + + (define_insn "" + [(set (match_operand:SI 0 "reg_or_0_operand" "=r") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") + (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO") + (reg:CC 0)] 0)))] + "" + "addu.ci %r0,%r1,%r2") ;;- subtract instructions *************** *** 1789,1793 **** (minus:DI (match_operand:DI 1 "register_operand" "r") (zero_extend:DI ! (match_operand:SI 2 "register_operand" "r"))))] "" "subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0" --- 2204,2209 ---- (minus:DI (match_operand:DI 1 "register_operand" "r") (zero_extend:DI ! (match_operand:SI 2 "register_operand" "r")))) ! (clobber (reg:CC 0))] "" "subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0" *************** *** 1798,1802 **** (minus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! (match_operand:DI 2 "register_operand" "r")))] "" "subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2" --- 2214,2219 ---- (minus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) ! (match_operand:DI 2 "register_operand" "r"))) ! (clobber (reg:CC 0))] "" "subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2" *************** *** 1806,1813 **** [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "register_operand" "r") ! (match_operand:DI 2 "register_operand" "r")))] "" "subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2" [(set_attr "type" "marith")]) ;;- multiply instructions --- 2223,2257 ---- [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "register_operand" "r") ! (match_operand:DI 2 "register_operand" "r"))) ! (clobber (reg:CC 0))] "" "subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2" [(set_attr "type" "marith")]) + + ;; Subtract with carry insns. + + (define_insn "" + [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r") + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") + (match_operand:SI 2 "reg_or_0_operand" "rO"))) + (set (reg:CC 0) + (unspec:CC [(match_dup 1) (match_dup 2)] 1))])] + "" + "subu.co %r0,%r1,%r2") + + (define_insn "" + [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO") + (match_operand:SI 1 "reg_or_0_operand" "rO")] + 1))] + "" + "subu.co %#r0,%r0,%r1") + + (define_insn "" + [(set (match_operand:SI 0 "reg_or_0_operand" "=r") + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") + (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO") + (reg:CC 0)] 1)))] + "" + "subu.ci %r0,%r1,%r2") ;;- multiply instructions *************** *** 2533,2537 **** (const_int 24)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "ld.b %0,%1" [(set_attr "type" "load")]) --- 2977,2981 ---- (const_int 24)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "%V1ld.b %0,%1" [(set_attr "type" "load")]) *************** *** 2541,2545 **** (const_int 24)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "ld.bu %0,%1" [(set_attr "type" "load")]) --- 2985,2989 ---- (const_int 24)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "%V1ld.bu %0,%1" [(set_attr "type" "load")]) *************** *** 2549,2553 **** (const_int 16)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "ld.h %0,%1" [(set_attr "type" "load")]) --- 2993,2997 ---- (const_int 16)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "%V1ld.h %0,%1" [(set_attr "type" "load")]) *************** *** 2557,2561 **** (const_int 16)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "ld.hu %0,%1" [(set_attr "type" "load")]) --- 3001,3005 ---- (const_int 16)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! "%V1ld.hu %0,%1" [(set_attr "type" "load")]) *************** *** 2765,2768 **** --- 3209,3231 ---- [(set_attr "type" "bit")]) + ;; find first set. + + ;; The ff1 instruction searches from the most significant bit while ffs + ;; searches from the least significant bit. The bit index and treatment of + ;; zero also differ. This amazing sequence was discovered using the GNU + ;; Superoptimizer. + + (define_insn "ffssi2" + [(set (match_operand:SI 0 "register_operand" "=r,&r") + (ffs:SI (match_operand:SI 1 "register_operand" "0,r"))) + (clobber (reg:CC 0)) + (clobber (match_scratch:SI 2 "=r,X"))] + "" + "@ + subu.co %2,%#r0,%1\;and %2,%2,%1\;addu.ci %2,%2,%2\;ff1 %0,%2 + subu.co %0,%#r0,%1\;and %0,%0,%1\;addu.ci %0,%0,%0\;ff1 %0,%0" + [(set_attr "type" "marith") + (set_attr "length" "4")]) + ;; Bit field instructions. *************** *** 2884,2899 **** [(set_attr "type" "dpadd")]) - (define_insn "" - [(set (match_operand:DF 0 "register_operand" "+r") - (neg:DF (match_dup 0)))] - "" - "xor.u %0,%0,0x8000") - (define_insn "negdf2" ! [(set (match_operand:DF 0 "register_operand" "=&r") ! (neg:DF (match_operand:DF 1 "register_operand" "r")))] "" ! "xor.u %0,%1,0x8000\;or %d0,%#r0,%d1" ! [(set_attr "type" "marith")]) (define_insn "negsf2" --- 3347,3358 ---- [(set_attr "type" "dpadd")]) (define_insn "negdf2" ! [(set (match_operand:DF 0 "register_operand" "=&r,r") ! (neg:DF (match_operand:DF 1 "register_operand" "r,0")))] "" ! "@ ! xor.u %0,%1,0x8000\;or %d0,%#r0,%d1 ! xor.u %0,%0,0x8000" ! [(set_attr "type" "marith,arith")]) (define_insn "negsf2" *************** *** 2906,2921 **** ;; machine-independent sequence). - (define_insn "" - [(set (match_operand:DF 0 "register_operand" "+r") - (abs:DF (match_dup 0)))] - "" - "and.u %0,%0,0x7fff") - (define_insn "absdf2" ! [(set (match_operand:DF 0 "register_operand" "=&r") ! (abs:DF (match_operand:DF 1 "register_operand" "r")))] "" ! "and.u %0,%1,0x7fff\;or %d0,%#r0,%d1" ! [(set_attr "type" "marith")]) (define_insn "abssf2" --- 3365,3376 ---- ;; machine-independent sequence). (define_insn "absdf2" ! [(set (match_operand:DF 0 "register_operand" "=&r,r") ! (abs:DF (match_operand:DF 1 "register_operand" "r,0")))] "" ! "@ ! and.u %0,%1,0x7fff\;or %d0,%#r0,%d1 ! and.u %0,%0,0x7fff" ! [(set_attr "type" "marith,arith")]) (define_insn "abssf2" *************** *** 3062,3068 **** (define_insn "return" [(return)] ! "null_epilogue ()" "jmp%. %#r1" [(set_attr "type" "jump")]) (define_insn "indirect_jump" --- 3517,3539 ---- (define_insn "return" [(return)] ! "reload_completed" "jmp%. %#r1" [(set_attr "type" "jump")]) + + (define_expand "prologue" + [(const_int 0)] + "" + "m88k_expand_prologue (); DONE;") + + (define_expand "epilogue" + [(return)] + "! null_prologue ()" + "m88k_expand_epilogue ();") + + (define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] + "" + "" + [(set_attr "length" "0")]) (define_insn "indirect_jump" diff -rc2N gcc-2.2.2/config/m88kdgux.h gcc-2.3.1/config/m88kdgux.h *** gcc-2.2.2/config/m88kdgux.h Sat Jun 13 17:19:19 1992 --- gcc-2.3.1/config/m88kdgux.h Wed Oct 28 15:23:35 1992 *************** *** 28,35 **** #define SDB_DEBUGGING_INFO #define PREFERRED_DEBUGGING_TYPE \ ! (VERSION_0300_SYNTAX ? DWARF_DEBUG : SDB_DEBUG) #ifndef NO_BUGS #define AS_BUG_IMMEDIATE_LABEL #endif --- 28,37 ---- #define SDB_DEBUGGING_INFO #define PREFERRED_DEBUGGING_TYPE \ ! (GET_VERSION_0300_SYNTAX ? DWARF_DEBUG : SDB_DEBUG) #ifndef NO_BUGS #define AS_BUG_IMMEDIATE_LABEL + /* The DG/UX 4.30 assembler doesn't accept the symbol `fcr63'. */ + #define AS_BUG_FLDCR #endif *************** *** 59,62 **** --- 61,66 ---- MASK_OCS_DEBUG_INFO | \ MASK_OCS_FRAME_POSITION) + #undef CPU_DEFAULT + #define CPU_DEFAULT MASK_88000 /* Macros to be automatically defined. __svr4__ is our extension. *************** *** 69,76 **** -D__svr4__ -Asystem(unix) -Acpu(m88k) -Amachine(m88k)" ! /* 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 (-V, silicon filter, legends for mxdb). */ --- 73,84 ---- -D__svr4__ -Asystem(unix) -Acpu(m88k) -Amachine(m88k)" ! /* If -m88100 is in effect, add -Dm88100; similarly for -m88110. ! Here, the CPU_DEFAULT is assumed to be -m88000. If not -ansi, ! -traditional, or restricting include files to one specific source ! target, specify full DG/UX features. */ #undef CPP_SPEC ! #define CPP_SPEC "%{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \ ! %{!m88000:%{!m88110:%{m88100:-D__m88100__}}} \ ! %{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}}" /* Assembler support (-V, silicon filter, legends for mxdb). */ *************** *** 79,83 **** %{V} %{v:%{!V:-V}} %{pipe: - %{msvr4:%{mversion-03.00:-KV3}}}\ %{!mlegend:%{mstandard:-Wc,off}}\ ! %{mlegend:-Wc,-fix-bb,-h\"gcc-2.0.3\",-s\"%i\"\ %{traditional:,-lc}%{!traditional:,-lansi-c}\ %{mstandard:,-keep-std}\ --- 87,91 ---- %{V} %{v:%{!V:-V}} %{pipe: - %{msvr4:%{mversion-03.00:-KV3}}}\ %{!mlegend:%{mstandard:-Wc,off}}\ ! %{mlegend:-Wc,-fix-bb,-h\"gcc-2.2.14\",-s\"%i\"\ %{traditional:,-lc}%{!traditional:,-lansi-c}\ %{mstandard:,-keep-std}\ *************** *** 121,125 **** /* DGUX V.4 isn't quite ELF--yet. */ #undef VERSION_0300_SYNTAX ! #define VERSION_0300_SYNTAX (TARGET_SVR4 && TARGET_VERSION_0300) /* Output the legend info for mxdb when debugging except if standard --- 129,137 ---- /* DGUX V.4 isn't quite ELF--yet. */ #undef VERSION_0300_SYNTAX ! #define VERSION_0300_SYNTAX (TARGET_SVR4 && m88k_version_0300) ! ! /* Same, but used before OVERRIDE_OPTIONS has been processed. */ ! #define GET_VERSION_0300_SYNTAX \ ! (TARGET_SVR4 && m88k_version != 0 && strcmp (m88k_version, "03.00") >= 0) /* Output the legend info for mxdb when debugging except if standard diff -rc2N gcc-2.2.2/config/m88kdolph.h gcc-2.3.1/config/m88kdolph.h *** gcc-2.2.2/config/m88kdolph.h Sat Jun 13 17:19:06 1992 --- gcc-2.3.1/config/m88kdolph.h Wed Oct 28 15:23:38 1992 *************** *** 27,32 **** as: "/usr/tmp/cca22733.s": cannot reduce symbol table, unused symbols remain when compiling some programs. ! example program (C++): struct bad { bad(); }; bad::bad() {} */ ! #undef SDB_ALLOW_FORWARD_REFERENCES /* Use T_ARG as T_VOID. T_VOID is not defined in as it should be. */ --- 27,35 ---- as: "/usr/tmp/cca22733.s": cannot reduce symbol table, unused symbols remain when compiling some programs. ! example program (C++): struct bad { bad(); }; bad::bad() {} ! ! This problem seems to have gone away, perhaps with release 3.6 of the O/S ! from Dolphin. */ ! /* #undef SDB_ALLOW_FORWARD_REFERENCES */ /* Use T_ARG as T_VOID. T_VOID is not defined in as it should be. */ diff -rc2N gcc-2.2.2/config/m88kluna.h gcc-2.3.1/config/m88kluna.h *** gcc-2.2.2/config/m88kluna.h Sat Jun 13 17:18:56 1992 --- gcc-2.3.1/config/m88kluna.h Thu Oct 15 08:08:12 1992 *************** *** 38,42 **** #undef CPP_PREDEFINES #define CPP_PREDEFINES \ ! "-DMACH -Dmc88100 -Dm88k -Dunix -Dluna -Dluna88k -D__CLASSIFY_TYPE__=2" /* Specify extra dir to search for include files. */ --- 38,52 ---- #undef CPP_PREDEFINES #define CPP_PREDEFINES \ ! "-DMACH -Dm88k -Dunix -Dluna -Dluna88k -D__CLASSIFY_TYPE__=2" ! ! /* If -m88000 is in effect, add -Dmc88000; similarly for -m88100 and -m88110. ! However, reproduce the effect of -Dmc88100 previously in CPP_PREDEFINES. ! Here, the CPU_DEFAULT is assumed to be -m88100. */ ! #undef CPP_SPEC ! #define CPP_SPEC "%{m88000:-D__mc88000__} \ ! %{!m88000:%{m88100:%{m88110:-D__mc88000__}}} \ ! %{!m88000:%{!m88100:%{m88110:-D__mc88110__}}} \ ! %{!m88000:%{!m88110:%{!ansi:%{traditional:-Dmc88100}} \ ! -D__mc88100__ -D__mc88100}}" /* Specify extra dir to search for include files. */ diff -rc2N gcc-2.2.2/config/m88kv3.h gcc-2.3.1/config/m88kv3.h *** gcc-2.2.2/config/m88kv3.h Sat Jun 13 17:18:45 1992 --- gcc-2.3.1/config/m88kv3.h Wed Oct 28 15:23:43 1992 *************** *** 1,4 **** /* Definitions of target machine for GNU compiler. ! Motorola m88100 running the AT&T/Unisoft/Motorla V.3 reference port. Copyright (C) 1990, 1991 Free Software Foundation, Inc. Contributed by Ray Essick (ressick@mot.com) --- 1,4 ---- /* Definitions of target machine for GNU compiler. ! Motorola m88100 running the AT&T/Unisoft/Motorola V.3 reference port. Copyright (C) 1990, 1991 Free Software Foundation, Inc. Contributed by Ray Essick (ressick@mot.com) *************** *** 31,35 **** /* Macros to be automatically defined. */ #undef CPP_PREDEFINES ! #define CPP_PREDEFINES "-Dm88000 -Dm88k -DsysV88 -D__CLASSIFY_TYPE__=2" /* Override svr3.h to link with ?crt0.o instead of ?crt1.o and ?crtn.o. --- 31,35 ---- /* Macros to be automatically defined. */ #undef CPP_PREDEFINES ! #define CPP_PREDEFINES "-Dm88000 -Dm88k -Dunix -DsysV88 -D__CLASSIFY_TYPE__=2" /* Override svr3.h to link with ?crt0.o instead of ?crt1.o and ?crtn.o. diff -rc2N gcc-2.2.2/config/mips-5.h gcc-2.3.1/config/mips-5.h *** gcc-2.2.2/config/mips-5.h --- gcc-2.3.1/config/mips-5.h Sat Sep 26 18:02:54 1992 *************** *** 0 **** --- 1,29 ---- + /* Definitions of target machine for GNU compiler. MIPS RISC-OS 5.0 + default version. + Copyright (C) 1992 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 LINK_SPEC "\ + %{G*} \ + %{!mgas: \ + %{EB} %{!EB: -EB} \ + %{EL: %e-EL not supported} \ + %{mips1} %{mips2} %{mips3} %{bestGnum} \ + %{shared} %{non_shared} %{!shared: %{!non_shared: -non_shared}}" + + #include "mips.h" diff -rc2N gcc-2.2.2/config/mips-5bsd.h gcc-2.3.1/config/mips-5bsd.h *** gcc-2.2.2/config/mips-5bsd.h --- gcc-2.3.1/config/mips-5bsd.h Sat Sep 26 18:02:54 1992 *************** *** 0 **** --- 1,56 ---- + /* Definitions of target machine for GNU compiler. MIPS RISC-OS, 5.0 BSD version. + Copyright (C) 1991 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 MIPS_BSD43 + + #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43" + + #define SYSTEM_INCLUDE_DIR "/bsd43/usr/include" + + #define CPP_SPEC "\ + %{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.cxx: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \ + %{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ + %{!.S: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" + + #define LINK_SPEC "\ + %{G*} \ + %{!mgas: \ + %{EB} %{!EB: -EB} \ + %{EL: %e-EL not supported} \ + %{mips1} %{mips2} %{mips3} %{bestGnum} \ + %{shared} %{non_shared} %{!shared: %{!non_shared: -non_shared}} \ + -systype /bsd43/ }" + + #define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} -lc" + + #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt1.o%s crtn.o%s}}" + + #define MACHINE_TYPE "RISC-OS BSD Mips" + + /* Generate calls to memcpy, etc., not bcopy, etc. */ + #define TARGET_MEM_FUNCTIONS + + /* Override defaults for finding the MIPS tools. */ + #define MD_STARTFILE_PREFIX "/bsd43/usr/lib/cmplrs/cc/" + #define MD_EXEC_PREFIX "/bsd43/usr/lib/cmplrs/cc/" + + #include "mips.h" diff -rc2N gcc-2.2.2/config/mips-5g4.h gcc-2.3.1/config/mips-5g4.h *** gcc-2.2.2/config/mips-5g4.h --- gcc-2.3.1/config/mips-5g4.h Sat Sep 26 18:02:55 1992 *************** *** 0 **** --- 1,22 ---- + /* Definitions of target machine for GNU compiler. Mips RISC-OS 5.0 System V.4 version + using encapsulated stabs. + Copyright (C) 1992 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 PREFERRED_DEBUGGING_TYPE DBX_DEBUG + #include "mips-5svr4.h" diff -rc2N gcc-2.2.2/config/mips-5gbsd.h gcc-2.3.1/config/mips-5gbsd.h *** gcc-2.2.2/config/mips-5gbsd.h --- gcc-2.3.1/config/mips-5gbsd.h Sat Sep 26 18:02:55 1992 *************** *** 0 **** --- 1,22 ---- + /* Definitions of target machine for GNU compiler. Mips RISC-OS 5.0 BSD version + using encapsulated stabs. + Copyright (C) 1992 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 PREFERRED_DEBUGGING_TYPE DBX_DEBUG + #include "mips-5bsd.h" diff -rc2N gcc-2.2.2/config/mips-5gdb.h gcc-2.3.1/config/mips-5gdb.h *** gcc-2.2.2/config/mips-5gdb.h --- gcc-2.3.1/config/mips-5gdb.h Sat Sep 26 18:02:56 1992 *************** *** 0 **** --- 1,22 ---- + /* Definitions of target machine for GNU compiler. MIPS RISC-OS 5.0 + default version using encapsulated stabs. + Copyright (C) 1992 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 PREFERRED_DEBUGGING_TYPE DBX_DEBUG + #include "mips-5.h" diff -rc2N gcc-2.2.2/config/mips-5gsysv.h gcc-2.3.1/config/mips-5gsysv.h *** gcc-2.2.2/config/mips-5gsysv.h --- gcc-2.3.1/config/mips-5gsysv.h Sat Sep 26 18:02:56 1992 *************** *** 0 **** --- 1,22 ---- + /* Definitions of target machine for GNU compiler. Mips RISC-OS 5.0 System V version + using encapsulated stabs. + Copyright (C) 1992 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 PREFERRED_DEBUGGING_TYPE DBX_DEBUG + #include "mips-5sysv.h" diff -rc2N gcc-2.2.2/config/mips-5svr4.h gcc-2.3.1/config/mips-5svr4.h *** gcc-2.2.2/config/mips-5svr4.h --- gcc-2.3.1/config/mips-5svr4.h Sat Sep 26 18:02:56 1992 *************** *** 0 **** --- 1,70 ---- + /* Definitions of target machine for GNU compiler. MIPS RISC-OS 5.0 System V.4 version. + Copyright (C) 1992 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 MIPS_SVR4 + + #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SVR4" + + #define SYSTEM_INCLUDE_DIR "/svr4/usr/include" + + #define CPP_SPEC "\ + %{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.cxx: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \ + %{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ + %{!.S: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" + + #define LINK_SPEC "\ + %{G*} \ + %{!mgas: \ + %{EB} %{!EB:-EB} \ + %{EL: %e-EL not supported} \ + %{mips1} %{mips2} %{mips3} %{bestGnum} \ + %{shared} %{non_shared} %{!shared: %{!non_shared: -non_shared}} \ + -systype /svr4/}" + + #define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} -lc crtn.o%s" + + #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt1.o%s}}" + + #define MACHINE_TYPE "RISC-OS System V.4 Mips" + + /* Override defaults for finding the MIPS tools. */ + #define MD_STARTFILE_PREFIX "/svr4/usr/lib/cmplrs/cc/" + #define MD_EXEC_PREFIX "/svr4/usr/lib/cmplrs/cc/" + + /* 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 + + #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 + + #include "mips.h" diff -rc2N gcc-2.2.2/config/mips-5sysv.h gcc-2.3.1/config/mips-5sysv.h *** gcc-2.2.2/config/mips-5sysv.h --- gcc-2.3.1/config/mips-5sysv.h Sat Sep 26 18:02:57 1992 *************** *** 0 **** --- 1,72 ---- + /* Definitions of target machine for GNU compiler. MIPS RISC-OS 5.0 System V version. + Copyright (C) 1991 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 MIPS_SYSV + + #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SYSV" + + #define SYSTEM_INCLUDE_DIR "/sysv/usr/include" + + #define CPP_SPEC "\ + %{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.cxx: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \ + %{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \ + %{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ + %{!.S: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" + + #define LINK_SPEC "\ + %{G*} \ + %{!mgas: \ + %{EB} %{!EB:-EB} \ + %{EL: %e-EL not supported} \ + %{mips1} %{mips2} %{mips3} %{bestGnum} \ + %{shared} %{non_shared} %{!shared: %{!non_shared: -non_shared}} \ + -systype /sysv/}" + + #define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} -lc crtn.o%s" + + #define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt1.o%s}}" + + #define MACHINE_TYPE "RISC-OS System V Mips" + + /* Override defaults for finding the MIPS tools. */ + #define MD_STARTFILE_PREFIX "/sysv/usr/lib/cmplrs/cc/" + #define MD_EXEC_PREFIX "/sysv/usr/lib/cmplrs/cc/" + + /* Mips System V 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 + #include + + #ifdef _SC_PAGE_SIZE + #define getpagesize() sysconf(_SC_PAGE_SIZE) + + #else /* older rev of OS */ + #define getpagesize() (NBPC) + #endif /* !_SC_PAGE_SIZE */ + #endif /* L_trampoline */ + + /* Generate calls to memcpy, etc., not bcopy, etc. */ + #define TARGET_MEM_FUNCTIONS + + #include "mips.h" diff -rc2N gcc-2.2.2/config/mips-bsd.h gcc-2.3.1/config/mips-bsd.h *** gcc-2.2.2/config/mips-bsd.h Thu Jun 11 00:12:06 1992 --- gcc-2.3.1/config/mips-bsd.h Thu Oct 1 17:28:20 1992 *************** *** 20,24 **** #define MIPS_BSD43 ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43" #define SYSTEM_INCLUDE_DIR "/bsd43/usr/include" --- 20,25 ---- #define MIPS_BSD43 ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43 \ ! -D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_BSD43" #define SYSTEM_INCLUDE_DIR "/bsd43/usr/include" *************** *** 37,41 **** %{EB} %{!EB: -EB} \ %{EL: %e-EL not supported} \ ! %{bestGnum} \ %{mips1} %{mips2} %{mips3} \ -systype /bsd43/ }" --- 38,42 ---- %{EB} %{!EB: -EB} \ %{EL: %e-EL not supported} \ ! %{bestGnum} %{shared} %{non_shared} \ %{mips1} %{mips2} %{mips3} \ -systype /bsd43/ }" diff -rc2N gcc-2.2.2/config/mips-n5.h gcc-2.3.1/config/mips-n5.h *** gcc-2.2.2/config/mips-n5.h Thu Jun 11 00:16:11 1992 --- gcc-2.3.1/config/mips-n5.h Wed Aug 26 14:31:56 1992 *************** *** 36,40 **** %{!mgas: %{mips1} %{mips2} %{mips3} \ %{EB} %{!EB:-EB} %{EL: %e-EL not supported} \ ! %{bestGnum}}" #define LIB_SPEC "\ --- 36,40 ---- %{!mgas: %{mips1} %{mips2} %{mips3} \ %{EB} %{!EB:-EB} %{EL: %e-EL not supported} \ ! %{bestGnum} %{shared} %{non_shared}}" #define LIB_SPEC "\ diff -rc2N gcc-2.2.2/config/mips-svr4.h gcc-2.3.1/config/mips-svr4.h *** gcc-2.2.2/config/mips-svr4.h Thu Jun 11 00:12:29 1992 --- gcc-2.3.1/config/mips-svr4.h Thu Oct 1 17:28:21 1992 *************** *** 20,24 **** #define MIPS_SVR4 ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SVR4" #define SYSTEM_INCLUDE_DIR "/svr4/usr/include" --- 20,25 ---- #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" #define SYSTEM_INCLUDE_DIR "/svr4/usr/include" *************** *** 37,41 **** %{EB} %{!EB:-EB} \ %{EL: %e-EL not supported} \ ! %{bestGnum} \ %{mips1} %{mips2} %{mips3} \ -systype /svr4/}" --- 38,42 ---- %{EB} %{!EB:-EB} \ %{EL: %e-EL not supported} \ ! %{bestGnum} %{shared} %{non_shared} \ %{mips1} %{mips2} %{mips3} \ -systype /svr4/}" diff -rc2N gcc-2.2.2/config/mips-sysv.h gcc-2.3.1/config/mips-sysv.h *** gcc-2.2.2/config/mips-sysv.h Thu Jun 11 00:10:30 1992 --- gcc-2.3.1/config/mips-sysv.h Thu Oct 1 17:28:21 1992 *************** *** 20,24 **** #define MIPS_SYSV ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SYSV" #define SYSTEM_INCLUDE_DIR "/sysv/usr/include" --- 20,25 ---- #define MIPS_SYSV ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SYSV \ ! -D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_SYSV" #define SYSTEM_INCLUDE_DIR "/sysv/usr/include" *************** *** 37,41 **** %{EB} %{!EB:-EB} \ %{EL: %e-EL not supported} \ ! %{bestGnum} \ %{mips1} %{mips2} %{mips3} \ -systype /sysv/}" --- 38,42 ---- %{EB} %{!EB:-EB} \ %{EL: %e-EL not supported} \ ! %{bestGnum} %{shared} %{non_shared} \ %{mips1} %{mips2} %{mips3} \ -systype /sysv/}" diff -rc2N gcc-2.2.2/config/mips.c gcc-2.3.1/config/mips.c *** gcc-2.2.2/config/mips.c Fri Jun 12 17:20:01 1992 --- gcc-2.3.1/config/mips.c Thu Oct 22 12:24:04 1992 *************** *** 63,97 **** #endif ! extern char *getenv (); - extern char *permalloc (); - extern void debug_rtx (); - extern void abort_with_insn (); - extern rtx copy_to_reg (); - extern rtx adj_offsettable_operand (); - extern int offsettable_address_p (); - extern tree lookup_name (); - - extern rtx gen_movqi (); - extern rtx gen_movhi (); - extern rtx gen_movsi (); - extern rtx gen_movsi_ulw (); - extern rtx gen_movsi_usw (); - extern rtx gen_movstrsi_internal (); - extern rtx gen_addsi3 (); - extern rtx gen_iorsi3 (); - extern rtx gen_andsi3 (); - extern rtx gen_bne (); - extern rtx gen_beq (); - extern rtx gen_cmpsi (); - extern rtx gen_jump (); - - extern char call_used_regs[]; - extern char *asm_file_name; - extern FILE *asm_out_file; extern tree current_function_decl; ! extern char **save_argv; ! extern char *version_string; ! extern char *language_string; /* Enumeration for all of the relational tests, so that we can build --- 63,81 ---- #endif ! extern void abort (); ! extern int atoi (); ! extern char *getenv (); ! extern char *mktemp (); ! ! extern rtx adj_offsettable_operand (); ! extern rtx copy_to_reg (); ! extern void error (); ! extern void fatal (); ! extern tree lookup_name (); ! extern void pfatal_with_name (); ! extern void warning (); extern tree current_function_decl; ! extern FILE *asm_out_file; /* Enumeration for all of the relational tests, so that we can build *************** *** 124,131 **** int num_source_filenames = 0; - /* Count of the number of functions created so far, in order to make - unique labels for omitting the frame pointer. */ - int number_functions_processed = 0; - /* Count the number of sdb related labels are generated (to find block start and end boundaries). */ --- 108,111 ---- *************** *** 197,200 **** --- 177,184 ---- enum cmp_type branch_type; + /* Number of previously seen half-pic pointers and references. */ + static int prev_half_pic_ptrs = 0; + static int prev_half_pic_refs = 0; + /* which cpu are we scheduling for */ enum processor_type mips_cpu; *************** *** 421,425 **** enum machine_mode mode; { ! long value; if (GET_CODE (op) != CONST_INT) --- 405,409 ---- enum machine_mode mode; { ! HOST_WIDE_INT value; if (GET_CODE (op) != CONST_INT) *************** *** 427,437 **** value = INTVAL (op); ! if ((value & 0xffff0000) == 0) /* ior reg,$r0,value */ return FALSE; ! if ((value & 0xffff0000) == 0xffff0000) /* subu reg,$r0,value */ return FALSE; ! if ((value & 0x0000ffff) == 0) /* lui reg,value>>16 */ return FALSE; --- 411,421 ---- value = INTVAL (op); ! if ((value & ~0x0000ffff) == 0) /* ior reg,$r0,value */ return FALSE; ! if (((unsigned long)(value + 32768)) <= 32767) /* subu reg,$r0,value */ return FALSE; ! if ((value & 0xffff0000) == value) /* lui reg,value>>16 */ return FALSE; *************** *** 448,451 **** --- 432,438 ---- switch (GET_CODE (op)) { + default: + break; + case CONST_INT: return (INTVAL (op) == 0); *************** *** 559,562 **** --- 546,552 ---- switch (GET_CODE (addr)) { + default: + break; + case REG: return TRUE; *************** *** 820,823 **** --- 810,816 ---- switch (GET_CODE (addr)) { + default: + break; + case REG: case CONST_INT: *************** *** 1014,1021 **** switch (GET_MODE (op1)) { ! case SFmode: ret = "lw\t%0,%1"; break; ! case SImode: ret = "lw\t%0,%1"; break; ! case HImode: ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; break; ! case QImode: ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; break; } } --- 1007,1015 ---- switch (GET_MODE (op1)) { ! default: break; ! case SFmode: ret = "lw\t%0,%1"; break; ! case SImode: ret = "lw\t%0,%1"; break; ! case HImode: ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; break; ! case QImode: ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; break; } } *************** *** 1050,1059 **** else if (GP_REG_P (regno0)) ! { ! if ((INTVAL (operands[1]) & 0x0000ffff) == 0) ! ret = "lui\t%0,(%X1)>>16"; ! else ! ret = "li\t%0,%1"; ! } } --- 1044,1048 ---- else if (GP_REG_P (regno0)) ! ret = (INTVAL (op1) < 0) ? "li\t%0,%1\t\t\t# %X1" : "li\t%0,%X1\t\t# %1"; } *************** *** 1080,1098 **** else if (code1 == LABEL_REF) - ret = "la\t%0,%a1"; - - else if (code1 == SYMBOL_REF || code1 == CONST) { if (TARGET_STATS) mips_count_memory_refs (op1, 1); if (HALF_PIC_P () && CONSTANT_P (op1) && HALF_PIC_ADDRESS_P (op1)) { ! delay = DELAY_LOAD; ! ret = "lw\t%0,%2\t\t# pic reference"; ! operands[2] = HALF_PIC_PTR (op1); } else ! ret = "la\t%0,%a1"; } --- 1069,1117 ---- else if (code1 == LABEL_REF) { if (TARGET_STATS) mips_count_memory_refs (op1, 1); + ret = "la\t%0,%a1"; + } + + else if (code1 == SYMBOL_REF || code1 == CONST) + { if (HALF_PIC_P () && CONSTANT_P (op1) && HALF_PIC_ADDRESS_P (op1)) { ! rtx offset = const0_rtx; ! ! if (GET_CODE (op1) == CONST) ! op1 = eliminate_constant_term (XEXP (op1, 0), &offset); ! ! if (GET_CODE (op1) == SYMBOL_REF) ! { ! operands[2] = HALF_PIC_PTR (op1); ! ! if (TARGET_STATS) ! mips_count_memory_refs (operands[2], 1); ! ! if (INTVAL (offset) == 0) ! { ! delay = DELAY_LOAD; ! ret = "lw\t%0,%2"; ! } ! else ! { ! dslots_load_total++; ! operands[3] = offset; ! ret = (SMALL_INT (offset)) ! ? "lw\t%0,%2%#\n\tadd\t%0,%0,%3" ! : "lw\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]"; ! } ! } } else ! { ! if (TARGET_STATS) ! mips_count_memory_refs (op1, 1); ! ! ret = "la\t%0,%a1"; ! } } *************** *** 1127,1130 **** --- 1146,1150 ---- switch (mode) { + default: break; case SFmode: ret = "sw\t%1,%0"; break; case SImode: ret = "sw\t%1,%0"; break; *************** *** 1142,1145 **** --- 1162,1166 ---- switch (mode) { + default: break; case SFmode: ret = "sw\t%z1,%0"; break; case SImode: ret = "sw\t%z1,%0"; break; *************** *** 1153,1156 **** --- 1174,1178 ---- switch (mode) { + default: break; case SFmode: ret = "sw\t%.,%0"; break; case SImode: ret = "sw\t%.,%0"; break; *************** *** 1280,1285 **** else { ! operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); ! operands[3] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1)); ret = "li\t%M0,%3\n\tli\t%L0,%2"; } --- 1302,1307 ---- else { ! operands[2] = GEN_INT (CONST_DOUBLE_LOW (op1)); ! operands[3] = GEN_INT (CONST_DOUBLE_HIGH (op1)); ret = "li\t%M0,%3\n\tli\t%L0,%2"; } *************** *** 1317,1321 **** else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0)) { ! operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) >= 0 ? 0 : -1); ret = "li\t%M0,%2\n\tli\t%L0,%1"; } --- 1339,1343 ---- else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0)) { ! operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1); ret = "li\t%M0,%2\n\tli\t%L0,%1"; } *************** *** 1418,1421 **** --- 1440,1446 ---- switch (GET_CODE (addr)) { + default: + break; + case LO_SUM: case HIGH: *************** *** 1459,1462 **** --- 1484,1490 ---- switch (GET_CODE (plus1)) { + default: + break; + case CONST_INT: { *************** *** 1489,1492 **** --- 1517,1521 ---- switch (test_code) { + default: break; case EQ: test = ITEST_EQ; break; case NE: test = ITEST_NE; break; *************** *** 1507,1512 **** /* Generate the code to compare two integer values. The return value is: (reg:SI xx) The pseudo register the comparison is in - (const_int 0) The comparison is always false - (const_int 1) The comparison is always true (rtx)0 No register, generate a simple branch. */ --- 1536,1539 ---- *************** *** 1518,1522 **** rtx cmp1; /* second operand to compare */ int *p_invert; /* NULL or ptr to hold whether branch needs */ ! /* to reserse it's test */ { struct cmp_info { --- 1545,1549 ---- rtx cmp1; /* second operand to compare */ int *p_invert; /* NULL or ptr to hold whether branch needs */ ! /* to reverse its test */ { struct cmp_info { *************** *** 1559,1608 **** eqne_p = (p_info->test_code == XOR); - /* See if the test is always true or false. */ - if ((GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG) - && GET_CODE (cmp1) == CONST_INT) - { - int value = INTVAL (cmp1); - rtx truth = (rtx)0; - - if (test == ITEST_GEU && value == 0) - truth = const1_rtx; - - else if (test == ITEST_LTU && value == 0) - truth = const0_rtx; - - else if (!TARGET_INT64) - { - if (test == ITEST_LTU && value == -1) - truth = const1_rtx; - - else if (test == ITEST_GTU && value == -1) - truth = const0_rtx; - - else if (test == ITEST_LEU && value == -1) - truth = const1_rtx; - - else if (test == ITEST_GT && value == 0x7fffffff) - truth = const0_rtx; - - else if (test == ITEST_LE && value == 0x7fffffff) - truth = const1_rtx; - - else if (test == ITEST_LT && value == 0x80000000) - truth = const0_rtx; - - else if (test == ITEST_GE && value == 0x80000000) - truth = const1_rtx; - } - - if (truth != (rtx)0) - { - if (result != (rtx)0) - emit_move_insn (result, truth); - - return truth; - } - } - /* Eliminate simple branches */ branch_p = (result == (rtx)0); --- 1586,1589 ---- *************** *** 1620,1624 **** } ! /* allocate a psuedo to calculate the value in. */ result = gen_reg_rtx (SImode); } --- 1601,1605 ---- } ! /* allocate a pseudo to calculate the value in. */ result = gen_reg_rtx (SImode); } *************** *** 1630,1634 **** if (GET_CODE (cmp1) == CONST_INT) { ! int value = INTVAL (cmp1); if (value < p_info->const_low || value > p_info->const_high) cmp1 = force_reg (SImode, cmp1); --- 1611,1615 ---- if (GET_CODE (cmp1) == CONST_INT) { ! HOST_WIDE_INT value = INTVAL (cmp1); if (value < p_info->const_low || value > p_info->const_high) cmp1 = force_reg (SImode, cmp1); *************** *** 1651,1655 **** { if (p_info->const_add != 0) ! cmp1 = gen_rtx (CONST_INT, VOIDmode, INTVAL (cmp1) + p_info->const_add); } else if (p_info->reverse_regs) --- 1632,1636 ---- { if (p_info->const_add != 0) ! cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add); } else if (p_info->reverse_regs) *************** *** 1788,1792 **** break; } ! /* Generate the jump */ if (invert) --- 1769,1773 ---- break; } ! /* Generate the jump */ if (invert) *************** *** 1815,1822 **** The load is emitted directly, and the store insn is returned. */ static rtx block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src) ! rtx src_reg; /* register holding source memory addresss */ ! rtx dest_reg; /* register holding dest. memory addresss */ int *p_bytes; /* pointer to # bytes remaining */ int *p_offset; /* pointer to current offset */ --- 1796,1804 ---- The load is emitted directly, and the store insn is returned. */ + #if 0 static rtx block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src) ! rtx src_reg; /* register holding source memory address */ ! rtx dest_reg; /* register holding dest. memory address */ int *p_bytes; /* pointer to # bytes remaining */ int *p_offset; /* pointer to current offset */ *************** *** 1887,1892 **** else { ! src_addr = gen_rtx (PLUS, Pmode, src_reg, gen_rtx (CONST_INT, VOIDmode, offset)); ! dest_addr = gen_rtx (PLUS, Pmode, dest_reg, gen_rtx (CONST_INT, VOIDmode, offset)); } --- 1869,1874 ---- else { ! src_addr = gen_rtx (PLUS, Pmode, src_reg, GEN_INT (offset)); ! dest_addr = gen_rtx (PLUS, Pmode, dest_reg, GEN_INT (offset)); } *************** *** 1901,1904 **** --- 1883,1887 ---- return (*store_func) (gen_rtx (MEM, mode, dest_addr), reg); } + #endif *************** *** 1919,1922 **** --- 1902,1906 ---- in deference to the R4000. */ + #if 0 static void block_move_sequence (dest_reg, src_reg, bytes, align, orig_src) *************** *** 1955,1958 **** --- 1939,1943 ---- emit_insn (cur_store); } + #endif *************** *** 1992,2000 **** rtx dest_mem = gen_rtx (MEM, BLKmode, dest_reg); rtx src_mem = gen_rtx (MEM, BLKmode, src_reg); ! rtx align_rtx = gen_rtx (CONST_INT, VOIDmode, align); rtx label; rtx final_src; rtx bytes_rtx; - int i; int leftover; --- 1977,1984 ---- rtx dest_mem = gen_rtx (MEM, BLKmode, dest_reg); rtx src_mem = gen_rtx (MEM, BLKmode, src_reg); ! rtx align_rtx = GEN_INT (align); rtx label; rtx final_src; rtx bytes_rtx; int leftover; *************** *** 2007,2011 **** label = gen_label_rtx (); final_src = gen_reg_rtx (Pmode); ! bytes_rtx = gen_rtx (CONST_INT, VOIDmode, bytes); if (bytes > 0x7fff) --- 1991,1995 ---- label = gen_label_rtx (); final_src = gen_reg_rtx (Pmode); ! bytes_rtx = GEN_INT (bytes); if (bytes > 0x7fff) *************** *** 2019,2023 **** emit_label (label); ! bytes_rtx = gen_rtx (CONST_INT, VOIDmode, MAX_MOVE_BYTES); emit_insn (gen_movstrsi_internal (dest_mem, src_mem, bytes_rtx, align_rtx)); emit_insn (gen_addsi3 (src_reg, src_reg, bytes_rtx)); --- 2003,2007 ---- emit_label (label); ! bytes_rtx = GEN_INT (MAX_MOVE_BYTES); emit_insn (gen_movstrsi_internal (dest_mem, src_mem, bytes_rtx, align_rtx)); emit_insn (gen_addsi3 (src_reg, src_reg, bytes_rtx)); *************** *** 2028,2032 **** if (leftover) emit_insn (gen_movstrsi_internal (dest_mem, src_mem, ! gen_rtx (CONST_INT, VOIDmode, leftover), align_rtx)); } --- 2012,2016 ---- if (leftover) emit_insn (gen_movstrsi_internal (dest_mem, src_mem, ! GEN_INT (leftover), align_rtx)); } *************** *** 2117,2121 **** emit_insn (gen_iorsi3 (temp, src_reg, dest_reg)); ! emit_insn (gen_andsi3 (temp, temp, gen_rtx (CONST_INT, VOIDmode, UNITS_PER_WORD-1))); emit_insn (gen_cmpsi (temp, const0_rtx)); emit_jump_insn (gen_beq (aligned_label)); --- 2101,2105 ---- emit_insn (gen_iorsi3 (temp, src_reg, dest_reg)); ! emit_insn (gen_andsi3 (temp, temp, GEN_INT (UNITS_PER_WORD-1))); emit_insn (gen_cmpsi (temp, const0_rtx)); emit_jump_insn (gen_beq (aligned_label)); *************** *** 2142,2147 **** emit_insn (gen_movstrsi_internal (gen_rtx (MEM, BLKmode, dest_reg), gen_rtx (MEM, BLKmode, src_reg), ! gen_rtx (CONST_INT, VOIDmode, leftover), ! gen_rtx (CONST_INT, VOIDmode, align))); } } --- 2126,2131 ---- emit_insn (gen_movstrsi_internal (gen_rtx (MEM, BLKmode, dest_reg), gen_rtx (MEM, BLKmode, src_reg), ! GEN_INT (leftover), ! GEN_INT (align))); } } *************** *** 2417,2421 **** if (TARGET_DEBUG_E_MODE) ! fprintf (stderr, "\ninit_cumulative_args\n"); cum->gp_reg_found = 0; --- 2401,2417 ---- if (TARGET_DEBUG_E_MODE) ! { ! fprintf (stderr, "\ninit_cumulative_args, fntype = 0x%.8lx", (long)fntype); ! if (!fntype) ! fputc ('\n', stderr); ! ! else ! { ! tree ret_type = TREE_TYPE (fntype); ! fprintf (stderr, ", fntype code = %s, ret code = %s\n", ! tree_code_name[ (int)TREE_CODE (fntype) ], ! tree_code_name[ (int)TREE_CODE (ret_type) ]); ! } ! } cum->gp_reg_found = 0; *************** *** 2437,2458 **** cum->gp_reg_found = 1; } - - /* Determine if the function is returning a structure, if so, - advance by one argument. */ - - if (fntype - && (TREE_CODE (fntype) == FUNCTION_TYPE || TREE_CODE (fntype) == METHOD_TYPE) - && TREE_TYPE (fntype) != 0) - { - tree ret_type = TREE_TYPE (fntype); - enum tree_code ret_code = TREE_CODE (ret_type); - - if (ret_code == RECORD_TYPE || ret_code == UNION_TYPE) - { - cum->gp_reg_found = 1; - cum->arg_number = 1; - cum->arg_words = 1; - } - } } --- 2433,2436 ---- *************** *** 2464,2467 **** --- 2442,2446 ---- enum machine_mode mode; /* current arg mode */ tree type; /* type of the argument or 0 if lib support */ + int named; /* whether or not the argument was named */ { if (TARGET_DEBUG_E_MODE) *************** *** 2551,2556 **** break; - case VOIDmode: case BLKmode: case QImode: case HImode: --- 2530,2541 ---- break; case BLKmode: + if (type != (tree)0 && TYPE_ALIGN (type) > BITS_PER_WORD) + cum->arg_words += (cum->arg_words & 1); + + regbase = GP_ARG_FIRST; + break; + + case VOIDmode: case QImode: case HImode: *************** *** 2715,2766 **** #ifdef SIGINFO - #include - static void siginfo (signo) int signo; { - char select_pgrp[15]; - char *argv[4]; - pid_t pid; - pid_t pgrp; - int status; - fprintf (stderr, "compiling '%s' in '%s'\n", (current_function_name != (char *)0) ? current_function_name : "", (current_function_file != (char *)0) ? current_function_file : ""); ! ! pgrp = getpgrp (); ! if (pgrp != -1) ! sprintf (select_pgrp, "-g%d", pgrp); ! else ! strcpy (select_pgrp, "-a"); ! ! /* Spawn a ps to tell about current memory usage, etc. */ ! argv[0] = "ps"; ! argv[1] = "-ouser,pid,pri,nice,usertime,systime,pcpu,cp,inblock,oublock,vsize,rss,pmem,ucomm"; ! argv[2] = select_pgrp; ! argv[3] = (char *)0; ! ! pid = vfork (); ! if (pid == 0) /* child context */ ! { ! execv ("/usr/bin/ps", argv); ! execv ("/usr/sbin/ps", argv); ! execvp ("ps", argv); ! perror ("ps"); ! _exit (1); ! } ! ! else if (pid > 0) /* parent context */ ! { ! void (*sigint)(int) = signal (SIGINT, SIG_IGN); ! void (*sigquit)(int) = signal (SIGQUIT, SIG_IGN); ! ! (void) waitpid (pid, &status, 0); ! ! (void) signal (SIGINT, sigint); ! (void) signal (SIGQUIT, sigquit); ! } } #endif /* SIGINFO */ --- 2700,2711 ---- #ifdef SIGINFO static void siginfo (signo) int signo; { fprintf (stderr, "compiling '%s' in '%s'\n", (current_function_name != (char *)0) ? current_function_name : "", (current_function_file != (char *)0) ? current_function_file : ""); ! fflush (stderr); } #endif /* SIGINFO */ *************** *** 2907,2921 **** #endif ! #ifdef _IOLBF /* If -mstats and -quiet, make stderr line buffered. */ if (quiet_flag && TARGET_STATS) ! { ! #ifdef MIPS_BSD43 ! setlinebuf (stderr); ! #else ! setvbuf (stderr, (char *)0, _IOLBF, BUFSIZ); #endif #endif - } /* Set up the classification arrays now. */ --- 2852,2862 ---- #endif ! #if defined(_IOLBF) ! #if defined(ultrix) || defined(__ultrix) || defined(__OSF1__) || defined(__osf__) || defined(osf) /* If -mstats and -quiet, make stderr line buffered. */ if (quiet_flag && TARGET_STATS) ! setvbuf (stderr, (char *)0, _IOLBF, BUFSIZ); #endif #endif /* Set up the classification arrays now. */ *************** *** 3018,3026 **** /* ! * If the frame pointer has been eliminated, the offset for an auto ! * or argument will be based on the stack pointer. But this is not ! * what the debugger expects--it needs to find an offset off of the ! * frame pointer (whether it exists or not). So here we turn all ! * offsets into those based on the (possibly virtual) frame pointer. */ --- 2959,2970 ---- /* ! * The MIPS debug format wants all automatic variables and arguments ! * to be in terms of the virtual frame pointer (stack pointer before ! * any adjustment in the function), while the MIPS 3.0 linker wants ! * the frame pointer to be the stack pointer after the initial ! * adjustment. So, we do the adjustment here. The arg pointer (which ! * is eliminated) points to the virtual frame pointer, while the frame ! * pointer (which may be eliminated) points to the stack pointer after ! * the initial adjustments. */ *************** *** 3036,3040 **** offset = INTVAL (offset2); ! if (reg == stack_pointer_rtx) { int frame_size = (!current_frame_info.initialized) --- 2980,2984 ---- offset = INTVAL (offset2); ! if (reg == stack_pointer_rtx || reg == frame_pointer_rtx) { int frame_size = (!current_frame_info.initialized) *************** *** 3044,3055 **** offset = offset - frame_size; } - /* Any other register is, we hope, either the frame pointer, - or a pseudo equivalent to the frame pointer. (Assign_parms - copies the arg pointer to a pseudo if ARG_POINTER_REGNUM is - equal to FRAME_POINTER_REGNUM, so references off of the - arg pointer are all off a pseudo.) Seems like all we can - do is to just return OFFSET and hope for the best. */ - return offset; } --- 2988,2994 ---- offset = offset - frame_size; } + else if (reg != arg_pointer_rtx) + abort_with_insn (addr, "mips_debugger_offset called with non stack/frame/arg pointer."); return offset; } *************** *** 3348,3351 **** --- 3287,3293 ---- case REG: + if (REGNO (addr) == ARG_POINTER_REGNUM) + abort_with_insn (addr, "Arg pointer not eliminated."); + fprintf (file, "0(%s)", reg_names [REGNO (addr)]); break; *************** *** 3381,3384 **** --- 3323,3329 ---- abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, illegal insn #2"); + if (REGNO (reg) == ARG_POINTER_REGNUM) + abort_with_insn (addr, "Arg pointer not eliminated."); + output_addr_const (file, offset); fprintf (file, "(%s)", reg_names [REGNO (reg)]); *************** *** 3552,3555 **** --- 3497,3558 ---- + /* If defined, a C statement to be executed just prior to the + output of assembler code for INSN, to modify the extracted + operands so they will be output differently. + + Here the argument OPVEC is the vector containing the operands + extracted from INSN, and NOPERANDS is the number of elements of + the vector which contain meaningful data for this insn. The + contents of this vector are what will be used to convert the + insn template into assembler code, so you can change the + assembler output by changing the contents of the vector. + + We use it to check if the current insn needs a nop in front of it + because of load delays, and also to update the delay slot + statistics. */ + + void + final_prescan_insn (insn, opvec, noperands) + rtx insn; + rtx opvec[]; + int noperands; + { + if (dslots_number_nops > 0) + { + rtx pattern = PATTERN (insn); + int length = get_attr_length (insn); + + /* Do we need to emit a NOP? */ + if (length == 0 + || (mips_load_reg != (rtx)0 && reg_mentioned_p (mips_load_reg, pattern)) + || (mips_load_reg2 != (rtx)0 && reg_mentioned_p (mips_load_reg2, pattern)) + || (mips_load_reg3 != (rtx)0 && reg_mentioned_p (mips_load_reg3, pattern)) + || (mips_load_reg4 != (rtx)0 && reg_mentioned_p (mips_load_reg4, pattern))) + fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file); + + else + dslots_load_filled++; + + while (--dslots_number_nops > 0) + fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file); + + mips_load_reg = (rtx)0; + mips_load_reg2 = (rtx)0; + mips_load_reg3 = (rtx)0; + mips_load_reg4 = (rtx)0; + + if (set_noreorder && --set_noreorder == 0) + fputs ("\t.set\treorder\n", asm_out_file); + } + + if (TARGET_STATS) + { + enum rtx_code code = GET_CODE (insn); + if (code == JUMP_INSN || code == CALL_INSN) + dslots_jump_total++; + } + } + + /* Output at beginning of assembler file. If we are optimizing to use the global pointer, create a temporary *************** *** 3736,3743 **** | | +-----------------------+ - | | - | local variables | - | | - +-----------------------+ | | | fp register save | --- 3739,3742 ---- *************** *** 3749,3752 **** --- 3748,3755 ---- +-----------------------+ | | + | local variables | + | | + +-----------------------+ + | | | alloca allocations | | | *************** *** 3781,3795 **** int fp_bits; /* bitmask to use for each fp register */ - extra_size = MIPS_STACK_ALIGN (((TARGET_ABICALLS) ? UNITS_PER_WORD : 0) - -STARTING_FRAME_OFFSET); - - var_size = MIPS_STACK_ALIGN (size); - args_size = MIPS_STACK_ALIGN (current_function_outgoing_args_size); - total_size = var_size + args_size + extra_size; gp_reg_size = 0; fp_reg_size = 0; mask = 0; fmask = 0; /* Calculate space needed for gp registers. */ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) --- 3784,3805 ---- int fp_bits; /* bitmask to use for each fp register */ gp_reg_size = 0; fp_reg_size = 0; mask = 0; fmask = 0; + extra_size = MIPS_STACK_ALIGN (((TARGET_ABICALLS) ? UNITS_PER_WORD : 0)); + var_size = MIPS_STACK_ALIGN (size); + args_size = MIPS_STACK_ALIGN (current_function_outgoing_args_size); + + /* The MIPS 3.0 linker does not like functions that dynamically + allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it + looks like we are trying to create a second frame pointer to the + function, so allocate some stack space to make it happy. */ + + if (args_size == 0 && current_function_calls_alloca) + args_size = 4*UNITS_PER_WORD; + total_size = var_size + args_size + extra_size; + /* Calculate space needed for gp registers. */ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) *************** *** 3839,3846 **** current_frame_info.fmask = fmask; current_frame_info.initialized = reload_completed; if (mask) { ! unsigned long offset = args_size + gp_reg_size - UNITS_PER_WORD; current_frame_info.gp_sp_offset = offset; current_frame_info.gp_save_offset = offset - total_size; --- 3849,3858 ---- current_frame_info.fmask = fmask; current_frame_info.initialized = reload_completed; + current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD; + current_frame_info.num_fp = fp_reg_size / (2*UNITS_PER_WORD); if (mask) { ! unsigned long offset = args_size + var_size + gp_reg_size - UNITS_PER_WORD; current_frame_info.gp_sp_offset = offset; current_frame_info.gp_save_offset = offset - total_size; *************** *** 3849,3853 **** if (fmask) { ! unsigned long offset = args_size + gp_reg_rounded + fp_reg_size - 2*UNITS_PER_WORD; current_frame_info.fp_sp_offset = offset; current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD; --- 3861,3865 ---- if (fmask) { ! unsigned long offset = args_size + var_size + gp_reg_rounded + fp_reg_size - 2*UNITS_PER_WORD; current_frame_info.fp_sp_offset = offset; current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD; *************** *** 3859,3863 **** ! /* Common code to save/restore registers. */ void --- 3871,3875 ---- ! /* Save/restore registers printing out the instructions to a file. */ void *************** *** 3934,3937 **** --- 3946,4032 ---- + /* Common code to emit the insns to save/restore registers. */ + + static void + save_restore_insns (store_p) + int store_p; /* true if this is prologue */ + { + int regno; + rtx base_reg_rtx = stack_pointer_rtx; + unsigned long mask = current_frame_info.mask; + unsigned long fmask = current_frame_info.fmask; + unsigned long gp_offset; + unsigned long fp_offset; + unsigned long max_offset; + + if (mask == 0 && fmask == 0) + return; + + gp_offset = current_frame_info.gp_sp_offset; + fp_offset = current_frame_info.fp_sp_offset; + max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset; + + /* Deal with calling functions with a large structure. */ + if (max_offset >= 32768) + { + base_reg_rtx = gen_rtx (REG, Pmode, MIPS_TEMP2_REGNUM); + emit_move_insn (base_reg_rtx, GEN_INT (max_offset)); + emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx)); + gp_offset = max_offset - gp_offset; + fp_offset = max_offset - fp_offset; + } + + /* Save registers starting from high to low. The debuggers prefer + at least the return register be stored at func+4, and also it + allows us not to need a nop in the epilog if at least one + register is reloaded in addition to return address. */ + + if (mask || frame_pointer_needed) + { + for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--) + { + if ((mask & (1L << (regno - GP_REG_FIRST))) != 0 + || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)) + { + rtx reg_rtx = gen_rtx (REG, Pmode, regno); + rtx mem_rtx = gen_rtx (MEM, Pmode, + gen_rtx (PLUS, Pmode, base_reg_rtx, + GEN_INT (gp_offset))); + + if (store_p) + emit_move_insn (mem_rtx, reg_rtx); + else + emit_move_insn (reg_rtx, mem_rtx); + + gp_offset -= UNITS_PER_WORD; + } + } + } + + if (fmask) + { + int fp_inc = (TARGET_FLOAT64) ? 1 : 2; + + for (regno = FP_REG_LAST-1; regno >= FP_REG_FIRST; regno -= fp_inc) + { + if ((fmask & (1L << (regno - FP_REG_FIRST))) != 0) + { + rtx reg_rtx = gen_rtx (REG, DFmode, regno); + rtx mem_rtx = gen_rtx (MEM, DFmode, + gen_rtx (PLUS, Pmode, base_reg_rtx, + GEN_INT (fp_offset))); + + if (store_p) + emit_move_insn (mem_rtx, reg_rtx); + else + emit_move_insn (reg_rtx, mem_rtx); + + fp_offset -= 2*UNITS_PER_WORD; + } + } + } + } + + /* Set up the stack and frame (if desired) for the function. */ *************** *** 3941,3959 **** int size; { ! int regno; ! int tsize; ! char *sp_str = reg_names[STACK_POINTER_REGNUM]; ! char *fp_str = (!frame_pointer_needed) ! ? sp_str ! : reg_names[FRAME_POINTER_REGNUM]; ! tree fndecl = current_function_decl; /* current... is tooo long */ ! tree fntype = TREE_TYPE (fndecl); ! tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE) ! ? DECL_ARGUMENTS (fndecl) ! : 0; ! tree next_arg; ! tree cur_arg; ! char *arg_name = (char *)0; ! CUMULATIVE_ARGS args_so_far; ASM_OUTPUT_SOURCE_FILENAME (file, DECL_SOURCE_FILE (current_function_decl)); --- 4036,4040 ---- int size; { ! int tsize = current_frame_info.total_size; ASM_OUTPUT_SOURCE_FILENAME (file, DECL_SOURCE_FILE (current_function_decl)); *************** *** 3972,3975 **** --- 4053,4095 ---- reg_names[ GP_REG_FIRST + 25 ]); + tsize = current_frame_info.total_size; + if (tsize > 0 && TARGET_ABICALLS) + fprintf (file, "\t.cprestore %d\n", tsize + STARTING_FRAME_OFFSET); + + fprintf (file, "\t.frame\t%s,%d,%s\t\t# vars= %d, regs= %d/%d, args = %d, extra= %d\n", + reg_names[ (frame_pointer_needed) ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM ], + tsize, + reg_names[31 + GP_REG_FIRST], + current_frame_info.var_size, + current_frame_info.num_gp, + current_frame_info.num_fp, + current_function_outgoing_args_size, + current_frame_info.extra_size); + + fprintf (file, "\t.mask\t0x%08lx,%d\n\t.fmask\t0x%08lx,%d\n", + current_frame_info.mask, + current_frame_info.gp_save_offset, + current_frame_info.fmask, + current_frame_info.fp_save_offset); + } + + + /* Expand the prologue into a bunch of separate insns. */ + + void + mips_expand_prologue () + { + int regno; + int tsize; + tree fndecl = current_function_decl; /* current... is tooo long */ + tree fntype = TREE_TYPE (fndecl); + tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE) + ? DECL_ARGUMENTS (fndecl) + : 0; + tree next_arg; + tree cur_arg; + char *arg_name = (char *)0; + CUMULATIVE_ARGS args_so_far; + /* Determine the last argument, and get its name. */ for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg) *************** *** 4031,4096 **** } ! if (regno <= GP_ARG_LAST && (regno & 1) != 0) { ! fprintf (file, "\tsw\t%s,%d(%s)\t\t# varargs home register\n", ! reg_names[regno], (regno - 4) * 4, sp_str); ! regno++; ! } ! for (; regno <= GP_ARG_LAST; regno += 2) ! { ! fprintf (file, "\tsd\t%s,%d(%s)\t\t# varargs home register\n", ! reg_names[regno], (regno - 4) * 4, sp_str); } } ! size = MIPS_STACK_ALIGN (size); ! tsize = (!current_frame_info.initialized) ! ? compute_frame_size (size) ! : current_frame_info.total_size; ! if (tsize > 0) { ! if (tsize <= 32767) ! fprintf (file, ! "\tsubu\t%s,%s,%d\t\t# vars= %d, regs= %d/%d, args = %d, extra= %d\n", ! sp_str, sp_str, tsize, current_frame_info.var_size, ! current_frame_info.gp_reg_size / 4, ! current_frame_info.fp_reg_size / 8, ! current_function_outgoing_args_size, ! current_frame_info.extra_size); ! else ! fprintf (file, ! "\tli\t%s,%d\n\tsubu\t%s,%s,%s\t\t# vars= %d, regs= %d/%d, args = %d, sfo= %d\n", ! reg_names[MIPS_TEMP1_REGNUM], tsize, sp_str, sp_str, ! reg_names[MIPS_TEMP1_REGNUM], current_frame_info.var_size, ! current_frame_info.gp_reg_size / 4, ! current_frame_info.fp_reg_size / 8, ! current_function_outgoing_args_size, ! current_frame_info.extra_size); ! } ! ! if (TARGET_ABICALLS) ! fprintf (file, "\t.cprestore %d\n", tsize + STARTING_FRAME_OFFSET); ! fprintf (file, "\t.frame\t%s,%d,%s\n\t.mask\t0x%08lx,%d\n\t.fmask\t0x%08lx,%d\n", ! fp_str, ! (frame_pointer_needed) ? 0 : tsize, ! reg_names[31 + GP_REG_FIRST], ! current_frame_info.mask, ! current_frame_info.gp_save_offset, ! current_frame_info.fmask, ! current_frame_info.fp_save_offset); ! save_restore (file, "sw", "sd", "s.d"); ! if (frame_pointer_needed) ! { ! if (tsize <= 32767) ! fprintf (file, "\taddu\t%s,%s,%d\t# set up frame pointer\n", fp_str, sp_str, tsize); ! else ! fprintf (file, "\taddu\t%s,%s,%s\t# set up frame pointer\n", fp_str, sp_str, ! reg_names[MIPS_TEMP1_REGNUM]); } } --- 4151,4183 ---- } ! for (; regno <= GP_ARG_LAST; regno++) { ! rtx ptr = stack_pointer_rtx; ! if (regno != GP_ARG_FIRST) ! ptr = gen_rtx (PLUS, Pmode, ptr, ! GEN_INT ((regno - GP_ARG_FIRST) * UNITS_PER_WORD)); ! emit_move_insn (gen_rtx (MEM, Pmode, ptr), gen_rtx (REG, Pmode, regno)); } } ! tsize = compute_frame_size (get_frame_size ()); if (tsize > 0) { ! rtx tsize_rtx = GEN_INT (tsize); ! if (tsize > 32767) ! { ! rtx tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM); ! emit_move_insn (tmp_rtx, tsize_rtx); ! tsize_rtx = tmp_rtx; ! } ! emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx)); ! save_restore_insns (TRUE); ! if (frame_pointer_needed) ! emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); } } *************** *** 4195,4207 **** if (frame_pointer_needed) ! { ! char *fp_str = reg_names[FRAME_POINTER_REGNUM]; ! if (tsize > 32767) ! fprintf (file,"\tsubu\t%s,%s,%s\t\t# sp not trusted here\n", ! sp_str, fp_str, t1_str); ! else ! fprintf (file,"\tsubu\t%s,%s,%d\t\t# sp not trusted here\n", ! sp_str, fp_str, tsize); ! } save_restore (file, "lw", "ld", "l.d"); --- 4282,4287 ---- if (frame_pointer_needed) ! fprintf (file, "\tmove\t%s,%s\t\t\t# sp not trusted here\n", ! sp_str, reg_names[FRAME_POINTER_REGNUM]); save_restore (file, "lw", "ld", "l.d"); *************** *** 4271,4274 **** --- 4351,4358 ---- int num_fp_regs = current_frame_info.fp_reg_size / 8; int num_regs = num_gp_regs + num_fp_regs; + char *name = current_function_name; + + if (name[0] == '*') + name++; dslots_load_total += num_regs; *************** *** 4293,4297 **** fprintf (stderr, "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3ld reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d", ! current_function_name, (frame_pointer_needed) ? 'y' : 'n', ((current_frame_info.mask & (1 << 31)) != 0) ? 'n' : 'y', --- 4377,4381 ---- fprintf (stderr, "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3ld reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d", ! name, (frame_pointer_needed) ? 'y' : 'n', ((current_frame_info.mask & (1 << 31)) != 0) ? 'n' : 'y', *************** *** 4305,4313 **** num_refs[0], num_refs[1], num_refs[2]); ! if (HALF_PIC_NUMBER_PTRS) ! fprintf (stderr, " half-pic=%3d", HALF_PIC_NUMBER_PTRS); ! if (HALF_PIC_NUMBER_REFS) ! fprintf (stderr, " pic-ref=%3d", HALF_PIC_NUMBER_REFS); fputc ('\n', stderr); --- 4389,4403 ---- num_refs[0], num_refs[1], num_refs[2]); ! if (HALF_PIC_NUMBER_PTRS > prev_half_pic_ptrs) ! { ! fprintf (stderr, " half-pic=%3d", HALF_PIC_NUMBER_PTRS - prev_half_pic_ptrs); ! prev_half_pic_ptrs = HALF_PIC_NUMBER_PTRS; ! } ! if (HALF_PIC_NUMBER_REFS > prev_half_pic_refs) ! { ! fprintf (stderr, " pic-ref=%3d", HALF_PIC_NUMBER_REFS - prev_half_pic_refs); ! prev_half_pic_refs = HALF_PIC_NUMBER_REFS; ! } fputc ('\n', stderr); *************** *** 4326,4330 **** mips_load_reg = (rtx)0; mips_load_reg2 = (rtx)0; - number_functions_processed++; current_frame_info = zero_frame_info; --- 4416,4419 ---- *************** *** 4338,4341 **** --- 4427,4459 ---- + /* Expand the epilogue into a bunch of separate insns. */ + + void + mips_expand_epilogue () + { + int tsize = current_frame_info.total_size; + rtx tsize_rtx = GEN_INT (tsize); + + if (tsize > 32767) + { + rtx tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM); + emit_move_insn (tmp_rtx, tsize_rtx); + tsize_rtx = tmp_rtx; + } + + if (tsize > 0) + { + if (frame_pointer_needed) + emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); + + save_restore_insns (FALSE); + + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx)); + } + + emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, GP_REG_FIRST+31))); + } + + /* Define the number of delay slots needed for the function epilogue. *************** *** 4364,4368 **** int ! null_epilogue () { if (!reload_completed) --- 4482,4486 ---- int ! simple_epilogue_p () { if (!reload_completed) *************** *** 4374,4376 **** return (compute_frame_size (get_frame_size ())) == 0; } - --- 4492,4493 ---- diff -rc2N gcc-2.2.2/config/mips.h gcc-2.3.1/config/mips.h *** gcc-2.2.2/config/mips.h Fri Jun 12 17:18:07 1992 --- gcc-2.3.1/config/mips.h Sat Oct 31 00:44:24 1992 *************** *** 29,38 **** /* Standard GCC variables that we reference. */ ! extern int target_flags; ! extern int optimize; ! extern int may_call_alloca; ! extern int current_function_calls_alloca; ! extern int frame_pointer_needed; ! extern int flag_omit_frame_pointer; /* MIPS external variables defined in mips.c. */ --- 29,43 ---- /* Standard GCC variables that we reference. */ ! extern char *asm_file_name; ! extern char call_used_regs[]; ! extern int current_function_calls_alloca; ! extern int flag_omit_frame_pointer; ! extern int frame_pointer_needed; ! extern char *language_string; ! extern int may_call_alloca; ! extern int optimize; ! extern char **save_argv; ! extern int target_flags; ! extern char *version_string; /* MIPS external variables defined in mips.c. */ *************** *** 126,129 **** --- 131,135 ---- extern int equality_op (); extern int fcmp_op (); + extern void final_prescan_insn (); extern int fpsw_register_operand (); extern struct rtx_def * function_arg (); *************** *** 140,148 **** extern void mips_asm_file_end (); extern void mips_asm_file_start (); - extern void mips_declare_object (); extern int mips_const_double_ok (); extern void mips_count_memory_refs (); extern int mips_debugger_offset (); extern int mips_epilogue_delay_slots (); extern char *mips_fill_delay_slot (); extern char *mips_move_1word (); --- 146,156 ---- extern void mips_asm_file_end (); extern void mips_asm_file_start (); extern int mips_const_double_ok (); extern void mips_count_memory_refs (); extern int mips_debugger_offset (); + extern void mips_declare_object (); extern int mips_epilogue_delay_slots (); + extern void mips_expand_epilogue (); + extern void mips_expand_prologue (); extern char *mips_fill_delay_slot (); extern char *mips_move_1word (); *************** *** 160,163 **** --- 168,172 ---- extern void print_options (); extern int reg_or_0_operand (); + extern int simple_epilogue_p (); extern int simple_memory_operand (); extern int small_int (); *************** *** 166,170 **** extern int uns_cmp_op (); ! /* Functions in varasm.c that we reference. */ extern void data_section (); extern void rdata_section (); --- 175,192 ---- extern int uns_cmp_op (); ! /* Recognition functions that return if a condition is true. */ ! extern int address_operand (); ! extern int const_double_operand (); ! extern int const_int_operand (); ! extern int general_operand (); ! extern int immediate_operand (); ! extern int memory_address_p (); ! extern int memory_operand (); ! extern int nonimmediate_operand (); ! extern int nonmemory_operand (); ! extern int register_operand (); ! extern int scratch_operand (); ! ! /* Functions to change what output section we are using. */ extern void data_section (); extern void rdata_section (); *************** *** 173,176 **** --- 195,215 ---- extern void text_section (); + /* Functions in the rest of the compiler that we reference. */ + extern void abort_with_insn (); + extern void debug_rtx (); + extern void fatal_io_error (); + extern int get_frame_size (); + extern int offsettable_address_p (); + extern void output_address (); + extern char *permalloc (); + extern int reg_mentioned_p (); + + /* Functions in the standard library that we reference. */ + extern void abort (); + extern int atoi (); + extern char *getenv (); + extern char *mktemp (); + + /* Stubs for half-pic support if not OSF/1 reference platform. */ *************** *** 334,338 **** #ifndef CPP_PREDEFINES ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43" #endif --- 373,378 ---- #ifndef CPP_PREDEFINES ! #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43 \ ! -D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_BSD43" #endif *************** *** 356,362 **** has run to stuff the mips debug information into the object file. This is needed because the $#!%^ MIPS assembler provides no way ! of specifying such information in the assembly file. */ #ifndef ASM_FINAL_SPEC #define ASM_FINAL_SPEC "\ %{!mgas: %{!mno-mips-tfile: \ --- 396,405 ---- has run to stuff the mips debug information into the object file. This is needed because the $#!%^ MIPS assembler provides no way ! of specifying such information in the assembly file. If we are ! cross compiling, disable mips-tfile unless the user specifies ! -mmips-tfile. */ #ifndef ASM_FINAL_SPEC + #ifndef CROSS_COMPILE #define ASM_FINAL_SPEC "\ %{!mgas: %{!mno-mips-tfile: \ *************** *** 364,371 **** %{K: -I %b.o~} \ %{!K: %{save-temps: -I %b.o~}} \ ! %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %b.o} \ %{.s:%i} %{!.s:%g.s}}}" ! #endif /* Redefinition of libraries used. Mips doesn't support normal UNIX style profiling via calling _mcount. It does offer --- 407,425 ---- %{K: -I %b.o~} \ %{!K: %{save-temps: -I %b.o~}} \ ! %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ %{.s:%i} %{!.s:%g.s}}}" ! ! #else /* CROSS_COMPILE */ ! #define ASM_FINAL_SPEC "\ ! %{!mgas: %{mmips-tfile: \ ! \n mips-tfile %{v*: -v} \ ! %{K: -I %b.o~} \ ! %{!K: %{save-temps: -I %b.o~}} \ ! %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ ! %{.s:%i} %{!.s:%g.s}}}" + #endif /* CROSS_COMPILE */ + #endif /* ASM_FINAL_SPEC */ + /* Redefinition of libraries used. Mips doesn't support normal UNIX style profiling via calling _mcount. It does offer *************** *** 386,392 **** %{EL: %e-EL not supported} \ %{mips1} %{mips2} %{mips3} \ ! %{bestGnum}}" #endif /* LINK_SPEC defined */ /* Specs for the compiler proper */ --- 440,452 ---- %{EL: %e-EL not supported} \ %{mips1} %{mips2} %{mips3} \ ! %{bestGnum} %{shared} %{non_shared}}" #endif /* LINK_SPEC defined */ + /* Define this macro meaning that `gcc' should find the library + `libgcc.a' by hand, rather than passing the argument `-lgcc' to + tell the linker to do the search. */ + + #define LINK_LIBGCC_SPECIAL 1 + /* Specs for the compiler proper */ *************** *** 429,433 **** /* Print subsidiary information on the compiler version in use. */ ! #define MIPS_VERSION "[AL 1.1, MM 19]" #ifndef MACHINE_TYPE --- 489,493 ---- /* Print subsidiary information on the compiler version in use. */ ! #define MIPS_VERSION "[AL 1.1, MM 28]" #ifndef MACHINE_TYPE *************** *** 607,612 **** sprintf ((BUFFER), ".%dfake", (NUMBER)); ! /* Correct the offset of automatic variables and arguments ! if the frame pointer has been eliminated. */ #define DEBUGGER_AUTO_OFFSET(X) mips_debugger_offset (X, 0) --- 667,676 ---- sprintf ((BUFFER), ".%dfake", (NUMBER)); ! /* Correct the offset of automatic variables and arguments. Note that ! the MIPS debug format wants all automatic variables and arguments ! to be in terms of the virtual frame pointer (stack pointer before ! any adjustment in the function), while the MIPS 3.0 linker wants ! the frame pointer to be the stack pointer after the initial ! adjustment. */ #define DEBUGGER_AUTO_OFFSET(X) mips_debugger_offset (X, 0) *************** *** 1137,1141 **** /* Register to use for pushing function arguments. */ ! #define STACK_POINTER_REGNUM 29 /* Offset from the stack pointer to the first available location. */ --- 1201,1205 ---- /* Register to use for pushing function arguments. */ ! #define STACK_POINTER_REGNUM (GP_REG_FIRST + 29) /* Offset from the stack pointer to the first available location. */ *************** *** 1143,1147 **** /* Base register for access to local variables of the function. */ ! #define FRAME_POINTER_REGNUM 30 /* Value should be nonzero if functions must have frame pointers. --- 1207,1211 ---- /* Base register for access to local variables of the function. */ ! #define FRAME_POINTER_REGNUM (GP_REG_FIRST + 30) /* Value should be nonzero if functions must have frame pointers. *************** *** 1152,1163 **** /* 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. */ ! #define STATIC_CHAIN_REGNUM 2 ! /* Register in which address to store a structure value ! is passed to a function. */ ! #define STRUCT_VALUE_REGNUM 4 /* Mips registers used in prologue/epilogue code when the stack frame --- 1216,1233 ---- /* Base register for access to arguments of the function. */ ! #define ARG_POINTER_REGNUM GP_REG_FIRST /* Register in which static-chain is passed to a function. */ ! #define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2) ! /* If the structure value address is passed in a register, then ! `STRUCT_VALUE_REGNUM' should be the number of that register. */ ! /* #define STRUCT_VALUE_REGNUM (GP_REG_FIRST + 4) */ ! ! /* If the structure value address is not passed in a register, define ! `STRUCT_VALUE' as an expression returning an RTX for the place ! where the address is passed. If it returns 0, the address is ! passed as an "invisible" first argument. */ ! #define STRUCT_VALUE ((rtx)0) /* Mips registers used in prologue/epilogue code when the stack frame *************** *** 1166,1171 **** arguments and any other information used in the calling sequence (such as pic). */ ! #define MIPS_TEMP1_REGNUM 8 ! #define MIPS_TEMP2_REGNUM 9 /* Define this macro if it is as good or better to call a constant --- 1236,1241 ---- arguments and any other information used in the calling sequence (such as pic). */ ! #define MIPS_TEMP1_REGNUM (GP_REG_FIRST + 8) ! #define MIPS_TEMP2_REGNUM (GP_REG_FIRST + 9) /* Define this macro if it is as good or better to call a constant *************** *** 1185,1189 **** 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 28 --- 1255,1259 ---- 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 (GP_REG_FIRST + 28) *************** *** 1257,1262 **** { 0xffffffff, 0x00000000, 0x00000000 }, /* integer registers */ \ { 0x00000000, 0xffffffff, 0x00000000 }, /* floating registers*/ \ ! { 0x00000000, 0x00000000, 0x00000001 }, /* lo register */ \ ! { 0x00000000, 0x00000000, 0x00000002 }, /* hi register */ \ { 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \ { 0x00000000, 0x00000000, 0x00000004 }, /* status registers */ \ --- 1327,1332 ---- { 0xffffffff, 0x00000000, 0x00000000 }, /* integer registers */ \ { 0x00000000, 0xffffffff, 0x00000000 }, /* floating registers*/ \ ! { 0x00000000, 0x00000000, 0x00000001 }, /* hi register */ \ ! { 0x00000000, 0x00000000, 0x00000002 }, /* lo register */ \ { 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \ { 0x00000000, 0x00000000, 0x00000004 }, /* status registers */ \ *************** *** 1343,1352 **** : (C) == 'K' ? ((unsigned) (VALUE) < 0x10000) \ : (C) == 'L' ? (((VALUE) & 0xffff0000) == (VALUE)) \ ! : (C) == 'M' ? ((((VALUE) & 0xffff0000) != 0) \ ! && (((VALUE) & 0xffff0000) != 0xffff0000) \ && ((VALUE) & 0x0000ffff) != 0) \ ! : (C) == 'N' ? (((VALUE) & 0xffff0000) == 0xffff0000) \ : (C) == 'O' ? (exact_log2 (VALUE) >= 0) \ ! : (C) == 'P' ? ((VALUE) != 0 && (((VALUE) & 0xffff0000) == 0)) \ : 0) --- 1413,1422 ---- : (C) == 'K' ? ((unsigned) (VALUE) < 0x10000) \ : (C) == 'L' ? (((VALUE) & 0xffff0000) == (VALUE)) \ ! : (C) == 'M' ? ((((VALUE) & ~0x0000ffff) != 0) \ ! && (((VALUE) & ~0x0000ffff) != ~0x0000ffff) \ && ((VALUE) & 0x0000ffff) != 0) \ ! : (C) == 'N' ? (((VALUE) & ~0x0000ffff) == ~0x0000ffff) \ : (C) == 'O' ? (exact_log2 (VALUE) >= 0) \ ! : (C) == 'P' ? ((VALUE) != 0 && (((VALUE) & ~0x0000ffff) == 0)) \ : 0) *************** *** 1394,1397 **** --- 1464,1482 ---- : CLASS)) + /* Certain machines have the property that some registers cannot be + copied to some other registers without using memory. Define this + macro on those machines to be a C expression that is non-zero if + objects of mode MODE in registers of CLASS1 can only be copied to + registers of class CLASS2 by storing a register of CLASS1 into + memory and loading that memory location into a register of CLASS2. + + Do not define this macro if its value would always be zero. */ + + #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ + (!TARGET_DEBUG_H_MODE \ + && GET_MODE_CLASS (MODE) == MODE_INT \ + && ((CLASS1 == FP_REGS && CLASS2 == GR_REGS) \ + || (CLASS1 == GR_REGS && CLASS2 == FP_REGS))) + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. */ *************** *** 1426,1430 **** 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. --- 1511,1515 ---- 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. *************** *** 1432,1436 **** first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ ! #define STARTING_FRAME_OFFSET (-8) /* Structure to be filled in by compute_frame_size with register --- 1517,1544 ---- first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ ! #define STARTING_FRAME_OFFSET current_function_outgoing_args_size ! ! /* Offset from the stack pointer register to an item dynamically ! allocated on the stack, e.g., by `alloca'. ! ! The default value for this macro is `STACK_POINTER_OFFSET' plus the ! length of the outgoing arguments. The default is correct for most ! machines. See `function.c' for details. ! ! The MIPS ABI states that functions which dynamically allocate the ! stack must not have 0 for STACK_DYNAMIC_OFFSET, since it looks like ! we are trying to create a second frame pointer to the function, so ! allocate some stack space to make it happy. ! ! However, the linker currently complains about linking any code that ! dynamically allocates stack space, and there seems to be a bug in ! STACK_DYNAMIC_OFFSET, so don't define this right now. */ ! ! #if 0 ! #define STACK_DYNAMIC_OFFSET(FUNDECL) \ ! ((current_function_outgoing_args_size == 0 && current_function_calls_alloca) \ ! ? 4*UNITS_PER_WORD \ ! : current_function_outgoing_args_size) ! #endif /* Structure to be filled in by compute_frame_size with register *************** *** 1452,1455 **** --- 1560,1565 ---- unsigned long fp_sp_offset; /* offset from new sp to store fp registers */ int initialized; /* != 0 if frame size already calculated */ + int num_gp; /* number of gp registers saved */ + int num_fp; /* number of fp registers saved */ }; *************** *** 1461,1467 **** of the fixed parts of the stack frame and on how registers are saved. */ ! #define INITIAL_FRAME_POINTER_OFFSET(VAR) \ ! ((VAR) = compute_frame_size (get_frame_size ())) /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. --- 1571,1638 ---- of the fixed parts of the stack frame and on how registers are saved. */ ! /* #define INITIAL_FRAME_POINTER_OFFSET(VAR) \ ! ((VAR) = compute_frame_size (get_frame_size ())) */ + /* 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 \ + {{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_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) \ + (!frame_pointer_needed \ + || ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)) + + /* 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) \ + { 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) = current_frame_info.total_size; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = current_frame_info.total_size; \ + else \ + abort (); \ + } + + /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. *************** *** 1480,1493 **** #define ACCUMULATE_OUTGOING_ARGS ! /* Offset of first parameter from the argument pointer register value. */ #define FIRST_PARM_OFFSET(FNDECL) 0 ! ! /* Offset from top-of-stack address to location to store the ! function parameter if it can't go in a register. ! Addresses for following parameters are computed relative to this one. ! ! It also has the effect of counting register arguments in the total ! argument size. */ ! #define FIRST_PARM_CALLER_OFFSET(FNDECL) 0 /* When a parameter is passed in a register, stack space is still --- 1651,1678 ---- #define ACCUMULATE_OUTGOING_ARGS ! /* Offset from the argument pointer register to the first argument's ! address. On some machines it may depend on the data type of the ! function. ! ! If `ARGS_GROW_DOWNWARD', this is the offset to the location above ! the first argument's address. ! ! On the MIPS, we must skip the first argument position if we are ! returning a structure or a union, to account for it's address being ! passed in $4. However, at the current time, this produces a compiler ! that can't bootstrap, so comment it out for now. */ ! ! #if 0 ! #define FIRST_PARM_OFFSET(FNDECL) \ ! (FNDECL != 0 \ ! && TREE_TYPE (FNDECL) != 0 \ ! && TREE_TYPE (TREE_TYPE (FNDECL)) != 0 \ ! && (TREE_CODE (TREE_TYPE (TREE_TYPE (FNDECL))) == RECORD_TYPE \ ! || TREE_CODE (TREE_TYPE (TREE_TYPE (FNDECL))) == UNION_TYPE) \ ! ? UNITS_PER_WORD \ ! : 0) ! #else #define FIRST_PARM_OFFSET(FNDECL) 0 ! #endif /* When a parameter is passed in a register, stack space is still *************** *** 1499,1503 **** are a0 (a2,a3), but we should push over a1... */ ! #define REG_PARM_STACK_SPACE(FNDECL) (4*4) /* Define this if it is the responsibility of the caller to --- 1684,1688 ---- are a0 (a2,a3), but we should push over a1... */ ! #define REG_PARM_STACK_SPACE(FNDECL) ((4*UNITS_PER_WORD) - FIRST_PARM_OFFSET (FNDECL)) /* Define this if it is the responsibility of the caller to *************** *** 1719,1723 **** && get_attr_length (INSN) == 1 \ && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (INSN)) \ ! && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (INSN))) /* Tell prologue and epilogue if register REGNO should be saved / restored. */ --- 1904,1909 ---- && get_attr_length (INSN) == 1 \ && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (INSN)) \ ! && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (INSN)) \ ! && ! reg_mentioned_p (arg_pointer_rtx, PATTERN (INSN))) /* Tell prologue and epilogue if register REGNO should be saved / restored. */ *************** *** 1726,1734 **** ((regs_ever_live[regno] && !call_used_regs[regno]) \ || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \ ! || (regno == 31 && regs_ever_live[31])) /* ALIGN FRAMES on double word boundaries */ ! #define MIPS_STACK_ALIGN(LOC) (((LOC)+7) & 0xfffffff8) --- 1912,1920 ---- ((regs_ever_live[regno] && !call_used_regs[regno]) \ || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \ ! || (regno == (GP_REG_FIRST + 31) && regs_ever_live[GP_REG_FIRST + 31])) /* ALIGN FRAMES on double word boundaries */ ! #define MIPS_STACK_ALIGN(LOC) (((LOC)+7) & ~7) *************** *** 2227,2231 **** case CONST: \ { \ - extern rtx eliminate_constant_term (); \ rtx offset = const0_rtx; \ rtx symref = eliminate_constant_term (X, &offset); \ --- 2413,2416 ---- *************** *** 2505,2549 **** #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ ! do \ ! { \ ! if (dslots_number_nops > 0 && mips_load_reg != (rtx)0) \ ! { \ ! enum machine_mode mode = GET_MODE (mips_load_reg); \ ! rtx pattern = PATTERN (INSN); \ ! \ ! if (reg_mentioned_p (mips_load_reg, pattern) \ ! || (mips_load_reg2 != (rtx)0 \ ! && reg_mentioned_p (mips_load_reg2, pattern)) \ ! || (mips_load_reg3 != (rtx)0 \ ! && reg_mentioned_p (mips_load_reg3, pattern)) \ ! || (mips_load_reg4 != (rtx)0 \ ! && reg_mentioned_p (mips_load_reg4, pattern)) \ ! || get_attr_length (INSN) == 0) \ ! { \ ! fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file); \ ! } \ ! else \ ! dslots_load_filled++; \ ! \ ! while (--dslots_number_nops > 0) \ ! fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file); \ ! \ ! mips_load_reg = (rtx)0; \ ! mips_load_reg2 = (rtx)0; \ ! mips_load_reg3 = (rtx)0; \ ! mips_load_reg4 = (rtx)0; \ ! \ ! if (set_noreorder && --set_noreorder == 0) \ ! fputs ("\t.set\treorder\n", asm_out_file); \ ! } \ ! \ ! if (TARGET_STATS) \ ! { \ ! enum rtx_code code = GET_CODE (INSN); \ ! if (code == JUMP_INSN || code == CALL_INSN) \ ! dslots_jump_total++; \ ! } \ ! } \ ! while (0) --- 2690,2694 ---- #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ ! final_prescan_insn (INSN, OPVEC, NOPERANDS) *************** *** 2593,2597 **** operation code OP is applied to rtx X. */ ! #define SELECT_CC_MODE(OP, X) \ (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ ? SImode \ --- 2738,2742 ---- operation code OP is applied to rtx X. */ ! #define SELECT_CC_MODE(OP, X, Y) \ (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ ? SImode \ *************** *** 2699,2702 **** --- 2844,2862 ---- } + /* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c. + So define this for it. */ + #define DEBUG_REGISTER_NAMES \ + { \ + "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", \ + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \ + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \ + "t8", "t9", "k0", "k1", "gp", "sp", "$fp", "ra", \ + "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", \ + "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \ + "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \ + "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \ + "hi", "lo", "$fcr31" \ + } + /* If defined, a C initializer for an array of structures containing a name and a register number. This macro defines *************** *** 2898,2903 **** $Lc[0-9]+ Label for use in s operation. $Le[0-9]+ End blocks for MIPS debug support ! $Lp\..+ Half-pic labels. ! $Ls[0-9]+ FP-SP difference if -fomit-frame-pointer */ /* This is how to output the definition of a user-level label named NAME, --- 3058,3062 ---- $Lc[0-9]+ Label for use in s operation. $Le[0-9]+ End blocks for MIPS debug support ! $Lp\..+ Half-pic labels. */ /* This is how to output the definition of a user-level label named NAME, *************** *** 3218,3224 **** and select that section. */ ! #define SELECT_SECTION_MODE(MODE,RTX) \ { \ - extern int mips_section_threshold; \ if ((GET_MODE_SIZE(MODE) / BITS_PER_UNIT) <= mips_section_threshold \ && mips_section_threshold > 0) \ --- 3377,3382 ---- and select that section. */ ! #define SELECT_RTX_SECTION(MODE,RTX) \ { \ if ((GET_MODE_SIZE(MODE) / BITS_PER_UNIT) <= mips_section_threshold \ && mips_section_threshold > 0) \ *************** *** 3230,3234 **** #define SELECT_SECTION(DECL,RELOC) \ { \ - extern int mips_section_threshold; \ if (int_size_in_bytes (TREE_TYPE (DECL)) <= mips_section_threshold \ && mips_section_threshold > 0) \ --- 3388,3391 ---- *************** *** 3311,3313 **** #define MIPS_MARK_STAB(code) ((code)+CODE_MASK) #define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK) - --- 3468,3469 ---- diff -rc2N gcc-2.2.2/config/mips.md gcc-2.3.1/config/mips.md *** gcc-2.2.2/config/mips.md Fri Jun 12 17:19:09 1992 --- gcc-2.3.1/config/mips.md Sat Oct 31 00:44:38 1992 *************** *** 52,59 **** ;; multi multiword sequence (or user asm statements) ;; nop no operation - ;; pic OSF/rose half pic load (define_attr "type" ! "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop,pic" (const_string "unknown")) --- 52,58 ---- ;; multi multiword sequence (or user asm statements) ;; nop no operation (define_attr "type" ! "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop" (const_string "unknown")) *************** *** 66,70 **** ;; whether or not an instruction has a mandatory delay slot (define_attr "dslot" "no,yes" ! (if_then_else (eq_attr "type" "branch,jump,call,load,xfer,hilo,fcmp,pic") (const_string "yes") (const_string "no"))) --- 65,69 ---- ;; whether or not an instruction has a mandatory delay slot (define_attr "dslot" "no,yes" ! (if_then_else (eq_attr "type" "branch,jump,call,load,xfer,hilo,fcmp") (const_string "yes") (const_string "no"))) *************** *** 125,138 **** ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY ! ; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST]) ;; Make the default case (PROCESSOR_DEFAULT) handle the worst case (define_function_unit "memory" 1 0 ! (and (eq_attr "type" "load,pic") (eq_attr "cpu" "!r3000")) 3 0) (define_function_unit "memory" 1 0 ! (and (eq_attr "type" "load,pic") (eq_attr "cpu" "r3000")) 2 0) --- 124,137 ---- ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY ! ; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) ;; Make the default case (PROCESSOR_DEFAULT) handle the worst case (define_function_unit "memory" 1 0 ! (and (eq_attr "type" "load") (eq_attr "cpu" "!r3000")) 3 0) (define_function_unit "memory" 1 0 ! (and (eq_attr "type" "load") (eq_attr "cpu" "r3000")) 2 0) *************** *** 146,241 **** (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "!r3000,r4000")) ! 17 34) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000")) ! 12 24) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r4000")) ! 10 20) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "!r3000,r4000")) ! 38 76) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000")) ! 35 70) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000")) ! 69 138) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r6000")) ! 4 8) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000")) ! 2 4) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r6000")) ! 3 6) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "!r3000")) ! 2 4) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000")) ! 1 2) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) ! 7 14) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) ! 4 8) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) ! 5 10) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) ! 8 16) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) ! 5 10) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) ! 6 12) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) ! 23 46) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) ! 12 24) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) ! 15 30) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) ! 36 72) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) ! 19 34) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) ! 16 32) ! (define_function_unit "divide" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 108) ! (define_function_unit "divide" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 224) --- 145,240 ---- (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "!r3000,r4000")) ! 17 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000")) ! 12 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r4000")) ! 10 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "!r3000,r4000")) ! 38 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000")) ! 35 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000")) ! 69 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r6000")) ! 4 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000")) ! 2 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r6000")) ! 3 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "!r3000")) ! 2 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000")) ! 1 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) ! 7 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) ! 4 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) ! 5 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) ! 8 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) ! 5 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) ! 6 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) ! 23 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) ! 12 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) ! 15 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) ! 36 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) ! 19 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) ! 16 0) ! (define_function_unit "divide" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0) ! (define_function_unit "divide" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0) *************** *** 243,268 **** ;; much less memory in genattrtab.c. ! ;; (define_function_unit "memory" 1 0 (eq_attr "type" "load,pic") 3 0) ! ;; (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) ;; ! ;; (define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0) ;; ! ;; (define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0) ! ;; (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0) ;; ! ;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "imul") 17 34) ! ;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "idiv") 38 76) ;; ! ;; (define_function_unit "adder" 1 1 (eq_attr "type" "fadd") 4 8) ! ;; (define_function_unit "adder" 1 1 (eq_attr "type" "fabs,fneg") 2 4) ;; ! ;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "SF")) 7 14) ! ;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "DF")) 8 16) ;; ! ;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "SF")) 23 46) ! ;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "DF")) 36 72) ;; ! ;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 108) ! ;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 224) --- 242,267 ---- ;; much less memory in genattrtab.c. ! ;; (define_function_unit "memory" 1 0 (eq_attr "type" "load") 3 0) ! ;; (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) ;; ! ;; (define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0) ;; ! ;; (define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0) ! ;; (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0) ;; ! ;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "imul") 17 0) ! ;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "idiv") 38 0) ;; ! ;; (define_function_unit "adder" 1 1 (eq_attr "type" "fadd") 4 0) ! ;; (define_function_unit "adder" 1 1 (eq_attr "type" "fabs,fneg") 2 0) ;; ! ;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "SF")) 7 0) ! ;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "DF")) 8 0) ;; ! ;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "SF")) 23 0) ! ;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "DF")) 36 0) ;; ! ;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0) ! ;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0) *************** *** 295,308 **** (set_attr "length" "1")]) ! (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=d") ! (plus:SI (match_operand:SI 1 "arith_operand" "%d") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) ! ? \"subu\\t%0,%1,%n2\" ! : \"addu\\t%0,%1,%2\"; }" [(set_attr "type" "arith") --- 294,318 ---- (set_attr "length" "1")]) ! (define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "=d") ! (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "arith_operand" "dI")))] "" + " + { + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768) + operands[2] = force_reg (SImode, operands[2]); + }") + + (define_insn "addsi3_internal" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") + (match_operand:SI 2 "arith_operand" "dI")))] + "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768" "* { return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) ! ? \"subu\\t%0,%z1,%n2\" ! : \"addu\\t%0,%z1,%2\"; }" [(set_attr "type" "arith") *************** *** 487,495 **** (set_attr "length" "1")]) ! (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=d") (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { --- 497,516 ---- (set_attr "length" "1")]) ! (define_expand "subsi3" [(set (match_operand:SI 0 "register_operand" "=d") (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "arith_operand" "dI")))] "" + " + { + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768) + operands[2] = force_reg (SImode, operands[2]); + }") + + (define_insn "subsi3_internal" + [(set (match_operand:SI 0 "register_operand" "=d") + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") + (match_operand:SI 2 "arith_operand" "dI")))] + "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768" "* { *************** *** 1149,1170 **** ;; - ;; Be more liberal in allowing logical operations than the machine actually - ;; supports. This causes better code to be generated for bitfields, since - ;; the optimizer can fold things together, at the expense of not moving the - ;; constant out of loops. - (define_insn "andsi3" ! [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") ! (and:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") ! (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] "" "@ and\\t%0,%1,%2 ! andi\\t%0,%1,%x2 ! %[li\\t%@,%X2\;and\\t%0,%1,%@%] ! %[li\\t%@,%X2\;and\\t%0,%1,%@%]" ! [(set_attr "type" "arith,arith,multi,multi") (set_attr "mode" "SI") ! (set_attr "length" "1,1,2,3")]) (define_insn "anddi3" --- 1170,1184 ---- ;; (define_insn "andsi3" ! [(set (match_operand:SI 0 "register_operand" "=d,d") ! (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") ! (match_operand:SI 2 "uns_arith_operand" "d,K")))] "" "@ and\\t%0,%1,%2 ! andi\\t%0,%1,%x2" ! [(set_attr "type" "arith") (set_attr "mode" "SI") ! (set_attr "length" "1")]) (define_insn "anddi3" *************** *** 1192,1207 **** (define_insn "iorsi3" ! [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") ! (ior:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") ! (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] "" "@ or\\t%0,%1,%2 ! ori\\t%0,%1,%x2 ! %[li\\t%@,%X2\;or\\t%0,%1,%@%] ! %[li\\t%@,%X2\;or\\t%0,%1,%@%]" ! [(set_attr "type" "arith,arith,multi,multi") (set_attr "mode" "SI") ! (set_attr "length" "1,1,2,3")]) (define_insn "iordi3" --- 1206,1219 ---- (define_insn "iorsi3" ! [(set (match_operand:SI 0 "register_operand" "=d,d") ! (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") ! (match_operand:SI 2 "uns_arith_operand" "d,K")))] "" "@ or\\t%0,%1,%2 ! ori\\t%0,%1,%x2" ! [(set_attr "type" "arith") (set_attr "mode" "SI") ! (set_attr "length" "1")]) (define_insn "iordi3" *************** *** 1229,1244 **** (define_insn "xorsi3" ! [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") ! (xor:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") ! (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] "" "@ xor\\t%0,%1,%2 ! xori\\t%0,%1,%x2 ! %[li\\t%@,%X2\;xor\\t%0,%1,%@%] ! %[li\\t%@,%X2\;xor\\t%0,%1,%@%]" ! [(set_attr "type" "arith,arith,multi,multi") (set_attr "mode" "SI") ! (set_attr "length" "1,1,2,3")]) (define_insn "xordi3" --- 1241,1254 ---- (define_insn "xorsi3" ! [(set (match_operand:SI 0 "register_operand" "=d,d") ! (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") ! (match_operand:SI 2 "uns_arith_operand" "d,K")))] "" "@ xor\\t%0,%1,%2 ! xori\\t%0,%1,%x2" ! [(set_attr "type" "arith") (set_attr "mode" "SI") ! (set_attr "length" "1")]) (define_insn "xordi3" *************** *** 1466,1474 **** ;; .................... ! (define_insn "fix_truncdfsi2_internal" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) ! (clobber (match_operand:SI 2 "register_operand" "d,*d,d,d")) ! (clobber (match_operand:DF 3 "register_operand" "f,*f,f,f"))] "TARGET_HARD_FLOAT" "* --- 1476,1484 ---- ;; .................... ! (define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) ! (clobber (match_scratch:SI 2 "=d,*d,d,d")) ! (clobber (match_scratch:DF 3 "=f,*X,f,f"))] "TARGET_HARD_FLOAT" "* *************** *** 1488,1513 **** [(set_attr "type" "fcvt") (set_attr "mode" "DF") ! (set_attr "length" "14,12,13,14")]) ! ! ! (define_expand "fix_truncdfsi2" ! [(parallel [(set (match_operand:SI 0 "register_operand" "=d") ! (fix:SI (match_operand:DF 1 "register_operand" "f"))) ! (clobber (match_dup 2)) ! (clobber (match_dup 3))])] ! "TARGET_HARD_FLOAT" ! " ! { ! operands[2] = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */ ! operands[3] = gen_reg_rtx (DFmode); /* fp reg that gets the conversion */ - /* Fall through and generate default code */ - }") ! (define_insn "fix_truncsfsi2_internal" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) ! (clobber (match_operand:SI 2 "register_operand" "d,*d,d,d")) ! (clobber (match_operand:SF 3 "register_operand" "f,*f,f,f"))] "TARGET_HARD_FLOAT" "* --- 1498,1509 ---- [(set_attr "type" "fcvt") (set_attr "mode" "DF") ! (set_attr "length" "11,9,10,11")]) ! (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) ! (clobber (match_scratch:SI 2 "=d,*d,d,d")) ! (clobber (match_scratch:SF 3 "=f,*X,f,f"))] "TARGET_HARD_FLOAT" "* *************** *** 1527,1546 **** [(set_attr "type" "fcvt") (set_attr "mode" "SF") ! (set_attr "length" "14,12,13,14")]) ! ! ! (define_expand "fix_truncsfsi2" ! [(parallel [(set (match_operand:SI 0 "register_operand" "=f") ! (fix:SI (match_operand:SF 1 "register_operand" "f"))) ! (clobber (match_dup 2)) ! (clobber (match_dup 3))])] ! "TARGET_HARD_FLOAT" ! " ! { ! operands[2] = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */ ! operands[3] = gen_reg_rtx (SFmode); /* fp reg that gets the conversion */ ! ! /* Fall through and generate default code */ ! }") --- 1523,1527 ---- [(set_attr "type" "fcvt") (set_attr "mode" "SF") ! (set_attr "length" "11,9,10,11")]) *************** *** 1561,1564 **** --- 1542,1546 ---- (set_attr "length" "3,4,3")]) + (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f,f,f") *************** *** 1593,1597 **** if (reg1) /* turn off complaints about unreached code */ { - extern rtx gen_cmpdf (); emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); do_pending_stack_adjust (); --- 1575,1578 ---- *************** *** 1621,1624 **** --- 1602,1606 ---- }") + (define_expand "fixuns_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "") *************** *** 1636,1640 **** if (reg1) /* turn off complaints about unreached code */ { - extern rtx gen_cmpsf (); emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); do_pending_stack_adjust (); --- 1618,1621 ---- *************** *** 1680,1686 **** " { - extern rtx gen_movsi_ulw (); - extern rtx gen_movsi (); - /* Handle loads. */ if (GET_CODE (operands[0]) == MEM) --- 1661,1664 ---- *************** *** 1715,1719 **** "* { - extern rtx eliminate_constant_term (); enum rtx_code code; char *ret; --- 1693,1696 ---- *************** *** 1766,1770 **** "* { - extern rtx eliminate_constant_term (); rtx offset = const0_rtx; rtx addr = XEXP (operands[0], 0); --- 1743,1746 ---- *************** *** 1799,1802 **** --- 1775,1779 ---- (set_attr "length" "2,4")]) + ;; 64-bit integer moves *************** *** 1805,1812 **** ;; the compiler, have memoized the insn number already. ! (define_insn "movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*d,*x") (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,*x,*d"))] ! "" "* return mips_move_2words (operands, insn); " [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo") --- 1782,1810 ---- ;; the compiler, have memoized the insn number already. ! (define_expand "movdi" ! [(set (match_operand:DI 0 "nonimmediate_operand" "") ! (match_operand:DI 1 "general_operand" ""))] ! "" ! " ! { ! if ((reload_in_progress | reload_completed) == 0 ! && !register_operand (operands[0], DImode) ! && !register_operand (operands[1], DImode) ! && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) ! && operands[1] != CONST0_RTX (DImode)) ! { ! rtx temp = force_reg (DImode, operands[1]); ! emit_move_insn (operands[0], temp); ! DONE; ! } ! }") ! ! (define_insn "movdi_internal" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*d,*x") (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,*x,*d"))] ! "register_operand (operands[0], DImode) ! || register_operand (operands[1], DImode) ! || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) ! || operands[1] == CONST0_RTX (DImode)" "* return mips_move_2words (operands, insn); " [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo") *************** *** 1853,1881 **** " { ! /* If this is a half-pic address being moved to a register, convert the ! address into a load, so that scheduling and stuff works properly. */ ! ! if (HALF_PIC_P() ! && GET_CODE (operands[0]) == REG ! && GET_CODE (operands[1]) == SYMBOL_REF ! && HALF_PIC_ADDRESS_P (operands[1])) { ! rtx ptr = HALF_PIC_PTR (operands[1]); ! if (XSTR (ptr, 0) != XSTR (operands[1], 0)) ! { ! emit_move_insn (operands[0], gen_rtx (MEM, Pmode, ptr)); ! DONE; ! } } }") ! (define_insn "movsi_internal" ! [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*fz,*f,*f,*f,*R,*m,*x,*d") ! (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*fz,*d,*f,*R,*m,*f,*f,*d,*x"))] ! "" "* return mips_move_1word (operands, insn, TRUE);" ! [(set_attr "type" "move,pic,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo") (set_attr "mode" "SI") ! (set_attr "length" "1,4,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1")]) ;; 16-bit Integer moves --- 1851,1892 ---- " { ! if ((reload_in_progress | reload_completed) == 0 ! && !register_operand (operands[0], SImode) ! && !register_operand (operands[1], SImode) ! && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)) { ! rtx temp = force_reg (SImode, operands[1]); ! emit_move_insn (operands[0], temp); ! DONE; } }") ! ;; The difference between these two is whether or not ints are allowed ! ;; in FP registers (off by default, use -mdebugh to enable). ! ! (define_insn "movsi_internal1" ! [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*d") ! (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,*d,*x"))] ! "TARGET_DEBUG_H_MODE ! && (register_operand (operands[0], SImode) ! || register_operand (operands[1], SImode) ! || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" ! "* return mips_move_1word (operands, insn, TRUE);" ! [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo") ! (set_attr "mode" "SI") ! (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1")]) ! ! (define_insn "movsi_internal2" ! [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*d,*x") ! (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,*x,*d"))] ! "!TARGET_DEBUG_H_MODE ! && (register_operand (operands[0], SImode) ! || register_operand (operands[1], SImode) ! || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, TRUE);" ! [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo") (set_attr "mode" "SI") ! (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,1")]) ! ;; 16-bit Integer moves *************** *** 1886,1893 **** ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined ! (define_insn "movhi" ! [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d") ! (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*fz,*d,*f,*d,*x"))] "" "* return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") --- 1897,1927 ---- ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined ! (define_expand "movhi" ! [(set (match_operand:HI 0 "nonimmediate_operand" "") ! (match_operand:HI 1 "general_operand" ""))] "" + " + { + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], HImode) + && !register_operand (operands[1], HImode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)) + { + rtx temp = force_reg (HImode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } + }") + + ;; The difference between these two is whether or not ints are allowed + ;; in FP registers (off by default, use -mdebugh to enable). + + (define_insn "movhi_internal1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x,*d") + (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] + "TARGET_DEBUG_H_MODE + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") *************** *** 1895,1898 **** --- 1929,1945 ---- (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) + (define_insn "movhi_internal2" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") + (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] + "!TARGET_DEBUG_H_MODE + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + "* return mips_move_1word (operands, insn, TRUE);" + [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") + (set_attr "mode" "HI") + (set_attr "length" "1,1,1,2,1,2,1,1,1,1")]) + + ;; 8-bit Integer moves *************** *** 1902,1909 **** ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined ! (define_insn "movqi" ! [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d") ! (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*fz,*d,*f,*d,*x"))] "" "* return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") --- 1949,1979 ---- ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined ! (define_expand "movqi" ! [(set (match_operand:QI 0 "nonimmediate_operand" "") ! (match_operand:QI 1 "general_operand" ""))] "" + " + { + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], QImode) + && !register_operand (operands[1], QImode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)) + { + rtx temp = force_reg (QImode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } + }") + + ;; The difference between these two is whether or not ints are allowed + ;; in FP registers (off by default, use -mdebugh to enable). + + (define_insn "movqi_internal1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d") + (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] + "TARGET_DEBUG_H_MODE + && (register_operand (operands[0], QImode) + || register_operand (operands[1], QImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") *************** *** 1911,1921 **** (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) ;; 32-bit floating point moves ! (define_insn "movsf" ! [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") ! (match_operand:SF 1 "general_operand" "f,G,R,Em,fG,fG,*d,*f,*Gd,*R,*Em,*d,*d"))] "" "* return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "move,xfer,load,load,store,store,xfer,xfer,move,load,load,store,store") --- 1981,2024 ---- (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) + (define_insn "movqi_internal2" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") + (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] + "!TARGET_DEBUG_H_MODE + && (register_operand (operands[0], QImode) + || register_operand (operands[1], QImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + "* return mips_move_1word (operands, insn, TRUE);" + [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") + (set_attr "mode" "QI") + (set_attr "length" "1,1,1,2,1,2,1,1,1,1")]) + ;; 32-bit floating point moves ! (define_expand "movsf" ! [(set (match_operand:SF 0 "nonimmediate_operand" "") ! (match_operand:SF 1 "general_operand" ""))] "" + " + { + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], SFmode) + && !register_operand (operands[1], SFmode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) + && operands[1] != CONST0_RTX (SFmode)) + { + rtx temp = force_reg (SFmode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } + }") + + (define_insn "movsf_internal" + [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") + (match_operand:SF 1 "general_operand" "f,G,R,Em,fG,fG,*d,*f,*G*d,*R,*E*m,*d,*d"))] + "register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (SFmode)" "* return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "move,xfer,load,load,store,store,xfer,xfer,move,load,load,store,store") *************** *** 1923,1932 **** (set_attr "length" "1,1,1,2,1,2,1,1,1,1,2,1,2")]) ;; 64-bit floating point moves ! (define_insn "movdf" ! [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,o,f,*f,*d,*d,*d,*d,*R,*o") ! (match_operand:DF 1 "general_operand" "f,R,o,fG,fG,E,*d,*f,*dG,*R,*oE,*d,*d"))] "" "* return mips_move_2words (operands, insn); " [(set_attr "type" "move,load,load,store,store,load,xfer,xfer,move,load,load,store,store") --- 2026,2057 ---- (set_attr "length" "1,1,1,2,1,2,1,1,1,1,2,1,2")]) + ;; 64-bit floating point moves ! (define_expand "movdf" ! [(set (match_operand:DF 0 "nonimmediate_operand" "") ! (match_operand:DF 1 "general_operand" ""))] "" + " + { + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], DFmode) + && !register_operand (operands[1], DFmode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) + && operands[1] != CONST0_RTX (DFmode)) + { + rtx temp = force_reg (DFmode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } + }") + + (define_insn "movdf_internal" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,o,f,*f,*d,*d,*d,*d,*R,*o") + (match_operand:DF 1 "general_operand" "f,R,o,fG,fG,E,*d,*f,*d*G,*R,*o*E,*d,*d"))] + "register_operand (operands[0], DFmode) + || register_operand (operands[1], DFmode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (DFmode)" "* return mips_move_2words (operands, insn); " [(set_attr "type" "move,load,load,store,store,load,xfer,xfer,move,load,load,store,store") *************** *** 2095,2099 **** (define_insn "ashldi3_internal" ! [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) --- 2220,2224 ---- (define_insn "ashldi3_internal" ! [(set (match_operand:DI 0 "register_operand" "=&d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) *************** *** 2295,2299 **** (define_insn "ashrdi3_internal" ! [(set (match_operand:DI 0 "register_operand" "=d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) --- 2420,2424 ---- (define_insn "ashrdi3_internal" ! [(set (match_operand:DI 0 "register_operand" "=&d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) *************** *** 2827,2831 **** [(set (pc) (if_then_else (match_operator:SI 0 "cmp_op" ! [(match_operand:SI 1 "arith32_operand" "rn") (const_int 0)]) (match_operand 2 "pc_or_label_operand" "") --- 2952,2956 ---- [(set (pc) (if_then_else (match_operator:SI 0 "cmp_op" ! [(match_operand:SI 1 "register_operand" "d") (const_int 0)]) (match_operand 2 "pc_or_label_operand" "") *************** *** 2835,2866 **** { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - - /* Handle places where CSE has folded a constant into the register operand. */ - if (GET_CODE (operands[1]) == CONST_INT) - { - int value = INTVAL (operands[1]); - int truth = 0; - - switch (GET_CODE (operands[0])) - { - default: abort (); - case EQ: truth = (value == 0); break; - case NE: truth = (value != 0); break; - case GT: truth = (value > 0); break; - case GE: truth = (value >= 0); break; - case LT: truth = (value < 0); break; - case LE: truth = (value <= 0); break; - case GTU: truth = (((unsigned)value) > 0); break; - case GEU: truth = 1; break; - case LTU: truth = 0; break; - case LEU: truth = (((unsigned)value) <= 0); break; - } - - if (operands[2] != pc_rtx) - return (truth) ? \"%*beq%?\\t%.,%.,%2\" : \"%*bne%?\\t%.,%.,%2\"; - else - return (truth) ? \"%*bne%?\\t%.,%.,%2\" : \"%*beq%?\\t%.,%.,%2\"; - } - if (operands[2] != pc_rtx) { /* normal jump */ --- 2960,2963 ---- *************** *** 2872,2876 **** case LEU: return \"%*beq%?\\t%z1,%.,%2\"; case GEU: return \"%*j\\t%2\"; ! case LTU: return \"#%*bltuz\\t%z1,%2\"; } --- 2969,2973 ---- case LEU: return \"%*beq%?\\t%z1,%.,%2\"; case GEU: return \"%*j\\t%2\"; ! case LTU: return \"%*bne%?\\t%.,%.,%2\"; } *************** *** 2885,2889 **** case GTU: return \"%*beq%?\\t%z1,%.,%3\"; case LEU: return \"%*bne%?\\t%z1,%.,%3\"; ! case GEU: return \"#%*bgeuz\\t%z1,%3\"; case LTU: return \"%*j\\t%3\"; } --- 2982,2986 ---- case GTU: return \"%*beq%?\\t%z1,%.,%3\"; case LEU: return \"%*bne%?\\t%z1,%.,%3\"; ! case GEU: return \"%*beq%?\\t%.,%.,%3\"; case LTU: return \"%*j\\t%3\"; } *************** *** 3093,3098 **** " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; --- 3190,3193 ---- *************** *** 3158,3163 **** " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; --- 3253,3256 ---- *************** *** 3222,3227 **** " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; --- 3315,3318 ---- *************** *** 3339,3344 **** " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; --- 3430,3433 ---- *************** *** 3404,3409 **** " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; --- 3493,3496 ---- *************** *** 3521,3526 **** " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; --- 3608,3611 ---- *************** *** 3849,3860 **** ;; eliminate jumps to jumps if no stack space is used. ! (define_insn "return" ! [(return)] ! "null_epilogue ()" ! "* ! { ! operands[0] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); ! return \"%*j\\t%0\"; ! }" [(set_attr "type" "jump") (set_attr "mode" "none") --- 3934,3953 ---- ;; eliminate jumps to jumps if no stack space is used. ! ;; (define_expand "return" ! ;; [(set (pc) (reg:SI 31))] ! ;; "simple_epilogue_p ()" ! ;; "") ! ! (define_expand "return" ! [(parallel [(return) ! (use (reg:SI 31))])] ! "simple_epilogue_p ()" ! "") ! ! (define_insn "return_internal" ! [(parallel [(return) ! (use (match_operand:SI 0 "register_operand" "d"))])] ! "" ! "%*j\\t%0" [(set_attr "type" "jump") (set_attr "mode" "none") *************** *** 3865,3868 **** --- 3958,3997 ---- ;; .................... ;; + ;; Function prologue/epilogue + ;; + ;; .................... + ;; + + (define_expand "prologue" + [(const_int 1)] + "" + " + { + if (mips_isa >= 0) /* avoid unused code warnings */ + { + mips_expand_prologue (); + DONE; + } + }") + + ;; At present, don't expand the epilogue, reorg.c will clobber the + ;; return register in compiling gen_lowpart (emit-rtl.c). + ;; + ;; (define_expand "epilogue" + ;; [(const_int 2)] + ;; "" + ;; " + ;; { + ;; if (mips_isa >= 0) /* avoid unused code warnings */ + ;; { + ;; mips_expand_epilogue (); + ;; DONE; + ;; } + ;; }") + + + ;; + ;; .................... + ;; ;; FUNCTION CALLS ;; *************** *** 3899,3902 **** --- 4028,4038 ---- return \"%*jal\\t%0\"; + else if (GET_CODE (target) == CONST_INT) + { + operands[0] = target; + operands[1] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); + return \"%*%[li\\t%@,%0\\n\\tjal\\t%1,%@%]\"; + } + else { *************** *** 3942,3945 **** --- 4078,4088 ---- return \"%*jal\\t%1\"; + else if (GET_CODE (target) == CONST_INT) + { + operands[1] = target; + operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); + return \"%*%[li\\t%@,%1\\n\\tjal\\t%2,%@%]\"; + } + else { *************** *** 3994,3996 **** ;; eval: (modify-syntax-entry ?} "){") ;; End: - --- 4137,4138 ---- diff -rc2N gcc-2.2.2/config/mot3300.h gcc-2.3.1/config/mot3300.h *** gcc-2.2.2/config/mot3300.h Thu Jun 11 01:02:30 1992 --- gcc-2.3.1/config/mot3300.h Thu Jul 16 16:56:29 1992 *************** *** 62,66 **** #define TARGET_MEM_FUNCTIONS ! / * size_t is unsigned int. */ #define SIZE_TYPE "unsigned int" --- 62,66 ---- #define TARGET_MEM_FUNCTIONS ! /* size_t is unsigned int. */ #define SIZE_TYPE "unsigned int" *************** *** 633,636 **** --- 633,645 ---- XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)) + #if 0 + /* At end of a switch table, define LD%n iff the symbol LI%n was defined. */ + #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \ + { if (switch_table_difference_label_flag) \ + asm_fprintf (FILE, "\t%s %LLD%d,%LL%d-%LLI%d-2.b\n",\ + SET_ASM_OP, (NUM), (NUM), (NUM)) \ + switch_table_difference_label_flag = 0; } + #endif + /* Translate some opcodes to fit the sysV68 assembler syntax. */ /* The opcodes fdmov and fsmov are guesses. */ diff -rc2N gcc-2.2.2/config/news.h gcc-2.3.1/config/news.h *** gcc-2.2.2/config/news.h Sat Jun 13 17:29:43 1992 --- gcc-2.3.1/config/news.h Sat Oct 24 14:10:36 1992 *************** *** 1,3 **** ! /* Definitions of target machine for GNU compiler. SONY NEWS-OS 3.0 version. Copyright (C) 1987, 1989 Free Software Foundation, Inc. --- 1,3 ---- ! /* Definitions of target machine for GNU compiler. SONY NEWS-OS 4 version. Copyright (C) 1987, 1989 Free Software Foundation, Inc. *************** *** 145,149 **** fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \ else \ ! fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize); } \ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ --- 145,159 ---- fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \ else \ ! fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);\ ! } \ ! else if (fsize) \ ! { \ ! int amt = fsize + 4; \ ! /* Adding negative number is faster on the 68040. */ \ ! if (fsize + 4 < 0x8000) \ ! asm_fprintf (FILE, "\tadd.w %0I%d,%Rsp\n", - amt); \ ! else \ ! asm_fprintf (FILE, "\tadd.l %0I%d,%Rsp\n", - amt); \ ! } \ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) \ *************** *** 218,221 **** --- 228,238 ---- if (frame_pointer_needed) \ fprintf (FILE, "\tunlk fp\n"); \ + else if (fsize) \ + { \ + if (fsize + 4 < 0x8000) \ + fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \ + else \ + fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \ + } \ if (current_function_pops_args) \ fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \ *************** *** 246,249 **** --- 263,280 ---- #define ASM_OUTPUT_SKIP(FILE,SIZE) \ fprintf (FILE, "\t.space %u\n", (SIZE)) + + #if 0 + /* The NEWS assembler in version 3.4 complains about fmove.d, but this + macro proved not to work right. 3.4 is old, so forget about it. */ + #define ASM_OUTPUT_OPCODE(FILE, STRING) \ + { \ + if (!strncmp (STRING, "fmove.d", 7) \ + && CONSTANT_P (operands[1])) \ + { \ + fprintf (FILE, "fmove.x"); \ + STRING += 7; \ + } \ + } + #endif /* Store in OUTPUT a string (made with alloca) containing diff -rc2N gcc-2.2.2/config/news3.h gcc-2.3.1/config/news3.h *** gcc-2.2.2/config/news3.h --- gcc-2.3.1/config/news3.h Mon Jul 27 22:54:47 1992 *************** *** 0 **** --- 1,6 ---- + #include "news.h" + + /* This is to be compatible with types.h. + It was found to be necessary with Newsos 3. */ + + #define SIZE_TYPE "long int" diff -rc2N gcc-2.2.2/config/news3gas.h gcc-2.3.1/config/news3gas.h *** gcc-2.2.2/config/news3gas.h --- gcc-2.3.1/config/news3gas.h Mon Jul 27 22:54:56 1992 *************** *** 0 **** --- 1,6 ---- + #include "newsgas.h" + + /* This is to be compatible with types.h. + It was found to be necessary with Newsos 3. */ + + #define SIZE_TYPE "long int" diff -rc2N gcc-2.2.2/config/next.h gcc-2.3.1/config/next.h *** gcc-2.2.2/config/next.h Sat Jun 13 17:29:19 1992 --- gcc-2.3.1/config/next.h Thu Oct 22 08:58:39 1992 *************** *** 19,22 **** --- 19,43 ---- #include "m68k.h" + /* Use new NeXT include file search path. */ + + #ifndef CROSS_COMPILE /* In a cross compiler with NeXT as target, don't expect + the host to use Next's directory scheme. */ + #define INCLUDE_DEFAULTS \ + { \ + { GPLUSPLUS_INCLUDE_DIR, 1}, \ + { GCC_INCLUDE_DIR, 0}, \ + { LOCAL_INCLUDE_DIR, 0}, \ + { "/NextDeveloper/Headers", 0}, \ + { "/NextDeveloper/Headers/ansi", 0}, \ + { "/NextDeveloper/Headers/bsd", 0}, \ + { "/LocalDeveloper/Headers", 0}, \ + { "/LocalDeveloper/Headers/ansi", 0}, \ + { "/LocalDeveloper/Headers/bsd", 0}, \ + { "/NextDeveloper/2.0CompatibleHeaders", 0}, \ + { STANDARD_INCLUDE_DIR, 0}, \ + { 0, 0} \ + } + #endif /* CROSS_COMPILE */ + #define EXTRA_FORMAT_FUNCTIONS \ "NXPrintf", FALSE, 2, FALSE, \ *************** *** 79,82 **** --- 100,104 ---- (!strcmp (STR, "Ttext") ? 1 : \ !strcmp (STR, "Tdata") ? 1 : \ + !strcmp (STR, "Tbss") ? 1 : \ !strcmp (STR, "include") ? 1 : \ !strcmp (STR, "imacros") ? 1 : \ *************** *** 95,99 **** /* Names to predefine in the preprocessor for this target machine. */ ! #define CPP_PREDEFINES "-Dmc68000 -Dm68k -DNeXT -Dunix -D__MACH__" /* Machine dependent ccp options. */ --- 117,121 ---- /* Names to predefine in the preprocessor for this target machine. */ ! #define CPP_PREDEFINES "-Dmc68000 -Dm68k -DNeXT -Dunix -D__MACH__ -D__ARCHITECTURE__=\"m68k\"" /* Machine dependent ccp options. */ diff -rc2N gcc-2.2.2/config/ns32k.c gcc-2.3.1/config/ns32k.c *** gcc-2.2.2/config/ns32k.c Wed Jun 10 00:48:13 1992 --- gcc-2.3.1/config/ns32k.c Sun Sep 6 17:23:28 1992 *************** *** 47,51 **** hard_regno_mode_ok (regno, mode) int regno; ! int mode; { switch (mode) --- 47,51 ---- hard_regno_mode_ok (regno, mode) int regno; ! enum machine_mode mode; { switch (mode) *************** *** 108,112 **** return 0; } ! abort(0); } --- 108,115 ---- return 0; } ! ! /* Used to abort here, but simply saying "no" handles TImode ! much better. */ ! return 0; } *************** *** 421,428 **** else { ! #ifndef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC if (GET_CODE (x) == CONST_INT) #endif ! PUT_IMMEDIATE_PREFIX(file); output_addr_const (file, x); } --- 424,431 ---- else { ! #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC if (GET_CODE (x) == CONST_INT) #endif ! PUT_IMMEDIATE_PREFIX (file); output_addr_const (file, x); } *************** *** 527,531 **** /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */ if (base && !indexexp && GET_CODE (base) == REG ! && REG_OK_FOR_INDEX_P (REGNO (base)) { indexexp = base; --- 530,534 ---- /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */ if (base && !indexexp && GET_CODE (base) == REG ! && REG_OK_FOR_INDEX_P (base)) { indexexp = base; diff -rc2N gcc-2.2.2/config/ns32k.h gcc-2.3.1/config/ns32k.h *** gcc-2.2.2/config/ns32k.h Wed Jun 10 00:49:02 1992 --- gcc-2.3.1/config/ns32k.h Sat Jun 27 00:54:28 1992 *************** *** 838,845 **** But, in practice, it always will. */ #define NS32K_DISPLACEMENT_P(i) \ ! (((i) <= 16777215 && (i) >= -16777216) \ ! || ((TARGET_32532 || TARGET_32332) \ ! && (i) <= 536870913 && (i) >= -536870912)) /* Check for frame pointer or stack pointer. */ --- 838,848 ---- But, in practice, it always will. */ + /* idall@eleceng.adelaide.edu.au says that the 32016 and 32032 + can handle the full range of displacements--it is only the addresses + that have a limited range. So the following was deleted: + (((i) <= 16777215 && (i) >= -16777216) + || ((TARGET_32532 || TARGET_32332) && ...)) */ #define NS32K_DISPLACEMENT_P(i) \ ! ((i) < (1 << 29) && (i) >= - (1 << 29)) /* Check for frame pointer or stack pointer. */ diff -rc2N gcc-2.2.2/config/ns32k.md gcc-2.3.1/config/ns32k.md *** gcc-2.2.2/config/ns32k.md Wed Jun 10 00:49:45 1992 --- gcc-2.3.1/config/ns32k.md Sat Aug 15 00:50:12 1992 *************** *** 478,486 **** }") ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it won't successfully combine with anything. ! (define_insn "movstrsi" [(set (match_operand:BLK 0 "general_operand" "=g") (match_operand:BLK 1 "general_operand" "g")) --- 478,499 ---- }") + ;; This is here to accept 4 arguments and pass the first 3 along + ;; to the movstrsi1 pattern that really does the work. + (define_expand "movstrsi" + [(set (match_operand:BLK 0 "general_operand" "=g") + (match_operand:BLK 1 "general_operand" "g")) + (use (match_operand:SI 2 "general_operand" "rmn")) + (match_operand 3 "" "")] + "" + " + emit_insn (gen_movstrsi1 (operands[0], operands[1], operands[2])); + DONE; + ") + ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it won't successfully combine with anything. ! (define_insn "movstrsi1" [(set (match_operand:BLK 0 "general_operand" "=g") (match_operand:BLK 1 "general_operand" "g")) diff -rc2N gcc-2.2.2/config/pa-ghpux.h gcc-2.3.1/config/pa-ghpux.h *** gcc-2.2.2/config/pa-ghpux.h Sun May 10 17:16:33 1992 --- gcc-2.3.1/config/pa-ghpux.h Wed Oct 14 10:36:15 1992 *************** *** 2,6 **** --- 2,14 ---- /* Make GCC agree with types.h. */ + #undef SIZE_TYPE + #undef PTRDIFF_TYPE + #undef WCHAR_TYPE + #undef WCHAR_TYPE_SIZE + #define SIZE_TYPE "unsigned int" + #define PTRDIFF_TYPE "int" + #define WCHAR_TYPE "unsigned int" + #define WCHAR_TYPE_SIZE 32 /* Like the default, except no -lg. */ *************** *** 15,16 **** --- 23,32 ---- #undef CPP_PREDEFINES #define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE" + + /* Link against shared libraries */ + #ifdef hpux8 + #undef TARGET_DEFAULT + #define TARGET_DEFAULT 8 + #undef LINK_SPEC + #define LINK_SPEC "-u main" + #endif diff -rc2N gcc-2.2.2/config/pa-hpux.h gcc-2.3.1/config/pa-hpux.h *** gcc-2.2.2/config/pa-hpux.h Sun May 10 17:16:26 1992 --- gcc-2.3.1/config/pa-hpux.h Wed Oct 14 10:36:35 1992 *************** *** 2,6 **** --- 2,14 ---- /* Make GCC agree with types.h. */ + #undef SIZE_TYPE + #undef PTRDIFF_TYPE + #undef WCHAR_TYPE + #undef WCHAR_TYPE_SIZE + #define SIZE_TYPE "unsigned int" + #define PTRDIFF_TYPE "int" + #define WCHAR_TYPE "unsigned int" + #define WCHAR_TYPE_SIZE 32 /* HPUX doesn't use any debugging format that GCC knows about. */ *************** *** 18,19 **** --- 26,35 ---- #undef CPP_PREDEFINES #define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE" + + /* Link against shared libraries */ + #ifdef hpux8 + #undef TARGET_DEFAULT + #define TARGET_DEFAULT 8 + #undef LINK_SPEC + #define LINK_SPEC "-u main %{g*:-a archive} %{p:-a archive} %{pg:-a archive}" + #endif diff -rc2N gcc-2.2.2/config/pa.c gcc-2.3.1/config/pa.c *** gcc-2.2.2/config/pa.c Thu Jun 4 17:32:44 1992 --- gcc-2.3.1/config/pa.c Mon Oct 26 16:20:06 1992 *************** *** 34,37 **** --- 34,38 ---- #include "c-tree.h" #include "expr.h" + #include "obstack.h" /* Save the operands last given to a compare for use when we *************** *** 44,54 **** int hp_profile_labelno; - /* Global variables set by FUNCTION_PROLOGUE. */ - /* Size of frame. Need to know this to emit return insns from - leaf procedures. */ - int apparent_fsize; - int actual_fsize; - int local_fsize, save_fregs; - /* Name of where we pretend to think the frame pointer points. Normally, this is "4", but if we are in a leaf procedure, --- 45,48 ---- *************** *** 73,77 **** enum machine_mode mode; { ! return (REG_P (op) || CONSTANT_P (op)); } --- 67,72 ---- enum machine_mode mode; { ! return (REG_P (op) ! || (CONSTANT_P (op) && ! TARGET_LONG_CALLS)); } *************** *** 205,208 **** --- 200,219 ---- return reg_renumber && FP_REG_P (op); } + + int + check_fp_mov (operands) + rtx *operands; + { + enum machine_mode mode = GET_MODE (operands[0]); + + if (fp_reg_operand (operands[0], mode)) + return (register_operand (operands[1], mode) + || short_memory_operand (operands[1], mode)); + else if (fp_reg_operand (operands[1], mode)) + return (register_operand (operands[0], mode) + || short_memory_operand (operands[0], mode)); + else + return 1; + } extern int current_function_uses_pic_offset_table; *************** *** 316,326 **** } ! /* Return truth value of statement that OP is a call-clobbered register. */ int ! clobbered_register (op, mode) rtx op; enum machine_mode mode; { ! return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]); } --- 327,395 ---- } ! /* True iff zdepi can be used to generate this CONST_INT. */ ! int ! depi_cint_operand (op, mode) ! rtx op; ! enum machine_mode mode; ! { ! unsigned x; ! unsigned lbmask, t; ! ! if (GET_CODE (op) != CONST_INT) ! return 0; ! ! /* This might not be obvious, but it's at least fast. ! This function is critcal; we don't have the time loops would take. */ ! x = INTVAL (op); ! lbmask = x & -x; ! t = ((x >> 4) + lbmask) & ~(lbmask - 1); ! return ((t & (t - 1)) == 0); ! } ! ! /* True iff depi or extru can be used to compute (reg & mask). */ int ! consec_zeros_p (mask) ! unsigned mask; ! { ! mask = ~mask; ! mask += mask & -mask; ! return (mask & (mask - 1)) == 0; ! } ! ! /* True iff depi or extru can be used to compute (reg & OP). */ ! int ! and_operand (op, mode) ! rtx op; ! enum machine_mode mode; ! { ! return (register_operand (op, mode) ! || (GET_CODE (op) == CONST_INT && consec_zeros_p (INTVAL (op)))); ! } ! ! /* True iff depi can be used to compute (reg | MASK). */ ! int ! ior_mask_p (mask) ! unsigned mask; ! { ! mask += mask & -mask; ! return (mask & (mask - 1)) == 0; ! } ! ! /* True iff depi can be used to compute (reg | OP). */ ! int ! ior_operand (op, mode) ! rtx op; ! enum machine_mode mode; ! { ! return (register_operand (op, mode) ! || (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op)))); ! } ! ! int ! arith32_operand (op, mode) rtx op; enum machine_mode mode; { ! return register_operand (op, mode) || GET_CODE (op) == CONST_INT; } *************** *** 339,342 **** --- 408,414 ---- return 1; + if (depi_cint_operand (op, mode)) + return 1; + /* OK if ldo or ldil can be used. */ return (GET_CODE (op) == CONST_INT *************** *** 421,481 **** finalize_pic () { - /* The table we use to reference PIC data. */ - rtx global_offset_table; - /* Labels to get the PC in the prologue of this function. */ - rtx l1, l2; - rtx seq; - int orig_flag_pic = flag_pic; - - if (current_function_uses_pic_offset_table == 0) - return; - - if (! flag_pic) - abort (); - - flag_pic = 0; - l1 = gen_label_rtx (); - l2 = gen_label_rtx (); - - start_sequence (); - - emit_label (l1); - /* Note that we pun calls and jumps here! */ - emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, - gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)), - gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2))))); - emit_label (l2); - - /* Initialize every time through, since we can't easily - know this to be permanent. */ - global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "*__GLOBAL_OFFSET_TABLE_"); - pic_pc_rtx = gen_rtx (CONST, Pmode, - gen_rtx (MINUS, Pmode, - global_offset_table, - gen_rtx (CONST, Pmode, - gen_rtx (MINUS, Pmode, - gen_rtx (LABEL_REF, VOIDmode, l1), - pc_rtx)))); - - emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx, - gen_rtx (HIGH, Pmode, pic_pc_rtx))); - emit_insn (gen_rtx (SET, VOIDmode, - pic_offset_table_rtx, - gen_rtx (LO_SUM, Pmode, - pic_offset_table_rtx, pic_pc_rtx))); - emit_insn (gen_rtx (SET, VOIDmode, - pic_offset_table_rtx, - gen_rtx (PLUS, SImode, - pic_offset_table_rtx, gen_rtx (REG, SImode, 15)))); - /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */ - LABEL_PRESERVE_P (l1) = 1; - LABEL_PRESERVE_P (l2) = 1; - flag_pic = orig_flag_pic; - - seq = gen_sequence (); - end_sequence (); - emit_insn_after (seq, get_insns ()); - /* Need to emit this whether or not we obey regdecls, since setjmp/longjmp can cause life info to screw up. */ --- 493,496 ---- *************** *** 510,522 **** int ! emit_move_sequence (operands, mode) rtx *operands; enum machine_mode mode; { register rtx operand0 = operands[0]; register rtx operand1 = operands[1]; ! /* Handle most common case first: storing into a register. */ ! if (register_operand (operand0, mode)) { if (register_operand (operand1, mode) --- 525,558 ---- int ! emit_move_sequence (operands, mode, scratch_reg) rtx *operands; enum machine_mode mode; + rtx scratch_reg; { register rtx operand0 = operands[0]; register rtx operand1 = operands[1]; ! if (fp_reg_operand (operand0, mode) ! && GET_CODE (operand1) == MEM ! && !short_memory_operand (operand1, mode) ! && scratch_reg) ! { ! emit_move_insn (scratch_reg, XEXP (operand1 , 0)); ! emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode, ! scratch_reg))); ! return 1; ! } ! else if (fp_reg_operand (operand1, mode) ! && GET_CODE (operand0) == MEM ! && !short_memory_operand (operand0, mode) ! && scratch_reg) ! { ! emit_move_insn (scratch_reg, XEXP (operand0 , 0)); ! emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg), ! operand1)); ! return 1; ! } ! /* Handle most common case: storing into a register. */ ! else if (register_operand (operand0, mode)) { if (register_operand (operand1, mode) *************** *** 548,566 **** /* Simplify the source if we need to. */ - #if 0 - if (GET_CODE (operand1) == HIGH - && symbolic_operand (XEXP (operand1, 0), mode) - && !read_only_operand (XEXP (operand1, 0))) - { - rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (mode); - - emit_insn (gen_rtx (SET, VOIDmode, temp, operand1)); - emit_insn (gen_rtx (SET, VOIDmode, - operand0, - gen_rtx (PLUS, mode, - temp, gen_rtx (REG, mode, 27)))); - return 1; - } - #endif if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) { --- 584,587 ---- *************** *** 576,585 **** else if (read_only_operand (operand1)) { ! emit_insn (gen_rtx (SET, VOIDmode, operand0, ! gen_rtx (HIGH, mode, operand1))); emit_insn (gen_rtx (SET, VOIDmode, operand0, ! gen_rtx (LO_SUM, mode, operand0, operand1))); return 1; } --- 597,622 ---- else if (read_only_operand (operand1)) { ! rtx set = gen_rtx (SET, VOIDmode, operand0, ! gen_rtx (LO_SUM, mode, operand0, operand1)); ! emit_insn (gen_rtx (SET, VOIDmode, operand0, ! gen_rtx (HIGH, mode, operand1))); ! if (TARGET_SHARED_LIBS ! && function_label_operand (operand1, mode)) ! { ! rtx temp = reload_in_progress ? scratch_reg ! : gen_reg_rtx (mode); ! if (!temp) ! abort (); ! emit_insn (gen_rtx (PARALLEL, VOIDmode, ! gen_rtvec (2, ! set, ! gen_rtx (CLOBBER, VOIDmode, ! temp)))); ! } ! else ! emit_insn (set); return 1; } *************** *** 605,612 **** else { ! rtx temp1 = gen_reg_rtx (mode), temp2 = gen_reg_rtx (mode); ! emit_insn (gen_rtx (SET, VOIDmode, ! temp1, gen_rtx (HIGH, mode, operand1))); emit_insn (gen_rtx (SET, VOIDmode, temp2, --- 642,651 ---- else { ! rtx temp1, temp2 = gen_reg_rtx (mode); ! /* For 2.4 we could set RTX_UNCHANGING and add a ! REG_EQUAL note for the first insn. This would ! allow the first insn to be moved out of loops. */ ! temp1 = gen_rtx (HIGH, mode, operand1); emit_insn (gen_rtx (SET, VOIDmode, temp2, *************** *** 622,625 **** --- 661,666 ---- } } + else if (depi_cint_operand (operand1, VOIDmode)) + return 0; else if (GET_CODE (operand1) == CONST_INT ? (! SMALL_INT (operand1) *************** *** 671,674 **** --- 712,754 ---- + /* Compute position (in OPERANDS[2]) and width (in OPERANDS[3]) + useful for copying or or'ing IMM to a register using bit field + instructions. Store the immediate value to insert in OPERANDS[1]. */ + void + compute_xdepi_operands_from_integer (imm, operands) + unsigned imm; + rtx *operands; + { + int lsb, len; + + /* Find the least significant set bit in IMM. */ + for (lsb = 0; lsb < 32; lsb++) + { + if ((imm & 1) != 0) + break; + imm >>= 1; + } + + /* Choose variants based on *sign* of the 5-bit field. */ + if ((imm & 0x10) == 0) + len = (lsb <= 28) ? 4 : 32 - lsb; + else + { + /* Find the width of the bitstring in IMM. */ + for (len = 5; len < 32; len++) + { + if ((imm & (1 << len)) == 0) + break; + } + + /* Sign extend IMM as a 5-bit value. */ + imm = (imm & 0xf) - 0x10; + } + + operands[1] = gen_rtx (CONST_INT, VOIDmode, imm); + operands[2] = gen_rtx (CONST_INT, VOIDmode, 31 - lsb); + operands[3] = gen_rtx (CONST_INT, VOIDmode, len); + } + /* Output assembler code to perform a doubleword move insn with operands OPERANDS. */ *************** *** 720,728 **** { rtx addr = XEXP (operands[0], 0); ! if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC ! || GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC) { operands[0] = gen_rtx (MEM, SImode, addr); ! return "stw%M0 %1,%0\n\tstw%M0 %1,%0"; } } --- 800,812 ---- { rtx addr = XEXP (operands[0], 0); ! if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == PRE_INC) ! { ! operands[0] = gen_rtx (MEM, SImode, addr); ! return "stw%M0 %1,%0\n\tstw%M0 %R1,%0"; ! } ! else if (GET_CODE (addr) == POST_DEC || GET_CODE (addr) == PRE_DEC) { operands[0] = gen_rtx (MEM, SImode, addr); ! return "stw%M0 %R1,%0\n\tstw%M0 %1,%0"; } } *************** *** 744,748 **** { /* No overlap between high target register and address ! register. (We do this in an non-obious way to save a register file writeback) */ if (GET_CODE (addr) == POST_INC) --- 828,832 ---- { /* No overlap between high target register and address ! register. (We do this in a non-obvious way to save a register file writeback) */ if (GET_CODE (addr) == POST_INC) *************** *** 771,775 **** { /* No overlap between high target register and address ! register. (We do this in an non-obious way to save a register file writeback) */ if (GET_CODE (addr) == PRE_INC) --- 855,859 ---- { /* No overlap between high target register and address ! register. (We do this in a non-obvious way to save a register file writeback) */ if (GET_CODE (addr) == PRE_INC) *************** *** 838,845 **** /* Do the late half first. */ if (addreg1) ! output_asm_insn ("addi 4,%0", &addreg1); output_asm_insn (singlemove_string (latehalf), latehalf); if (addreg1) ! output_asm_insn ("addi -4,%0", &addreg1); /* Then clobber. */ return singlemove_string (operands); --- 922,929 ---- /* Do the late half first. */ if (addreg1) ! output_asm_insn ("ldo 4(%0),%0", &addreg1); output_asm_insn (singlemove_string (latehalf), latehalf); if (addreg1) ! output_asm_insn ("ldo -4(%0),%0", &addreg1); /* Then clobber. */ return singlemove_string (operands); *************** *** 859,865 **** /* Make any unoffsettable addresses point at high-numbered word. */ if (addreg0) ! output_asm_insn ("addi 4,%0", &addreg0); if (addreg1) ! output_asm_insn ("addi 4,%0", &addreg1); /* Do that word. */ --- 943,949 ---- /* Make any unoffsettable addresses point at high-numbered word. */ if (addreg0) ! output_asm_insn ("ldo 4(%0),%0", &addreg0); if (addreg1) ! output_asm_insn ("ldo 4(%0),%0", &addreg1); /* Do that word. */ *************** *** 868,874 **** /* Undo the adds we just did. */ if (addreg0) ! output_asm_insn ("addi -4,%0", &addreg0); if (addreg1) ! output_asm_insn ("addi -4,%0", &addreg1); return ""; --- 952,958 ---- /* Undo the adds we just did. */ if (addreg0) ! output_asm_insn ("ldo -4(%0),%0", &addreg0); if (addreg1) ! output_asm_insn ("ldo -4(%0),%0", &addreg1); return ""; *************** *** 940,1022 **** } - /* Load the address specified by OPERANDS[3] into the register - specified by OPERANDS[0]. - - OPERANDS[3] may be the result of a sum, hence it could either be: - - (1) CONST - (2) REG - (2) REG + CONST_INT - (3) REG + REG + CONST_INT - (4) REG + REG (special case of 3). - - Note that (3) is not a legitimate address. - All cases are handled here. */ - - void - output_load_address (operands) - rtx *operands; - { - rtx base, offset; - - if (CONSTANT_P (operands[3])) - { - output_asm_insn ("ldi %3,%0", operands); - return; - } - - if (REG_P (operands[3])) - { - if (REGNO (operands[0]) != REGNO (operands[3])) - output_asm_insn ("copy %3,%0", operands); - return; - } - - if (GET_CODE (operands[3]) != PLUS) - abort (); - - base = XEXP (operands[3], 0); - offset = XEXP (operands[3], 1); - - if (GET_CODE (base) == CONST_INT) - { - rtx tmp = base; - base = offset; - offset = tmp; - } - - if (GET_CODE (offset) != CONST_INT) - { - /* Operand is (PLUS (REG) (REG)). */ - base = operands[3]; - offset = const0_rtx; - } - - if (REG_P (base)) - { - operands[6] = base; - operands[7] = offset; - if (INT_14_BITS (offset)) - output_asm_insn ("ldo %7(%6),%0", operands); - else - output_asm_insn ("addil L'%7,%6\n\tldo R'%7(1),%0", operands); - } - else if (GET_CODE (base) == PLUS) - { - operands[6] = XEXP (base, 0); - operands[7] = XEXP (base, 1); - operands[8] = offset; - - if (offset == const0_rtx) - output_asm_insn ("add %6,%7,%0", operands); - else if (INT_14_BITS (offset)) - output_asm_insn ("add %6,%7,%0\n\taddi %8,%0", operands); - else - output_asm_insn ("addil L'%8,%6\n\tldo R'%8(1),%0\n\tadd %0,%7,%0", operands); - } - else - abort (); - } - /* Emit code to perform a block move. --- 1024,1027 ---- *************** *** 1140,1144 **** if (size_is_constant) { ! /* Size is an compile-time determined, and also not very small (such small cases are handled above). */ operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes - 4); --- 1145,1149 ---- if (size_is_constant) { ! /* Size is compile-time determined, and also not very small (such small cases are handled above). */ operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes - 4); *************** *** 1191,1194 **** --- 1196,1281 ---- + char * + output_and (operands) + rtx *operands; + { + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) + { + unsigned mask = INTVAL (operands[2]); + int ls0, ls1, ms0, p, len; + + for (ls0 = 0; ls0 < 32; ls0++) + if ((mask & (1 << ls0)) == 0) + break; + + for (ls1 = ls0; ls1 < 32; ls1++) + if ((mask & (1 << ls1)) != 0) + break; + + for (ms0 = ls1; ms0 < 32; ms0++) + if ((mask & (1 << ms0)) == 0) + break; + + if (ms0 != 32) + abort(); + + if (ls1 == 32) + { + len = ls0; + + if (len == 0) + abort (); + + operands[2] = gen_rtx (CONST_INT, VOIDmode, len); + return "extru %1,31,%2,%0"; + } + else + { + /* We could use this `depi' for the case above as well, but `depi' + requires one more register file access than an `extru'. */ + + p = 31 - ls0; + len = ls1 - ls0; + + operands[2] = gen_rtx (CONST_INT, VOIDmode, p); + operands[3] = gen_rtx (CONST_INT, VOIDmode, len); + return "depi 0,%2,%3,%0"; + } + } + else + return "and %1,%2,%0"; + } + + char * + output_ior (operands) + rtx *operands; + { + if (GET_CODE (operands[2]) == CONST_INT) + { + unsigned mask = INTVAL (operands[2]); + int bs0, bs1, bs2, p, len; + + for (bs0 = 0; bs0 < 32; bs0++) + if ((mask & (1 << bs0)) != 0) + break; + + for (bs1 = bs0; bs1 < 32; bs1++) + if ((mask & (1 << bs1)) == 0) + break; + + if (bs1 != 32 && ((unsigned) 1 << bs1) <= mask) + abort(); + + p = 31 - bs0; + len = bs1 - bs0; + + operands[2] = gen_rtx (CONST_INT, VOIDmode, p); + operands[3] = gen_rtx (CONST_INT, VOIDmode, len); + return "depi -1,%2,%3,%0"; + } + else + return "or %1,%2,%0"; + } + /* Output an ascii string. */ output_ascii (file, p, size) *************** *** 1337,1344 **** } int ! compute_frame_size (size, leaf_function) int size; int leaf_function; { extern int current_function_outgoing_args_size; --- 1424,1439 ---- } + /* Global variables set by FUNCTION_PROLOGUE. */ + /* Size of frame. Need to know this to emit return insns from + leaf procedures. */ + int apparent_fsize; + int actual_fsize; + int local_fsize, save_fregs; + int ! compute_frame_size (size, leaf_function, fregs_live) int size; int leaf_function; + int *fregs_live; { extern int current_function_outgoing_args_size; *************** *** 1362,1366 **** if (regs_ever_live[i]) { ! actual_fsize += 8; save_fregs++; } } --- 1457,1463 ---- if (regs_ever_live[i]) { ! actual_fsize += 8; ! if (fregs_live) ! *fregs_live = 1; } } *************** *** 1370,1374 **** if (regs_ever_live[i] || regs_ever_live[i + 1]) { ! actual_fsize += 8; save_fregs++; } } --- 1467,1473 ---- if (regs_ever_live[i] || regs_ever_live[i + 1]) { ! actual_fsize += 8; ! if (fregs_live) ! *fregs_live = 1; } } *************** *** 1384,1390 **** extern char call_used_regs[]; extern int frame_pointer_needed; int i, offset; ! actual_fsize = compute_frame_size (size, leaf_function) + 32; if (TARGET_SNAKE) actual_fsize = (actual_fsize + 63) & ~63; --- 1483,1491 ---- extern char call_used_regs[]; extern int frame_pointer_needed; + extern int current_function_returns_struct; int i, offset; ! save_fregs = 0; ! actual_fsize = compute_frame_size (size, leaf_function, &save_fregs) + 32; if (TARGET_SNAKE) actual_fsize = (actual_fsize + 63) & ~63; *************** *** 1393,1397 **** /* This might be right a lot of the time */ fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=%d", actual_fsize); ! if (regs_ever_live[2]) fprintf (file, ",CALLS,SAVE_RP\n"); else --- 1494,1498 ---- /* This might be right a lot of the time */ fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=%d", actual_fsize); ! if (regs_ever_live[2] || profile_flag) fprintf (file, ",CALLS,SAVE_RP\n"); else *************** *** 1427,1430 **** --- 1528,1537 ---- actual_fsize, actual_fsize); } + /* The hppa calling conventions say that that %r19, the pic offset + register, is saved at sp - 32 (in this function's frame) */ + if (flag_pic) + { + fprintf (file, "\tstw %%r19,-32(%%r30)\n"); + } /* Instead of taking one argument, the counter label, as most normal mcounts do, _mcount appears to behave differently on the HPPA. It *************** *** 1440,1449 **** : (VAL_14_BITS_P (actual_fsize) ? 4 : 8))); int i, arg_offset; ! for (i = 26, arg_offset = -36; i >= 23; i--, arg_offset -= 4) if (regs_ever_live[i]) { ! print_stw (file, i, arg_offset, 4); ! pc_offset += 4; } fprintf (file, --- 1547,1571 ---- : (VAL_14_BITS_P (actual_fsize) ? 4 : 8))); int i, arg_offset; + int basereg, offsetadj; ! /* When the function has a frame pointer, use that as the base ! register for saving/restoring registers. Else use the stack ! pointer. Adjust the offset according to the frame size if this ! function does not have a frame pointer. */ ! ! basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM ! : STACK_POINTER_REGNUM; ! offsetadj = frame_pointer_needed ? 0 : actual_fsize; ! ! if (current_function_returns_struct) ! print_stw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); ! for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) if (regs_ever_live[i]) { ! print_stw (file, i, arg_offset, basereg); ! /* It is possible for the arg_offset not to fit in 14 bits ! when profiling a function without a frame pointer. Deal ! with such cases. */ ! pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8; } fprintf (file, *************** *** 1452,1458 **** \tldo %d(%%r2),%%r25\n", hp_profile_labelno, hp_profile_labelno, -pc_offset - 12 - 8); ! for (i = 26, arg_offset = -36; i >= 23; i--, arg_offset -= 4) if (regs_ever_live[i]) ! print_ldw (file, i, arg_offset, 4); } --- 1574,1582 ---- \tldo %d(%%r2),%%r25\n", hp_profile_labelno, hp_profile_labelno, -pc_offset - 12 - 8); ! for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) if (regs_ever_live[i]) ! print_ldw (file, i, arg_offset, basereg); ! if (current_function_returns_struct) ! print_ldw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); } *************** *** 1595,1599 **** { fprintf (file, "\tldo 8(4),30\n"); ! if (regs_ever_live[2]) fprintf (file, "\tldw -28(0,30),2\n"); fprintf (file, "\tbv 0(2)\n\tldwm -8(30),4\n"); --- 1719,1723 ---- { fprintf (file, "\tldo 8(4),30\n"); ! if (regs_ever_live[2] || profile_flag) fprintf (file, "\tldw -28(0,30),2\n"); fprintf (file, "\tbv 0(2)\n\tldwm -8(30),4\n"); *************** *** 1601,1608 **** else if (actual_fsize) { ! if (regs_ever_live[2] && VAL_14_BITS_P (actual_fsize + 20)) fprintf (file, "\tldw %d(30),2\n\tbv 0(2)\n\tldo %d(30),30\n", -(actual_fsize + 20), -actual_fsize); ! else if (regs_ever_live[2]) fprintf (file, "\taddil L'%d,30\n\tldw %d(1),2\n\tbv 0(2)\n\tldo R'%d(1),30\n", --- 1725,1733 ---- else if (actual_fsize) { ! if ((regs_ever_live[2] || profile_flag) ! && VAL_14_BITS_P (actual_fsize + 20)) fprintf (file, "\tldw %d(30),2\n\tbv 0(2)\n\tldo %d(30),30\n", -(actual_fsize + 20), -actual_fsize); ! else if (regs_ever_live[2] || profile_flag) fprintf (file, "\taddil L'%d,30\n\tldw %d(1),2\n\tbv 0(2)\n\tldo R'%d(1),30\n", *************** *** 1632,1636 **** rtx x, y; { ! enum machine_mode mode = SELECT_CC_MODE (code, x); rtx cc_reg = gen_rtx (REG, mode, 0); --- 1757,1761 ---- rtx x, y; { ! enum machine_mode mode = SELECT_CC_MODE (code, x, y); rtx cc_reg = gen_rtx (REG, mode, 0); *************** *** 2054,2063 **** { import_milli (mulU); ! return "bl $$mulU,31\n\tnop"; } else { import_milli (mulI); ! return "bl $$mulI,31\n\tnop"; } } --- 2179,2188 ---- { import_milli (mulU); ! return "bl $$mulU,31%#"; } else { import_milli (mulI); ! return "bl $$mulI,31%#"; } } *************** *** 2250,2255 **** } ! /* Memory loads/stores to/from fp registers may need a scratch ! register in which to reload the address. */ enum reg_class --- 2375,2380 ---- } ! /* Memory loads/stores to/from the shift need to go through ! the general registers. */ enum reg_class *************** *** 2261,2272 **** int regno = true_regnum (in); ! if (regno >= FIRST_PSEUDO_REGISTER) ! regno = -1; - if (class == FP_REGS || class == SNAKE_FP_REGS || class == HI_SNAKE_FP_REGS) - { - if (regno == -1 || !REGNO_OK_FOR_FP_P (regno)) - return GENERAL_REGS; - } return NO_REGS; } --- 2386,2398 ---- int regno = true_regnum (in); ! if ((TARGET_SHARED_LIBS && function_label_operand (in, mode)) ! || ((regno >= FIRST_PSEUDO_REGISTER || regno == -1) ! && ((mode == QImode || mode == HImode || mode == SImode ! || mode == DImode) ! && (class == FP_REGS || class == SNAKE_FP_REGS ! || class == HI_SNAKE_FP_REGS))) ! || (class == SHIFT_REGS && (regno <= 0 || regno >= 32))) ! return GENERAL_REGS; return NO_REGS; } *************** *** 2297,2310 **** } - int - use_milli_regs (insn) - rtx insn; - { - return (reg_mentioned_p (gen_rtx (REG, SImode, 1), insn) || - reg_mentioned_p (gen_rtx (REG, SImode, 25), insn) || - reg_mentioned_p (gen_rtx (REG, SImode, 26), insn) || - reg_mentioned_p (gen_rtx (REG, SImode, 29), insn) || - reg_mentioned_p (gen_rtx (REG, SImode, 31), insn)); - } /* Do what is necessary for `va_start'. The argument is ignored; --- 2423,2426 ---- *************** *** 2328,2351 **** else offset = current_function_arg_offset_rtx; ! /* Allocate the va_list structure. */ ! block = assign_stack_local (BLKmode, 4 * UNITS_PER_WORD, BITS_PER_UNIT); ! RTX_UNCHANGING_P (block) = 1; ! RTX_UNCHANGING_P (XEXP (block, 0)) = 1; ! /* ! * Store a pointer to where arguments should begin on the stack in ! * __va_stack_start. ! */ ! emit_move_insn (change_address (block, Pmode, XEXP (block, 0)), ! copy_to_reg ! (plus_constant (current_function_internal_arg_pointer, ! -16))); ! /* Store where to start getting args from in the __va_int member. */ ! emit_move_insn (change_address (block, Pmode, ! plus_constant (XEXP (block, 0), ! UNITS_PER_WORD)), ! copy_to_reg (expand_binop (Pmode, add_optab, ! current_function_internal_arg_pointer, ! offset, ! 0, 0, OPTAB_LIB_WIDEN))); /* Store general registers on the stack. */ move_block_from_reg (23, --- 2444,2448 ---- else offset = current_function_arg_offset_rtx; ! /* Store general registers on the stack. */ move_block_from_reg (23, *************** *** 2354,2418 **** (current_function_internal_arg_pointer, -16)), 4); ! /* ! * Allocate space for the float args, and store it in the ! * __va_float member. ! */ ! float_addr = copy_to_reg (XEXP (float_mem = ! assign_stack_local (BLKmode, ! 4 * UNITS_PER_WORD, -1), ! 0)); ! MEM_IN_STRUCT_P (float_mem) = 1; ! RTX_UNCHANGING_P (float_mem) = 1; ! RTX_UNCHANGING_P (XEXP (float_mem, 0)) = 1; ! emit_move_insn (change_address (block, Pmode, ! plus_constant (XEXP (block, 0), ! 2 * UNITS_PER_WORD)), ! copy_to_reg (expand_binop (Pmode, add_optab, ! float_addr, ! plus_constant (offset, 4 * ! UNITS_PER_WORD), ! 0, 0, OPTAB_LIB_WIDEN))); ! /* Store fp registers. */ ! emit_move_insn (gen_rtx (MEM, SFmode, float_addr), ! gen_rtx (REG, SFmode, TARGET_SNAKE ? 60 : 39)); ! emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr, ! gen_rtx (CONST_INT, ! Pmode, 4))), ! gen_rtx (REG, SFmode, TARGET_SNAKE ? 58 : 38)); ! emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr, ! gen_rtx (CONST_INT, ! Pmode, 8))), ! gen_rtx (REG, SFmode, TARGET_SNAKE ? 56 : 37)); ! emit_move_insn (gen_rtx (MEM, SFmode, gen_rtx (PLUS, Pmode, float_addr, ! gen_rtx (CONST_INT, ! Pmode, 12))), ! gen_rtx (REG, SFmode, TARGET_SNAKE ? 54 : 36)); ! /* ! * Allocate space for the double args, and store it in the ! * __va_double member. ! */ ! float_addr = copy_to_reg (XEXP (float_mem = ! assign_stack_local (BLKmode, ! 4 * UNITS_PER_WORD, -1), ! 0)); ! MEM_IN_STRUCT_P (float_mem) = 1; ! RTX_UNCHANGING_P (float_mem) = 1; ! RTX_UNCHANGING_P (XEXP (float_mem, 0)) = 1; ! emit_move_insn (change_address (block, Pmode, ! plus_constant (XEXP (block, 0), ! 3 * UNITS_PER_WORD)), ! copy_to_reg (expand_binop (Pmode, add_optab, ! float_addr, ! plus_constant (offset, 4 * ! UNITS_PER_WORD), ! 0, 0, OPTAB_LIB_WIDEN))); ! /* Store fp registers as doubles. */ ! ! emit_move_insn (gen_rtx (MEM, DFmode, float_addr), ! (gen_rtx (REG, DFmode, TARGET_SNAKE ? 60 : 39))); ! emit_move_insn (gen_rtx (MEM, DFmode, gen_rtx (PLUS, Pmode, float_addr, ! gen_rtx (CONST_INT, ! Pmode, 8))), ! gen_rtx (REG, DFmode, TARGET_SNAKE ? 56 : 37)); ! return copy_to_reg (XEXP (block, 0)); } --- 2451,2486 ---- (current_function_internal_arg_pointer, -16)), 4); ! return copy_to_reg (expand_binop (Pmode, add_optab, ! current_function_internal_arg_pointer, ! offset, 0, 0, OPTAB_LIB_WIDEN)); ! } ! ! extern struct obstack *saveable_obstack; ! ! /* In HPUX 8.0's shared library scheme, special relocations are needed ! for function labels if they might be passed to a function ! in a shared library (because shared libraries don't live in code ! space), and special magic is needed to construct their address. */ ! ! void ! hppa_encode_label (sym) ! rtx sym; ! { ! char *str = XSTR (sym, 0); ! int len = strlen (str); ! char *newstr = obstack_alloc (saveable_obstack, len + 2) ; ! ! if (str[0] == '*') ! *newstr++ = *str++; ! strcpy (newstr + 1, str); ! *newstr = '@'; ! XSTR (sym,0) = newstr; ! } ! ! int ! function_label_operand (op, mode) ! rtx op; ! enum machine_mode mode; ! { ! return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0)); } diff -rc2N gcc-2.2.2/config/pa.h gcc-2.3.1/config/pa.h *** gcc-2.2.2/config/pa.h Thu Jun 4 17:32:35 1992 --- gcc-2.3.1/config/pa.h Tue Oct 27 13:38:38 1992 *************** *** 33,39 **** #if (TARGET_DEFAULT & 1) == 0 ! #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}" #else ! #define CPP_SPEC "-D__hp9000s700 -D_PA_RISC1_1" #endif --- 33,40 ---- #if (TARGET_DEFAULT & 1) == 0 ! #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\ ! %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}" #else ! #define CPP_SPEC "%{!mpa-risc-1-0:-D__hp9000s700 -D_PA_RISC1_1}" #endif *************** *** 56,59 **** --- 57,67 ---- #endif + /* Make gcc agree with */ + + #define SIZE_TYPE "unsigned int" + #define PTRDIFF_TYPE "int" + #define WCHAR_TYPE "short unsigned int" + #define WCHAR_TYPE_SIZE 16 + /* Omit frame pointer at high optimization levels. */ *************** *** 64,74 **** } - /* These compiler options take an argument. We ignore -target for now. */ - - #define WORD_SWITCH_TAKES_ARG(STR) \ - (!strcmp (STR, "Tdata") || !strcmp (STR, "include") \ - || !strcmp (STR, "imacros") || !strcmp (STR, "target")\ - || !strcmp (STR, "aux-info")) - /* Names to predefine in the preprocessor for this target machine. */ --- 72,75 ---- *************** *** 77,92 **** /* Print subsidiary information on the compiler version in use. */ ! #define TARGET_VERSION fprintf (stderr, " (hp9000s800)"); ! /* Run-time compilation parameters selecting different hardware subsets. - On the the hp9k800, we don't yet need any. But ... */ - extern int target_flags; ! /* compile code for PA-RISC 1.1 ("Snake") */ #define TARGET_SNAKE (target_flags & 1) /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, --- 78,116 ---- /* Print subsidiary information on the compiler version in use. */ ! #define TARGET_VERSION fprintf (stderr, " (hppa)"); ! /* Run-time compilation parameters selecting different hardware subsets. */ extern int target_flags; ! /* compile code for HP-PA 1.1 ("Snake") */ #define TARGET_SNAKE (target_flags & 1) + /* Force gcc not to use the bss segment. This is (temporarily) provided + for sites which are using pa-gas-1.36 versions prior to Aug 7, 1992. */ + + #define TARGET_NO_BSS (target_flags & 2) + + /* Force gcc to only use instructions which are safe when compiling kernels. + Specifically, avoid using add instructions with dp (r27) as an argument. + Use addil instructions instead. Doing so avoids a nasty bug in the + HPUX linker. When HP fixes their linker take this option out. */ + + #define TARGET_KERNEL (target_flags & 4) + + /* Generate code that will link against HPUX 8.0 shared libraries. + Older linkers and assemblers might not support this. */ + + #define TARGET_SHARED_LIBS (target_flags & 8) + + /* Force all function calls to indirect addressing via a register. This + avoids lossage when the function is very far away from the current PC. + + ??? What about simple jumps, they can suffer from the same problem. + Would require significant surgery in pa.md. */ + + #define TARGET_LONG_CALLS (target_flags & 16) + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, *************** *** 97,100 **** --- 121,132 ---- #define TARGET_SWITCHES \ {{"snake", 1}, \ + {"nosnake", -1}, \ + {"pa-risc-1-0", -1}, \ + {"pa-risc-1-1", 1}, \ + {"no-bss", 2}, \ + {"kernel", 4}, \ + {"shared-libs", 8}, \ + {"no-shared-libs", -8},\ + {"long-calls", 16}, \ { "", TARGET_DEFAULT}} *************** *** 108,117 **** /* Define this if most significant byte of a word is the lowest numbered. */ ! /* That is true on the hp9k8. */ #define BYTES_BIG_ENDIAN 1 /* Define this if most significant word of a multiword number is lowest numbered. */ ! /* For the hp9k800 we can decide arbitrarily since there are no machine instructions for them. */ #define WORDS_BIG_ENDIAN 1 --- 140,149 ---- /* Define this if most significant byte of a word is the lowest numbered. */ ! /* That is true on the HP-PA. */ #define BYTES_BIG_ENDIAN 1 /* Define this if most significant word of a multiword number is lowest numbered. */ ! /* For the HP-PA we can decide arbitrarily since there are no machine instructions for them. */ #define WORDS_BIG_ENDIAN 1 *************** *** 184,188 **** even those that are not normally considered general registers. ! The hp9k800 has 32 fullword registers and 16 floating point registers. The floating point registers hold either word or double word values. --- 216,220 ---- even those that are not normally considered general registers. ! HP-PA 1.0 has 32 fullword registers and 16 floating point registers. The floating point registers hold either word or double word values. *************** *** 190,194 **** 16 additional registers are reserved. ! PA-RISC 1.1 has 32 fullword registers and 32 floating point registers. However, the floating point registers behave differently: the left and right halves of registers are addressable --- 222,226 ---- 16 additional registers are reserved. ! HP-PA 1.1 has 32 fullword registers and 32 floating point registers. However, the floating point registers behave differently: the left and right halves of registers are addressable *************** *** 203,207 **** and are not available for the register allocator. ! On the hp9k800, these are: Reg 0 = 0 (hardware). However, 0 is used for condition code, so is not fixed. --- 235,239 ---- and are not available for the register allocator. ! On the HP-PA, these are: Reg 0 = 0 (hardware). However, 0 is used for condition code, so is not fixed. *************** *** 211,215 **** Reg 4 = Frame Pointer (Gnu) Reg 5-18 = Preserved Registers ! Reg 19-22 = Temporary Registers Reg 23-26 = Temporary/Parameter Registers Reg 27 = Global Data Pointer (hp) --- 243,248 ---- Reg 4 = Frame Pointer (Gnu) Reg 5-18 = Preserved Registers ! Reg 19 = Linkage Table Register in HPUX 8.0 shared library scheme. ! Reg 20-22 = Temporary Registers Reg 23-26 = Temporary/Parameter Registers Reg 27 = Global Data Pointer (hp) *************** *** 344,348 **** but can be less for certain modes in special long registers. ! On the hp9k800, ordinary registers hold 32 bits worth; The floating point registers are 64 bits wide. Snake fp regs are 32 bits wide */ --- 377,381 ---- but can be less for certain modes in special long registers. ! On the HP-PA, ordinary registers hold 32 bits worth; The floating point registers are 64 bits wide. Snake fp regs are 32 bits wide */ *************** *** 352,357 **** /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. ! On the hp9k800, the cpu registers can hold any mode. We force this to be an even register is it cannot hold the full mode. */ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ ((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \ --- 385,391 ---- /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. ! On the HP-PA, the cpu registers can hold any mode. We force this to be an even register is it cannot hold the full mode. */ + #if 0 #define HARD_REGNO_MODE_OK(REGNO, MODE) \ ((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \ *************** *** 360,363 **** --- 394,404 ---- : (GET_MODE_SIZE (MODE) > 4 ? ((REGNO) & 1) == 0 \ : GET_MODE_SIZE (MODE) == 4)) + #endif + #define HARD_REGNO_MODE_OK(REGNO, MODE) \ + ((REGNO) == 0 ? (MODE) == CCmode || (MODE) == CCFPmode \ + : (REGNO) < 32 ? ((GET_MODE_SIZE (MODE) <= 4) ? 1 : ((REGNO) & 1) == 0)\ + : (REGNO) < 48 ? (GET_MODE_SIZE (MODE) >= 4) \ + : (GET_MODE_SIZE (MODE) > 4 ? ((REGNO) & 1) == 0 \ + : 1)) /* Value is 1 if it is a good idea to tie two pseudo registers *************** *** 371,375 **** The values of these macros are register numbers. */ ! /* the hp9k800 pc isn't overloaded on a register that the compiler knows about. */ /* #define PC_REGNUM */ --- 412,416 ---- The values of these macros are register numbers. */ ! /* The HP-PA pc isn't overloaded on a register that the compiler knows about. */ /* #define PC_REGNUM */ *************** *** 396,400 **** frame pointer. If it is a leaf function, we guessed right! */ #define INITIAL_FRAME_POINTER_OFFSET(VAR) \ ! do { int __fsize = compute_frame_size (get_frame_size (), 1) + 32; \ (VAR) = -(TARGET_SNAKE ? (__fsize + 63) & ~63 : __fsize); } while (0) --- 437,441 ---- frame pointer. If it is a leaf function, we guessed right! */ #define INITIAL_FRAME_POINTER_OFFSET(VAR) \ ! do { int __fsize = compute_frame_size (get_frame_size (), 1, 0) + 32; \ (VAR) = -(TARGET_SNAKE ? (__fsize + 63) & ~63 : __fsize); } while (0) *************** *** 409,413 **** data references. */ ! #define PIC_OFFSET_TABLE_REGNUM 18 #define INITIALIZE_PIC initialize_pic () --- 450,454 ---- data references. */ ! #define PIC_OFFSET_TABLE_REGNUM 19 #define INITIALIZE_PIC initialize_pic () *************** *** 438,448 **** class that represents their union. */ ! /* The hp9k800 has four kinds of registers: general regs, 1.0 fp regs, 1.1 fp regs, and the high 1.1 fp regs, to which the operands of ! fmpyadd and fmpysub are restricted. */ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS, HI_SNAKE_FP_REGS, SNAKE_FP_REGS, GENERAL_OR_SNAKE_FP_REGS, ! SHIFT_REGS, ALL_REGS, LIM_REG_CLASSES}; #define N_REG_CLASSES (int) LIM_REG_CLASSES --- 479,492 ---- class that represents their union. */ ! /* The HP-PA has four kinds of registers: general regs, 1.0 fp regs, 1.1 fp regs, and the high 1.1 fp regs, to which the operands of ! fmpyadd and fmpysub are restricted. ! ! FP_OR_SNAKE_FP_REGS is for reload_{in,out}di only and isn't used ! anywhere else.*/ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS, HI_SNAKE_FP_REGS, SNAKE_FP_REGS, GENERAL_OR_SNAKE_FP_REGS, ! FP_OR_SNAKE_FP_REGS, SHIFT_REGS, ALL_REGS, LIM_REG_CLASSES}; #define N_REG_CLASSES (int) LIM_REG_CLASSES *************** *** 453,457 **** { "NO_REGS", "R1_REGS", "GENERAL_REGS", "FP_REGS", "GENERAL_OR_FP_REGS",\ "HI_SNAKE_FP_REGS", "SNAKE_FP_REGS", "GENERAL_OR_SNAKE_FP_REGS",\ ! "SHIFT_REGS", "ALL_REGS"} /* Define which registers fit in which classes. --- 497,501 ---- { "NO_REGS", "R1_REGS", "GENERAL_REGS", "FP_REGS", "GENERAL_OR_FP_REGS",\ "HI_SNAKE_FP_REGS", "SNAKE_FP_REGS", "GENERAL_OR_SNAKE_FP_REGS",\ ! "FP_OR_SNAKE_FP_REGS","SHIFT_REGS", "ALL_REGS"} /* Define which registers fit in which classes. *************** *** 469,472 **** --- 513,517 ---- {0, 0xffff0000, ~0, 0xffff}, /* SNAKE_FP_REGS */ \ {-2, 0xffff0000, ~0, 0xffff}, /* GENERAL_OR_SNAKE_FP_REGS */\ + {0, ~0, ~0, 0xffff}, /* FP_OR_SNAKE_FP_REGS */\ {0, 0, 0, 0x10000}, /* SHIFT_REGS */ \ {-2, ~0, ~0, 0x1ffff}} /* ALL_REGS */ *************** *** 493,502 **** #define REG_CLASS_FROM_LETTER(C) \ ! ((C) == 'r' ? GENERAL_REGS : \ ! ((C) == 'f' ? (!TARGET_SNAKE ? FP_REGS : NO_REGS) : \ ! ((C) == 'x' ? (TARGET_SNAKE ? SNAKE_FP_REGS : NO_REGS) : \ ! ((C) == 'y' ? (TARGET_SNAKE ? HI_SNAKE_FP_REGS : NO_REGS) :\ ! ((C) == 'q' ? SHIFT_REGS : \ ! ((C) == 'a' ? R1_REGS : NO_REGS)))))) /* The letters I, J, K, L and M in a register constraint string --- 538,547 ---- #define REG_CLASS_FROM_LETTER(C) \ ! ((C) == 'f' ? (!TARGET_SNAKE ? FP_REGS : NO_REGS) : \ ! ((C) == 'x' ? (TARGET_SNAKE ? SNAKE_FP_REGS : NO_REGS) : \ ! ((C) == 'y' ? (TARGET_SNAKE ? HI_SNAKE_FP_REGS : NO_REGS) : \ ! ((C) == 'q' ? SHIFT_REGS : \ ! ((C) == 'a' ? R1_REGS : \ ! ((C) == 'z' ? FP_OR_SNAKE_FP_REGS : NO_REGS)))))) /* The letters I, J, K, L and M in a register constraint string *************** *** 506,510 **** Return 1 if VALUE is in the range specified by C. ! HP9000/800 immediate field sizes: 5 bits: scalar/floating short loads + stores; deposit; conditional branch 11 bits: arithmetic immediate, compare immediate --- 551,555 ---- Return 1 if VALUE is in the range specified by C. ! HP-PA immediate field sizes: 5 bits: scalar/floating short loads + stores; deposit; conditional branch 11 bits: arithmetic immediate, compare immediate *************** *** 525,528 **** --- 570,575 ---- : (C) == 'L' ? (unsigned) ((VALUE) + 0x10) < 0x20 \ : (C) == 'M' ? (VALUE) == 0 \ + : (C) == 'O' ? (((VALUE) & ((VALUE) + 1)) == 0) \ + : (C) == 'P' ? consec_zeros_p (VALUE) \ : 0) *************** *** 574,578 **** /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. ! On the hp9k800, don't define this because there are no push insns. */ /* #define PUSH_ROUNDING(BYTES) */ --- 621,625 ---- /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. ! On the HP-PA, don't define this because there are no push insns. */ /* #define PUSH_ROUNDING(BYTES) */ *************** *** 631,635 **** otherwise, FUNC is 0. */ ! /* On the hp9k800 the value is found in register(s) 28(-29), unless the mode is SF or DF. Then the value is returned in fr4 (36, ) */ --- 678,682 ---- otherwise, FUNC is 0. */ ! /* On the HP-PA the value is found in register(s) 28(-29), unless the mode is SF or DF. Then the value is returned in fr4 (36, ) */ *************** *** 667,671 **** such as FUNCTION_ARG to determine where the next arg should go. ! On the hp9k800, this is a single integer, which is a number of words of arguments scanned so far (including the invisible argument, if any, which holds the structure-value-address). --- 714,718 ---- such as FUNCTION_ARG to determine where the next arg should go. ! On the HP-PA, this is a single integer, which is a number of words of arguments scanned so far (including the invisible argument, if any, which holds the structure-value-address). *************** *** 691,695 **** #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ ! (((((CUM) & 01) && (TYPE) != 0 && TYPE_ALIGN (TYPE) > BITS_PER_WORD)\ && (CUM)++), (CUM) += FUNCTION_ARG_SIZE(MODE, TYPE)) --- 738,742 ---- #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ ! (((((CUM) & 01) && (TYPE) != 0 && FUNCTION_ARG_SIZE(MODE, TYPE) > 1)\ && (CUM)++), (CUM) += FUNCTION_ARG_SIZE(MODE, TYPE)) *************** *** 707,726 **** (otherwise it is an extra parameter matching an ellipsis). */ ! /* On the hp9k800 the first four words of args are normally in registers and the rest are pushed. But any arg that won't entirely fit in regs ! is pushed. */ #define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding ((MODE), (TYPE)) #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ (4 >= ((CUM) + FUNCTION_ARG_SIZE ((MODE), (TYPE))) \ ! ? gen_rtx (REG, \ ! (MODE), \ ! ((MODE) == SFmode ? \ ! (TARGET_SNAKE ? 56 + 2 * (CUM) : 36 + (CUM)) : \ ! ((MODE) == DFmode ? ((CUM) ? \ ! (TARGET_SNAKE ? 62 : 39) : \ ! (TARGET_SNAKE ? 58 : 37)) : \ ! (27 - (CUM) - FUNCTION_ARG_SIZE ((MODE), (TYPE)))))) \ : 0) --- 754,776 ---- (otherwise it is an extra parameter matching an ellipsis). */ ! /* On the HP-PA the first four words of args are normally in registers and the rest are pushed. But any arg that won't entirely fit in regs ! is pushed. + Arguments passed in registers are either 1 or 2 words long. */ + #define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding ((MODE), (TYPE)) #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ (4 >= ((CUM) + FUNCTION_ARG_SIZE ((MODE), (TYPE))) \ ! ? gen_rtx (REG, (MODE), \ ! (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \ ! ? ((MODE) == DFmode \ ! ? ((CUM) ? (TARGET_SNAKE ? 62 : 39) \ ! : (TARGET_SNAKE ? 58 : 37)) \ ! : ((CUM) ? 23 : 25)) \ ! : ((MODE) == SFmode \ ! ? (TARGET_SNAKE ? 56 + 2 * (CUM) : 36 + (CUM)) \ ! : (27 - (CUM) - FUNCTION_ARG_SIZE ((MODE), (TYPE))))))\ : 0) *************** *** 768,771 **** --- 818,822 ---- fprintf (FILE, ",ARGW%d=FR", (ARG1));} while (0) #endif + #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ do { tree fntype = DECL_RESULT (DECL); \ *************** *** 774,780 **** int i; \ if (TREE_PUBLIC (DECL)) \ ! { \ fputs ("\t.EXPORT ", FILE); assemble_name (FILE, NAME); \ ! fputs (",PRIV_LEV=3", FILE); \ for (parm = DECL_ARGUMENTS (DECL), i = 0; parm && i < 4; \ parm = TREE_CHAIN (parm)) \ --- 825,831 ---- int i; \ if (TREE_PUBLIC (DECL)) \ ! { extern int current_function_varargs; \ fputs ("\t.EXPORT ", FILE); assemble_name (FILE, NAME); \ ! fputs (",ENTRY,PRIV_LEV=3", FILE); \ for (parm = DECL_ARGUMENTS (DECL), i = 0; parm && i < 4; \ parm = TREE_CHAIN (parm)) \ *************** *** 784,789 **** else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode) \ { \ ! if (i == 1) i++; \ ! ASM_DOUBLE_ARG_DESCRIPTORS (FILE, i++, i++); \ } \ else \ --- 835,845 ---- else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode) \ { \ ! if (i <= 2) \ ! { \ ! if (i == 1) i++; \ ! ASM_DOUBLE_ARG_DESCRIPTORS (FILE, i++, i++); \ ! } \ ! else \ ! break; \ } \ else \ *************** *** 805,811 **** } \ /* anonymous args */ \ ! if (TYPE_ARG_TYPES (tree_type) != 0 \ ! && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (tree_type)))\ ! != void_type_node)) \ { \ for (; i < 4; i++) \ --- 861,868 ---- } \ /* anonymous args */ \ ! if ((TYPE_ARG_TYPES (tree_type) != 0 \ ! && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (tree_type)))\ ! != void_type_node)) \ ! || current_function_varargs) \ { \ for (; i < 4; i++) \ *************** *** 952,962 **** ((REGNO) && ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)) #define REGNO_OK_FOR_FP_P(REGNO) \ ! (((REGNO) >= 32 || reg_renumber[REGNO] >= 32)\ ! && ((REGNO) <= 111 || reg_renumber[REGNO] <= 111)) /* Now macros that check whether X is a register and also, strictly, whether it is in a specified class. ! These macros are specific to the the hp9k800, and may be used only in code for printing assembler insns and in conditions for define_optimization. */ --- 1009,1019 ---- ((REGNO) && ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)) #define REGNO_OK_FOR_FP_P(REGNO) \ ! (((REGNO) >= 32 && (REGNO) <= 111)\ ! || (reg_renumber[REGNO] >= 32 && reg_renumber[REGNO] <= 111)) /* Now macros that check whether X is a register and also, strictly, whether it is in a specified class. ! These macros are specific to the the HP-PA, and may be used only in code for printing assembler insns and in conditions for define_optimization. */ *************** *** 1061,1065 **** that wants to use this address. ! On the hp9k800, the actual legitimate addresses must be REG+REG, REG+(REG*SCALE) or REG+SMALLINT. But we can treat a SYMBOL_REF as legitimate if it is part of this --- 1118,1122 ---- that wants to use this address. ! On the HP-PA, the actual legitimate addresses must be REG+REG, REG+(REG*SCALE) or REG+SMALLINT. But we can treat a SYMBOL_REF as legitimate if it is part of this *************** *** 1150,1154 **** opportunities to optimize the output. */ ! /* On the hp9k800, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */ #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ --- 1207,1211 ---- opportunities to optimize the output. */ ! /* On the HP-PA, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */ #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ *************** *** 1168,1183 **** goto WIN; \ if (flag_pic) (X) = legitimize_pic_address (X, MODE, gen_reg_rtx (Pmode));\ ! else if ((GET_CODE (X) == SYMBOL_REF & read_only_operand (X)) \ || GET_CODE (X) == LABEL_REF) \ (X) = gen_rtx (LO_SUM, Pmode, \ copy_to_mode_reg (Pmode, gen_rtx (HIGH, Pmode, X)), X); \ else if (GET_CODE (X) == SYMBOL_REF) \ ! (X) = gen_rtx (LO_SUM, Pmode, \ ! copy_to_mode_reg (Pmode, \ ! gen_rtx (PLUS, Pmode, \ ! copy_to_mode_reg (Pmode,\ ! gen_rtx (HIGH, Pmode, X)),\ ! gen_rtx (REG, Pmode, 27))),\ ! X); \ if (memory_address_p (MODE, X)) \ goto WIN;} --- 1225,1240 ---- goto WIN; \ if (flag_pic) (X) = legitimize_pic_address (X, MODE, gen_reg_rtx (Pmode));\ ! else if ((GET_CODE (X) == SYMBOL_REF && read_only_operand (X))\ || GET_CODE (X) == LABEL_REF) \ (X) = gen_rtx (LO_SUM, Pmode, \ copy_to_mode_reg (Pmode, gen_rtx (HIGH, Pmode, X)), X); \ else if (GET_CODE (X) == SYMBOL_REF) \ ! { \ ! rtx temp2 = gen_reg_rtx (Pmode); \ ! emit_insn (gen_rtx (SET, VOIDmode, temp2, \ ! gen_rtx (PLUS, Pmode, gen_rtx (REG, Pmode, 27),\ ! gen_rtx (HIGH, Pmode, X)))); \ ! (X) = gen_rtx (LO_SUM, Pmode, temp2, X); \ ! } \ if (memory_address_p (MODE, X)) \ goto WIN;} *************** *** 1207,1230 **** information). ! On the PA-RISC we use this to indicate if a symbol is in text or ! data space. */ #define ENCODE_SECTION_INFO(DECL)\ ! do \ ! { \ ! if (TREE_CODE (DECL) == FUNCTION_DECL) \ ! SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ ! else \ ! { \ ! rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ ! ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \ ! if (RTX_UNCHANGING_P (rtl) && !MEM_VOLATILE_P (rtl) \ ! && !flag_pic) \ ! SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \ ! } \ ! } \ while (0) /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ --- 1264,1305 ---- information). ! On the HP-PA we use this to indicate if a symbol is in text or ! data space. Also, function labels need special treatment. */ ! ! #define TEXT_SPACE_P(DECL)\ ! (TREE_CODE (DECL) == FUNCTION_DECL \ ! || (TREE_CODE (DECL) == VAR_DECL \ ! && TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL) \ ! && !flag_pic) \ ! || (*tree_code_type[(int) TREE_CODE (DECL)] == 'c' \ ! && !(TREE_CODE (DECL) == STRING_CST && flag_writable_strings))) ! ! #define FUNCTION_NAME_P(NAME) \ ! (*(NAME) == '@' || (*(NAME) == '*' && *((NAME) + 1) == '@')) #define ENCODE_SECTION_INFO(DECL)\ ! do \ ! { if (TEXT_SPACE_P (DECL)) \ ! { rtx _rtl; \ ! if (TREE_CODE (DECL) == FUNCTION_DECL \ ! || TREE_CODE (DECL) == VAR_DECL) \ ! _rtl = DECL_RTL (DECL); \ ! else \ ! _rtl = TREE_CST_RTL (DECL); \ ! SYMBOL_REF_FLAG (XEXP (_rtl, 0)) = 1; \ ! if (TREE_CODE (DECL) == FUNCTION_DECL) \ ! hppa_encode_label (XEXP (DECL_RTL (DECL), 0));\ ! } \ ! } \ while (0) + /* Store the user-specified part of SYMBOL_NAME in VAR. + This is sort of inverse to ENCODE_SECTION_INFO. */ + #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ + (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*' ? \ + 1 + (SYMBOL_NAME)[1] == '@'\ + : (SYMBOL_NAME)[0] == '@')) + /* Specify the machine mode that this machine uses for the index in the tablejump instruction. */ *************** *** 1289,1293 **** PLUS, MINUS, or NEG. CCmode should be used when no special processing is needed. */ ! #define SELECT_CC_MODE(OP,X) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode : CCmode) \ --- 1364,1368 ---- PLUS, MINUS, or NEG. CCmode should be used when no special processing is needed. */ ! #define SELECT_CC_MODE(OP,X,Y) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode : CCmode) \ *************** *** 1327,1332 **** ((((CLASS1 == FP_REGS || CLASS1 == SNAKE_FP_REGS \ || CLASS1 == HI_SNAKE_FP_REGS) \ ! && (CLASS2 == R1_REGS | CLASS2 == GENERAL_REGS)) \ ! || ((CLASS2 == R1_REGS | CLASS1 == GENERAL_REGS) \ && (CLASS2 == FP_REGS || CLASS2 == SNAKE_FP_REGS \ || CLASS2 == HI_SNAKE_FP_REGS))) ? 6 : 2) --- 1402,1407 ---- ((((CLASS1 == FP_REGS || CLASS1 == SNAKE_FP_REGS \ || CLASS1 == HI_SNAKE_FP_REGS) \ ! && (CLASS2 == R1_REGS || CLASS2 == GENERAL_REGS)) \ ! || ((CLASS1 == R1_REGS || CLASS1 == GENERAL_REGS) \ && (CLASS2 == FP_REGS || CLASS2 == SNAKE_FP_REGS \ || CLASS2 == HI_SNAKE_FP_REGS))) ? 6 : 2) *************** *** 1344,1348 **** case UMOD: \ return COSTS_N_INSNS (60); \ ! case PLUS: /* this includes shNadd insns */ \ return COSTS_N_INSNS (1) + 2; --- 1419,1423 ---- case UMOD: \ return COSTS_N_INSNS (60); \ ! case PLUS: /* this includes shNadd insns */ \ return COSTS_N_INSNS (1) + 2; *************** *** 1360,1363 **** --- 1435,1439 ---- do { fprintf (FILE, "\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\ *************** *** 1366,1370 **** \t.IMPORT $$dyncall,MILLICODE\n");\ if (profile_flag)\ ! fprintf (FILE, "\t.IMPORT __gcc_mcount, CODE\n");\ } while (0) --- 1442,1446 ---- \t.IMPORT $$dyncall,MILLICODE\n");\ if (profile_flag)\ ! fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\ } while (0) *************** *** 1379,1383 **** #define ASM_APP_OFF "" ! /* We don't yet know how to identify GCC to HP series 800. */ #define ASM_IDENTIFY_GCC(FILE) fprintf (FILE, "; gcc_compiled.:\n") --- 1455,1459 ---- #define ASM_APP_OFF "" ! /* We don't yet know how to identify GCC to HP-PA machines. */ #define ASM_IDENTIFY_GCC(FILE) fprintf (FILE, "; gcc_compiled.:\n") *************** *** 1392,1395 **** --- 1468,1491 ---- #define DATA_SECTION_ASM_OP "\t.SPACE $PRIVATE$\n\t.SUBSPA $DATA$\n" + /* Output before uninitialized data. */ + + #define BSS_SECTION_ASM_OP "\t.SPACE $PRIVATE$\n\t.SUBSPA $BSS$\n" + + /* Define the .bss section for ASM_OUTPUT_LOCAL to use. */ + + #define EXTRA_SECTIONS in_bss + + #define EXTRA_SECTION_FUNCTIONS \ + void \ + bss_section () \ + { \ + if (in_section != in_bss) \ + { \ + fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ + in_section = in_bss; \ + } \ + } + + /* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */ *************** *** 1428,1435 **** do { fputs ("\t.IMPORT ", FILE); \ assemble_name (FILE, NAME); \ ! if (TREE_CODE (DECL) == VAR_DECL && ! TREE_READONLY (DECL)) \ ! fputs (",DATA\n", FILE); \ ! else \ fputs (",CODE\n", FILE); \ } while (0) --- 1524,1531 ---- do { fputs ("\t.IMPORT ", FILE); \ assemble_name (FILE, NAME); \ ! if (FUNCTION_NAME_P (NAME)) \ fputs (",CODE\n", FILE); \ + else \ + fputs (",DATA\n", FILE); \ } while (0) *************** *** 1459,1463 **** #define ASM_GLOBALIZE_LABEL(FILE, NAME) \ do { fputs ("\t.EXPORT ", FILE); assemble_name (FILE, NAME); \ ! fputs ("\n", FILE);} while (0) /* This is how to output a reference to a user-level label named NAME. --- 1555,1562 ---- #define ASM_GLOBALIZE_LABEL(FILE, NAME) \ do { fputs ("\t.EXPORT ", FILE); assemble_name (FILE, NAME); \ ! if (FUNCTION_NAME_P (NAME)) \ ! fputs (",CODE\n", FILE); \ ! else \ ! fputs (",DATA\n", FILE);} while (0) /* This is how to output a reference to a user-level label named NAME. *************** *** 1465,1469 **** #define ASM_OUTPUT_LABELREF(FILE,NAME) \ ! fprintf (FILE, "%s", NAME) /* This is how to output an internal numbered label where --- 1564,1568 ---- #define ASM_OUTPUT_LABELREF(FILE,NAME) \ ! fprintf ((FILE), "%s", (NAME) + (FUNCTION_NAME_P (NAME) ? 1 : 0)) /* This is how to output an internal numbered label where *************** *** 1525,1528 **** --- 1624,1628 ---- output_ascii ((FILE), (P), (SIZE)) + #if 0 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ fprintf (FILE, "\tstws,mb %s,4(0,30)\n", reg_names[REGNO]) *************** *** 1533,1537 **** --- 1633,1640 ---- #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ fprintf (FILE, "\tldws,ma -4(0,30),%s\n", reg_names[REGNO]) + #endif + #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. Note that this method makes filling these branch delay slots *************** *** 1542,1546 **** /* This is how to output an element of a case-vector that is relative. ! (the hp9k800 does not use such vectors, but we must define this macro anyway.) */ --- 1645,1649 ---- /* This is how to output an element of a case-vector that is relative. ! (The HP-PA does not use such vectors, but we must define this macro anyway.) */ *************** *** 1561,1566 **** to define a global common symbol. */ #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ! ( data_section (), \ assemble_name ((FILE), (NAME)), \ fputs ("\t.comm ", (FILE)), \ --- 1664,1672 ---- to define a global common symbol. */ + /* Supposedly the assembler rejects the command if there is no tab! */ + + #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ! ( (TARGET_NO_BSS) ? data_section (): bss_section (), \ assemble_name ((FILE), (NAME)), \ fputs ("\t.comm ", (FILE)), \ *************** *** 1571,1578 **** #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! ( data_section (), \ fprintf ((FILE), "\t.align %d\n", (SIZE) <= 4 ? 4 : 8), \ assemble_name ((FILE), (NAME)), \ ! fprintf ((FILE), "\n\t.blockz %d\n", (ROUNDED))) /* Store in OUTPUT a string (made with alloca) containing --- 1677,1685 ---- #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! ( (TARGET_NO_BSS) ? data_section (): bss_section (), \ fprintf ((FILE), "\t.align %d\n", (SIZE) <= 4 ? 4 : 8), \ assemble_name ((FILE), (NAME)), \ ! (TARGET_NO_BSS) ? fprintf ((FILE), "\n\t.blockz %d\n", (ROUNDED)) \ ! : fprintf ((FILE), "\n\t.block %d\n", (ROUNDED))) /* Store in OUTPUT a string (made with alloca) containing *************** *** 1606,1610 **** For `%' followed by punctuation, CODE is the punctuation and X is null. ! On the hp9k800, the CODE can be `r', meaning this is a register-only operand and an immediate zero should be represented as `r0'. --- 1713,1717 ---- For `%' followed by punctuation, CODE is the punctuation and X is null. ! On the HP-PA, the CODE can be `r', meaning this is a register-only operand and an immediate zero should be represented as `r0'. *************** *** 1657,1660 **** --- 1764,1769 ---- /* Define functions in pa.c and used in insn-output.c. */ + extern char *output_and (); + extern char *output_ior (); extern char *output_move_double (); extern char *output_fp_move_double (); *************** *** 1671,1672 **** --- 1780,1784 ---- extern void output_global_address (); extern struct rtx_def *legitimize_pic_address (); + extern struct rtx_def *gen_cmp_fp (); + extern struct rtx_def *gen_scond_fp (); + extern void hppa_encode_label (); diff -rc2N gcc-2.2.2/config/pa.md gcc-2.3.1/config/pa.md *** gcc-2.2.2/config/pa.md Fri Jun 12 17:37:40 1992 --- gcc-2.3.1/config/pa.md Wed Oct 28 14:46:51 1992 *************** *** 2,6 **** ;; Copyright (C) 1992 Free Software Foundation, Inc. ;; Contributed by the Center for Software Science at the University ! ;; of Utah. ;; This file is part of GNU CC. --- 2,6 ---- ;; Copyright (C) 1992 Free Software Foundation, Inc. ;; Contributed by the Center for Software Science at the University ! ;; of Utah. ;; This file is part of GNU CC. *************** *** 31,44 **** (define_attr "type" ! "move,unary,binary,compare,load,store,branch,cbranch,call,dyncall,address,fpload,fpstore,fpalu,fpcc,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,misc,milli" (const_string "binary")) - ;; Set true if insn uses call-clobbered intermediate register. - (define_attr "use_clobbered" "false,true" - (if_then_else (and (eq_attr "type" "address") - (match_operand 0 "clobbered_register" "")) - (const_string "true") - (const_string "false"))) - ;; Length (in # of insns). (define_attr "length" "" --- 31,37 ---- (define_attr "type" ! "move,unary,binary,compare,load,store,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,misc,milli" (const_string "binary")) ;; Length (in # of insns). (define_attr "length" "" *************** *** 51,56 **** (const_int 2) (const_int 1)) - (eq_attr "type" "address") (const_int 2) - (eq_attr "type" "binary") (if_then_else (match_operand 2 "arith_operand" "") --- 44,47 ---- *************** *** 69,120 **** ;; Attributes for instruction and branch scheduling - (define_attr "in_call_delay" "false,true" - (cond [(eq_attr "type" "branch,cbranch,call,dyncall,multi,milli") - (const_string "false") - - (eq_attr "type" "load,fpload,store,fpstore") - (if_then_else (eq_attr "length" "1") - (const_string "true") - (const_string "false")) - - (eq_attr "type" "address") - (if_then_else (eq_attr "use_clobbered" "false") - (const_string "true") - (const_string "false"))] - - (if_then_else (eq_attr "length" "1") - (const_string "true") - (const_string "false")))) - - (define_attr "in_milli_delay" "false,true" - (cond [(eq_attr "length" "!1") - (const_string "false") - - (eq_attr "type" "branch,cbranch,call,dyncall,milli") - (const_string "false") - - (ne (symbol_ref "use_milli_regs (insn)") (const_int 0)) - (const_string "false")] - (const_string "true"))) - - (define_delay (eq_attr "type" "call") - [(eq_attr "in_call_delay" "true") (nil) (nil)]) - (define_attr "in_branch_delay" "false,true" ! (if_then_else (and (eq_attr "type" "!branch,cbranch,call,multi,milli") (eq_attr "length" "1")) (const_string "true") (const_string "false"))) ! (define_delay (eq_attr "type" "branch") [(eq_attr "in_branch_delay" "true") ! (eq_attr "in_branch_delay" "true") (nil)]) (define_delay (eq_attr "type" "cbranch") [(eq_attr "in_branch_delay" "true") (nil) (nil)]) - (define_delay (eq_attr "type" "milli") - [(eq_attr "in_milli_delay" "true") (nil) (nil)]) - ;; Function units of the HPPA. The following data is for the "Snake" ;; (Mustang CPU + Timex FPU) because that's what I have the docs for. --- 60,83 ---- ;; Attributes for instruction and branch scheduling (define_attr "in_branch_delay" "false,true" ! (if_then_else (and (eq_attr "type" "!branch,cbranch,fbranch,call,dyncall,multi,milli") (eq_attr "length" "1")) (const_string "true") (const_string "false"))) ! ;; Unconditional branch, call, and millicode call delay slot description. ! (define_delay (eq_attr "type" "branch,call,milli") ! [(eq_attr "in_branch_delay" "true") (nil) (nil)]) ! ! ;; Floating point conditional branch delay slot description. ! (define_delay (eq_attr "type" "fbranch") [(eq_attr "in_branch_delay" "true") ! (eq_attr "in_branch_delay" "true") ! (nil)]) + ;; Integer conditional branch delay slot description. (define_delay (eq_attr "type" "cbranch") [(eq_attr "in_branch_delay" "true") (nil) (nil)]) ;; Function units of the HPPA. The following data is for the "Snake" ;; (Mustang CPU + Timex FPU) because that's what I have the docs for. *************** *** 123,127 **** ;; (define_function_unit {name} {num-units} {n-users} {test} ! ;; {ready-delay} {busy-delay} [{conflict-list}]) ;; The integer ALU. --- 86,90 ---- ;; (define_function_unit {name} {num-units} {n-users} {test} ! ;; {ready-delay} {issue-delay} [{conflict-list}]) ;; The integer ALU. *************** *** 134,142 **** ;; Memory. Disregarding Cache misses, the Mustang memory times are: ! ;; load: 1 ;; store, fpstore: 3, no D-cache operations should be scheduled. ;; fpload: 3 (really 2 for flops, but I don't think we can specify that). ! (define_function_unit "memory" 1 1 (eq_attr "type" "load") 1 0) (define_function_unit "memory" 1 1 (eq_attr "type" "store,fpstore") 3 0) (define_function_unit "memory" 1 1 (eq_attr "type" "fpload") 3 0) --- 97,105 ---- ;; Memory. Disregarding Cache misses, the Mustang memory times are: ! ;; load: 2 ;; store, fpstore: 3, no D-cache operations should be scheduled. ;; fpload: 3 (really 2 for flops, but I don't think we can specify that). ! (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) (define_function_unit "memory" 1 1 (eq_attr "type" "store,fpstore") 3 0) (define_function_unit "memory" 1 1 (eq_attr "type" "fpload") 3 0) *************** *** 161,164 **** --- 124,128 ---- ;; fsqrt,dbl 18 MPY 18 + (define_function_unit "fp_alu" 1 0 (eq_attr "type" "fpcc") 4 2) (define_function_unit "fp_alu" 1 0 (eq_attr "type" "fpalu") 3 2) (define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpmul") 3 2) *************** *** 171,175 **** ;; 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. --- 135,139 ---- ;; 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. *************** *** 246,250 **** (define_expand "seq" [(set (match_operand:SI 0 "register_operand" "") ! (eq:CC (match_dup 1) (match_dup 2)))] "" --- 210,214 ---- (define_expand "seq" [(set (match_operand:SI 0 "register_operand" "") ! (eq:SI (match_dup 1) (match_dup 2)))] "" *************** *** 264,269 **** (define_expand "sne" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (ne:CC (match_dup 1) (match_dup 2)))] "" --- 228,233 ---- (define_expand "sne" ! [(set (match_operand:SI 0 "register_operand" "") ! (ne:SI (match_dup 1) (match_dup 2)))] "" *************** *** 281,286 **** (define_expand "slt" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (lt:CC (match_dup 1) (match_dup 2)))] "" --- 245,250 ---- (define_expand "slt" ! [(set (match_operand:SI 0 "register_operand" "") ! (lt:SI (match_dup 1) (match_dup 2)))] "" *************** *** 298,303 **** (define_expand "sgt" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (gt:CC (match_dup 1) (match_dup 2)))] "" --- 262,267 ---- (define_expand "sgt" ! [(set (match_operand:SI 0 "register_operand" "") ! (gt:SI (match_dup 1) (match_dup 2)))] "" *************** *** 315,320 **** (define_expand "sle" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (le:CC (match_dup 1) (match_dup 2)))] "" --- 279,284 ---- (define_expand "sle" ! [(set (match_operand:SI 0 "register_operand" "") ! (le:SI (match_dup 1) (match_dup 2)))] "" *************** *** 332,337 **** (define_expand "sge" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (ge:CC (match_dup 1) (match_dup 2)))] "" --- 296,301 ---- (define_expand "sge" ! [(set (match_operand:SI 0 "register_operand" "") ! (ge:SI (match_dup 1) (match_dup 2)))] "" *************** *** 349,354 **** (define_expand "sltu" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (ltu:CC (match_dup 1) (match_dup 2)))] "" --- 313,318 ---- (define_expand "sltu" ! [(set (match_operand:SI 0 "register_operand" "") ! (ltu:SI (match_dup 1) (match_dup 2)))] "" *************** *** 362,367 **** (define_expand "sgtu" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (gtu:CC (match_dup 1) (match_dup 2)))] "" --- 326,331 ---- (define_expand "sgtu" ! [(set (match_operand:SI 0 "register_operand" "") ! (gtu:SI (match_dup 1) (match_dup 2)))] "" *************** *** 375,380 **** (define_expand "sleu" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (leu:CC (match_dup 1) (match_dup 2)))] "" --- 339,344 ---- (define_expand "sleu" ! [(set (match_operand:SI 0 "register_operand" "") ! (leu:SI (match_dup 1) (match_dup 2)))] "" *************** *** 388,393 **** (define_expand "sgeu" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (geu:CC (match_dup 1) (match_dup 2)))] "" --- 352,357 ---- (define_expand "sgeu" ! [(set (match_operand:SI 0 "register_operand" "") ! (geu:SI (match_dup 1) (match_dup 2)))] "" *************** *** 405,409 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (match_operator:CC 3 "comparison_operator" [(match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "arith11_operand" "r,I")]))] --- 369,373 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r") ! (match_operator:SI 3 "comparison_operator" [(match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "arith11_operand" "r,I")]))] *************** *** 417,426 **** if (!(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)) PUT_CODE (operands[3], reverse_relop (GET_CODE (operands[3]))); ! output_asm_insn (\"comiclr,%N3 %2,%1,%0\;ldi 1,%0\", operands); ! return \"\"; } }" ! [(set_attr "type" "binary") ! (set_attr "length" "2")]) ;; Conditionals --- 381,389 ---- if (!(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)) PUT_CODE (operands[3], reverse_relop (GET_CODE (operands[3]))); ! return \"comiclr,%N3 %2,%1,%0\;ldi 1,%0\"; } }" ! [(set_attr "type" "binary,binary") ! (set_attr "length" "2,2")]) ;; Conditionals *************** *** 613,620 **** PUT_CODE (operands[3], reverse_relop (comp_code)); if (get_attr_length (insn) == 1) ! output_asm_insn (\"comib,%C3 %2,%1,%0%#\", operands); else ! output_asm_insn (\"comiclr,%N3 %2,%1,0\;bl %0,0%#\", operands); ! return \"\"; } }" --- 576,582 ---- PUT_CODE (operands[3], reverse_relop (comp_code)); if (get_attr_length (insn) == 1) ! return \"comib,%C3 %2,%1,%0%#\"; else ! return \"comiclr,%N3 %2,%1,0\;bl %0,0%#\"; } }" *************** *** 647,654 **** PUT_CODE (operands[3], reverse_relop (comp_code)); if (get_attr_length (insn) == 1) ! output_asm_insn (\"comib,%N3 %2,%1,%0%#\", operands); else ! output_asm_insn (\"comiclr,%C3 %2,%1,0%#\;bl %0,0%#\", operands); ! return \"\"; } }" --- 609,615 ---- PUT_CODE (operands[3], reverse_relop (comp_code)); if (get_attr_length (insn) == 1) ! return \"comib,%N3 %2,%1,%0%#\"; else ! return \"comiclr,%C3 %2,%1,0%#\;bl %0,0%#\"; } }" *************** *** 667,672 **** (pc)))] "" ! "ftest\;bl%* %0,0" ! [(set_attr "type" "cbranch") (set_attr "length" "2")]) --- 628,639 ---- (pc)))] "" ! "* ! { ! if (INSN_ANNULLED_BRANCH_P (insn)) ! return \"ftest\;bl,n %0,0\"; ! else ! return \"ftest\;bl%* %0,0\"; ! }" ! [(set_attr "type" "fbranch") (set_attr "length" "2")]) *************** *** 676,681 **** (label_ref (match_operand 0 "" ""))))] "" ! "ftest\;add,tr 0,0,0\;bl%* %0,0" ! [(set_attr "type" "cbranch") (set_attr "length" "3")]) --- 643,654 ---- (label_ref (match_operand 0 "" ""))))] "" ! "* ! { ! if (INSN_ANNULLED_BRANCH_P (insn)) ! return \"ftest\;add,tr 0,0,0\;bl,n %0,0\"; ! else ! return \"ftest\;add,tr 0,0,0\;bl%* %0,0\"; ! }" ! [(set_attr "type" "fbranch") (set_attr "length" "3")]) *************** *** 688,693 **** " { ! if (emit_move_sequence (operands, SImode)) DONE; }") --- 661,699 ---- " { ! if (emit_move_sequence (operands, SImode, 0)) ! DONE; ! }") ! ! ;; Reloading an SImode or DImode value requires a scratch register if ! ;; going in to or out of float point registers. ! ! (define_expand "reload_insi" ! [(set (match_operand:SI 0 "register_operand" "=z") ! (match_operand:SI 1 "general_operand" "")) ! (clobber (match_operand:SI 2 "register_operand" "=&r"))] ! "" ! " ! { ! if (emit_move_sequence (operands, SImode, operands[2])) ! DONE; ! ! /* We don't want the clobber emitted, so handle this ourselves. */ ! emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); ! DONE; ! }") ! ! (define_expand "reload_outsi" ! [(set (match_operand:SI 0 "general_operand" "") ! (match_operand:SI 1 "register_operand""z")) ! (clobber (match_operand:SI 2 "register_operand" "=&r"))] ! "" ! " ! { ! if (emit_move_sequence (operands, SImode, operands[2])) DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; }") *************** *** 708,715 **** [(set_attr "type" "move")]) (define_insn "" [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" ! "=r,r,Q,!r,!*f*x,!*f*x") ! (match_operand:SI 1 "move_operand" "rM,Q,rM,!*f*x*y,!r,!*f*x"))] "" "@ --- 714,750 ---- [(set_attr "type" "move")]) + ;;; Experimental + + (define_insn "" + [(set (match_operand:SI 0 "fp_reg_operand" "=fx") + (match_operand:SI 1 "short_memory_operand" "T"))] + "" + "fldws%F1 %1,%0" + [(set_attr "type" "fpload") + (set_attr "length" "1")]) + + (define_insn "" + [(set (match_operand:SI 0 "short_memory_operand" "=T") + (match_operand:SI 1 "fp_reg_operand" "fx"))] + "" + "fstws%F0 %1,%0" + [(set_attr "type" "fpstore") + (set_attr "length" "1")]) + + ;;; pic symbol refrences + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "symbolic_operand" ""))))] + "flag_pic && operands[1] == pic_offset_table_rtx" + "ldw T'%2(%1),%0" + [(set_attr "type" "load") + (set_attr "length" "1")]) + (define_insn "" [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" ! "=r,r,Q,!r,!fx,!fx") ! (match_operand:SI 1 "move_operand" "rM,Q,rM,!fxy,!r,!fx"))] "" "@ *************** *** 740,744 **** output_asm_insn (\"bl .+8,%0\;addil L'%1-%2,%0\", xoperands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label_rtx)); ! output_asm_insn (\"ldo R'%1(1),%0\", xoperands); return \"\"; } --- 775,779 ---- output_asm_insn (\"bl .+8,%0\;addil L'%1-%2,%0\", xoperands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label_rtx)); ! output_asm_insn (\"ldo R'%1-%2(1),%0\", xoperands); return \"\"; } *************** *** 749,755 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (match_operand:SI 1 "immediate_operand" "n"))] ! "(GET_CODE (operands[1]) == CONST_INT) && ! (INT_14_BITS (operands[1]) || !(INTVAL (operands[1]) & 0x7ff))" "* { --- 784,789 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (match_operand:SI 1 "const_int_operand" ""))] ! "INT_14_BITS (operands[1]) || (INTVAL (operands[1]) & 0x7ff) == 0" "* { *************** *** 763,787 **** (define_insn "" ! [(set (match_operand:SI 0 "register_operand" "=a,?*r") (plus:SI (match_operand:SI 1 "register_operand" "r,r") (high:SI (match_operand 2 "" ""))))] ! "" "@ addil L'%G2,%1 ldil L'%G2,%0\;add %0,%1,%0" ! [(set_attr "type" "binary") (set_attr "length" "1,2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "register_operand" "") ! (high:SI (match_operand 2 "" ""))))] "reload_completed && REGNO (operands[0]) != 1" ! [(set (match_dup 0) (high:SI (match_dup 2))) ! (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] "") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand 1 "" "")))] "check_pic (1)" --- 797,855 ---- (define_insn "" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (match_operand:SI 1 "depi_cint_operand" ""))] ! "" ! "* ! { ! rtx xoperands[4]; ! xoperands[0] = operands[0]; ! compute_xdepi_operands_from_integer (INTVAL (operands[1]), xoperands); ! output_asm_insn (\"zdepi %1,%2,%3,%0\", xoperands); ! return \"\"; ! }" ! [(set_attr "type" "move") ! (set_attr "length" "1")]) ! ! (define_insn "" ! [(set (match_operand:SI 0 "register_operand" "=a,&?*r") (plus:SI (match_operand:SI 1 "register_operand" "r,r") (high:SI (match_operand 2 "" ""))))] ! "!TARGET_KERNEL" "@ addil L'%G2,%1 ldil L'%G2,%0\;add %0,%1,%0" ! [(set_attr "type" "binary,binary") (set_attr "length" "1,2")]) + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=a") + (plus:SI (match_operand:SI 1 "register_operand" "r") + (high:SI (match_operand 2 "" ""))))] + "TARGET_KERNEL" + "@ + addil L'%G2,%1" + [(set_attr "type" "binary") + (set_attr "length" "1")]) + (define_split [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "register_operand" "") ! (high:SI (match_operand 2 "" "")))) ! (clobber (match_scratch:SI 3 ""))] "reload_completed && REGNO (operands[0]) != 1" ! [(set (match_dup 3) (high:SI (match_dup 2))) ! (set (match_dup 0) (plus:SI (match_dup 3) (match_dup 1)))] "") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (match_operand:SI 1 "function_label_operand" "")))] + "TARGET_SHARED_LIBS" + "ldil LP'%G1,%0" + [(set_attr "type" "move") + (set_attr "length" "1")]) + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand 1 "" "")))] "check_pic (1)" *************** *** 801,805 **** [(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")))] "" "ldo R'%G2(%1),%0" --- 869,883 ---- [(set (match_operand:SI 0 "register_operand" "=r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "function_label_operand" ""))) ! (clobber (match_operand:SI 3 "register_operand" "=r"))] ! "TARGET_SHARED_LIBS" ! "ldo RP'%G2(%1),%0\;extru,= %0,31,1,%3\;ldw -4(%%r27),%3\;add %0,%3,%0" ! [(set_attr "type" "multi") ! (set_attr "length" "4")]) ! ! (define_insn "" ! [(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")))] "" "ldo R'%G2(%1),%0" *************** *** 808,829 **** [(set_attr "length" "1")]) - ;;; Experimental - - (define_insn "" - [(set (match_operand:SI 0 "fp_reg_operand" "*f*x") - (match_operand:SI 1 "short_memory_operand" "T"))] - "" - "fldws%F1 %1,%0" - [(set_attr "type" "fpload") - (set_attr "length" "1")]) - - (define_insn "" - [(set (match_operand:SI 0 "short_memory_operand" "T") - (match_operand:SI 1 "fp_reg_operand" "*f*x"))] - "" - "fstws%F0 %1,%0" - [(set_attr "type" "fpstore") - (set_attr "length" "1")]) - (define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") --- 886,889 ---- *************** *** 832,855 **** " { ! if (emit_move_sequence (operands, HImode)) DONE; }") (define_insn "" ! [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") ! (match_operand:HI 1 "move_operand" "rM,Q,rM"))] "" "@ copy %r1,%0 ldh%M1 %1,%0 ! sth%M0 %r1,%0" ! [(set_attr "type" "move,load,store") ! (set_attr "length" "1,1,1")]) (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") ! (match_operand:HI 1 "immediate_operand" "n"))] ! "(GET_CODE (operands[1]) == CONST_INT) && ! (INT_14_BITS (operands[1]) || !(INTVAL (operands[1]) & 0x7ff))" "* { --- 892,917 ---- " { ! if (emit_move_sequence (operands, HImode, 0)) DONE; }") (define_insn "" ! [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,Q,!r,!*fx,!*fx") ! (match_operand:HI 1 "move_operand" "rM,Q,rM,*fx,r,!*fx"))] "" "@ copy %r1,%0 ldh%M1 %1,%0 ! sth%M0 %r1,%0 ! fstws %1,-16(30)\;ldw -16(30),%0 ! stw %1,-16(30)\;fldws -16(30),%0 ! fcpy,sgl %1,%0" ! [(set_attr "type" "move,load,store,move,move,fpalu") ! (set_attr "length" "1,1,1,2,2,1")]) (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") ! (match_operand:HI 1 "const_int_operand" ""))] ! "INT_14_BITS (operands[1]) || (INTVAL (operands[1]) & 0x7ff) == 0" "* { *************** *** 864,869 **** (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (lo_sum:HI (match_operand:HI 1 "register_operand" "r") ! (match_operand 2 "immediate_operand" "in")))] "" "ldo R'%G2(%1),%0" --- 926,946 ---- (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") + (match_operand:HI 1 "depi_cint_operand" ""))] + "" + "* + { + rtx xoperands[4]; + xoperands[0] = operands[0]; + compute_xdepi_operands_from_integer (INTVAL (operands[1]), xoperands); + output_asm_insn (\"zdepi %1,%2,%3,%0\", xoperands); + return \"\"; + }" + [(set_attr "type" "move") + (set_attr "length" "1")]) + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") (lo_sum:HI (match_operand:HI 1 "register_operand" "r") ! (match_operand 2 "immediate_operand" "i")))] "" "ldo R'%G2(%1),%0" *************** *** 876,893 **** " { ! if (emit_move_sequence (operands, QImode)) DONE; }") (define_insn "" ! [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,Q") ! (match_operand:QI 1 "move_operand" "rM,Q,rM"))] "" "@ copy %r1,%0 ldb%M1 %1,%0 ! stb%M0 %r1,%0" ! [(set_attr "type" "move,load,store") ! (set_attr "length" "1,1,1")]) (define_insn "" --- 953,973 ---- " { ! if (emit_move_sequence (operands, QImode, 0)) DONE; }") (define_insn "" ! [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,Q,!r,!*fx,!*fx") ! (match_operand:QI 1 "move_operand" "rM,Q,rM,*fx,r,*fx"))] "" "@ copy %r1,%0 ldb%M1 %1,%0 ! stb%M0 %r1,%0 ! fstws %1,-16(30)\;ldw -16(30),%0 ! stw %1,-16(30)\;fldws -16(30),%0 ! fcpy,sgl %1,%0" ! [(set_attr "type" "move,load,store,move,move,fpalu") ! (set_attr "length" "1,1,1,2,2,1")]) (define_insn "" *************** *** 902,910 **** [(set (match_operand:QI 0 "register_operand" "=r") (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") ! (match_operand 2 "immediate_operand" "in")) 0))] "" "ldo R'%G2(%1),%0" [(set_attr "length" "1")]) ;; The definition of this insn does not really explain what it does, ;; but it should suffice --- 982,1041 ---- [(set (match_operand:QI 0 "register_operand" "=r") (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r") ! (match_operand 2 "immediate_operand" "i")) 0))] "" "ldo R'%G2(%1),%0" [(set_attr "length" "1")]) + ;; Sneaky ways of using index modes + ;; We don't use unscaled modes since they can't be used unless we can tell + ;; which of the registers is the base and which is the index, due to PA's + ;; idea of segment selection using the top bits of the base register. + + (define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (mem:SI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") + (const_int 4)) + (match_operand:SI 2 "register_operand" "r"))))] + "" + "ldwx,s %1(0,%2),%0" + [(set_attr "type" "move") + (set_attr "length" "1")]) + + ; this will never match + ;(define_insn "" + ; [(set (match_operand:SI 0 "register_operand" "=r") + ; (mem:SI (match_operand:SI 1 "register_operand" "+r"))) + ; (set (match_dup 1) + ; (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") + ; (const_int 4)) + ; (match_dup 1)))] + ; "" + ; "ldwx,sm %2(0,%1),%0" + ; [(set_attr "type" "move") + ; (set_attr "length" "1")]) + + (define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (mem:HI (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") + (const_int 2)) + (match_operand:SI 1 "register_operand" "r"))))] + "" + "ldhx,s %2(0,%1),%0" + [(set_attr "type" "move") + (set_attr "length" "1")]) + + ; this will never match + ;(define_insn "" + ; [(set (match_operand:HI 0 "register_operand" "=r") + ; (mem:HI (match_operand:SI 1 "register_operand" "+r"))) + ; (set (match_dup 1) + ; (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") + ; (const_int 2)) + ; (match_dup 1)))] + ; "" + ; "ldhx,sm %2(0,%1),%0" + ; [(set_attr "type" "move") + ; (set_attr "length" "1")]) + ;; The definition of this insn does not really explain what it does, ;; but it should suffice *************** *** 916,921 **** (clobber (match_dup 0)) (clobber (match_dup 1)) ! (clobber (match_scratch:SI 4 "")) ! (clobber (match_scratch:SI 5 "")) (use (match_operand:SI 2 "arith_operand" "")) (use (match_operand:SI 3 "const_int_operand" ""))])] --- 1047,1052 ---- (clobber (match_dup 0)) (clobber (match_dup 1)) ! (clobber (match_dup 4)) ! (clobber (match_dup 5)) (use (match_operand:SI 2 "arith_operand" "")) (use (match_operand:SI 3 "const_int_operand" ""))])] *************** *** 923,931 **** " { ! /* If the blocks are not word-aligned and rather big (>16 items), or the size is indeterminate, don't inline the copy code. A procedure call is better since it can check the alignment at runtime and make the optimal decisions. */ ! if (INTVAL (operands[3]) != 4 && (GET_CODE (operands[2]) != CONST_INT || (INTVAL (operands[2]) / INTVAL (operands[3]) > 16))) --- 1054,1062 ---- " { ! /* If the blocks are not at least word-aligned and rather big (>16 items), or the size is indeterminate, don't inline the copy code. A procedure call is better since it can check the alignment at runtime and make the optimal decisions. */ ! if (INTVAL (operands[3]) < 4 && (GET_CODE (operands[2]) != CONST_INT || (INTVAL (operands[2]) / INTVAL (operands[3]) > 16))) *************** *** 934,938 **** operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); ! operands[2] = force_not_mem (operands[2]); }") --- 1065,1070 ---- operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); ! operands[4] = gen_reg_rtx (SImode); ! operands[5] = gen_reg_rtx (SImode); }") *************** *** 943,957 **** ;; determined, we need two scratch registers for the unrolled code. (define_insn "" ! [(set (mem:BLK (match_operand:SI 0 "register_operand" "r,r")) ! (mem:BLK (match_operand:SI 1 "register_operand" "r,r"))) (clobber (match_dup 0)) (clobber (match_dup 1)) ! (clobber (match_scratch:SI 2 "=r,r")) ;loop cnt/item tmp ! (clobber (match_scratch:SI 3 "=r,r")) ;item tmp (use (match_operand:SI 4 "arith_operand" "J,2")) ;byte count (use (match_operand:SI 5 "const_int_operand" "n,n"))] ;alignment "" "* return output_block_move (operands, !which_alternative);" ! [(set_attr "type" "multi")]) ;; Floating point move insns --- 1075,1089 ---- ;; determined, we need two scratch registers for the unrolled code. (define_insn "" ! [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r")) ! (mem:BLK (match_operand:SI 1 "register_operand" "+r,r"))) (clobber (match_dup 0)) (clobber (match_dup 1)) ! (clobber (match_operand:SI 2 "register_operand" "=r,r")) ;loop cnt/tmp ! (clobber (match_operand:SI 3 "register_operand" "=&r,&r")) ;item tmp (use (match_operand:SI 4 "arith_operand" "J,2")) ;byte count (use (match_operand:SI 5 "const_int_operand" "n,n"))] ;alignment "" "* return output_block_move (operands, !which_alternative);" ! [(set_attr "type" "multi,multi")]) ;; Floating point move insns *************** *** 985,989 **** " { ! if (emit_move_sequence (operands, DFmode)) DONE; }") --- 1117,1121 ---- " { ! if (emit_move_sequence (operands, DFmode, 0)) DONE; }") *************** *** 991,998 **** (define_insn "" [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" ! "=fx,r,Q,Q,fx,&r,?fx,?r") (match_operand:DF 1 "reg_or_nonsymb_mem_operand" ! "fx,r,fx,r,Q,Q,r,fx"))] ! "" "* { --- 1123,1131 ---- (define_insn "" [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" ! "=fx,*r,Q,?Q,fx,*&r,?fx,?r") (match_operand:DF 1 "reg_or_nonsymb_mem_operand" ! "fx,*r,fx,*r,Q,Q,*r,fx"))] ! "register_operand (operands[0], DFmode) ! || register_operand (operands[1], DFmode)" "* { *************** *** 1010,1015 **** " { ! if (emit_move_sequence (operands, DImode)) DONE; }") --- 1143,1178 ---- " { ! if (emit_move_sequence (operands, DImode, 0)) ! DONE; ! }") ! ! (define_expand "reload_indi" ! [(set (match_operand:DI 0 "register_operand" "=z") ! (match_operand:DI 1 "general_operand" "")) ! (clobber (match_operand:SI 2 "register_operand" "=&r"))] ! "" ! " ! { ! if (emit_move_sequence (operands, DImode, operands[2])) ! DONE; ! ! /* We don't want the clobber emitted, so handle this ourselves. */ ! emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); ! DONE; ! }") ! ! (define_expand "reload_outdi" ! [(set (match_operand:DI 0 "general_operand" "") ! (match_operand:DI 1 "register_operand" "z")) ! (clobber (match_operand:SI 2 "register_operand" "=&r"))] ! "" ! " ! { ! if (emit_move_sequence (operands, DImode, operands[2])) DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; }") *************** *** 1033,1036 **** --- 1196,1200 ---- else output_asm_insn (\"ldo 0(0),%0\", operands); + return \"\"; } else if (GET_CODE (op1) == CONST_DOUBLE) *************** *** 1043,1046 **** --- 1207,1211 ---- operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1)); output_asm_insn (singlemove_string (operands), operands); + return \"\"; } else *************** *** 1050,1058 **** (set_attr "length" "2")]) (define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" ! "=r,Q,&r,&r,*f*x,*f*x,*f*x,r,Q") (match_operand:DI 1 "general_operand" ! "r,r,Q,i,r,*f*x,Q,*f*x,*f*x"))] "" "* --- 1215,1241 ---- (set_attr "length" "2")]) + ;;; Experimental + + (define_insn "" + [(set (match_operand:DI 0 "fp_reg_operand" "=fx") + (match_operand:DI 1 "short_memory_operand" "T"))] + "" + "fldds%F1 %1,%0" + [(set_attr "type" "fpload") + (set_attr "length" "1")]) + + (define_insn "" + [(set (match_operand:DI 0 "short_memory_operand" "=T") + (match_operand:DI 1 "fp_reg_operand" "fx"))] + "" + "fstds%F0 %1,%0" + [(set_attr "type" "fpstore") + (set_attr "length" "1")]) + (define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" ! "=r,Q,&r,&r,fx,fx,r") (match_operand:DI 1 "general_operand" ! "r,r,Q,i,r,fx,fx"))] "" "* *************** *** 1062,1072 **** return output_move_double (operands); }" ! [(set_attr "type" "move,store,load,misc,multi,fpalu,fpload,multi,fpstore") ! (set_attr "length" "2,3,3,3,3,2,3,3,3")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") (lo_sum:DI (match_operand:DI 1 "register_operand" "0,r") ! (match_operand:DI 2 "immediate_operand" "in,in")))] "" "* --- 1245,1255 ---- return output_move_double (operands); }" ! [(set_attr "type" "move,store,load,misc,multi,fpalu,multi") ! (set_attr "length" "2,3,3,3,3,2,3")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") (lo_sum:DI (match_operand:DI 1 "register_operand" "0,r") ! (match_operand:DI 2 "immediate_operand" "i,i")))] "" "* *************** *** 1090,1094 **** " { ! if (emit_move_sequence (operands, SFmode)) DONE; }") --- 1273,1277 ---- " { ! if (emit_move_sequence (operands, SFmode, 0)) DONE; }") *************** *** 1101,1105 **** "" "@ ! fcpy %1,%0 copy %1,%0 fstws %1,-16(0,30)\;ldw -16(0,30),%0 --- 1284,1288 ---- "" "@ ! fcpy,sgl %1,%0 copy %1,%0 fstws %1,-16(0,30)\;ldw -16(0,30),%0 *************** *** 1173,1177 **** ldb%M1 %1,%0" [(set_attr "type" "unary,load") ! (set_attr "length" "1")]) (define_expand "zero_extendqisi2" --- 1356,1360 ---- ldb%M1 %1,%0" [(set_attr "type" "unary,load") ! (set_attr "length" "1,1")]) (define_expand "zero_extendqisi2" *************** *** 1205,1209 **** ldb%M1 %1,%0" [(set_attr "type" "unary,load") ! (set_attr "length" "1")]) ;;- sign extension instructions --- 1388,1392 ---- ldb%M1 %1,%0" [(set_attr "type" "unary,load") ! (set_attr "length" "1,1")]) ;;- sign extension instructions *************** *** 1327,1335 **** [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%r") ! (match_operand:DI 2 "register_operand" "r")))] "" ! "add %R1,%R2,%R0\;addc %1,%2,%0" ! [(set_attr "type" "binary") ! (set_attr "length" "2")]) (define_insn "addsi3" --- 1510,1528 ---- [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%r") ! (match_operand:DI 2 "arith11_operand" "rI")))] "" ! "* ! { ! if (GET_CODE (operands[2]) == CONST_INT) ! { ! if (INTVAL (operands[2]) >= 0) ! return \"addi %2,%R1,%R0\;addc %1,0,%0\"; ! else ! return \"addi %2,%R1,%R0\;subb %1,0,%0\"; ! } ! else ! return \"add %R2,%R1,%R0\;addc %2,%1,%0\"; ! }" ! [(set_attr "length" "2")]) (define_insn "addsi3" *************** *** 1371,1375 **** (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] "" ! "") (define_insn "" --- 1564,1589 ---- (set (match_operand:SI 0 "general_operand" "") (reg:SI 29))] "" ! " ! { ! if (TARGET_SNAKE) ! { ! rtx scratch = gen_reg_rtx (DImode); ! operands[1] = force_reg (SImode, operands[1]); ! operands[2] = force_reg (SImode, operands[2]); ! emit_insn (gen_umulsidi3 (scratch, operands[1], operands[2])); ! emit_insn (gen_rtx (SET, VOIDmode, ! operands[0], ! gen_rtx (SUBREG, SImode, scratch, 1))); ! DONE; ! } ! }") ! ! (define_insn "umulsidi3" ! [(set (match_operand:DI 0 "register_operand" "=x") ! (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "x")) ! (zero_extend:DI (match_operand:SI 2 "register_operand" "x"))))] ! "TARGET_SNAKE" ! "xmpyu %1,%2,%0" ! [(set_attr "type" "fpmul")]) (define_insn "" *************** *** 1501,1505 **** DONE; }") ! (define_insn "" [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) --- 1715,1719 ---- DONE; }") ! (define_insn "" [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) *************** *** 1579,1592 **** (define_insn "andsi3" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r")))] "" ! "and %1,%2,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") ! (and:DI (match_operand:DI 1 "register_operand" "r") ! (not:DI (match_operand:DI 2 "register_operand" "r"))))] "" "andcm %2,%1,%0\;andcm %R2,%R1,%R0" --- 1793,1806 ---- (define_insn "andsi3" ! [(set (match_operand:SI 0 "register_operand" "=r,r") ! (and:SI (match_operand:SI 1 "register_operand" "%r,0") ! (match_operand:SI 2 "and_operand" "rO,P")))] "" ! "* return output_and (operands); ") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") ! (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! (match_operand:DI 2 "register_operand" "r")))] "" "andcm %2,%1,%0\;andcm %R2,%R1,%R0" *************** *** 1595,1604 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (match_operand:SI 1 "register_operand" "%r") ! (not:SI (match_operand:SI 2 "register_operand" "r"))))] "" ! "andcm %1,%2,%0") - (define_expand "iordi3" [(set (match_operand:DI 0 "register_operand" "") --- 1809,1817 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) ! (match_operand:SI 2 "register_operand" "r")))] "" ! "andcm %2,%1,%0") (define_expand "iordi3" [(set (match_operand:DI 0 "register_operand" "") *************** *** 1623,1631 **** (define_insn "iorsi3" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (ior:SI (match_operand:SI 1 "register_operand" "%r") ! (match_operand:SI 2 "register_operand" "r")))] "" ! "or %1,%2,%0") (define_expand "xordi3" --- 1836,1844 ---- (define_insn "iorsi3" ! [(set (match_operand:SI 0 "register_operand" "=r,r") ! (ior:SI (match_operand:SI 1 "register_operand" "%r,0") ! (match_operand:SI 2 "ior_operand" "r,n")))] "" ! "* return output_ior (operands); ") (define_expand "xordi3" *************** *** 1655,1659 **** (match_operand:SI 2 "register_operand" "r")))] "" ! "xor %r1,%2,%0") (define_insn "negdi2" --- 1868,1872 ---- (match_operand:SI 2 "register_operand" "r")))] "" ! "xor %1,%2,%0") (define_insn "negdi2" *************** *** 1669,1674 **** (neg:SI (match_operand:SI 1 "register_operand" "r")))] "" ! "@ ! sub 0,%1,%0" [(set_attr "type" "unary")]) --- 1882,1886 ---- (neg:SI (match_operand:SI 1 "register_operand" "r")))] "" ! "sub 0,%1,%0" [(set_attr "type" "unary")]) *************** *** 1685,1689 **** (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") ! (not:DI (match_operand:DI 1 "arith_double_operand" "r")))] "" "uaddcm 0,%1,%0\;uaddcm 0,%R1,%R0" --- 1897,1901 ---- (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") ! (not:DI (match_operand:DI 1 "register_operand" "r")))] "" "uaddcm 0,%1,%0\;uaddcm 0,%R1,%R0" *************** *** 1815,1819 **** (const_int 24)))] "" ! "ldb%M1 %1,%0") (define_insn "" --- 2027,2042 ---- (const_int 24)))] "" ! "ldb%M1 %1,%0" ! [(set_attr "type" "load") ! (set_attr "length" "1")]) ! ! (define_insn "" ! [(set (match_operand:SI 0 "register_operand" "=r") ! (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") ! (const_int 16)))] ! "" ! "ldh%M1 %1,%0" ! [(set_attr "type" "load") ! (set_attr "length" "1")]) (define_insn "" *************** *** 1854,1858 **** [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:SI 1 "register_operand" "") ! (match_operand:SI 2 "arith5_operand" "")))] "" " --- 2077,2081 ---- [(set (match_operand:SI 0 "register_operand" "") (ashift:SI (match_operand:SI 1 "register_operand" "") ! (match_operand:SI 2 "arith32_operand" "")))] "" " *************** *** 1879,1892 **** [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "int5_operand" "L")))] "" "* { rtx xoperands[4]; ! xoperands[0] = operands[0]; xoperands[1] = operands[1]; xoperands[2] = gen_rtx (CONST_INT, VOIDmode, ! 31 - INTVAL (operands[2])); xoperands[3] = gen_rtx (CONST_INT, VOIDmode, ! 32 - INTVAL (operands[2])); output_asm_insn (\"zdep %1,%2,%3,%0\", xoperands); return \"\"; --- 2102,2116 ---- [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "const_int_operand" "n")))] "" "* { rtx xoperands[4]; ! xoperands[0] = operands[0]; ! xoperands[1] = operands[1]; xoperands[2] = gen_rtx (CONST_INT, VOIDmode, ! 31 - (INTVAL (operands[2]) & 31)); xoperands[3] = gen_rtx (CONST_INT, VOIDmode, ! 32 - (INTVAL (operands[2]) & 31)); output_asm_insn (\"zdep %1,%2,%3,%0\", xoperands); return \"\"; *************** *** 1904,1908 **** [(set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_operand:SI 1 "register_operand" "") ! (match_operand:SI 2 "arith5_operand" "")))] "" " --- 2128,2132 ---- [(set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_operand:SI 1 "register_operand" "") ! (match_operand:SI 2 "arith32_operand" "")))] "" " *************** *** 1929,1952 **** [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "int5_operand" "L")))] "" "* { rtx xoperands[4]; ! xoperands[0] = operands[0]; xoperands[1] = operands[1]; xoperands[2] = gen_rtx (CONST_INT, VOIDmode, ! 31 - INTVAL (operands[2])); xoperands[3] = gen_rtx (CONST_INT, VOIDmode, ! 32 - INTVAL (operands[2])); output_asm_insn (\"extrs %1,%2,%3,%0\", xoperands); return \"\"; }") - (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (minus:SI (const_int 31) ! (reg:SI 112))))] "" "vextrs %1,32,%0") --- 2153,2176 ---- [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "const_int_operand" "n")))] "" "* { rtx xoperands[4]; ! xoperands[0] = operands[0]; ! xoperands[1] = operands[1]; xoperands[2] = gen_rtx (CONST_INT, VOIDmode, ! 31 - (INTVAL (operands[2]) & 31)); xoperands[3] = gen_rtx (CONST_INT, VOIDmode, ! 32 - (INTVAL (operands[2]) & 31)); output_asm_insn (\"extrs %1,%2,%3,%0\", xoperands); return \"\"; }") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (minus:SI (const_int 31) ! (reg:SI 112))))] "" "vextrs %1,32,%0") *************** *** 1955,1959 **** [(set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_operand:SI 1 "register_operand" "") ! (match_operand:SI 2 "arith5_operand" "")))] "" " --- 2179,2183 ---- [(set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_operand:SI 1 "register_operand" "") ! (match_operand:SI 2 "arith32_operand" "")))] "" " *************** *** 1980,1993 **** [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "uint5_operand" "K")))] "" "* { rtx xoperands[4]; ! xoperands[0] = operands[0]; xoperands[1] = operands[1]; xoperands[2] = gen_rtx (CONST_INT, VOIDmode, ! 31 - INTVAL (operands[2])); xoperands[3] = gen_rtx (CONST_INT, VOIDmode, ! 32 - INTVAL (operands[2])); output_asm_insn (\"extru %1,%2,%3,%0\", xoperands); return \"\"; --- 2204,2218 ---- [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (match_operand:SI 2 "const_int_operand" "n")))] "" "* { rtx xoperands[4]; ! xoperands[0] = operands[0]; ! xoperands[1] = operands[1]; xoperands[2] = gen_rtx (CONST_INT, VOIDmode, ! 31 - (INTVAL (operands[2]) & 31)); xoperands[3] = gen_rtx (CONST_INT, VOIDmode, ! 32 - (INTVAL (operands[2]) & 31)); output_asm_insn (\"extru %1,%2,%3,%0\", xoperands); return \"\"; *************** *** 1997,2002 **** [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (minus:SI (const_int 31) ! (reg:SI 112))))] "" "vextru %1,32,%0") --- 2222,2227 ---- [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! (minus:SI (const_int 31) ! (reg:SI 112))))] "" "vextru %1,32,%0") *************** *** 2010,2026 **** [(set_attr "type" "branch")]) ! (define_insn "casesi" [(set (pc) ! (if_then_else (leu (minus:SI ! (match_operand:SI 0 "general_operand" "r") ! (match_operand:SI 1 "general_operand" "rI")) ! (match_operand:SI 2 "general_operand" "rI")) ! (plus:SI (mem:SI (plus:SI (pc) ! (minus:SI (match_dup 0) ! (match_dup 1)))) ! (label_ref (match_operand 3 "" ""))) (pc))) ! (use (label_ref (match_operand 4 "" ""))) ! (clobber (match_scratch:SI 5 "=r"))] "" "* --- 2235,2285 ---- [(set_attr "type" "branch")]) ! ;; Subroutines of "casesi". ! ;; operand 0 is index ! ;; operand 1 is the minimum bound ! ;; operand 2 is the maximum bound - minimum bound + 1 ! ;; operand 3 is CODE_LABEL for the table; ! ;; operand 4 is the CODE_LABEL to go to if index out of range. ! ! (define_expand "casesi" ! [(match_operand:SI 0 "general_operand" "") ! (match_operand:SI 1 "const_int_operand" "") ! (match_operand:SI 2 "const_int_operand" "") ! (match_operand 3 "" "") ! (match_operand 4 "" "")] ! "" ! " ! { ! if (GET_CODE (operands[0]) != REG) ! operands[0] = force_reg (SImode, operands[0]); ! ! if (operands[1] != const0_rtx) ! { ! rtx reg = gen_reg_rtx (SImode); ! ! operands[1] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1])); ! if (!INT_14_BITS (operands[1])) ! operands[1] = force_reg (SImode, operands[1]); ! emit_insn (gen_addsi3 (reg, operands[0], operands[1])); ! ! operands[0] = reg; ! } ! ! if (!INT_11_BITS (operands[2])) ! operands[2] = force_reg (SImode, operands[2]); ! ! emit_jump_insn (gen_casesi0 (operands[0], operands[2], ! operands[3], operands[4])); ! DONE; ! }") ! ! (define_insn "casesi0" [(set (pc) ! (if_then_else (leu (match_operand:SI 0 "register_operand" "r") ! (match_operand:SI 1 "arith11_operand" "rI")) ! (plus:SI (mem:SI (plus:SI (pc) (match_dup 0))) ! (label_ref (match_operand 2 "" ""))) (pc))) ! (use (label_ref (match_operand 3 "" "")))] "" "* *************** *** 2028,2066 **** if (GET_CODE (operands[1]) == CONST_INT) { ! if (GET_CODE (operands[2]) == CONST_INT) ! { ! operands[2] = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (operands[1]) + INTVAL (operands[2])); ! if (!INT_11_BITS (operands[2])) ! { ! output_asm_insn (\"ldo %2(0),%5\", operands); ! operands[2] = operands[5]; ! } ! } ! else ! output_asm_insn (\"ldo %1(%2),%2\", operands); ! output_asm_insn (\"addi,< %n1,%0,0\", operands); } else { ! if (GET_CODE (operands[2]) == CONST_INT) ! { ! output_asm_insn (\"ldo %2(%1),%5\", operands); ! operands[2] = operands[5]; ! } ! output_asm_insn (\"sub,< %0,%1,0\", operands); } - if (GET_CODE (operands[2]) == CONST_INT) - output_asm_insn (\"addi,<= %n2,%0,0\", operands); - else - output_asm_insn (\"sub,<= %0,%2,0\", operands); - output_asm_insn (\"b,n %l4\", operands); - if (GET_CODE (operands[1]) == CONST_INT) - output_asm_insn (\"ldo %n1(%0),%5\", operands); - else output_asm_insn (\"sub %0,%1,%5\", operands); - return \"blr %5,0\;nop\"; }" ! [(set_attr "length" "7")]) ! ;; Need nops for the calls because execution is supposed to continue ;; past; we don't want to nullify an instruction that we need. --- 2287,2301 ---- if (GET_CODE (operands[1]) == CONST_INT) { ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[1])); ! return \"addi,uv %1,%0,0\;blr,n %0,0\;b,n %l3\"; } else { ! return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\"; } }" ! [(set_attr "length" "3")]) ! ! ;; Need nops for the calls because execution is supposed to continue ;; past; we don't want to nullify an instruction that we need. *************** *** 2075,2079 **** " { ! operands[0] = gen_rtx (MEM, SImode, XEXP (operands[0], 0)); }") --- 2310,2318 ---- " { ! if (TARGET_LONG_CALLS) ! operands[0] = gen_rtx (MEM, SImode, ! force_reg (SImode, XEXP (operands[0], 0))); ! else ! operands[0] = gen_rtx (MEM, SImode, XEXP (operands[0], 0)); }") *************** *** 2107,2111 **** " { ! operands[1] = gen_rtx (MEM, SImode, XEXP (operands[1], 0)); }") --- 2346,2354 ---- " { ! if (TARGET_LONG_CALLS) ! operands[1] = gen_rtx (MEM, SImode, ! force_reg (SImode, XEXP (operands[1], 0))); ! else ! operands[1] = gen_rtx (MEM, SImode, XEXP (operands[1], 0)); }") *************** *** 2125,2133 **** { output_arg_descriptor (insn); ! return \"bl %1,2\;nop\"; } }" ! [(set_attr "type" "dyncall") ! (set_attr "length" "3,2")]) (define_insn "nop" --- 2368,2376 ---- { output_arg_descriptor (insn); ! return \"bl %1,2%#\"; } }" ! [(set_attr "type" "dyncall,call") ! (set_attr "length" "3,1")]) (define_insn "nop" *************** *** 2140,2144 **** [(set (pc) (match_operand:SI 0 "register_operand" "r"))] "" ! "bv 0(%0)%#" [(set_attr "type" "branch")]) --- 2383,2387 ---- [(set (pc) (match_operand:SI 0 "register_operand" "r"))] "" ! "bv%* 0(%0)" [(set_attr "type" "branch")]) *************** *** 2160,2169 **** (define_insn "insv" ! [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "uint5_operand" "") (match_operand:SI 2 "uint5_operand" "")) ! (match_operand:SI 3 "register_operand" "r"))] "" ! "dep %3,%2+%1-1,%1,%0") ;; This insn is used for some loop tests, typically loops reversed when --- 2403,2428 ---- (define_insn "insv" ! [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r") (match_operand:SI 1 "uint5_operand" "") (match_operand:SI 2 "uint5_operand" "")) ! (match_operand:SI 3 "arith5_operand" "r,L"))] "" ! "@ ! dep %3,%2+%1-1,%1,%0 ! depi %3,%2+%1-1,%1,%0") ! ! ;; Optimize insertion of const_int values of type 1...1xxxx. ! (define_insn "" ! [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") ! (match_operand:SI 1 "uint5_operand" "") ! (match_operand:SI 2 "uint5_operand" "")) ! (match_operand:SI 3 "const_int_operand" ""))] ! "(INTVAL (operands[3]) & 0x10) != 0 && ! (~INTVAL (operands[3]) & (1L << INTVAL (operands[1])) - 1 & ~0xf) == 0" ! "* ! { ! operands[3] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[3]) & 0xf) - 0x10); ! return \"depi %3,%2+%1-1,%1,%0\"; ! }") ;; This insn is used for some loop tests, typically loops reversed when diff -rc2N gcc-2.2.2/config/pa1-ghpux.h gcc-2.3.1/config/pa1-ghpux.h *** gcc-2.2.2/config/pa1-ghpux.h Mon May 4 14:09:15 1992 --- gcc-2.3.1/config/pa1-ghpux.h Wed Oct 14 10:37:34 1992 *************** *** 27,30 **** #undef TARGET_DEFAULT #define TARGET_DEFAULT 1 ! --- 27,33 ---- #undef TARGET_DEFAULT + #ifdef hpux8 + #define TARGET_DEFAULT 9 + #else #define TARGET_DEFAULT 1 ! #endif diff -rc2N gcc-2.2.2/config/pa1-hpux.h gcc-2.3.1/config/pa1-hpux.h *** gcc-2.2.2/config/pa1-hpux.h Mon May 4 14:09:00 1992 --- gcc-2.3.1/config/pa1-hpux.h Wed Oct 14 10:37:47 1992 *************** *** 27,30 **** --- 27,34 ---- #undef TARGET_DEFAULT + #ifdef hpux8 + #define TARGET_DEFAULT 9 + #else #define TARGET_DEFAULT 1 + #endif diff -rc2N gcc-2.2.2/config/pbd.h gcc-2.3.1/config/pbd.h *** gcc-2.2.2/config/pbd.h Thu Jun 11 01:01:52 1992 --- gcc-2.3.1/config/pbd.h Thu Oct 1 00:52:42 1992 *************** *** 67,71 **** #define SCCS_DIRECTIVE ! /* LINK_SPEC is needed only for Sunos 4. */ #undef LINK_SPEC --- 67,71 ---- #define SCCS_DIRECTIVE ! /* LINK_SPEC is needed only for SunOS 4. */ #undef LINK_SPEC *************** *** 150,157 **** #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ fprintf (FILE, "\t.word .L%d\n", VALUE) - - /* Underscores are not used on Unicom PBD coff systems. */ - /* This currently seems to only be needed for libgcc2.a */ - #define NO_UNDERSCORES /* Output assembler code to FILE to increment profiler label # LABELNO --- 150,153 ---- diff -rc2N gcc-2.2.2/config/plexus.h gcc-2.3.1/config/plexus.h *** gcc-2.2.2/config/plexus.h --- gcc-2.3.1/config/plexus.h Mon Jul 27 22:21:05 1992 *************** *** 0 **** --- 1,90 ---- + /* Definitions of target machine for GNU compiler. + Copyright (C) 1990 Free Software Foundation, Inc. + + Written by Randy Welch + Send bug reports, questions and improvements to any of the following + addresses: + + randy@kcin.alphacdc.com + rwelch@isis.cs.du.eu + rwelch@csn.org + + For Plexus P/60 and assumably P/35 P/75 P/95's running System V.2 + + This file outputs assembler source for gas-1.38.1 with the COFF patches + The patches for gas-1.38.1 to support COFF is on ftp.cs.umb.edu in pub/gnu + No debugging is supported, due to the fact that the only debugger Plexus + had was adb *sigh*. + + This is configured for label output default by gas as LXXX instead of + plexus cc/as combination requires .LXXX + + 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 1, 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 "m68k.h" + + /* Define __HAVE_68881 in preprocessor only if -m68881 is specified. + This will control the use of inline 68881 insns in certain macros. */ + + #define TARGET_DEFAULT 5 /* set to 5 if on a '020 box */ + + #define CPP_SPEC "%{m68881:-D__HAVE_68881__}" + #define CPP_PREDEFINES "-Dm68 -Dunix -Dplexus" + + #if TARGET_DEFAULT & 01 + #define ASM_SPEC\ + "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}" + #undef STRICT_ALIGNMENT + #define STRICT_ALIGNMENT 0 + #else + #define ASM_SPEC\ + "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!mc68020:-mc68000}}" + #endif + + /***************************************************************************/ + /* Un comment the following if you want adb to be able to follow a core */ + /* file if you compile a program with -O */ + /***************************************************************************/ + /* #define FRAME_POINTER_REQUIRED */ + + /* Let's be compatible with the Plexus C compiler by default. Why not? */ + #define PLEXUS_CC_COMPAT + + #ifdef PLEXUS_CC_COMPAT + #define STRUCTURE_SIZE_BOUNDARY 16 /* for compatiblity with cc */ + #undef STACK_BOUNDARY + #define STACK_BOUNDARY 32 /* ditto */ + #endif + + #undef NEED_PROBE + #define NEED_PROBE -132 /* plexus needs a stack probe */ + + #undef DBX_DEBUGGING_INFO /* no real debugger */ + #undef SDB_DEBUGGING_INFO + + #define TARGET_MEM_FUNCTIONS + + /***********************************************************************/ + /* items for collect2 */ + /***********************************************************************/ + + #define NM_FLAGS "" + #define NO_SYS_SIGLIST + #define NO_DUP2 + + #define SIZE_TYPE int diff -rc2N gcc-2.2.2/config/romp.c gcc-2.3.1/config/romp.c *** gcc-2.2.2/config/romp.c Wed Apr 22 17:11:03 1992 --- gcc-2.3.1/config/romp.c Fri Oct 23 07:48:23 1992 *************** *** 1810,1813 **** --- 1810,1815 ---- case CONST_DOUBLE: case CONST: + case SYMBOL_REF: + case LABEL_REF: type += 0x20; opbyte = 0; diff -rc2N gcc-2.2.2/config/romp.h gcc-2.3.1/config/romp.h *** gcc-2.2.2/config/romp.h Sat May 30 18:30:59 1992 --- gcc-2.3.1/config/romp.h Sun Sep 27 13:03:50 1992 *************** *** 84,87 **** --- 84,90 ---- } \ } + + /* Match 's definition. */ + #define SIZE_TYPE "long int" /* target machine storage layout */ *************** *** 419,423 **** && reg_renumber != 0 \ && reg_renumber[REGNO (OP)] < 0) \ ! || (memory_operand (OP, VOIDmode) \ && ! symbolic_memory_operand (OP, VOIDmode))) \ : (C) == 'R' ? current_function_operand (OP, VOIDmode) \ --- 422,426 ---- && reg_renumber != 0 \ && reg_renumber[REGNO (OP)] < 0) \ ! || (GET_CODE (OP) == MEM \ && ! symbolic_memory_operand (OP, VOIDmode))) \ : (C) == 'R' ? current_function_operand (OP, VOIDmode) \ *************** *** 1224,1229 **** /* Define this if shift instructions ignore all but the low-order ! few bits. */ ! #define SHIFT_COUNT_TRUNCATED /* Compute the cost of computing a constant rtl expression RTX whose --- 1227,1236 ---- /* Define this if shift instructions ignore all but the low-order ! few bits. ! ! This is not true on the RT since it uses the low-order 6, not 5, bits. ! At some point, this should be extended to see how to express that. */ ! ! /* #define SHIFT_COUNT_TRUNCATED */ /* Compute the cost of computing a constant rtl expression RTX whose diff -rc2N gcc-2.2.2/config/romp.md gcc-2.3.1/config/romp.md *** gcc-2.2.2/config/romp.md Sun Jun 7 15:57:16 1992 --- gcc-2.3.1/config/romp.md Wed Sep 23 19:18:23 1992 *************** *** 27,31 **** (define_attr "type" ! "branch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc" (const_string "arith")) --- 27,31 ---- (define_attr "type" ! "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc" (const_string "arith")) *************** *** 40,44 **** (const_int 2) (const_int 4)) ! (eq_attr "type" "return") (const_int 2) (eq_attr "type" "fp") (const_int 10) (eq_attr "type" "call") (const_int 4) --- 40,44 ---- (const_int 2) (const_int 4)) ! (eq_attr "type" "return,ibranch") (const_int 2) (eq_attr "type" "fp") (const_int 10) (eq_attr "type" "call") (const_int 4) *************** *** 61,70 **** (define_attr "in_delay_slot" "yes,no" (cond [(eq_attr "length" "8,10,38") (const_string "no") ! (eq_attr "type" "branch,return,call,multi") (const_string "no")] (const_string "yes"))) ! ;; Whether insn needs a delay slot. (define_attr "needs_delay_slot" "yes,no" ! (if_then_else (eq_attr "type" "branch,return,call") (const_string "yes") (const_string "no"))) --- 61,77 ---- (define_attr "in_delay_slot" "yes,no" (cond [(eq_attr "length" "8,10,38") (const_string "no") ! (eq_attr "type" "branch,ibranch,return,call,multi") ! (const_string "no")] (const_string "yes"))) ! ;; Whether insn needs a delay slot. We have to say that two-byte ! ;; branches do not need a delay slot. Otherwise, branch shortening will ! ;; try to do something with delay slot insns (we want it to on the PA). ! ;; This is a kludge, which should be cleaned up at some point. ! (define_attr "needs_delay_slot" "yes,no" ! (if_then_else (ior (and (eq_attr "type" "branch") ! (eq_attr "length" "4")) ! (eq_attr "type" "ibranch,return,call")) (const_string "yes") (const_string "no"))) *************** *** 76,80 **** (eq_attr "type" "store") (const_string "none") (eq_attr "type" "fp,call") (const_string "clobber") ! (eq_attr "type" "branch,return") (const_string "none") (eq_attr "type" "address") (const_string "change0") (eq_attr "type" "compare") (const_string "compare") --- 83,87 ---- (eq_attr "type" "store") (const_string "none") (eq_attr "type" "fp,call") (const_string "clobber") ! (eq_attr "type" "branch,ibranch,return") (const_string "none") (eq_attr "type" "address") (const_string "change0") (eq_attr "type" "compare") (const_string "compare") *************** *** 802,806 **** operands[3] = operand_subword (operands[0], 0, 0, DFmode); operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15)); ! operands[5] = operand_subword (operands[0], 0, 1, DFmode); operands[6] = gen_rtx (MEM, SImode, gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15), --- 809,813 ---- operands[3] = operand_subword (operands[0], 0, 0, DFmode); operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15)); ! operands[5] = operand_subword (operands[0], 1, 0, DFmode); operands[6] = gen_rtx (MEM, SImode, gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15), *************** *** 981,985 **** ;; Now zero extensions: (define_expand "zero_extendhisi2" ! [(set (match_operand:SI 0 "register_operand" "b") (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] "" --- 988,992 ---- ;; Now zero extensions: (define_expand "zero_extendhisi2" ! [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] "" *************** *** 1603,1607 **** [(set (match_operand:SI 0 "register_operand" "=r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") ! (match_operand:QI 2 "reg_or_cint_operand" "r,n")))] "" "@ --- 1610,1614 ---- [(set (match_operand:SI 0 "register_operand" "=r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") ! (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] "" "@ *************** *** 1613,1617 **** [(set (match_operand:SI 0 "register_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") ! (match_operand:QI 2 "reg_or_cint_operand" "r,n")))] "" "@ --- 1620,1624 ---- [(set (match_operand:SI 0 "register_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") ! (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] "" "@ *************** *** 1632,1636 **** [(set (match_operand:SI 0 "register_operand" "=r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0") ! (match_operand:QI 2 "reg_or_cint_operand" "r,n")))] "" "@ --- 1639,1643 ---- [(set (match_operand:SI 0 "register_operand" "=r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0") ! (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] "" "@ *************** *** 2712,2717 **** "" "br%# %0" ! [(set_attr "type" "branch") ! (set_attr "length" "2")]) ;; Table jump for switch statements: --- 2719,2723 ---- "" "br%# %0" ! [(set_attr "type" "ibranch")]) ;; Table jump for switch statements: *************** *** 2722,2727 **** "" "br%# %0" ! [(set_attr "type" "branch") ! (set_attr "length" "2")]) ;;- Local variables: --- 2728,2732 ---- "" "br%# %0" ! [(set_attr "type" "ibranch")]) ;;- Local variables: diff -rc2N gcc-2.2.2/config/rs6000-mach.h gcc-2.3.1/config/rs6000-mach.h *** gcc-2.2.2/config/rs6000-mach.h Sat Feb 1 09:18:06 1992 --- gcc-2.3.1/config/rs6000-mach.h Fri Jul 3 16:52:22 1992 *************** *** 30,34 **** #undef LINK_SPEC #define LINK_SPEC \ ! "-T0x10000000 -D0x20000000 -K -e __start \ -bnoso -berrmsg -btextro -bhalt:4 -bnodelcsect" --- 30,34 ---- #undef LINK_SPEC #define LINK_SPEC \ ! "-T0x10000000 -D0x20000000 -K %{!nostdlib:%{!r*:%{!e*:-e __start}}} \ -bnoso -berrmsg -btextro -bhalt:4 -bnodelcsect" diff -rc2N gcc-2.2.2/config/rs6000.c gcc-2.3.1/config/rs6000.c *** gcc-2.2.2/config/rs6000.c Fri May 22 06:33:15 1992 --- gcc-2.3.1/config/rs6000.c Sat Sep 19 15:35:26 1992 *************** *** 711,715 **** { case 'h': ! /* If constant, output low-order six bits. Otherwise, write normally. */ if (INT_P (x)) fprintf (file, "%d", INT_LOWPART (x) & 31); --- 711,716 ---- { case 'h': ! /* If constant, output low-order five bits. Otherwise, ! write normally. */ if (INT_P (x)) fprintf (file, "%d", INT_LOWPART (x) & 31); *************** *** 719,723 **** case 'H': ! /* X must be a constant. Output the low order 6 bits plus 24. */ if (! INT_P (x)) output_operand_lossage ("invalid %%H value"); --- 720,724 ---- case 'H': ! /* X must be a constant. Output the low order 5 bits plus 24. */ if (! INT_P (x)) output_operand_lossage ("invalid %%H value"); *************** *** 738,742 **** normally. */ if (INT_P (x)) ! fprintf (file, "%d", (INT_LOWPART (x) << 16) >> 16); else print_operand (file, x, 0); --- 739,744 ---- normally. */ if (INT_P (x)) ! fprintf (file, "%d", ! (INT_LOWPART (x) & 0xffff) - 2 * (INT_LOWPART (x) & 0x8000)); else print_operand (file, x, 0); *************** *** 1410,1419 **** ASM_OUTPUT_LABEL (file, fname); ! /* The .tbtab psuedo-op can only be used for the first eight expressions, since it can't handle the possibly variable length fields that follow. However, if you omit the optional fields, the assembler outputs zeros for all optional fields anyways, giving each variable length field is minimum length (as defined in sys/debug.h). ! Thus we can not use the .tbtab psuedo-op at all. */ /* An all-zero word flags the start of the tbtab, for debuggers that have --- 1412,1421 ---- ASM_OUTPUT_LABEL (file, fname); ! /* The .tbtab pseudo-op can only be used for the first eight expressions, since it can't handle the possibly variable length fields that follow. However, if you omit the optional fields, the assembler outputs zeros for all optional fields anyways, giving each variable length field is minimum length (as defined in sys/debug.h). ! Thus we can not use the .tbtab pseudo-op at all. */ /* An all-zero word flags the start of the tbtab, for debuggers that have *************** *** 1518,1522 **** and thus the maximum value is 13. */ /* Set parameters on stack bit if parameters are not in their original ! registers, irregardless of whether they are on the stack? Xlc seems to set the bit when not optimizing. */ fprintf (file, "%d\n", ((float_parms << 1) | (! optimize))); --- 1520,1524 ---- and thus the maximum value is 13. */ /* Set parameters on stack bit if parameters are not in their original ! registers, regardless of whether they are on the stack? Xlc seems to set the bit when not optimizing. */ fprintf (file, "%d\n", ((float_parms << 1) | (! optimize))); *************** *** 1542,1546 **** /* Interrupt handler mask. */ ! /* Omit this long, since we never set the iterrupt handler bit above. */ /* Number of CTL (controlled storage) anchors. */ --- 1544,1548 ---- /* Interrupt handler mask. */ ! /* Omit this long, since we never set the interrupt handler bit above. */ /* Number of CTL (controlled storage) anchors. */ diff -rc2N gcc-2.2.2/config/rs6000.h gcc-2.3.1/config/rs6000.h *** gcc-2.2.2/config/rs6000.h Sat May 30 18:30:42 1992 --- gcc-2.3.1/config/rs6000.h Sat Oct 24 21:03:46 1992 *************** *** 50,54 **** csects. See AIX documentation for more information about this. */ ! #define LINK_SPEC "-T512 -H512 -btextro -bhalt:4 -bnodelcsect" /* Profiled library versions are used by linking with special directories. */ --- 50,55 ---- csects. See AIX documentation for more information about this. */ ! #define LINK_SPEC "-T512 -H512 -btextro -bhalt:4 -bnodelcsect\ ! %{static:-bnso -bI:/lib/syscalls.exp}" /* Profiled library versions are used by linking with special directories. */ *************** *** 104,107 **** --- 105,119 ---- /* target machine storage layout */ + /* Define this macro if it is advisible 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) < 4) \ + (MODE) == SImode; + /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. */ *************** *** 331,343 **** On the RS/6000, bump this up a bit. */ ! #define MEMORY_MOVE_COST(MODE) 4 /* Specify the cost of a branch insn; roughly the number of extra insns that should be added to avoid a branch. ! Set this to 2 on the RS/6000 since that is roughly the average cost of an unscheduled conditional branch. */ ! #define BRANCH_COST 2 /* Specify the registers used for certain standard purposes. --- 343,355 ---- On the RS/6000, bump this up a bit. */ ! #define MEMORY_MOVE_COST(MODE) 6 /* Specify the cost of a branch insn; roughly the number of extra insns that should be added to avoid a branch. ! Set this to 3 on the RS/6000 since that is roughly the average cost of an unscheduled conditional branch. */ ! #define BRANCH_COST 3 /* Specify the registers used for certain standard purposes. *************** *** 402,406 **** enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS, NON_SPECIAL_REGS, MQ_REGS, LINK_REGS, CTR_REGS, LINK_OR_CTR_REGS, ! SPECIAL_REGS, CR0_REGS, CR_REGS, ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES --- 414,419 ---- enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS, NON_SPECIAL_REGS, MQ_REGS, LINK_REGS, CTR_REGS, LINK_OR_CTR_REGS, ! SPECIAL_REGS, SPEC_OR_GEN_REGS, CR0_REGS, CR_REGS, NON_FLOAT_REGS, ! ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES *************** *** 411,415 **** { "NO_REGS", "BASE_REGS", "GENERAL_REGS", "FLOAT_REGS", \ "NON_SPECIAL_REGS", "MQ_REGS", "LINK_REGS", "CTR_REGS", \ ! "LINK_OR_CTR_REGS", "SPECIAL_REGS", "CR0_REGS", "CR_REGS", "ALL_REGS" } /* Define which registers fit in which classes. --- 424,429 ---- { "NO_REGS", "BASE_REGS", "GENERAL_REGS", "FLOAT_REGS", \ "NON_SPECIAL_REGS", "MQ_REGS", "LINK_REGS", "CTR_REGS", \ ! "LINK_OR_CTR_REGS", "SPECIAL_REGS", "SPEC_OR_GEN_REGS", \ ! "CR0_REGS", "CR_REGS", "NON_FLOAT_REGS", "ALL_REGS" } /* Define which registers fit in which classes. *************** *** 419,425 **** #define REG_CLASS_CONTENTS \ { {0, 0, 0}, {0xfffffffe, 0, 8}, {~0, 0, 8}, \ ! {0, ~0, 0}, {~0, ~0, 0}, {0, 0, 1}, {0, 0, 2}, \ ! {0, 0, 4}, {0, 0, 6}, {0, 0, 7}, {0, 0, 16}, \ ! {0, 0, 0xff0}, {~0, ~0, 0xfff5} } /* The same information, inverted: --- 433,440 ---- #define REG_CLASS_CONTENTS \ { {0, 0, 0}, {0xfffffffe, 0, 8}, {~0, 0, 8}, \ ! {0, ~0, 0}, {~0, ~0, 8}, {0, 0, 1}, {0, 0, 2}, \ ! {0, 0, 4}, {0, 0, 6}, {0, 0, 7}, {~0, 0, 15}, \ ! {0, 0, 16}, {0, 0, 0xff0}, {~0, 0, 0xffff}, \ ! {~0, ~0, 0xffff} } /* The same information, inverted: *************** *** 497,502 **** an offset from a register. */ ! #define EXTRA_CONSTRAINT(OP, C) \ ! ((C) == 'Q' ? indirect_operand (OP, VOIDmode) : 0) /* Given an rtx X being reloaded into a reg required to be --- 512,518 ---- an offset from a register. */ ! #define EXTRA_CONSTRAINT(OP, C) \ ! ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \ ! : 0) /* Given an rtx X being reloaded into a reg required to be *************** *** 711,715 **** If this is floating-point and no prototype is specified, we use ! both an FP and integer register (or possibly FP reg and stack). */ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ --- 727,734 ---- If this is floating-point and no prototype is specified, we use ! both an FP and integer register (or possibly FP reg and stack). Library ! functions (when TYPE is zero) always have the proper types for args, ! so we can pass the FP value just in one register. emit_library_function ! doesn't support EXPR_LIST anyway. */ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ *************** *** 717,721 **** : ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST) ? 0 \ : USE_FP_FOR_ARG_P (CUM, MODE, TYPE) \ ! ? ((CUM).nargs_prototype > 0 \ ? gen_rtx (REG, MODE, (CUM).fregno) \ : ((CUM).words < 8 \ --- 736,740 ---- : ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST) ? 0 \ : USE_FP_FOR_ARG_P (CUM, MODE, TYPE) \ ! ? ((CUM).nargs_prototype > 0 || (TYPE) == 0 \ ? gen_rtx (REG, MODE, (CUM).fregno) \ : ((CUM).words < 8 \ *************** *** 1085,1089 **** } \ else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ ! && GET_CODE (XEXP (X, 1)) != CONST_INT) \ { \ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ --- 1104,1109 ---- } \ else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ ! && GET_CODE (XEXP (X, 1)) != CONST_INT \ ! && (MODE) != DImode && (MODE) != TImode) \ { \ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ *************** *** 1269,1273 **** the result of a comparison. CCmode should be used in all other cases. */ ! #define SELECT_CC_MODE(OP,X) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \ : (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \ --- 1289,1293 ---- the result of a comparison. CCmode should be used in all other cases. */ ! #define SELECT_CC_MODE(OP,X,Y) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \ : (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \ diff -rc2N gcc-2.2.2/config/rs6000.md gcc-2.3.1/config/rs6000.md *** gcc-2.2.2/config/rs6000.md Wed May 6 07:35:29 1992 --- gcc-2.3.1/config/rs6000.md Sat Oct 24 21:03:39 1992 *************** *** 98,102 **** (define_expand "zero_extendhisi2" ! [(set (match_operand:SI 0 "gpc_reg_operand" "r") (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "")))] "" --- 98,102 ---- (define_expand "zero_extendhisi2" ! [(set (match_operand:SI 0 "gpc_reg_operand" "") (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "")))] "" *************** *** 272,276 **** ;; For SMIN, SMAX, UMIN, and UMAX, we use DEFINE_EXPAND's that involve a doz[i] ;; instruction and some auxiliary computations. Then we just have a single ! ;; DEFINE_INSN for doz[i]. (define_expand "sminsi3" --- 272,277 ---- ;; For SMIN, SMAX, UMIN, and UMAX, we use DEFINE_EXPAND's that involve a doz[i] ;; instruction and some auxiliary computations. Then we just have a single ! ;; DEFINE_INSN for doz[i] and the define_splits to make them if made by ! ;; combine. (define_expand "sminsi3" *************** *** 286,289 **** --- 287,303 ---- { operands[3] = gen_reg_rtx (SImode); }") + (define_split + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (smin:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_short_operand" ""))) + (clobber (match_operand:SI 3 "gpc_reg_operand" ""))] + "" + [(set (match_dup 3) + (if_then_else:SI (gt:SI (match_dup 1) (match_dup 2)) + (const_int 0) + (minus:SI (match_dup 2) (match_dup 1)))) + (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 3)))] + "") + (define_expand "smaxsi3" [(set (match_dup 3) *************** *** 298,301 **** --- 312,328 ---- { operands[3] = gen_reg_rtx (SImode); }") + (define_split + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (smax:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_short_operand" ""))) + (clobber (match_operand:SI 3 "gpc_reg_operand" ""))] + "" + [(set (match_dup 3) + (if_then_else:SI (gt:SI (match_dup 1) (match_dup 2)) + (const_int 0) + (minus:SI (match_dup 2) (match_dup 1)))) + (set (match_dup 0) (plus:SI (match_dup 3) (match_dup 1)))] + "") + (define_expand "uminsi3" [(set (match_dup 3) (xor:SI (match_operand:SI 1 "gpc_reg_operand" "") *************** *** 536,546 **** (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")) (const_int 32)) ! (zero_extend:DI (match_operand:SI 2 "register_operand" "*q"))) (match_operand:SI 3 "gpc_reg_operand" "r"))) ! (set (match_operand:SI 4 "register_operand" "=*q") (umod:SI (plus:DI (lshift:DI (zero_extend:DI (match_dup 1)) (const_int 32)) ! (zero_extend:DI (match_dup 2))) (match_dup 3)))] --- 563,573 ---- (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")) (const_int 32)) ! (zero_extend:DI (match_operand:SI 4 "register_operand" "2"))) (match_operand:SI 3 "gpc_reg_operand" "r"))) ! (set (match_operand:SI 2 "register_operand" "=*q") (umod:SI (plus:DI (lshift:DI (zero_extend:DI (match_dup 1)) (const_int 32)) ! (zero_extend:DI (match_dup 4))) (match_dup 3)))] *************** *** 939,989 **** (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0")) ! (and:SI (match_dup 1) (match_operand:SI 3 "gpc_reg_operand" "r"))))] "" ! "maskir %0,%3,%1") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (ior:SI (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0")) (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_dup 1))))] "" ! "maskir %0,%3,%1") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_dup 1) (match_operand:SI 3 "gpc_reg_operand" "r")) ! (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0"))))] "" ! "maskir %0,%3,%1") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (ior:SI (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_dup 1)) ! (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0"))))] "" ! "maskir %0,%3,%1") (define_insn "" [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC ! (ior:SI (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0")) ! (and:SI (match_dup 1) (match_operand:SI 3 "gpc_reg_operand" "r"))) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (match_dup 1)) (match_dup 2)) ! (and:SI (match_dup 1) (match_dup 3))))] "" ! "maskir. %0,%3,%1" [(set_attr "type" "compare")]) --- 966,1016 ---- (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")) ! (match_operand:SI 1 "gpc_reg_operand" "0")) ! (and:SI (match_dup 2) (match_operand:SI 3 "gpc_reg_operand" "r"))))] "" ! "maskir %0,%3,%2") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (ior:SI (and:SI (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")) ! (match_operand:SI 1 "gpc_reg_operand" "0")) (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_dup 2))))] "" ! "maskir %0,%3,%2") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_operand:SI 2 "gpc_reg_operand" "r") (match_operand:SI 3 "gpc_reg_operand" "r")) ! (and:SI (not:SI (match_dup 2)) ! (match_operand:SI 1 "gpc_reg_operand" "0"))))] "" ! "maskir %0,%3,%2") (define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (ior:SI (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_operand:SI 2 "gpc_reg_operand" "r")) ! (and:SI (not:SI (match_dup 2)) ! (match_operand:SI 1 "gpc_reg_operand" "0"))))] "" ! "maskir %0,%3,%2") (define_insn "" [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC ! (ior:SI (and:SI (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")) ! (match_operand:SI 1 "gpc_reg_operand" "0")) ! (and:SI (match_dup 2) (match_operand:SI 3 "gpc_reg_operand" "r"))) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (not:SI (match_dup 2)) (match_dup 1)) ! (and:SI (match_dup 2) (match_dup 3))))] "" ! "maskir. %0,%3,%2" [(set_attr "type" "compare")]) *************** *** 991,1004 **** [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC ! (ior:SI (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0")) (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_dup 1))) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") ! (ior:SI (and:SI (not:SI (match_dup 1)) (match_dup 2)) ! (and:SI (match_dup 3) (match_dup 1))))] "" ! "maskir. %0,%3,%1" [(set_attr "type" "compare")]) --- 1018,1031 ---- [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC ! (ior:SI (and:SI (not:SI (match_operand:SI 2 "gpc_reg_operand" "r")) ! (match_operand:SI 1 "gpc_reg_operand" "0")) (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_dup 2))) (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") ! (ior:SI (and:SI (not:SI (match_dup 2)) (match_dup 1)) ! (and:SI (match_dup 3) (match_dup 2))))] "" ! "maskir. %0,%3,%2" [(set_attr "type" "compare")]) *************** *** 1006,1019 **** [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC ! (ior:SI (and:SI (match_dup 1) (match_operand:SI 3 "gpc_reg_operand" "r")) ! (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0"))) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_dup 1) (match_dup 3)) ! (and:SI (not:SI (match_dup 1)) (match_dup 2))))] "" ! "maskir. %0,%3,%1" [(set_attr "type" "compare")]) --- 1033,1046 ---- [(set (match_operand:CC 4 "cc_reg_operand" "=x") (compare:CC ! (ior:SI (and:SI (match_operand:SI 2 "gpc_reg_operand" "r") (match_operand:SI 3 "gpc_reg_operand" "r")) ! (and:SI (not:SI (match_dup 2)) ! (match_operand:SI 1 "gpc_reg_operand" "0"))) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_dup 2) (match_dup 3)) ! (and:SI (not:SI (match_dup 2)) (match_dup 1))))] "" ! "maskir. %0,%3,%2" [(set_attr "type" "compare")]) *************** *** 1022,1034 **** (compare:CC (ior:SI (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_dup 1)) ! (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) ! (match_operand:SI 2 "gpc_reg_operand" "0"))) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_dup 3) (match_dup 1)) ! (and:SI (not:SI (match_dup 1)) (match_dup 2))))] "" ! "maskir. %0,%3,%1" [(set_attr "type" "compare")]) --- 1049,1061 ---- (compare:CC (ior:SI (and:SI (match_operand:SI 3 "gpc_reg_operand" "r") ! (match_operand:SI 2 "gpc_reg_operand" "r")) ! (and:SI (not:SI (match_dup 2)) ! (match_operand:SI 1 "gpc_reg_operand" "0"))) (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") ! (ior:SI (and:SI (match_dup 3) (match_dup 2)) ! (and:SI (not:SI (match_dup 2)) (match_dup 1))))] "" ! "maskir. %0,%3,%2" [(set_attr "type" "compare")]) *************** *** 1888,1891 **** --- 1915,1926 ---- DONE; } + + if (rtx_equal_p (operands[1], operands[3])) + { + rtx temp; + + temp = operands[3]; operands[3] = operands[5]; operands[5] = temp; + temp = operands[4]; operands[4] = operands[1]; operands[1] = temp; + } }") *************** *** 1971,1975 **** "sf %L0,%L2,%L1\;sfe %0,%2,%1") ! (define_insn "negdi3" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))] --- 2006,2010 ---- "sf %L0,%L2,%L1\;sfe %0,%2,%1") ! (define_insn "negdi2" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))] *************** *** 2084,2087 **** --- 2119,2142 ---- [(set_attr "type" "*,load,*,*,*,*,*,mtlr")]) + ;; Split a load of a large constant into the appropriate two-insn + ;; sequence. + + (define_split + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (match_operand:SI 1 "const_int_operand" ""))] + "(unsigned) (INTVAL (operands[1]) + 0x8000) >= 0x10000 + && (INTVAL (operands[1]) & 0xffff) != 0" + [(set (match_dup 0) + (match_dup 2)) + (set (match_dup 0) + (ior:SI (match_dup 0) + (match_dup 3)))] + " + { + operands[2] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[1]) & 0xffff0000); + operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); + }") + (define_insn "" [(set (match_operand:CC 2 "cc_reg_operand" "=x") *************** *** 2426,2434 **** " { ! if (GET_CODE (operands[0]) == MEM) ! operands[1] = force_reg (DImode, operands[1]); ! ! else if (GET_CODE (operands[1]) == CONST_DOUBLE ! || GET_CODE (operands[1]) == CONST_INT) { emit_move_insn (operand_subword (operands[0], 0, 0, DImode), --- 2481,2486 ---- " { ! if (GET_CODE (operands[1]) == CONST_DOUBLE ! || GET_CODE (operands[1]) == CONST_INT) { emit_move_insn (operand_subword (operands[0], 0, 0, DImode), *************** *** 2438,2441 **** --- 2490,2496 ---- DONE; } + + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (DImode, operands[1]); }") *************** *** 2555,2561 **** (define_expand "load_multiple" ! [(match_parallel 3 "" [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" "")) ! (use (match_operand:SI 2 "" ""))])] "" " --- 2610,2616 ---- (define_expand "load_multiple" ! [(match_par_dup 3 [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" "")) ! (use (match_operand:SI 2 "" ""))])] "" " *************** *** 2620,2627 **** (define_expand "store_multiple" ! [(match_parallel 3 "" [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" "")) ! (clobber (scratch:SI)) ! (use (match_operand:SI 2 "" ""))])] "" " --- 2675,2682 ---- (define_expand "store_multiple" ! [(match_par_dup 3 [(set (match_operand:SI 0 "" "") ! (match_operand:SI 1 "" "")) ! (clobber (scratch:SI)) ! (use (match_operand:SI 2 "" ""))])] "" " *************** *** 2686,2691 **** "" "@ ! lux %3,%1,%2 ! lu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2741,2746 ---- "" "@ ! lux %3,%0,%2 ! lu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2698,2703 **** "" "@ ! stux %3,%1,%2 ! stu %3,%2(%1)") (define_insn "" --- 2753,2758 ---- "" "@ ! stux %3,%0,%2 ! stu %3,%2(%0)") (define_insn "" *************** *** 2709,2714 **** "" "@ ! lhzux %3,%1,%2 ! lhzu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2764,2769 ---- "" "@ ! lhzux %3,%0,%2 ! lhzu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2722,2727 **** "" "@ ! lhzux %3,%1,%2 ! lhzu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2777,2782 ---- "" "@ ! lhzux %3,%0,%2 ! lhzu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2735,2740 **** "" "@ ! lhaux %3,%1,%2 ! lhau %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2790,2795 ---- "" "@ ! lhaux %3,%0,%2 ! lhau %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2747,2752 **** "" "@ ! sthux %3,%1,%2 ! sthu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2802,2807 ---- "" "@ ! sthux %3,%0,%2 ! sthu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2759,2764 **** "" "@ ! lbzux %3,%1,%2 ! lbzu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2814,2819 ---- "" "@ ! lbzux %3,%0,%2 ! lbzu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2772,2777 **** "" "@ ! lbzux %3,%1,%2 ! lbzu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2827,2832 ---- "" "@ ! lbzux %3,%0,%2 ! lbzu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2784,2789 **** "" "@ ! stbux %3,%1,%2 ! stbu %3,%2(%1)") (define_insn "" --- 2839,2844 ---- "" "@ ! stbux %3,%0,%2 ! stbu %3,%2(%0)") (define_insn "" *************** *** 2795,2800 **** "" "@ ! lfsux %3,%1,%2 ! lfsu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2850,2855 ---- "" "@ ! lfsux %3,%0,%2 ! lfsu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2807,2812 **** "" "@ ! frsp %3,%3\;stfsux %3,%1,%2 ! frsp %3,%3\;stfsu %3,%2(%1)") (define_insn "" --- 2862,2867 ---- "" "@ ! frsp %3,%3\;stfsux %3,%0,%2 ! frsp %3,%3\;stfsu %3,%2(%0)") (define_insn "" *************** *** 2818,2823 **** "" "@ ! lfdux %3,%1,%2 ! lfdu %3,%2(%1)" [(set_attr "type" "load,load")]) --- 2873,2878 ---- "" "@ ! lfdux %3,%0,%2 ! lfdu %3,%2(%0)" [(set_attr "type" "load,load")]) *************** *** 2830,2835 **** "" "@ ! stfdux %3,%1,%2 ! stfdu %3,%2(%1)") ;; Next come insns related to the calling sequence. --- 2885,2890 ---- "" "@ ! stfdux %3,%0,%2 ! stfdu %3,%2(%0)") ;; Next come insns related to the calling sequence. *************** *** 2840,2844 **** (define_expand "allocate_stack" [(set (reg:SI 1) ! (minus:SI (reg:SI 1) (match_operand:SI 0 "reg_or_cint_operand" "")))] "" " --- 2895,2899 ---- (define_expand "allocate_stack" [(set (reg:SI 1) ! (minus:SI (reg:SI 1) (match_operand:SI 0 "reg_or_short_operand" "")))] "" " *************** *** 2986,2990 **** (define_insn "" ! [(set (match_operand 0 "" "fg,fg") (call (mem:SI (match_operand:SI 1 "call_operand" "l,s")) (match_operand 2 "" "fg,fg"))) --- 3041,3045 ---- (define_insn "" ! [(set (match_operand 0 "" "=fg,fg") (call (mem:SI (match_operand:SI 1 "call_operand" "l,s")) (match_operand 2 "" "fg,fg"))) *************** *** 4513,4517 **** (define_insn "" [(set (pc) ! (match_operand:SI 0 "register_operand" "c,r")) (use (label_ref (match_operand 1 "" "")))] "" --- 4568,4572 ---- (define_insn "" [(set (pc) ! (match_operand:SI 0 "register_operand" "c,l")) (use (label_ref (match_operand 1 "" "")))] "" diff -rc2N gcc-2.2.2/config/seq386.h gcc-2.3.1/config/seq386.h *** gcc-2.2.2/config/seq386.h Sat Mar 14 00:16:41 1992 --- gcc-2.3.1/config/seq386.h Sun Sep 20 21:14:00 1992 *************** *** 24,31 **** #include "bsd386.h" - /* By default, target has a 80387. */ - - #define TARGET_DEFAULT 1 - /* Specify predefined symbols in preprocessor. */ --- 24,27 ---- *************** *** 48,51 **** --- 44,50 ---- #define DBX_DEBUGGING_INFO + /* Sequent Symmetry has size_t defined as int in /usr/include/sys/types.h */ + #define SIZE_TYPE "int" + /* gcc order is ax, dx, cx, bx, si, di, bp, sp, st, st. * dbx order is ax, dx, cx, st(0), st(1), bx, si, di, st(2), st(3), *************** *** 73,85 **** && ! (REGNO == 2 && GET_MODE_UNIT_SIZE (MODE) > 4)) - /* Floating-point return values come in the FP register. */ - - #define VALUE_REGNO(MODE) \ - (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0) - - /* 1 if N is a possible register number for a function value. */ - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG) - /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. */ --- 72,75 ---- *************** *** 115,116 **** --- 105,118 ---- } \ } + + /* 10-Aug-92 pes Local labels are prefixed with ".L" */ + #undef LPREFIX + #define LPREFIX ".L" + + #undef ASM_GENERATE_INTERNAL_LABEL + #define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER)\ + sprintf ((BUF), "*.%s%d", (PREFIX), (NUMBER)) + + #undef ASM_OUTPUT_INTERNAL_LABEL + #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)\ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM) diff -rc2N gcc-2.2.2/config/sequent.h gcc-2.3.1/config/sequent.h *** gcc-2.2.2/config/sequent.h Sat Mar 28 01:16:47 1992 --- gcc-2.3.1/config/sequent.h Fri Jul 3 16:58:34 1992 *************** *** 43,46 **** --- 43,54 ---- #define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} " + /* gcc should find libgcc.a itself, not ask linker to do so. */ + + #define LINK_LIBGCC_SPECIAL + + /* GCC must match what sys/types.h uses for size_t. */ + + #define SIZE_TYPE "int" + /* This is how to align the code that follows an unconditional branch. Don't define it, since it confuses the assembler (we hear). */ diff -rc2N gcc-2.2.2/config/sol2-c1.asm gcc-2.3.1/config/sol2-c1.asm *** gcc-2.2.2/config/sol2-c1.asm --- gcc-2.3.1/config/sol2-c1.asm Wed Sep 9 05:02:37 1992 *************** *** 0 **** --- 1,85 ---- + ! crt1.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, 675 Mass Ave, Cambridge, MA 02139, 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 + ! 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 -rc2N gcc-2.2.2/config/sol2-ci.asm gcc-2.3.1/config/sol2-ci.asm *** gcc-2.2.2/config/sol2-ci.asm --- gcc-2.3.1/config/sol2-ci.asm Mon Jul 27 22:55:26 1992 *************** *** 0 **** --- 1,59 ---- + ! crti.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, 675 Mass Ave, Cambridge, MA 02139, 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 make a stack frame for the contents of the .fini and + ! .init sections. Users may put any desired instructions in those + ! sections. + + ! This file is linked in before the Values-Xx.o files and also before + ! crtbegin, with which perhaps it should be merged. + + .file "crti.s" + + .section ".init" + .proc 022 + .global _init + .type _init,#function + .align 4 + _init: + save %sp, -96, %sp + + + .section ".fini" + .proc 022 + .global _fini + .type _fini,#function + .align 4 + _fini: + save %sp, -96, %sp diff -rc2N gcc-2.2.2/config/sol2-cn.asm gcc-2.3.1/config/sol2-cn.asm *** gcc-2.2.2/config/sol2-cn.asm --- gcc-2.3.1/config/sol2-cn.asm Mon Jul 27 22:55:31 1992 *************** *** 0 **** --- 1,53 ---- + ! crtn.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, 675 Mass Ave, Cambridge, MA 02139, 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 makes sure that the .fini and .init sections do in + ! fact return. Users may put any desired instructions in those sections. + ! This file is the last thing linked into any executable. + + .file "crtn.s" + + .section ".init" + .align 4 + + ret + restore + + .section ".fini" + .align 4 + + ret + restore + + ! Th-th-th-that's all folks! diff -rc2N gcc-2.2.2/config/sparc.c gcc-2.3.1/config/sparc.c *** gcc-2.2.2/config/sparc.c Sun Jun 14 17:10:58 1992 --- gcc-2.3.1/config/sparc.c Tue Oct 13 14:05:17 1992 *************** *** 457,461 **** rtx x, y; { ! enum machine_mode mode = SELECT_CC_MODE (code, x); rtx cc_reg = gen_rtx (REG, mode, 0); --- 457,461 ---- rtx x, y; { ! enum machine_mode mode = SELECT_CC_MODE (code, x, y); rtx cc_reg = gen_rtx (REG, mode, 0); *************** *** 499,503 **** { if (leaf_return_peephole_ok ()) ! return (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE); return 0; } --- 499,503 ---- { if (leaf_return_peephole_ok ()) ! return (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE); return 0; } *************** *** 984,988 **** for memory accesses whose size is 8 bytes or larger. */ ! static int mem_aligned_8 (mem) register rtx mem; --- 984,988 ---- for memory accesses whose size is 8 bytes or larger. */ ! int mem_aligned_8 (mem) register rtx mem; *************** *** 993,997 **** if (GET_CODE (mem) != MEM) ! abort (); /* It's gotta be a MEM! */ addr = XEXP (mem, 0); --- 993,997 ---- if (GET_CODE (mem) != MEM) ! return 0; /* It's gotta be a MEM! */ addr = XEXP (mem, 0); *************** *** 1019,1023 **** /* If it's the stack or frame pointer, check offset alignment. ! We can have improper aligment in the function entry code. */ if (base && (REGNO (base) == FRAME_POINTER_REGNUM --- 1019,1023 ---- /* If it's the stack or frame pointer, check offset alignment. ! We can have improper alignment in the function entry code. */ if (base && (REGNO (base) == FRAME_POINTER_REGNUM *************** *** 1218,1222 **** /* Output assembler code to perform a quadword move insn ! with operands OPERANDS. This is very similar to the preceeding output_move_double function. */ --- 1218,1222 ---- /* Output assembler code to perform a quadword move insn ! with operands OPERANDS. This is very similar to the preceding output_move_double function. */ *************** *** 1958,1963 **** #define T_MODES (~C_MODES) ! /* Modes for single-float quantities. */ ! #define SF_MODES ((1 << (int) SFmode)) /* Modes for double-float quantities. */ --- 1958,1965 ---- #define T_MODES (~C_MODES) ! /* Modes for single-float quantities. We must allow any single word or ! smaller quantity. This is because the fix/float conversion instructions ! take integer inputs/outputs from the float registers. */ ! #define SF_MODES (S_MODES) /* Modes for double-float quantities. */ *************** *** 2475,2517 **** } } - - /* Output assembler code for a SImode to SFmode conversion. */ - - char * - output_floatsisf2 (operands) - rtx *operands; - { - if (GET_CODE (operands[1]) == MEM) - return "ld %1,%0\n\tfitos %0,%0"; - else if (FP_REG_P (operands[1])) - return "fitos %1,%0"; - return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitos %0,%0"; - } - - /* Output assembler code for a SImode to DFmode conversion. */ - - char * - output_floatsidf2 (operands) - rtx *operands; - { - if (GET_CODE (operands[1]) == MEM) - return "ld %1,%0\n\tfitod %0,%0"; - else if (FP_REG_P (operands[1])) - return "fitod %1,%0"; - return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitod %0,%0"; - } - - /* Output assembler code for a SImode to TFmode conversion. */ - - char * - output_floatsitf2 (operands) - rtx *operands; - { - if (GET_CODE (operands[1]) == MEM) - return "ld %1,%0\n\tfitoq %0,%0"; - else if (FP_REG_P (operands[1])) - return "fitoq %1,%0"; - return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitoq %0,%0"; - } /* Leaf functions and non-leaf functions have different needs. */ --- 2477,2480 ---- *************** *** 2597,2601 **** int ! registers_ok_for_ldd (reg1, reg2) rtx reg1, reg2; { --- 2560,2564 ---- int ! registers_ok_for_ldd_peep (reg1, reg2) rtx reg1, reg2; { *************** *** 2632,2636 **** int ! memory_ok_for_ldd (addr1, addr2) rtx addr1, addr2; { --- 2595,2599 ---- int ! addrs_ok_for_ldd_peep (addr1, addr2) rtx addr1, addr2; { *************** *** 2677,2681 **** return 0; ! /* The first offset must be evenly divisable by 8 to ensure the address is 64 bit aligned. */ if (offset1 % 8 != 0) --- 2640,2644 ---- return 0; ! /* The first offset must be evenly divisible by 8 to ensure the address is 64 bit aligned. */ if (offset1 % 8 != 0) *************** *** 2690,2693 **** --- 2653,2676 ---- return 1; } + + /* Return 1 if reg is a pseudo, or is the first register in + a hard register pair. This makes it a candidate for use in + ldd and std insns. */ + + int + register_ok_for_ldd (reg) + rtx reg; + { + + /* We might have been passed a SUBREG. */ + if (GET_CODE (reg) != REG) + return 0; + + if (REGNO (reg) < FIRST_PSEUDO_REGISTER) + return (REGNO (reg) % 2 == 0); + else + return 1; + + } /* Print operand X (an rtx) in assembler syntax to file FILE. *************** *** 2709,2715 **** return; case '*': ! /* Output an annul flag if there's nothing for the delay slot. */ ! if (dbr_sequence_length () == 0) ! fputs (",a", file); return; case 'Y': --- 2692,2707 ---- return; case '*': ! /* Output an annul flag if there's nothing for the delay slot and we ! are optimizing. This is always used with '(' below. */ ! /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch; ! this is a dbx bug. So, we only do this when optimizing. */ ! if (dbr_sequence_length () == 0 && optimize) ! fputs (",a", file); ! return; ! case '(': ! /* Output a 'nop' if there's nothing for the delay slot and we are ! not optimizing. This is always used with '*' above. */ ! if (dbr_sequence_length () == 0 && ! optimize) ! fputs ("\n\tnop", file); return; case 'Y': *************** *** 2796,2800 **** default: /* Undocumented flag. */ ! abort (); } --- 2788,2792 ---- default: /* Undocumented flag. */ ! output_operand_lossage ("invalid operand output code"); } *************** *** 3029,3032 **** --- 3021,3029 ---- case COMPLEX_TYPE: /* GNU Fortran COMPLEX type. */ + /* ??? We need to dinguish between double and float complex types, + but I don't know how yet because I can't reach this code from + existing front-ends. */ + return (qualifiers | 7); /* Who knows? */ + case CHAR_TYPE: /* GNU Pascal CHAR type. Not used in C. */ case BOOLEAN_TYPE: /* GNU Fortran BOOLEAN type. */ *************** *** 3042,3151 **** } ! #ifdef HANDLE_PRAGMA ! /* Handle a pragma directive. HANDLE_PRAGMA conspires to parse the ! input following #pragma into tokens based on yylex. TOKEN is the ! current token, and STRING is its printable form. */ void ! handle_pragma_token (string, token) ! char *string; ! tree token; ! { ! static enum pragma_state ! { ! ps_start, ! ps_done, ! ps_bad, ! ps_weak, ! ps_name, ! ps_equals, ! ps_value, ! } state = ps_start, type; ! static char *name; ! static char *value; ! static int align; ! if (string == 0) { ! #ifdef WEAK_ASM_OP ! if (type == ps_weak) { ! if (state == ps_name || state == ps_value) { ! fprintf (asm_out_file, "\t%s\t", WEAK_ASM_OP); ! ASM_OUTPUT_LABELREF (asm_out_file, name); ! fputc ('\n', asm_out_file); ! if (state == ps_value) { ! fputc ('\t', asm_out_file); ! ASM_OUTPUT_LABELREF (asm_out_file, name); ! fputs (" = ", asm_out_file); ! ASM_OUTPUT_LABELREF (asm_out_file, value); ! fputc ('\n', asm_out_file); } } - else if (! (state == ps_done || state == ps_start)) - warning ("ignoring malformed #pragma weak symbol [=value]"); } - #endif /* WEAK_ASM_OP */ - - type = state = ps_start; - return; } ! switch (state) { ! case ps_start: ! if (token && TREE_CODE (token) == IDENTIFIER_NODE) { ! #ifdef WEAK_ASM_OP ! if (strcmp (IDENTIFIER_POINTER (token), "weak") == 0) ! type = state = ps_weak; ! else ! #endif ! type = state = ps_done; } else ! type = state = ps_done; ! break; ! #ifdef WEAK_ASM_OP ! case ps_weak: ! if (token && TREE_CODE (token) == IDENTIFIER_NODE) ! { ! name = IDENTIFIER_POINTER (token); ! state = ps_name; } else ! state = ps_bad; ! break; ! case ps_name: ! state = (strcmp (string, "=") ? ps_bad : ps_equals); ! break; ! case ps_equals: ! if (token && TREE_CODE (token) == IDENTIFIER_NODE) { ! value = IDENTIFIER_POINTER (token); ! state = ps_value; } - else - state = ps_bad; - break; ! case ps_value: ! state = ps_bad; ! break; ! #endif /* WEAK_ASM_OP */ ! case ps_bad: ! case ps_done: ! break; ! default: ! abort (); } } - #endif /* HANDLE_PRAGMA */ --- 3039,3527 ---- } ! /* Subroutines to support a flat (single) register window calling ! convention. */ ! ! /* Single-register window sparc stack frames look like: ! ! Before call After call ! +-----------------------+ +-----------------------+ ! high | | | | ! mem. | | | | ! | caller's temps. | | caller's temps. | ! | | | | ! +-----------------------+ +-----------------------+ ! | | | | ! | arguments on stack. | | arguments on stack. | ! | |FP+92->| | ! +-----------------------+ +-----------------------+ ! | 6 words to save | | 6 words to save | ! | arguments passed | | arguments passed | ! | in registers, even | | in registers, even | ! SP+68->| if not passed. |FP+68->| if not passed. | ! +-----------------------+ +-----------------------+ ! | 1 word struct addr |FP+64->| 1 word struct addr | ! +-----------------------+ +-----------------------+ ! | | | | ! | 16 word reg save area | | 16 word reg save area | ! SP->| | FP->| | ! +-----------------------+ +-----------------------+ ! | 4 word area for | ! FP-16->| fp/alu reg moves | ! +-----------------------+ ! | | ! | local variables | ! | | ! +-----------------------+ ! | | ! | fp register save | ! | | ! +-----------------------+ ! | | ! | gp register save | ! | | ! +-----------------------+ ! | | ! | alloca allocations | ! | | ! +-----------------------+ ! | | ! | arguments on stack | ! SP+92->| | ! +-----------------------+ ! | 6 words to save | ! | arguments passed | ! | in registers, even | ! low SP+68->| if not passed. | ! memory +-----------------------+ ! SP+64->| 1 word struct addr | ! +-----------------------+ ! | | ! I 16 word reg save area | ! SP->| | ! +-----------------------+ */ ! ! /* Structure to be filled in by sparc_frw_compute_frame_size with register ! save masks, and offsets for the current function. */ ! ! struct sparc_frame_info ! { ! unsigned long total_size; /* # bytes that the entire frame takes up. */ ! unsigned long var_size; /* # bytes that variables take up. */ ! unsigned long args_size; /* # bytes that outgoing arguments take up. */ ! unsigned long extra_size; /* # bytes of extra gunk. */ ! unsigned int gp_reg_size; /* # bytes needed to store gp regs. */ ! unsigned int fp_reg_size; /* # bytes needed to store fp regs. */ ! unsigned long mask; /* Mask of saved gp registers. */ ! unsigned long fmask; /* Mask of saved fp registers. */ ! unsigned long gp_sp_offset; /* Offset from new sp to store gp regs. */ ! unsigned long fp_sp_offset; /* Offset from new sp to store fp regs. */ ! int initialized; /* Nonzero if frame size already calculated. */ ! }; ! ! /* Current frame information calculated by sparc_frw_compute_frame_size. */ ! struct sparc_frame_info current_frame_info; ! ! /* Zero structure to initialize current_frame_info. */ ! struct sparc_frame_info zero_frame_info; ! ! /* Tell prologue and epilogue if register REGNO should be saved / restored. */ ! ! #define MUST_SAVE_REGISTER(regno) \ ! ((regs_ever_live[regno] && !call_used_regs[regno]) \ ! || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \ ! || (regno == 15 && regs_ever_live[15])) ! ! #ifndef SPARC_STACK_ALIGN ! #define STACK_BYTES (STACK_BOUNDARY / 8) ! #define SPARC_STACK_ALIGN(X) (((X) + STACK_BYTES - 1) & -STACK_BYTES) ! #endif ! ! /* Return the bytes needed to compute the frame pointer from the current ! stack pointer. */ ! ! unsigned long ! sparc_frw_compute_frame_size (size) ! int size; /* # of var. bytes allocated. */ ! { ! int regno; ! unsigned long total_size; /* # bytes that the entire frame takes up. */ ! unsigned long var_size; /* # bytes that variables take up. */ ! unsigned long args_size; /* # bytes that outgoing arguments take up. */ ! unsigned long extra_size; /* # extra bytes. */ ! unsigned int gp_reg_size; /* # bytes needed to store gp regs. */ ! unsigned int fp_reg_size; /* # bytes needed to store fp regs. */ ! unsigned long mask; /* Mask of saved gp registers. */ ! unsigned long fmask; /* Mask of saved fp registers. */ ! ! /* This is the size of the 16 word reg save area, 1 word struct addr ! area, and 4 word fp/alu register copy area. */ ! extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0); ! var_size = size; ! /* Also include the size needed for the 6 parameter registers. */ ! args_size = current_function_outgoing_args_size + 24; ! total_size = var_size + args_size + extra_size; ! gp_reg_size = 0; ! fp_reg_size = 0; ! mask = 0; ! fmask = 0; ! ! /* Calculate space needed for gp registers. */ ! for (regno = 1; regno <= 31; regno++) ! { ! if (MUST_SAVE_REGISTER (regno)) ! { ! if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1)) ! { ! if (gp_reg_size % 8 != 0) ! gp_reg_size += UNITS_PER_WORD; ! gp_reg_size += 2 * UNITS_PER_WORD; ! mask |= 3 << regno; ! regno++; ! } ! else ! { ! gp_reg_size += UNITS_PER_WORD; ! mask |= 1 << regno; ! } ! } ! } ! /* Add extra word in case we have to align the space to a double word ! boundary. */ ! if (gp_reg_size != 0) ! gp_reg_size += UNITS_PER_WORD; ! /* Calculate space needed for fp registers. */ ! for (regno = 32; regno <= 63; regno++) ! { ! if (regs_ever_live[regno] && !call_used_regs[regno]) ! { ! fp_reg_size += UNITS_PER_WORD; ! fmask |= 1 << (regno - 32); ! } ! } ! ! total_size += gp_reg_size + fp_reg_size; ! ! if (total_size == extra_size) ! total_size = extra_size = 0; ! ! total_size = SPARC_STACK_ALIGN (total_size); ! ! /* Save other computed information. */ ! current_frame_info.total_size = total_size; ! current_frame_info.var_size = var_size; ! current_frame_info.args_size = args_size; ! current_frame_info.extra_size = extra_size; ! current_frame_info.gp_reg_size = gp_reg_size; ! current_frame_info.fp_reg_size = fp_reg_size; ! current_frame_info.mask = mask; ! current_frame_info.fmask = fmask; ! current_frame_info.initialized = reload_completed; ! ! if (mask) ! { ! unsigned long offset = args_size; ! if (extra_size) ! offset += FIRST_PARM_OFFSET(0); ! current_frame_info.gp_sp_offset = offset; ! } ! ! if (fmask) ! { ! unsigned long offset = args_size + gp_reg_size; ! if (extra_size) ! offset += FIRST_PARM_OFFSET(0); ! current_frame_info.fp_sp_offset = offset; ! } + /* Ok, we're done. */ + return total_size; + } + + /* Common code to save/restore registers. */ + void ! sparc_frw_save_restore (file, word_op, doubleword_op) ! FILE *file; /* Stream to write to. */ ! char *word_op; /* Operation to do for one word. */ ! char *doubleword_op; /* Operation to do for doubleword. */ ! { ! int regno; ! unsigned long mask = current_frame_info.mask; ! unsigned long fmask = current_frame_info.fmask; ! unsigned long gp_offset; ! unsigned long fp_offset; ! unsigned long max_offset; ! char *base_reg; ! ! if (mask == 0 && fmask == 0) ! return; ! ! base_reg = reg_names[STACK_POINTER_REGNUM]; ! gp_offset = current_frame_info.gp_sp_offset; ! fp_offset = current_frame_info.fp_sp_offset; ! max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset; ! ! /* Deal with calling functions with a large structure. */ ! if (max_offset >= 4096) ! { ! char *temp = "%g2"; ! fprintf (file, "\tset %ld,%s\n", max_offset, temp); ! fprintf (file, "\tadd %s,%s,%s\n", temp, base_reg, temp); ! base_reg = temp; ! gp_offset = max_offset - gp_offset; ! fp_offset = max_offset - fp_offset; ! } ! /* Save registers starting from high to low. The debuggers prefer ! at least the return register be stored at func+4, and also it ! allows us not to need a nop in the epilog if at least one ! register is reloaded in addition to return address. */ ! ! if (mask || frame_pointer_needed) { ! for (regno = 1; regno <= 31; regno++) { ! if ((mask & (1L << regno)) != 0 ! || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)) { ! if ((regno & 0x1) == 0 && ((mask & (1L << regno+1)) != 0)) ! { ! if (gp_offset % 8 != 0) ! gp_offset += UNITS_PER_WORD; ! ! if (word_op[0] == 's') ! fprintf (file, "\t%s %s,[%s+%d]\n", ! doubleword_op, reg_names[regno], ! base_reg, gp_offset); ! else ! fprintf (file, "\t%s [%s+%d],%s\n", ! doubleword_op, base_reg, gp_offset, ! reg_names[regno]); ! ! gp_offset += 2 * UNITS_PER_WORD; ! regno++; ! } ! else { ! if (word_op[0] == 's') ! fprintf (file, "\t%s %s,[%s+%d]\n", ! word_op, reg_names[regno], ! base_reg, gp_offset); ! else ! fprintf (file, "\t%s [%s+%d],%s\n", ! word_op, base_reg, gp_offset, reg_names[regno]); ! ! gp_offset += UNITS_PER_WORD; } } } } ! if (fmask) { ! for (regno = 32; regno <= 63; regno++) { ! if ((fmask & (1L << (regno - 32))) != 0) ! { ! if (word_op[0] == 's') ! fprintf (file, "\t%s %s,[%s+%d]\n", ! word_op, reg_names[regno], ! base_reg, gp_offset); ! else ! fprintf (file, "\t%s [%s+%d],%s\n", ! word_op, base_reg, gp_offset, reg_names[regno]); ! ! fp_offset += UNITS_PER_WORD; ! } } + } + } + + /* Set up the stack and frame (if desired) for the function. */ + + void + sparc_frw_output_function_prologue (file, size, ignored) + FILE *file; + int size; + { + extern char call_used_regs[]; + int regno; + int tsize; + char *sp_str = reg_names[STACK_POINTER_REGNUM]; + frame_base_name + = (!frame_pointer_needed) ? "%sp+80" : reg_names[FRAME_POINTER_REGNUM]; + + fprintf (file, "\t!#PROLOGUE# 0\n"); + + size = SPARC_STACK_ALIGN (size); + tsize = (! current_frame_info.initialized + ? sparc_frw_compute_frame_size (size) + : current_frame_info.total_size); + + if (tsize > 0) + { + if (tsize <= 4095) + fprintf (file, + "\tsub %s,%d,%s\t\t!# vars= %d, regs= %d/%d, args = %d, extra= %d\n", + sp_str, tsize, sp_str, current_frame_info.var_size, + current_frame_info.gp_reg_size / 4, + current_frame_info.fp_reg_size / 8, + current_function_outgoing_args_size, + current_frame_info.extra_size); + else + fprintf (file, + "\tset %d,%s\n\tsub\t%s,%s,%s\t\t!# vars= %d, regs= %d/%d, args = %d, sfo= %d\n", + tsize, "%g1", sp_str, "%g1", + sp_str, current_frame_info.var_size, + current_frame_info.gp_reg_size / 4, + current_frame_info.fp_reg_size / 8, + current_function_outgoing_args_size, + current_frame_info.extra_size); + } + + sparc_frw_save_restore (file, "st", "std"); + + if (frame_pointer_needed) + { + if (tsize <= 4095) + fprintf (file, "\tadd %s,%d,%s\t!# set up frame pointer\n", sp_str, + tsize, frame_base_name); else ! fprintf (file, "\tadd %s,%s,%s\t!# set up frame pointer\n", sp_str, ! "%g1", frame_base_name); ! } ! } ! ! /* Do any necessary cleanup after a function to restore stack, frame, ! and regs. */ ! void ! sparc_frw_output_function_epilogue (file, size, ignored1, ignored2) ! FILE *file; ! int size; ! { ! extern FILE *asm_out_data_file, *asm_out_file; ! extern char call_used_regs[]; ! extern int frame_pointer_needed; ! int tsize; ! char *sp_str = reg_names[STACK_POINTER_REGNUM]; ! char *t1_str = "%g1"; ! rtx epilogue_delay = current_function_epilogue_delay_list; ! int noepilogue = FALSE; ! int load_nop = FALSE; ! int load_only_r15; ! ! /* The epilogue does not depend on any registers, but the stack ! registers, so we assume that if we have 1 pending nop, it can be ! ignored, and 2 it must be filled (2 nops occur for integer ! multiply and divide). */ ! ! size = SPARC_STACK_ALIGN (size); ! tsize = (!current_frame_info.initialized ! ? sparc_frw_compute_frame_size (size) ! : current_frame_info.total_size); ! ! if (tsize == 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) ! { ! /* In the reload sequence, we don't need to fill the load delay ! slots for most of the loads, also see if we can fill the final ! delay slot if not otherwise filled by the reload sequence. */ ! ! if (tsize > 4095) ! fprintf (file, "\tset %d,%s\n", tsize, t1_str); ! ! if (frame_pointer_needed) ! { ! char *fp_str = reg_names[FRAME_POINTER_REGNUM]; ! if (tsize > 4095) ! fprintf (file,"\tsub %s,%s,%s\t\t!# sp not trusted here\n", ! fp_str, t1_str, sp_str); ! else ! fprintf (file,"\tsub %s,%d,%s\t\t!# sp not trusted here\n", ! fp_str, tsize, sp_str); } + + sparc_frw_save_restore (file, "ld", "ldd"); + + load_only_r15 = (current_frame_info.mask == (1 << 15) + && current_frame_info.fmask == 0); + + if (current_function_returns_struct) + fprintf (file, "\tjmp %%o7+12\n"); else ! fprintf (file, "\tretl\n"); ! /* 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 (epilogue_delay) { ! if (tsize) ! abort (); ! final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); } ! else if (tsize > 4095) ! fprintf (file, "\tadd %s,%s,%s\n", sp_str, t1_str, sp_str); ! else if (tsize > 0) ! fprintf (file, "\tadd %s,%d,%s\n", sp_str, tsize, sp_str); ! else ! fprintf (file, "\tnop\n"); } + + /* Reset state info for each function. */ + current_frame_info = zero_frame_info; + } + + /* Define the number of delay slots needed for the function epilogue. + + On the sparc, we need a slot if either no stack has been allocated, + or the only register saved is the return register. */ + + int + sparc_frw_epilogue_delay_slots () + { + if (!current_frame_info.initialized) + (void) sparc_frw_compute_frame_size (get_frame_size ()); + + if (current_frame_info.total_size == 0) + return 1; + + if (current_frame_info.mask == (1 << 15) && current_frame_info.fmask == 0) + return 1; + + return 0; + } + + /* Return true is TRIAL is a valid insn for the epilogue delay slot. + Any single length instruction which doesn't reference the stack or frame + pointer is OK. */ + + int + sparc_frw_eligible_for_epilogue_delay (trial, slot) + rtx trial; + int slot; + { + if (get_attr_length (trial) == 1 + && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial)) + && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial))) + return 1; + return 0; } diff -rc2N gcc-2.2.2/config/sparc.h gcc-2.3.1/config/sparc.h *** gcc-2.2.2/config/sparc.h Sat Jun 13 16:40:13 1992 --- gcc-2.3.1/config/sparc.h Tue Oct 20 17:12:29 1992 *************** *** 27,31 **** #define LINK_SPEC \ ! "%{!nostdlib:%{!e*:-e start}} -dc -dp %{static:-Bstatic} %{assert*}" /* Special flags to the Sun-4 assembler when using pipe for input. */ --- 27,31 ---- #define LINK_SPEC \ ! "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" /* Special flags to the Sun-4 assembler when using pipe for input. */ *************** *** 34,38 **** /* Define macros to distinguish architectures. */ ! #define CPP_SPEC "%{msparclite:-D__sparclite__} %{mv8:-D__sparcv8__}" /* Prevent error on `-sun4' and `-target sun4' options. */ --- 34,38 ---- /* Define macros to distinguish architectures. */ ! #define CPP_SPEC "%{msparclite:-D__sparclite__} %{mv8:-D__sparc_v8__}" /* Prevent error on `-sun4' and `-target sun4' options. */ *************** *** 66,70 **** #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "target") \ || !strcmp (STR, "assert") || !strcmp (STR, "aux-info")) --- 66,71 ---- #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ ! || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "target") \ || !strcmp (STR, "assert") || !strcmp (STR, "aux-info")) *************** *** 171,174 **** --- 172,179 ---- #define STACK_BOUNDARY 64 + /* ALIGN FRAMES on double word boundaries */ + + #define SPARC_STACK_ALIGN(LOC) (((LOC)+7) & 0xfffffff8) + /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY 32 *************** *** 191,196 **** /* 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. */ --- 196,202 ---- /* 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. */ *************** *** 353,357 **** This is computed in `reload', in reload1.c. ! Used in flow.c, global-alloc.c, and reload1.c. */ extern int leaf_function; --- 359,363 ---- This is computed in `reload', in reload1.c. ! Used in flow.c, global.c, and reload1.c. */ extern int leaf_function; *************** *** 560,567 **** On the SPARC, when PIC, we need a temporary when loading some addresses ! into a register. */ ! #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ ! (flag_pic && pic_address_needs_scratch (IN) ? GENERAL_REGS : NO_REGS) /* Return the maximum number of consecutive registers --- 566,593 ---- On the SPARC, when PIC, we need a temporary when loading some addresses ! into a register. ! Also, we need a temporary when loading/storing a HImode/QImode value ! between memory and the FPU registers. This can happen when combine puts ! a paradoxical subreg in a float/fix conversion insn. */ ! ! #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ ! (flag_pic && pic_address_needs_scratch (IN) ? GENERAL_REGS \ ! : ((CLASS) == FP_REGS && ((MODE) == HImode || (MODE) == QImode)\ ! && (GET_CODE (IN) == MEM \ ! || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \ ! && true_regnum (IN) == -1))) ? GENERAL_REGS : NO_REGS) ! ! #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN) \ ! ((CLASS) == FP_REGS && ((MODE) == HImode || (MODE) == QImode) \ ! && (GET_CODE (IN) == MEM \ ! || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \ ! && true_regnum (IN) == -1)) ? GENERAL_REGS : NO_REGS) ! ! /* On SPARC it is not possible to directly move data between ! GENERAL_REGS and FP_REGS. */ ! #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ ! (((CLASS1) == FP_REGS && (CLASS2) == GENERAL_REGS) \ ! || ((CLASS1) == GENERAL_REGS && (CLASS2) == FP_REGS)) /* Return the maximum number of consecutive registers *************** *** 842,851 **** for profiling a function entry. */ ! #define FUNCTION_PROFILER(FILE, LABELNO) \ ! fprintf (FILE, "\tsethi %%hi(LP%d),%%o0\n\tcall mcount\n\tor %%lo(LP%d),%%o0,%%o0\n", \ ! (LABELNO), (LABELNO)) /* Output assembler code to FILE to initialize this source file's basic block profiling info, if that has not already been done. */ #define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \ --- 868,884 ---- for profiling a function entry. */ ! #define FUNCTION_PROFILER(FILE, LABELNO) \ ! do { \ ! fputs ("\tsethi %hi(", (FILE)); \ ! ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \ ! fputs ("),%o0\n\tcall mcount\n\tor %lo(", (FILE)); \ ! ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \ ! fputs ("),%o0,%o0\n", (FILE)); \ ! } while (0) /* Output assembler code to FILE to initialize this source file's basic block profiling info, if that has not already been done. */ + /* FIXME -- this does not parameterize how it generates labels (like the + above FUNCTION_PROFILER). Broken on Solaris-2. --gnu@cygnus.com */ #define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \ *************** *** 1072,1077 **** : (C) == 'S' \ ? (CONSTANT_P (OP) || memory_address_p (Pmode, OP)) \ : 0) ! #else --- 1105,1114 ---- : (C) == 'S' \ ? (CONSTANT_P (OP) || memory_address_p (Pmode, OP)) \ + : (C) == 'T' \ + ? (mem_aligned_8 (OP)) \ + : (C) == 'U' \ + ? (register_ok_for_ldd (OP)) \ : 0) ! #else *************** *** 1094,1098 **** ? (CONSTANT_P (OP) \ || (GET_CODE (OP) == REG && reg_renumber[REGNO (OP)] > 0)\ ! || strict_memory_address_p (Pmode, OP)) : 0))) #endif --- 1131,1139 ---- ? (CONSTANT_P (OP) \ || (GET_CODE (OP) == REG && reg_renumber[REGNO (OP)] > 0)\ ! || strict_memory_address_p (Pmode, OP)) \ ! : ((C) == 'T' ? \ ! mem_aligned_8 (OP) && strict_memory_address_p (Pmode, OP) \ ! : ((C) == 'U' ? \ ! register_ok_for_ldd (OP) : 0))))) #endif *************** *** 1237,1240 **** --- 1278,1289 ---- #define MOVE_MAX 8 + /* This is the value of the error code EDOM for this machine, + used by the sqrt instruction. */ + #define TARGET_EDOM 33 + + /* This is how to refer to the variable errno. */ + #define GEN_ERRNO_RTX \ + gen_rtx (MEM, SImode, gen_rtx (SYMBOL_REF, Pmode, "errno")) + /* Define if normal loads of shorter-than-word items from memory clears the rest of the bigs in the register. */ *************** *** 1293,1297 **** PLUS, MINUS, or NEG. CCmode should be used when no special processing is needed. */ ! #define SELECT_CC_MODE(OP,X) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ --- 1342,1346 ---- PLUS, MINUS, or NEG. CCmode should be used when no special processing is needed. */ ! #define SELECT_CC_MODE(OP,X,Y) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ *************** *** 1405,1408 **** --- 1454,1461 ---- #define ASM_APP_OFF "" + #define ASM_LONG ".word" + #define ASM_SHORT ".half" + #define ASM_BYTE_OP ".byte" + /* Output before read-only data. */ *************** *** 1472,1476 **** fprintf (FILE, "_%s", NAME) ! /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. */ --- 1525,1529 ---- fprintf (FILE, "_%s", NAME) ! /* 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. */ *************** *** 1478,1481 **** --- 1531,1543 ---- fprintf (FILE, "%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. */ + /* FIXME: This should be used throughout gcc, and documented in the texinfo + files. There is no reason you should have to allocate a buffer and + `sprintf' to reference an internal label (as opposed to defining it). */ + + #define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \ + fprintf (FILE, "%s%d", PREFIX, NUM) + /* This is how to store into the string LABEL the symbol_ref name of an internal numbered label where *************** *** 1493,1504 **** #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ { \ ! if (REAL_VALUE_ISINF (VALUE)) \ ! fprintf (FILE, "\t.double 0r%sinf\n", (VALUE) > 0 ? "" : "-"); \ ! else if (REAL_VALUE_ISNAN (VALUE) \ ! || REAL_VALUE_MINUS_ZERO (VALUE)) \ { \ ! union { double d; long l[2];} t; \ ! t.d = (VALUE); \ ! fprintf (FILE, "\t.word 0x%lx\n\t.word 0x%lx\n", t.l[0], t.l[1]); \ } \ else \ --- 1555,1566 ---- #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%s\t0x%lx\n\t%s\t0x%lx\n", \ ! ASM_LONG, t[0], ASM_LONG, t[1]); \ } \ else \ *************** *** 1510,1521 **** #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ { \ ! if (REAL_VALUE_ISINF (VALUE)) \ ! fprintf (FILE, "\t.single 0r%sinf\n", (VALUE) > 0 ? "" : "-"); \ ! else if (REAL_VALUE_ISNAN (VALUE) \ ! || REAL_VALUE_MINUS_ZERO (VALUE)) \ { \ ! union { float f; long l;} t; \ ! t.f = (VALUE); \ ! fprintf (FILE, "\t.word 0x%lx\n", t.l); \ } \ else \ --- 1572,1582 ---- #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%s\t0x%lx\n", ASM_LONG, t); \ } \ else \ *************** *** 1526,1530 **** #define ASM_OUTPUT_INT(FILE,VALUE) \ ! ( fprintf (FILE, "\t.word "), \ output_addr_const (FILE, (VALUE)), \ fprintf (FILE, "\n")) --- 1587,1591 ---- #define ASM_OUTPUT_INT(FILE,VALUE) \ ! ( fprintf (FILE, "\t%s\t", ASM_LONG), \ output_addr_const (FILE, (VALUE)), \ fprintf (FILE, "\n")) *************** *** 1537,1546 **** #define ASM_OUTPUT_SHORT(FILE,VALUE) \ ! ( fprintf (FILE, "\t.half "), \ 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")) --- 1598,1607 ---- #define ASM_OUTPUT_SHORT(FILE,VALUE) \ ! ( fprintf (FILE, "\t%s\t", ASM_SHORT), \ output_addr_const (FILE, (VALUE)), \ fprintf (FILE, "\n")) #define ASM_OUTPUT_CHAR(FILE,VALUE) \ ! ( fprintf (FILE, "\t%s\t", ASM_BYTE_OP), \ output_addr_const (FILE, (VALUE)), \ fprintf (FILE, "\n")) *************** *** 1549,1553 **** #define ASM_OUTPUT_BYTE(FILE,VALUE) \ ! fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) /* This is how to output an element of a case-vector that is absolute. */ --- 1610,1614 ---- #define ASM_OUTPUT_BYTE(FILE,VALUE) \ ! fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) /* This is how to output an element of a case-vector that is absolute. */ *************** *** 1627,1631 **** #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ ! ((CHAR) == '@' || (CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^') /* Print operand X (an rtx) in assembler syntax to file FILE. --- 1688,1693 ---- #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ ! ((CHAR) == '@' || (CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' \ ! || (CHAR) == '(') /* Print operand X (an rtx) in assembler syntax to file FILE. *************** *** 1707,1713 **** extern char *output_cbranch (); extern char *output_return (); - extern char *output_floatsisf2 (); - extern char *output_floatsidf2 (); - extern char *output_floatsitf2 (); /* Defined in flags.h, but insn-emit.c does not include flags.h. */ --- 1769,1772 ---- diff -rc2N gcc-2.2.2/config/sparc.md gcc-2.3.1/config/sparc.md *** gcc-2.2.2/config/sparc.md Thu Jun 11 00:42:08 1992 --- gcc-2.3.1/config/sparc.md Tue Oct 13 14:29:53 1992 *************** *** 30,34 **** (define_attr "type" ! "move,unary,binary,compare,load,store,branch,call,call_no_delay_slot,address,fpload,fpstore,fp,fpcmp,fpmul,fpdiv,fpsqrt,multi,misc" (const_string "binary")) --- 30,34 ---- (define_attr "type" ! "move,unary,binary,compare,load,store,uncond_branch,branch,call,call_no_delay_slot,address,fpload,fpstore,fp,fpcmp,fpmul,fpdiv,fpsqrt,multi,misc" (const_string "binary")) *************** *** 73,77 **** (define_attr "in_call_delay" "false,true" ! (cond [(eq_attr "type" "branch,call,call_no_delay_slot,multi") (const_string "false") (eq_attr "type" "load,fpload,store,fpstore") --- 73,77 ---- (define_attr "in_call_delay" "false,true" ! (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") (const_string "false") (eq_attr "type" "load,fpload,store,fpstore") *************** *** 94,111 **** ;; a floating point branch. (define_attr "in_branch_delay" "false,true" ! (if_then_else (and (eq_attr "type" "!branch,call,call_no_delay_slot,multi") (eq_attr "length" "1")) (const_string "true") (const_string "false"))) (define_delay (eq_attr "type" "branch") [(eq_attr "in_branch_delay" "true") ! (nil) (eq_attr "in_branch_delay" "true")]) ;; Function units of the SPARC ;; (define_function_unit {name} {num-units} {n-users} {test} ! ;; {ready-delay} {busy-delay} [{conflict-list}]) ;; The integer ALU. --- 94,135 ---- ;; a floating point branch. + ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions + ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so. + ;; This is because doing so will add several pipeline stalls to the path + ;; that the load/store did not come from. Unfortunately, there is no way + ;; to prevent fill_eager_delay_slots from using load/store without completely + ;; disabling them. For the SPEC benchmark set, this is a serious lose, + ;; because it prevents us from moving back the final store of inner loops. + (define_attr "in_branch_delay" "false,true" ! (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") ! (eq_attr "length" "1")) ! (const_string "true") ! (const_string "false"))) ! ! (define_attr "in_uncond_branch_delay" "false,true" ! (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") (eq_attr "length" "1")) (const_string "true") (const_string "false"))) + (define_attr "in_annul_branch_delay" "false,true" + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi") + (eq_attr "length" "1")) + (const_string "true") + (const_string "false"))) + (define_delay (eq_attr "type" "branch") [(eq_attr "in_branch_delay" "true") ! (nil) (eq_attr "in_annul_branch_delay" "true")]) + (define_delay (eq_attr "type" "uncond_branch") + [(eq_attr "in_uncond_branch_delay" "true") + (nil) (nil)]) + ;; Function units of the SPARC ;; (define_function_unit {name} {num-units} {n-users} {test} ! ;; {ready-delay} {issue-delay} [{conflict-list}]) ;; The integer ALU. *************** *** 117,121 **** ;; Memory with load-delay of 1 (i.e., 2 cycle load). ! (define_function_unit "memory" 1 0 (eq_attr "type" "load,fpload") 2 0) ;; SPARC has two floating-point units: the FP ALU, --- 141,145 ---- ;; Memory with load-delay of 1 (i.e., 2 cycle load). ! (define_function_unit "memory" 1 1 (eq_attr "type" "load,fpload") 2 0) ;; SPARC has two floating-point units: the FP ALU, *************** *** 138,145 **** ;; More insns cause the chip to stall. ! (define_function_unit "fp_alu" 1 2 (eq_attr "type" "fp") 5 0) ! (define_function_unit "fp_mul" 1 2 (eq_attr "type" "fpmul") 7 0) ! (define_function_unit "fp_div" 1 2 (eq_attr "type" "fpdiv") 37 0) ! (define_function_unit "fp_sqrt" 1 2 (eq_attr "type" "fpsqrt") 63 0) ;; Compare instructions. --- 162,169 ---- ;; More insns cause the chip to stall. ! (define_function_unit "fp_alu" 1 1 (eq_attr "type" "fp") 5 0) ! (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpmul") 7 0) ! (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpdiv") 37 0) ! (define_function_unit "fp_mds" 1 1 (eq_attr "type" "fpsqrt") 63 0) ;; Compare instructions. *************** *** 361,365 **** (define_insn "" [(set (reg:CC 0) ! (compare:CC (match_operand:SI 0 "register_operand" "rJ") (match_operand:SI 1 "arith_operand" "rI")))] "" --- 385,389 ---- (define_insn "" [(set (reg:CC 0) ! (compare:CC (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "arith_operand" "rI")))] "" *************** *** 610,614 **** (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (match_operator:SI 1 "normal_comp_operator" [(reg 0) (const_int 0)]))] "" "* return output_scc_insn (operands, insn); " --- 634,638 ---- (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") ! (match_operator:SI 1 "noov_compare_op" [(reg 0) (const_int 0)]))] "" "* return output_scc_insn (operands, insn); " *************** *** 1032,1037 **** (define_insn "" ! [(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) ! (mem:BLK (match_operand:SI 1 "register_operand" "r"))) (use (match_operand:SI 2 "nonmemory_operand" "rn")) (use (match_operand:SI 3 "immediate_operand" "i")) --- 1056,1061 ---- (define_insn "" ! [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r")) ! (mem:BLK (match_operand:SI 1 "register_operand" "+r"))) (use (match_operand:SI 2 "nonmemory_operand" "rn")) (use (match_operand:SI 3 "immediate_operand" "i")) *************** *** 1147,1152 **** (define_insn "" ! [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=f,r,Q,Q,f,&r,?f,?r") ! (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "f,r,f,r,Q,Q,r,f"))] "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" --- 1171,1176 ---- (define_insn "" ! [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,f,r,Q,Q,f,&r,?f,?r") ! (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,f,r,f,r,Q,Q,r,f"))] "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" *************** *** 1157,1162 **** return output_move_double (operands); }" ! [(set_attr "type" "fp,move,fpstore,store,fpload,load,multi,multi") ! (set_attr "length" "2,2,3,3,3,3,3,3")]) (define_insn "" --- 1181,1186 ---- return output_move_double (operands); }" ! [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load,multi,multi") ! (set_attr "length" "1,1,2,2,3,3,3,3,3,3")]) (define_insn "" *************** *** 1501,1526 **** (define_insn "floatsisf2" ! [(set (match_operand:SF 0 "general_operand" "=f") ! (float:SF (match_operand:SI 1 "nonimmediate_operand" "rfm")))] "" ! "* return output_floatsisf2 (operands);" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) (define_insn "floatsidf2" ! [(set (match_operand:DF 0 "general_operand" "=f") ! (float:DF (match_operand:SI 1 "nonimmediate_operand" "rfm")))] "" ! "* return output_floatsidf2 (operands);" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) (define_insn "floatsitf2" ! [(set (match_operand:TF 0 "general_operand" "=f") ! (float:TF (match_operand:SI 1 "nonimmediate_operand" "rfm")))] "" ! "* return output_floatsitf2 (operands);" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) ;; Convert a float to an actual integer. --- 1525,1547 ---- (define_insn "floatsisf2" ! [(set (match_operand:SF 0 "register_operand" "=f") ! (float:SF (match_operand:SI 1 "register_operand" "f")))] "" ! "fitos %1,%0" ! [(set_attr "type" "fp")]) (define_insn "floatsidf2" ! [(set (match_operand:DF 0 "register_operand" "=f") ! (float:DF (match_operand:SI 1 "register_operand" "f")))] "" ! "fitod %1,%0" ! [(set_attr "type" "fp")]) (define_insn "floatsitf2" ! [(set (match_operand:TF 0 "register_operand" "=f") ! (float:TF (match_operand:SI 1 "register_operand" "f")))] "" ! "fitox %1,%0" ! [(set_attr "type" "fp")]) ;; Convert a float to an actual integer. *************** *** 1528,1730 **** (define_insn "fix_truncsfsi2" ! [(set (match_operand:SI 0 "general_operand" "=rm") ! (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm")))) ! (clobber (match_scratch:SF 2 "=&f"))] "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fstoi %1,%2\", operands); ! else ! output_asm_insn (\"ld %1,%2\;fstoi %2,%2\", operands); ! if (GET_CODE (operands[0]) == MEM) ! return \"st %2,%0\"; ! else ! return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) (define_insn "fix_truncdfsi2" ! [(set (match_operand:SI 0 "general_operand" "=rm") ! (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm")))) ! (clobber (match_scratch:DF 2 "=&f"))] "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fdtoi %1,%2\", operands); ! else ! { ! rtx xoperands[3]; ! xoperands[0] = operands[2]; ! xoperands[1] = operands[1]; ! output_asm_insn (output_fp_move_double (xoperands), xoperands); ! output_asm_insn (\"fdtoi %2,%2\", operands); ! } ! if (GET_CODE (operands[0]) == MEM) ! return \"st %2,%0\"; ! else ! return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) (define_insn "fix_trunctfsi2" ! [(set (match_operand:SI 0 "general_operand" "=rm") ! (fix:SI (fix:TF (match_operand:TF 1 "general_operand" "fm")))) ! (clobber (match_scratch:DF 2 "=&f"))] ! "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fqtoi %1,%2\", operands); ! else ! { ! rtx xoperands[3]; ! xoperands[0] = operands[2]; ! xoperands[1] = operands[1]; ! output_asm_insn (output_fp_move_quad (xoperands), xoperands); ! output_asm_insn (\"fqtoi %2,%2\", operands); ! } ! if (GET_CODE (operands[0]) == MEM) ! return \"st %2,%0\"; ! else ! return \"st %2,[%%fp-4]\;ld [%%fp-4],%0\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) ! ! ;; Allow combiner to combine a fix_trunctfsi2 with a floatsitf2 ! ;; This eliminates 2 useless instructions. ! ;; The first one matches if the fixed result is needed. The second one ! ;; matches if the fixed result is not needed. ! ! (define_insn "" ! [(set (match_operand:TF 0 "general_operand" "=f") ! (float:TF (fix:SI (fix:TF (match_operand:TF 1 "general_operand" "fm"))))) ! (set (match_operand:SI 2 "general_operand" "=rm") ! (fix:SI (fix:TF (match_dup 1))))] ! "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fqtoi %1,%0\", operands); ! else ! { ! output_asm_insn (output_fp_move_quad (operands), operands); ! output_asm_insn (\"fqtoi %0,%0\", operands); ! } ! if (GET_CODE (operands[2]) == MEM) ! return \"st %0,%2\;fitoq %0,%0\"; ! else ! return \"st %0,[%%fp-4]\;fitoq %0,%0\;ld [%%fp-4],%2\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "5")]) ! ! (define_insn "" ! [(set (match_operand:TF 0 "general_operand" "=f") ! (float:TF (fix:SI (fix:TF (match_operand:TF 1 "general_operand" "fm")))))] ! "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fqtoi %1,%0\", operands); ! else ! { ! output_asm_insn (output_fp_move_quad (operands), operands); ! output_asm_insn (\"fqtoi %0,%0\", operands); ! } ! return \"fitoq %0,%0\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) ! ! ;; Allow combiner to combine a fix_truncdfsi2 with a floatsidf2 ! ;; This eliminates 2 useless instructions. ! ;; The first one matches if the fixed result is needed. The second one ! ;; matches if the fixed result is not needed. ! ! (define_insn "" ! [(set (match_operand:DF 0 "general_operand" "=f") ! (float:DF (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))) ! (set (match_operand:SI 2 "general_operand" "=rm") ! (fix:SI (fix:DF (match_dup 1))))] ! "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fdtoi %1,%0\", operands); ! else ! { ! output_asm_insn (output_fp_move_double (operands), operands); ! output_asm_insn (\"fdtoi %0,%0\", operands); ! } ! if (GET_CODE (operands[2]) == MEM) ! return \"st %0,%2\;fitod %0,%0\"; ! else ! return \"st %0,[%%fp-4]\;fitod %0,%0\;ld [%%fp-4],%2\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "5")]) ! ! (define_insn "" ! [(set (match_operand:DF 0 "general_operand" "=f") ! (float:DF (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm")))))] ! "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fdtoi %1,%0\", operands); ! else ! { ! output_asm_insn (output_fp_move_double (operands), operands); ! output_asm_insn (\"fdtoi %0,%0\", operands); ! } ! return \"fitod %0,%0\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) ! ! ;; Allow combiner to combine a fix_truncsfsi2 with a floatsisf2 ! ;; This eliminates 2 useless instructions. ! ;; The first one matches if the fixed result is needed. The second one ! ;; matches if the fixed result is not needed. ! ! (define_insn "" ! [(set (match_operand:SF 0 "general_operand" "=f") ! (float:SF (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))) ! (set (match_operand:SI 2 "general_operand" "=rm") ! (fix:SI (fix:SF (match_dup 1))))] ! "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fstoi %1,%0\", operands); ! else ! output_asm_insn (\"ld %1,%0\;fstoi %0,%0\", operands); ! if (GET_CODE (operands[2]) == MEM) ! return \"st %0,%2\;fitos %0,%0\"; ! else ! return \"st %0,[%%fp-4]\;fitos %0,%0\;ld [%%fp-4],%2\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "5")]) ! ! (define_insn "" ! [(set (match_operand:SF 0 "general_operand" "=f") ! (float:SF (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm")))))] "" ! "* ! { ! if (FP_REG_P (operands[1])) ! output_asm_insn (\"fstoi %1,%0\", operands); ! else ! output_asm_insn (\"ld %1,%0\;fstoi %0,%0\", operands); ! return \"fitos %0,%0\"; ! }" ! [(set_attr "type" "fp") ! (set_attr "length" "3")]) ;;- arithmetic instructions --- 1549,1571 ---- (define_insn "fix_truncsfsi2" ! [(set (match_operand:SI 0 "register_operand" "=f") ! (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] "" ! "fstoi %1,%0" ! [(set_attr "type" "fp")]) (define_insn "fix_truncdfsi2" ! [(set (match_operand:SI 0 "register_operand" "=f") ! (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] "" ! "fdtoi %1,%0" ! [(set_attr "type" "fp")]) (define_insn "fix_trunctfsi2" ! [(set (match_operand:SI 0 "register_operand" "=f") ! (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))] "" ! "fqtoi %1,%0" ! [(set_attr "type" "fp")]) ;;- arithmetic instructions *************** *** 1977,1980 **** --- 1818,1836 ---- "and %1,%2,%0") + (define_split + [(set (match_operand:SI 0 "register_operand" "") + (and:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" ""))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))] + " + { + operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); + }") + (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") *************** *** 2037,2040 **** --- 1893,1911 ---- "or %1,%2,%0") + (define_split + [(set (match_operand:SI 0 "register_operand" "") + (ior:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" ""))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))] + " + { + operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); + }") + (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") *************** *** 2097,2100 **** --- 1968,2001 ---- "xor %r1,%2,%0") + (define_split + [(set (match_operand:SI 0 "register_operand" "") + (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" ""))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))] + " + { + operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); + }") + + (define_split + [(set (match_operand:SI 0 "register_operand" "") + (not:SI (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "" "")))) + (clobber (match_operand:SI 3 "register_operand" ""))] + "GET_CODE (operands[2]) == CONST_INT + && !SMALL_INT (operands[2]) + && (INTVAL (operands[2]) & 0x3ff) == 0x3ff" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))] + " + { + operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); + }") + ;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b). ;; Combine now canonicalizes to the rightmost expression. *************** *** 2510,2521 **** ;; Unconditional and other jump instructions ! ;; Note that for the Sparc, by setting the annul bit on an unconditional ! ;; branch, the following insn is never executed. This saves us a nop, ! ;; but requires a debugger which can handle annulled branches. (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" ! "b%* %l0" ! [(set_attr "type" "branch")]) (define_expand "tablejump" --- 2411,2422 ---- ;; Unconditional and other jump instructions ! ;; On the Sparc, by setting the annul bit on an unconditional branch, the ! ;; following insn is never executed. This saves us a nop. Dbx does not ! ;; handle such branches though, so we only use them when optimizing. (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" ! "b%* %l0%(" ! [(set_attr "type" "uncond_branch")]) (define_expand "tablejump" *************** *** 2540,2544 **** "" "jmp %%o7+%0%#" ! [(set_attr "type" "branch")]) (define_insn "" --- 2441,2445 ---- "" "jmp %%o7+%0%#" ! [(set_attr "type" "uncond_branch")]) (define_insn "" *************** *** 2547,2551 **** "" "jmp %a0%#" ! [(set_attr "type" "branch")]) (define_insn "" --- 2448,2452 ---- "" "jmp %a0%#" ! [(set_attr "type" "uncond_branch")]) (define_insn "" *************** *** 2554,2558 **** "" "call %l0%#" ! [(set_attr "type" "branch")]) ;; This pattern recognizes the "instruction" that appears in --- 2455,2459 ---- "" "call %l0%#" ! [(set_attr "type" "uncond_branch")]) ;; This pattern recognizes the "instruction" that appears in *************** *** 2729,2733 **** "" "jmp %a0%#" ! [(set_attr "type" "branch")]) (define_expand "nonlocal_goto" --- 2630,2634 ---- "" "jmp %a0%#" ! [(set_attr "type" "uncond_branch")]) (define_expand "nonlocal_goto" *************** *** 2739,2748 **** " { - rtx temp; /* Trap instruction to flush all the registers window. */ emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, gen_rtvec (1, const0_rtx), 0)); /* Load the fp value for the containing fn into %fp. ! This is needed because operands[2] refers to %fp. */ emit_move_insn (virtual_stack_vars_rtx, operands[0]); /* Find the containing function's current nonlocal goto handler, --- 2640,2653 ---- " { /* Trap instruction to flush all the registers window. */ emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, gen_rtvec (1, const0_rtx), 0)); /* Load the fp value for the containing fn into %fp. ! This is needed because operands[2] refers to %fp. ! Virtual register instantiation fails if the virtual %fp isn't set from a ! register. Thus we must copy operands[0] into a register if it isn't ! already one. */ ! if (GET_CODE (operands[0]) != REG) ! operands[0] = force_reg (SImode, operands[0]); emit_move_insn (virtual_stack_vars_rtx, operands[0]); /* Find the containing function's current nonlocal goto handler, *************** *** 2968,2998 **** (define_peephole ! [(set (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "memory_operand" "")) ! (set (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "memory_operand" ""))] ! "registers_ok_for_ldd (operands[0], operands[2]) && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) ! && memory_ok_for_ldd (XEXP (operands[1], 0), XEXP (operands[3], 0))" "ldd %1,%0") (define_peephole [(set (match_operand:SI 0 "memory_operand" "") ! (match_operand:SI 1 "register_operand" "r")) (set (match_operand:SI 2 "memory_operand" "") ! (match_operand:SI 3 "register_operand" "r"))] ! "registers_ok_for_ldd (operands[1], operands[3]) && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) ! && memory_ok_for_ldd (XEXP (operands[0], 0), XEXP (operands[2], 0))" "std %1,%0") (define_peephole ! [(set (match_operand:SF 0 "register_operand" "fr") (match_operand:SF 1 "memory_operand" "")) ! (set (match_operand:SF 2 "register_operand" "fr") (match_operand:SF 3 "memory_operand" ""))] ! "registers_ok_for_ldd (operands[0], operands[2]) && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) ! && memory_ok_for_ldd (XEXP (operands[1], 0), XEXP (operands[3], 0))" "ldd %1,%0") --- 2873,2903 ---- (define_peephole ! [(set (match_operand:SI 0 "register_operand" "=rf") (match_operand:SI 1 "memory_operand" "")) ! (set (match_operand:SI 2 "register_operand" "=rf") (match_operand:SI 3 "memory_operand" ""))] ! "registers_ok_for_ldd_peep (operands[0], operands[2]) && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) ! && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" "ldd %1,%0") (define_peephole [(set (match_operand:SI 0 "memory_operand" "") ! (match_operand:SI 1 "register_operand" "rf")) (set (match_operand:SI 2 "memory_operand" "") ! (match_operand:SI 3 "register_operand" "rf"))] ! "registers_ok_for_ldd_peep (operands[1], operands[3]) && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) ! && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" "std %1,%0") (define_peephole ! [(set (match_operand:SF 0 "register_operand" "=fr") (match_operand:SF 1 "memory_operand" "")) ! (set (match_operand:SF 2 "register_operand" "=fr") (match_operand:SF 3 "memory_operand" ""))] ! "registers_ok_for_ldd_peep (operands[0], operands[2]) && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3]) ! && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" "ldd %1,%0") *************** *** 3002,3038 **** (set (match_operand:SF 2 "memory_operand" "") (match_operand:SF 3 "register_operand" "fr"))] ! "registers_ok_for_ldd (operands[1], operands[3]) && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) ! && memory_ok_for_ldd (XEXP (operands[0], 0), XEXP (operands[2], 0))" "std %1,%0") (define_peephole ! [(set (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "memory_operand" "")) ! (set (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "memory_operand" ""))] ! "registers_ok_for_ldd (operands[2], operands[0]) && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) ! && memory_ok_for_ldd (XEXP (operands[3], 0), XEXP (operands[1], 0))" "ldd %3,%2") (define_peephole [(set (match_operand:SI 0 "memory_operand" "") ! (match_operand:SI 1 "register_operand" "r")) (set (match_operand:SI 2 "memory_operand" "") ! (match_operand:SI 3 "register_operand" "r"))] ! "registers_ok_for_ldd (operands[3], operands[1]) && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) ! && memory_ok_for_ldd (XEXP (operands[2], 0), XEXP (operands[0], 0))" "std %3,%2") (define_peephole ! [(set (match_operand:SF 0 "register_operand" "fr") (match_operand:SF 1 "memory_operand" "")) ! (set (match_operand:SF 2 "register_operand" "fr") (match_operand:SF 3 "memory_operand" ""))] ! "registers_ok_for_ldd (operands[2], operands[0]) && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) ! && memory_ok_for_ldd (XEXP (operands[3], 0), XEXP (operands[1], 0))" "ldd %3,%2") --- 2907,2943 ---- (set (match_operand:SF 2 "memory_operand" "") (match_operand:SF 3 "register_operand" "fr"))] ! "registers_ok_for_ldd_peep (operands[1], operands[3]) && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2]) ! && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))" "std %1,%0") (define_peephole ! [(set (match_operand:SI 0 "register_operand" "=rf") (match_operand:SI 1 "memory_operand" "")) ! (set (match_operand:SI 2 "register_operand" "=rf") (match_operand:SI 3 "memory_operand" ""))] ! "registers_ok_for_ldd_peep (operands[2], operands[0]) && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) ! && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" "ldd %3,%2") (define_peephole [(set (match_operand:SI 0 "memory_operand" "") ! (match_operand:SI 1 "register_operand" "rf")) (set (match_operand:SI 2 "memory_operand" "") ! (match_operand:SI 3 "register_operand" "rf"))] ! "registers_ok_for_ldd_peep (operands[3], operands[1]) && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) ! && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" "std %3,%2") (define_peephole ! [(set (match_operand:SF 0 "register_operand" "=fr") (match_operand:SF 1 "memory_operand" "")) ! (set (match_operand:SF 2 "register_operand" "=fr") (match_operand:SF 3 "memory_operand" ""))] ! "registers_ok_for_ldd_peep (operands[2], operands[0]) && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1]) ! && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))" "ldd %3,%2") *************** *** 3042,3052 **** (set (match_operand:SF 2 "memory_operand" "") (match_operand:SF 3 "register_operand" "fr"))] ! "registers_ok_for_ldd (operands[3], operands[1]) && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) ! && memory_ok_for_ldd (XEXP (operands[2], 0), XEXP (operands[0], 0))" "std %3,%2") ;; Optimize the case of following a reg-reg move with a test ! ;; of reg just moved. (define_peephole --- 2947,2958 ---- (set (match_operand:SF 2 "memory_operand" "") (match_operand:SF 3 "register_operand" "fr"))] ! "registers_ok_for_ldd_peep (operands[3], operands[1]) && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0]) ! && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" "std %3,%2") ;; Optimize the case of following a reg-reg move with a test ! ;; of reg just moved. Don't allow floating point regs for operand 0 or 1. ! ;; This can result from a float to fix conversion. (define_peephole *************** *** 3056,3061 **** (compare:CC (match_operand:SI 2 "register_operand" "r") (const_int 0)))] ! "rtx_equal_p (operands[2], operands[0]) ! || rtx_equal_p (operands[2], operands[1])" "orcc %1,%%g0,%0") --- 2962,2968 ---- (compare:CC (match_operand:SI 2 "register_operand" "r") (const_int 0)))] ! "(rtx_equal_p (operands[2], operands[0]) ! || rtx_equal_p (operands[2], operands[1])) ! && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" "orcc %1,%%g0,%0") diff -rc2N gcc-2.2.2/config/sparcv4.h gcc-2.3.1/config/sparcv4.h *** gcc-2.2.2/config/sparcv4.h Thu Jun 11 00:44:12 1992 --- gcc-2.3.1/config/sparcv4.h Wed Sep 2 13:42:31 1992 *************** *** 47,50 **** --- 47,51 ---- #undef COMMON_ASM_OP #undef SKIP_ASM_OP + #undef SET_ASM_OP /* Has no equivalent. See ASM_OUTPUT_DEF below. */ /* Provide a set of pre-definitions and pre-assertions appropriate for *************** *** 151,183 **** #define CTORS_SECTION_ASM_OP ".section\t\".ctors\",#alloc" #define DTORS_SECTION_ASM_OP ".section\t\".dtors\",#alloc" - - /* Code to handle #pragma directives. The interface is a bit messy, - but there's no simpler way to do this while still using yylex. */ - #define HANDLE_PRAGMA(FILE) \ - do { \ - while (c == ' ' || c == '\t') \ - c = getc (FILE); \ - if (c == '\n' || c == EOF) \ - { \ - handle_pragma_token (0, 0); \ - return c; \ - } \ - ungetc (c, FILE); \ - switch (yylex ()) \ - { \ - case IDENTIFIER: \ - case TYPENAME: \ - case STRING: \ - case CONSTANT: \ - handle_pragma_token (token_buffer, yylval.ttype); \ - break; \ - default: \ - handle_pragma_token (token_buffer, 0); \ - } \ - if (nextchar >= 0) \ - c = nextchar, nextchar = -1; \ - else \ - c = getc (FILE); \ - } while (1) /* If the host and target formats match, output the floats as hex. */ --- 152,155 ---- diff -rc2N gcc-2.2.2/config/spc-sol2.h gcc-2.3.1/config/spc-sol2.h *** gcc-2.2.2/config/spc-sol2.h Thu Jun 11 00:45:13 1992 --- gcc-2.3.1/config/spc-sol2.h Tue Oct 13 14:55:13 1992 *************** *** 1,7 **** ! /* Target definitions for GNU compiler for Sparc running Solaris 2.x ! Copyright (C) 1992 Free Software Foundation, Inc. - Written by Ron Guilmette (rfg@ncd.com). - This file is part of GNU CC. --- 1,7 ---- ! /* Definitions of target machine for GNU compiler, for SPARC running Solaris 2 ! Copyright 1992 Free Software Foundation, Inc. ! Contributed by Ron Guilmette (rfg@ncd.com) and ! David V. Henkel-Wallace (gumby@cygnus.com). This file is part of GNU CC. *************** *** 20,35 **** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! /* This is basically just a Sparc running svr4. */ ! #include "sparcv4.h" ! /* Solaris 2.x on a Sparc uses BSD stabs, not DWARF. */ ! #undef DWARF_DEBUGGING_INFO #define DBX_DEBUGGING_INFO /* If we cannot find the GNU *crt*.o files in the STANDARD_STARTFILE_PREFIX directory, our fallback strategy must be to look for these files instead in the Sun C 2.0 directory. */ ! #define MD_STARTFILE_PREFIX_1 "/opt/SUNWste/SC2.0/" --- 20,161 ---- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! /* Supposedly the same as vanilla sparc svr4, except for the stuff below: */ #include "sparcv4.h" ! #undef CPP_PREDEFINES ! #define CPP_PREDEFINES \ ! "-Dsun -Dsparc -Dunix -D__svr4__ -Asystem(unix) -Acpu(sparc) -Amachine(sparc)" ! ! /* 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" ! ! /* 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. */ #define DBX_DEBUGGING_INFO + #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + + #define DBX_BLOCKS_FUNCTION_RELATIVE 1 + /* "gcc2_compiled." must be a .stabs, not an ordinary symbol, or GDB won't + see it. Furthermore, since GDB reads the input piecemeal, starting + with each N_SO, it's a lot easier if the gcc2 flag symbol is *after* + the N_SO rather than before it. So we emit an N_OPT stab here. */ + + #define ASM_IDENTIFY_GCC(FILE) /* Do nothing */ + + #define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) \ + fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE) + + #undef CTORS_SECTION_ASM_OP + #undef DTORS_SECTION_ASM_OP + + #if 0 /* These seems unnecessary; the ones in sparcv4.h look right. */ + #undef TEXT_SECTION_ASM_OP + #undef DATA_SECTION_ASM_OP + #undef BSS_SECTION_ASM_OP + #undef CONST_SECTION_ASM_OP + #undef INIT_SECTION_ASM_OP + + #define TEXT_SECTION_ASM_OP "\t.section\t\".text\"" + #define DATA_SECTION_ASM_OP "\t.section\t\".data\"" + #define BSS_SECTION_ASM_OP "\t.section\t\".bss\"" + + #define CONST_SECTION_ASM_OP "\t.section\t\".rodata\"" + #define INIT_SECTION_ASM_OP "\t.section\t\".init\"" + #endif + + #define CTORS_SECTION_ASM_OP "\t.section\t\".ctors\",#alloc,#execinstr\n" + #define DTORS_SECTION_ASM_OP "\t.section\t\".dtors\",#alloc,#execinstr\n" + + /* 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) + + /* in Solaris 2.0, linenos are relative to the current fn. */ + #undef ASM_OUTPUT_SOURCE_LINE + #define ASM_OUTPUT_SOURCE_LINE(file, line) \ + { static int sym_lineno = 1; \ + fprintf (file, ".stabn 68,0,%d,.LM%d-%s\n.LM%d:\n", \ + line, sym_lineno, \ + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)),\ + sym_lineno); \ + sym_lineno += 1; } + + /* But, to make this work, we have to output the stabs for the function + name *first*... */ + #define DBX_FUNCTION_FIRST + + + /* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. + We don't use the standard LIB_SPEC only because we don't yet support c++ */ + /* If we cannot find the GNU *crt*.o files in the STANDARD_STARTFILE_PREFIX directory, our fallback strategy must be to look for these files instead in the Sun C 2.0 directory. */ ! #undef MD_STARTFILE_PREFIX ! #define MD_STARTFILE_PREFIX "/opt/SUNWspro/SC2.0/" ! ! #undef STARTFILE_SPEC ! #define STARTFILE_SPEC "%{!shared: \ ! %{!symbolic: \ ! %{pg:crt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} \ ! %{pg:gmon.o%s} \ ! %{pg:crti.o%s}%{!pg:crti.o%s} \ ! %{ansi:/usr/ccs/lib/values-Xc.o%s} \ ! %{!ansi: \ ! %{traditional:/usr/ccs/lib/values-Xt.o%s} \ ! %{!traditional:/usr/ccs/lib/values-Xa.o%s}}}} \ ! crtbegin.o%s" ! ! #undef LIB_SPEC ! #define LIB_SPEC \ ! "%{!shared:%{!symbolic:-lc}} \ ! crtend.o%s \ ! %{!shared:%{!symbolic:%{pg:crtn.o%s}%{!pg:crtn.o%s}}}" diff -rc2N gcc-2.2.2/config/sun2.h gcc-2.3.1/config/sun2.h *** gcc-2.2.2/config/sun2.h Sat Jun 13 17:32:04 1992 --- gcc-2.3.1/config/sun2.h Tue Oct 20 16:52:56 1992 *************** *** 49,53 **** #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "target") \ || !strcmp (STR, "assert") || !strcmp (STR, "aux-info")) --- 49,54 ---- #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ ! || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "target") \ || !strcmp (STR, "assert") || !strcmp (STR, "aux-info")) diff -rc2N gcc-2.2.2/config/sun2o4.h gcc-2.3.1/config/sun2o4.h *** gcc-2.2.2/config/sun2o4.h Sat Jun 13 17:32:33 1992 --- gcc-2.3.1/config/sun2o4.h Mon Jul 13 23:28:49 1992 *************** *** 93,97 **** #undef LINK_SPEC ! #define LINK_SPEC "%{!e*:-e start} -dc -dp %{static:-Bstatic}" #undef ASM_OUTPUT_DOUBLE --- 93,98 ---- #undef LINK_SPEC ! #define LINK_SPEC \ ! "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic}" #undef ASM_OUTPUT_DOUBLE diff -rc2N gcc-2.2.2/config/sun3.h gcc-2.3.1/config/sun3.h *** gcc-2.2.2/config/sun3.h Sat Jun 13 17:33:00 1992 --- gcc-2.3.1/config/sun3.h Tue Oct 20 16:53:13 1992 *************** *** 73,77 **** #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "target") \ || !strcmp (STR, "assert") || !strcmp (STR, "aux-info")) --- 73,78 ---- #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ ! || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "target") \ || !strcmp (STR, "assert") || !strcmp (STR, "aux-info")) *************** *** 149,153 **** #define LINK_SPEC \ ! "%{!nostdlib:%{!e*:-e start}} -dc -dp %{static:-Bstatic} %{assert*}" /* Every structure or union's size must be a multiple of 2 bytes. */ --- 150,154 ---- #define LINK_SPEC \ ! "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" /* Every structure or union's size must be a multiple of 2 bytes. */ diff -rc2N gcc-2.2.2/config/svr3.h gcc-2.3.1/config/svr3.h *** gcc-2.2.2/config/svr3.h Thu May 21 04:06:43 1992 --- gcc-2.3.1/config/svr3.h Tue Aug 4 15:11:06 1992 *************** *** 40,43 **** --- 40,46 ---- */ + /* Define a symbol indicating that we are using svr3.h. */ + #define USING_SVR3_H + /* Define a symbol so that libgcc* can know what sort of operating environment and assembler syntax we are targeting for. */ *************** *** 256,262 **** FINI_SECTION_FUNCTION #define INIT_SECTION_FUNCTION \ void \ ! init_section () \ { \ if (in_section != in_init) \ --- 259,276 ---- FINI_SECTION_FUNCTION + #define BSS_SECTION_FUNCTION \ + void \ + bss_section () \ + { \ + if (in_section != in_bss) \ + { \ + fprintf (asm_out_file, "\t%s\n", BSS_SECTION_ASM_OP); \ + in_section = in_bss; \ + } \ + } + #define INIT_SECTION_FUNCTION \ void \ ! init_section () \ { \ if (in_section != in_init) \ *************** *** 294,298 **** } ! #if 0 #define CTORS_SECTION_FUNCTION \ void \ --- 308,314 ---- } ! /* The ctors and dtors sections are not normally put into use ! by EXTRA_SECTIONS and EXTRA_SECTION_FUNCTIONS as defined in svr3.h, ! but it can't hurt to define these macros for whatever systems use them. */ #define CTORS_SECTION_FUNCTION \ void \ *************** *** 316,320 **** } \ } - #endif /* This is machine-dependent --- 332,335 ---- diff -rc2N gcc-2.2.2/config/svr4.h gcc-2.3.1/config/svr4.h *** gcc-2.2.2/config/svr4.h Sat May 23 17:24:27 1992 --- gcc-2.3.1/config/svr4.h Tue Aug 4 15:11:07 1992 *************** *** 40,43 **** --- 40,46 ---- */ + /* 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 *************** *** 194,201 **** C compilers. */ #define ASM_FILE_END(FILE) \ do { \ ! fprintf ((FILE), "\t.ident\t\"GCC: (GNU) %s\"\n", \ ! version_string); \ } while (0) --- 197,206 ---- 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) *************** *** 207,211 **** #define ASM_OUTPUT_IDENT(FILE, NAME) \ ! fprintf (FILE, "\t.ident \"%s\"\n", NAME); /* Use periods rather than dollar signs in special g++ assembler names. */ --- 212,216 ---- #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. */ *************** *** 221,224 **** --- 226,233 ---- #define TARGET_MEM_FUNCTIONS + /* Handle #pragma weak and #pragma pack. */ + + #define HANDLE_SYSV_PRAGMA + /* System V Release 4 uses DWARF debugging info. */ *************** *** 315,318 **** --- 324,349 ---- sprintf (LABEL, "*.%s%d", PREFIX, NUM); \ } while (0) + + /* Output the label which preceeds 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 diff -rc2N gcc-2.2.2/config/t-decrose gcc-2.3.1/config/t-decrose *** gcc-2.2.2/config/t-decrose Thu Jun 11 00:55:33 1992 --- gcc-2.3.1/config/t-decrose Wed Jun 24 00:19:12 1992 *************** *** 7,11 **** # PREMADE_ATTRTAB_MD = $(srcdir)/config/mips-at.md ! # Supress building libgcc1.a, since the MIPS compiler port is complete # and does not need anything from libgcc1.a. LIBGCC1 = libgcc1.null --- 7,11 ---- # PREMADE_ATTRTAB_MD = $(srcdir)/config/mips-at.md ! # Suppress building libgcc1.a, since the MIPS compiler port is complete # and does not need anything from libgcc1.a. LIBGCC1 = libgcc1.null diff -rc2N gcc-2.2.2/config/t-decstatn gcc-2.3.1/config/t-decstatn *** gcc-2.2.2/config/t-decstatn Thu Jun 11 00:55:54 1992 --- gcc-2.3.1/config/t-decstatn Thu Oct 15 15:09:17 1992 *************** *** 1,5 **** EXTRA_PASSES = mips-tfile mips-tdump - CCLIBFLAGS = -O -G 0 - LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) -g1 -G 0 CONFIG2_H = $(srcdir)/config/mips.h --- 1,3 ---- *************** *** 8,12 **** # PREMADE_ATTRTAB_MD = $(srcdir)/config/mips-at.md ! # Supress building libgcc1.a, since the MIPS compiler port is complete # and does not need anything from libgcc1.a. LIBGCC1 = libgcc1.null --- 6,10 ---- # PREMADE_ATTRTAB_MD = $(srcdir)/config/mips-at.md ! # Suppress building libgcc1.a, since the MIPS compiler port is complete # and does not need anything from libgcc1.a. LIBGCC1 = libgcc1.null diff -rc2N gcc-2.2.2/config/t-hp320g gcc-2.3.1/config/t-hp320g *** gcc-2.2.2/config/t-hp320g --- gcc-2.3.1/config/t-hp320g Mon Jul 27 22:56:53 1992 *************** *** 0 **** --- 1,8 ---- + # Control how libgcc.a is made. + LIBGCC1 = libgcc1.conv + + AR=$(tooldir)/ar + RANLIB=$(tooldir)/ranlib + RANLIB_TEST = [ -f $(tooldir)/ranlib ] + + LIBCONVERT=$(tooldir)/hpxt diff -rc2N gcc-2.2.2/config/t-i386rose gcc-2.3.1/config/t-i386rose *** gcc-2.2.2/config/t-i386rose Sun Apr 19 21:40:05 1992 --- gcc-2.3.1/config/t-i386rose Tue Sep 22 17:04:01 1992 *************** *** 1,4 **** LIMITS_H = ! CONFIG2_H = $(srcdir)/config/i386.h $(srcdir)/config/i386rose.h # Add additional dependencies to recompile selected modules whenever the --- 1,5 ---- + EXTRA_OBJS = halfpic.o LIMITS_H = ! CONFIG2_H = $(srcdir)/config/i386.h $(srcdir)/config/i386rose.h $(srcdir)/halfpic.h # Add additional dependencies to recompile selected modules whenever the *************** *** 34,35 **** --- 35,38 ---- recog.o: $(CONFIG2_H) reload.o: $(CONFIG2_H) + + halfpic.o: halfpic.c $(CONFIG_H) $(CONFIG2_H) $(RTL_H) $(TREE_H) diff -rc2N gcc-2.2.2/config/t-libc-ok gcc-2.3.1/config/t-libc-ok *** gcc-2.2.2/config/t-libc-ok --- gcc-2.3.1/config/t-libc-ok Mon Jul 27 23:07:12 1992 *************** *** 0 **** --- 1 ---- + LIBGCC1=libgcc1.null diff -rc2N gcc-2.2.2/config/t-m88k gcc-2.3.1/config/t-m88k *** gcc-2.2.2/config/t-m88k Sat Jun 13 17:35:09 1992 --- gcc-2.3.1/config/t-m88k Wed Oct 7 16:18:03 1992 *************** *** 2,6 **** MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ ! moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm $(MOVE_ASM): $(srcdir)/config/m88k-move.sh --- 2,7 ---- 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-move.sh diff -rc2N gcc-2.2.2/config/t-m88kluna gcc-2.3.1/config/t-m88kluna *** gcc-2.2.2/config/t-m88kluna Sat Jun 13 17:35:18 1992 --- gcc-2.3.1/config/t-m88kluna Wed Oct 7 16:18:04 1992 *************** *** 2,6 **** MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ ! moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm $(MOVE_ASM): $(srcdir)/config/m88k-move.sh --- 2,7 ---- 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-move.sh diff -rc2N gcc-2.2.2/config/t-m88kv4 gcc-2.3.1/config/t-m88kv4 *** gcc-2.2.2/config/t-m88kv4 Sat Jun 13 17:35:28 1992 --- gcc-2.3.1/config/t-m88kv4 Wed Oct 7 16:18:05 1992 *************** *** 2,6 **** MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ ! moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm # Use the -abi option for version 03.00 syntax. --- 2,7 ---- MOVE_ASM = moveHI15x.asm moveQI16x.asm moveSI46x.asm moveSI64n.asm \ ! moveHI48x.asm moveSI45x.asm moveSI47x.asm moveSI96x.asm \ ! moveDI96x.asm # Use the -abi option for version 03.00 syntax. diff -rc2N gcc-2.2.2/config/t-mips gcc-2.3.1/config/t-mips *** gcc-2.2.2/config/t-mips Thu Jun 11 00:47:10 1992 --- gcc-2.3.1/config/t-mips Thu Oct 15 15:09:16 1992 *************** *** 1,5 **** EXTRA_PASSES = mips-tfile mips-tdump - CCLIBFLAGS = -O -G 0 - LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) -g1 -G 0 CONFIG2_H = $(srcdir)/config/mips.h --- 1,3 ---- *************** *** 8,12 **** # PREMADE_ATTRTAB_MD = $(srcdir)/config/mips-at.md ! # Supress building libgcc1.a, since the MIPS compiler port is complete # and does not need anything from libgcc1.a. LIBGCC1 = libgcc1.null --- 6,10 ---- # PREMADE_ATTRTAB_MD = $(srcdir)/config/mips-at.md ! # Suppress building libgcc1.a, since the MIPS compiler port is complete # and does not need anything from libgcc1.a. LIBGCC1 = libgcc1.null diff -rc2N gcc-2.2.2/config/t-next gcc-2.3.1/config/t-next *** gcc-2.2.2/config/t-next Sat Jun 13 17:35:48 1992 --- gcc-2.3.1/config/t-next Fri Oct 23 03:26:35 1992 *************** *** 2,3 **** --- 2,8 ---- LIBGCC1= + # Specify other dirs of system header files to be fixed. + OTHER_FIXINCLUDES_DIRS= /NextDeveloper/Headers \ + /NextDeveloper/Headers/ansi /NextDeveloper/Headers/bsd \ + /LocalDeveloper/Headers /LocalDeveloper/Headers/ansi \ + /LocalDeveloper/Headers/bsd diff -rc2N gcc-2.2.2/config/t-pa gcc-2.3.1/config/t-pa *** gcc-2.2.2/config/t-pa --- gcc-2.3.1/config/t-pa Thu Sep 17 14:52:30 1992 *************** *** 0 **** --- 1,2 ---- + LIBGCC1=libgcc1.null + INSTALLED_H = float.h stdarg.h varargs.h $(USER_H) limits.h diff -rc2N gcc-2.2.2/config/t-sol2 gcc-2.3.1/config/t-sol2 *** gcc-2.2.2/config/t-sol2 --- gcc-2.3.1/config/t-sol2 Sun Nov 1 03:28:47 1992 *************** *** 0 **** --- 1,24 ---- + # we need startup files for solaris, since we don't get them with the system + + EXTRA_PARTS=crt1.o crti.o crtn.o gmon.o crtbegin.o crtend.o + + # we need to supply our own assembly versions of libgcc1.c files, + # since the user may not have native 'cc' available + + # ??? This is wrong! + INSTALL_TARGET = install-cross + + LIBGCC1 = libgcc1.null + + # gmon build rule: + gmon.o: config/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \ + -c $(srcdir)/config/gmon-sol2.c -o gmon.o + + # Assemble startup files. + crt1.o: config/sol2-c1.asm + $(AS) -o crt1.o $(srcdir)/config/sol2-c1.asm + crti.o: config/sol2-ci.asm + $(AS) -o crti.o $(srcdir)/config/sol2-ci.asm + crtn.o: config/sol2-cn.asm + $(AS) -o crtn.o $(srcdir)/config/sol2-cn.asm diff -rc2N gcc-2.2.2/config/t-svr4 gcc-2.3.1/config/t-svr4 *** gcc-2.2.2/config/t-svr4 Sat Jan 18 02:06:53 1992 --- gcc-2.3.1/config/t-svr4 Mon Jul 27 22:52:01 1992 *************** *** 3,8 **** EXTRA_PARTS=crtbegin.o crtend.o - - # For svr4 we run the special svr4 fixincludes script. - - FIXINCLUDES=fixinc.svr4 --- 3,4 ---- diff -rc2N gcc-2.2.2/config/tahoe.h gcc-2.3.1/config/tahoe.h *** gcc-2.2.2/config/tahoe.h Sat Apr 18 15:55:58 1992 --- gcc-2.3.1/config/tahoe.h Mon Jul 27 22:44:56 1992 *************** *** 257,265 **** #define REGNO_REG_CLASS(REGNO) (REGNO == 16 ? FPP_REG : GENERAL_REGS) ! /* only gereral registers can be used as a base reg */ #define BASE_REG_CLASS GENERAL_REGS ! /* only gereral registers can be used to index */ #define INDEX_REG_CLASS GENERAL_REGS --- 257,265 ---- #define REGNO_REG_CLASS(REGNO) (REGNO == 16 ? FPP_REG : GENERAL_REGS) ! /* only general registers can be used as a base reg */ #define BASE_REG_CLASS GENERAL_REGS ! /* only general registers can be used to index */ #define INDEX_REG_CLASS GENERAL_REGS *************** *** 514,518 **** goto ADDR; } } ! /* Is the rtx X a valid memoy address for operand of mode MODE? */ /* If it is, go to ADDR */ --- 514,518 ---- goto ADDR; } } ! /* Is the rtx X a valid memory address for operand of mode MODE? */ /* If it is, go to ADDR */ diff -rc2N gcc-2.2.2/config/tahoe.md gcc-2.3.1/config/tahoe.md *** gcc-2.2.2/config/tahoe.md Sat Mar 14 00:16:57 1992 --- gcc-2.3.1/config/tahoe.md Mon Jul 27 22:45:08 1992 *************** *** 461,465 **** ! ; Subtraction from the sp (needed by the built in alloc funtion) needs ; to be different since the sp cannot be directly read on the tahoe. ; If it's a simple constant, you just use displacement. Otherwise, you --- 461,465 ---- ! ; Subtraction from the sp (needed by the built in alloc function) needs ; to be different since the sp cannot be directly read on the tahoe. ; If it's a simple constant, you just use displacement. Otherwise, you *************** *** 1636,1640 **** (define_insn "call_value" ! [(set (match_operand 0 "" "g") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g")))] --- 1636,1640 ---- (define_insn "call_value" ! [(set (match_operand 0 "" "=g") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g")))] diff -rc2N gcc-2.2.2/config/tek6000.h gcc-2.3.1/config/tek6000.h *** gcc-2.2.2/config/tek6000.h --- gcc-2.3.1/config/tek6000.h Mon Jul 27 22:50:43 1992 *************** *** 0 **** --- 1,233 ---- + /* Definitions of target machine for GNU compiler. + Generic Tektronix 6000 series NS32000 version. + See tek6100.h and tek6200.h, which include this file. + Copyright (C) 1990 Free Software Foundation, Inc. + Created by Snoopy (sopwith.uucp!snoopy). + Based on work by Mark Mason (mason@reed.bitnet, + pyramid!unify!mason@uunet.uu.net) and Keith Packard. + + 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. */ + + /* Generate syntax for the UTek assembler. */ + #ifndef UTEK_ASM + #define UTEK_ASM + #endif + + /* Two flags to control how addresses are printed in assembler insns. */ + + /* The way PUT_ABSOLUTE_PREFIX in ns32k.h works, setting it to 0 will + * turn it off. Define ABSOLUTE_PREFIX before including ns32k.h. + */ + #define ABSOLUTE_PREFIX 0 + #define IMMEDIATE_PREFIX '$' + + #include "ns32k.h" + + /* Define these after ns32k.c so we will notice if gcc tries to + * output external mode addressing. UTek's as and ld do not support + * external mode addressing, according to Daryl McDaniel (illian.uucp!darylm). + * Hopefully the UTek assembler will complain if gcc feeds it this stuff. + * They don't seem to do anything, I think that gcc is not actually + * trying to generate external mode operands. + */ + #undef PUT_EXTERNAL_PREFIX + #define PUT_EXTERNAL_PREFIX(arg) fprintf(arg, " Should not be using external mode under UTek. ") + #define EXTERNAL_PREFIX '%' + + /* Used in ns32k.c to control syntax. */ + #define NO_ABSOLUTE_PREFIX_IF_SYMBOLIC + #define NO_IMMEDIATE_PREFIX_IF_SYMBOLIC + + /* Used in ns32k.md to specify syntax of bsr/jsr operand. */ + #define CALL_MEMREF_IMPLICIT + + /* #define PC_RELATIVE */ /* Seems to break things. */ + #define BASE_REG_NEEDED /* Seems to fix problem where external mode + * syntax was being generated. + */ + + /* ------------ Debugging Support ----------------------------- */ + + /* The sdb support does not yet work with UTek. Need to teach gcc + * how to create sdb type stabs as well as dbx style stabs. + */ + #define DBX_DEBUGGING_INFO + /* #define SDB_DEBUGGING_INFO */ + + /* Act the same as the UTek complier: -g for dbx, -go for sdb. + * This is used in toplev.c. + */ + #define PREFERRED_DEBUGGING_TYPE \ + ((len > 1 && !strncmp(str, "go", len)) ? SDB_DEBUG : DBX_DEBUG ) + + /* Sequent has some changes in the format of DBX symbols. */ + #define DBX_NO_XREFS 1 + + /* Don't split DBX symbols into continuations. */ + #define DBX_CONTIN_LENGTH 0 + + /* ------------------------------------------- */ + + #define TARGET_DEFAULT 1 + + /* These control the C++ compiler somehow. */ + #define FASCIST_ASSEMBLER + #define USE_COLLECT + + /* Print subsidiary information on the compiler version in use. */ + #undef TARGET_VERSION + #define TARGET_VERSION fprintf (stderr, " (ns32k, UTek syntax)"); + + /* The tek6100.h and tek6200.h files add stratos or merlin respectively. */ + + #define CPP_PREDEFINES_Tek6000 \ + "-Dns16000 -Dns32000 -Dns32k -Dns32016 -DUTek -DUTEK -Dbsd -DBSD" + #undef CPP_PREDEFINES + #define CPP_PREDEFINES "CPP_PREDEFINES_Tek6000" + + /* This is how to align the code that follows an unconditional branch. + Don't define it, since it confuses the assembler (we hear). */ + + #undef ASM_OUTPUT_ALIGN_CODE + + /* Assembler pseudo-op for shared data segment. */ + #define SHARED_SECTION_ASM_OP ".shdata" + + #ifdef UTEK_ASM + #undef FUNCTION_PROLOGUE + + /* This differs from the one in ns32k.h in printing a bitmask + rather than a register list in the enter or save instruction. */ + + #define FUNCTION_PROLOGUE(FILE, SIZE) \ + { register int regno, g_regs_used = 0; \ + int used_regs_buf[8], *bufp = used_regs_buf; \ + int used_fregs_buf[8], *fbufp = used_fregs_buf; \ + extern char call_used_regs[]; \ + MAIN_FUNCTION_PROLOGUE; \ + for (regno = 0; regno < 8; regno++) \ + if (regs_ever_live[regno] \ + && ! call_used_regs[regno]) \ + { \ + *bufp++ = regno; g_regs_used++; \ + } \ + *bufp = -1; \ + for (; regno < 16; regno++) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) { \ + *fbufp++ = regno; \ + } \ + *fbufp = -1; \ + bufp = used_regs_buf; \ + if (frame_pointer_needed) \ + fprintf (FILE, "\tenter "); \ + else if (g_regs_used) \ + fprintf (FILE, "\tsave "); \ + if (frame_pointer_needed || g_regs_used) \ + { \ + char mask = 0; \ + while (*bufp >= 0) \ + mask |= 1 << *bufp++; \ + fprintf (FILE, "$0x%x", (int) mask & 0xff); \ + } \ + if (frame_pointer_needed) \ + fprintf (FILE, ",$%d\n", SIZE); \ + else if (g_regs_used) \ + fprintf (FILE, "\n"); \ + fbufp = used_fregs_buf; \ + while (*fbufp >= 0) \ + { \ + if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) \ + fprintf (FILE, "\tmovf f%d,tos\n", *fbufp++ - 8); \ + else \ + { \ + fprintf (FILE, "\tmovl f%d,tos\n", fbufp[0] - 8); \ + fbufp += 2; \ + } \ + } \ + } + + #undef FUNCTION_EPILOGUE + + /* This differs from the one in ns32k.h in printing a bitmask + rather than a register list in the exit or restore instruction. */ + + #define FUNCTION_EPILOGUE(FILE, SIZE) \ + { register int regno, g_regs_used = 0, f_regs_used = 0; \ + int used_regs_buf[8], *bufp = used_regs_buf; \ + int used_fregs_buf[8], *fbufp = used_fregs_buf; \ + extern char call_used_regs[]; \ + *fbufp++ = -2; \ + for (regno = 8; regno < 16; regno++) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) { \ + *fbufp++ = regno; f_regs_used++; \ + } \ + fbufp--; \ + for (regno = 0; regno < 8; regno++) \ + if (regs_ever_live[regno] \ + && ! call_used_regs[regno]) \ + { \ + *bufp++ = regno; g_regs_used++; \ + } \ + while (fbufp > used_fregs_buf) \ + { \ + if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) \ + { \ + fprintf (FILE, "\tmovl tos,f%d\n", fbufp[-1] - 8); \ + fbufp -= 2; \ + } \ + else fprintf (FILE, "\tmovf tos,f%d\n", *fbufp-- - 8); \ + } \ + if (frame_pointer_needed) \ + fprintf (FILE, "\texit "); \ + else if (g_regs_used) \ + fprintf (FILE, "\trestore "); \ + if (g_regs_used || frame_pointer_needed) \ + { \ + char mask = 0; \ + \ + while (bufp > used_regs_buf) \ + { \ + /* Utek assembler takes care of reversing this */ \ + mask |= 1 << *--bufp; \ + } \ + fprintf (FILE, "$0x%x\n", (int) mask & 0xff); \ + } \ + if (current_function_pops_args) \ + fprintf (FILE, "\tret $%d\n", current_function_pops_args); \ + else fprintf (FILE, "\tret $0\n"); } + + /* UTek assembler needs "ret $0", not "ret 0". */ + #undef TRANSFER_FROM_TRAMPOLINE + #define TRANSFER_FROM_TRAMPOLINE \ + void \ + __transfer_from_trampoline () \ + { \ + asm ("___trampoline:"); \ + asm ("movd 16(r2),tos"); \ + asm ("movd 12(r2),r2"); \ + asm ("ret $0"); \ + } + + #endif /* UTEK_ASM */ + + #undef PRINT_OPERAND_ADDRESS + #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address(FILE, ADDR) + + /* The UTek library supplies bcopy() and friends, not memcpy(). */ + #ifdef TARGET_MEM_FUNCTIONS + #undef TARGET_MEM_FUNCTIONS + #endif diff -rc2N gcc-2.2.2/config/tek6100.h gcc-2.3.1/config/tek6100.h *** gcc-2.2.2/config/tek6100.h --- gcc-2.3.1/config/tek6100.h Mon Jul 27 22:50:47 1992 *************** *** 0 **** --- 1,6 ---- + #include "tek6000.h" + + #undef CPP_PREDEFINES + #define CPP_PREDEFINES \ + "-Dns32000 -Dns32k -Dns16000 -Dns32016 -DUTek -DUTEK -Dbsd -DBSD -Dstratos" + diff -rc2N gcc-2.2.2/config/tek6200.h gcc-2.3.1/config/tek6200.h *** gcc-2.2.2/config/tek6200.h --- gcc-2.3.1/config/tek6200.h Mon Jul 27 22:50:51 1992 *************** *** 0 **** --- 1,6 ---- + #include "tek6000.h" + + #undef CPP_PREDEFINES + #define CPP_PREDEFINES \ + "-Dns32000 -Dns32k -Dns16000 -Dns32016 -DUTek -DUTEK -Dbsd -DBSD -Dmerlin" + diff -rc2N gcc-2.2.2/config/tower-as.h gcc-2.3.1/config/tower-as.h *** gcc-2.2.2/config/tower-as.h Thu Jun 11 01:03:17 1992 --- gcc-2.3.1/config/tower-as.h Thu Jul 30 00:55:58 1992 *************** *** 654,667 **** #define BSS_SECTION_ASM_OP "section\t~bss" - #define BSS_SECTION_FUNCTION \ - void \ - bss_section () \ - { \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ - } #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ --- 654,657 ---- diff -rc2N gcc-2.2.2/config/tower.h gcc-2.3.1/config/tower.h *** gcc-2.2.2/config/tower.h Thu Jun 11 01:02:44 1992 --- gcc-2.3.1/config/tower.h Thu Oct 1 00:53:29 1992 *************** *** 79,86 **** #define IDENT_DIRECTIVE - /* This is only used in g++, don't prepend underscore. */ - - #define NO_UNDERSCORES - /* Every structure and union's size must be a multiple of two bytes. */ --- 79,82 ---- diff -rc2N gcc-2.2.2/config/unx386.h gcc-2.3.1/config/unx386.h *** gcc-2.2.2/config/unx386.h Mon May 11 15:46:09 1992 --- gcc-2.3.1/config/unx386.h Thu Sep 24 02:08:23 1992 *************** *** 48,52 **** CODE is the letter used in an operand spec (L, B, W, S or Q). CH is the corresponding lower case letter ! (except if CODE is L then CH is `l'). */ #define PUT_OP_SIZE(CODE,CH,FILE) putc (CH,(FILE)) --- 48,52 ---- CODE is the letter used in an operand spec (L, B, W, S or Q). CH is the corresponding lower case letter ! (except if CODE is `Q' then CH is `l', unless GAS_MNEMONICS). */ #define PUT_OP_SIZE(CODE,CH,FILE) putc (CH,(FILE)) *************** *** 126,127 **** --- 126,145 ---- #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE)) + + /* By default, target has a 80387, uses IEEE compatible arithmetic, + and returns float values in the 387, ie, + (TARGET_80387 | TARGET_IEEE_FP | TARGET_FLOAT_RETURNS_IN_80387) */ + + #define TARGET_DEFAULT 0301 + + /* Floating-point return values come in the FP register. */ + + #define VALUE_REGNO(MODE) \ + (GET_MODE_CLASS (MODE) == MODE_FLOAT \ + && TARGET_FLOAT_RETURNS_IN_80387 ? FIRST_FLOAT_REG : 0) + + /* 1 if N is a possible register number for a function value. */ + + #define FUNCTION_VALUE_REGNO_P(N) \ + ((N) == 0 || ((N)== FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)) + diff -rc2N gcc-2.2.2/config/vax-vms.h gcc-2.3.1/config/vax-vms.h *** gcc-2.2.2/config/vax-vms.h Thu Jun 11 01:01:32 1992 --- gcc-2.3.1/config/vax-vms.h Mon Jul 20 22:03:33 1992 *************** *** 64,68 **** /* We redefine this because there is a hidden variable on the stack that VAXC$ESTABLISH uses. We just need to add four bytes to whatever ! gcc thinks that we need. Similarily, we need to move all local variables down 4 bytes in the stack. */ --- 64,68 ---- /* We redefine this because there is a hidden variable on the stack that VAXC$ESTABLISH uses. We just need to add four bytes to whatever ! gcc thinks that we need. Similarly, we need to move all local variables down 4 bytes in the stack. */ *************** *** 95,99 **** { extern char *current_function_name; \ if (!strcmp ("main", current_function_name)) \ ! fprintf(FILE, "\tjsb _c$main_args\n"); \ else { \ char *p = current_function_name; \ --- 95,99 ---- { extern char *current_function_name; \ if (!strcmp ("main", current_function_name)) \ ! fprintf(FILE, "\tjsb _C$MAIN_ARGS\n"); \ else { \ char *p = current_function_name; \ *************** *** 101,105 **** if (*p == *__MAIN_NAME) \ if (strncmp(p, __MAIN_NAME, (sizeof __MAIN_NAME)-1) == 0) {\ ! fprintf(FILE, "\tjsb _c$main_args\n");\ break; \ } else \ --- 101,105 ---- if (*p == *__MAIN_NAME) \ if (strncmp(p, __MAIN_NAME, (sizeof __MAIN_NAME)-1) == 0) {\ ! fprintf(FILE, "\tjsb _C$MAIN_ARGS\n");\ break; \ } else \ *************** *** 119,123 **** #define ENCODE_SECTION_INFO(decl) \ ! if (TREE_EXTERNAL (decl) && TREE_PUBLIC (decl)) \ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; --- 119,123 ---- #define ENCODE_SECTION_INFO(decl) \ ! if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) \ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; diff -rc2N gcc-2.2.2/config/vax.c gcc-2.3.1/config/vax.c *** gcc-2.2.2/config/vax.c Thu Jun 11 00:58:44 1992 --- gcc-2.3.1/config/vax.c Thu Aug 20 15:22:59 1992 *************** *** 36,39 **** --- 36,40 ---- split_quadword_operands (operands, low, n) rtx *operands, *low; + int n; { int i; *************** *** 577,578 **** --- 578,668 ---- return c; } + + #ifdef VMS + /* Additional support code for VMS. */ + + #ifdef QSORT_WORKAROUND + /* + Do not use VAXCRTL's qsort() due to a severe bug: once you've + sorted something which has a size that's an exact multiple of 4 + and is longword aligned, you cannot safely sort anything which + is either not a multiple of 4 in size or not longword aligned. + A static "move-by-longword" optimization flag inside qsort() is + never reset. This is known of affect VMS V4.6 through VMS V5.5-1. + + In this work-around an insertion sort is used for simplicity. + The qsort code from glibc should probably be used instead. + */ + void + not_qsort (array, count, size, compare) + void *array; + unsigned count, size; + int (*compare)(); + { + + if (size == sizeof (short)) + { + register int i; + register short *next, *prev; + short tmp, *base = array; + + for (next = base, i = count - 1; i > 0; i--) + { + prev = next++; + if ((*compare)(next, prev) < 0) + { + tmp = *next; + do *(prev + 1) = *prev; + while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0); + *(prev + 1) = tmp; + } + } + } + else if (size == sizeof (long)) + { + register int i; + register long *next, *prev; + long tmp, *base = array; + + for (next = base, i = count - 1; i > 0; i--) + { + prev = next++; + if ((*compare)(next, prev) < 0) + { + tmp = *next; + do *(prev + 1) = *prev; + while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0); + *(prev + 1) = tmp; + } + } + } + else /* arbitrary size */ + { + #ifdef USE_C_ALLOCA + extern void *alloca (); + #endif + register int i; + register char *next, *prev, *tmp = alloca (size), *base = array; + + for (next = base, i = count - 1; i > 0; i--) + { /* count-1 forward iterations */ + prev = next, next += size; /* increment front pointer */ + if ((*compare)(next, prev) < 0) + { /* found element out of order; move others up then re-insert */ + memcpy (tmp, next, size); /* save smaller element */ + do { memcpy (prev + size, prev, size); /* move larger elem. up */ + prev -= size; /* decrement back pointer */ + } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0); + memcpy (prev + size, tmp, size); /* restore small element */ + } + } + #ifdef USE_C_ALLOCA + alloca (0); + #endif + } + + return; + } + #endif /* QSORT_WORKAROUND */ + + #endif /* VMS */ diff -rc2N gcc-2.2.2/config/vax.h gcc-2.3.1/config/vax.h *** gcc-2.2.2/config/vax.h Thu Jun 11 00:59:26 1992 --- gcc-2.3.1/config/vax.h Mon Oct 12 18:31:11 1992 *************** *** 1189,1192 **** --- 1189,1193 ---- letter print C reverse branch condition + D 64-bit immediate operand B the low 8 bits of the complement of a constant operand H the low 16 bits of the complement of a constant operand *************** *** 1199,1202 **** --- 1200,1207 ---- # 'd' or 'g' depending on whether dfloat or gfloat is used */ + /* The purpose of D is to get around a quirk or bug in vax assembler + whereby -1 in a 64-bit immediate operand means 0x00000000ffffffff, + which is not a 64-bit minus one. */ + #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ((CODE) == '#') *************** *** 1207,1210 **** --- 1212,1217 ---- else if (CODE == 'C') \ fputs (rev_cond_name (X), FILE); \ + else if (CODE == 'D' && GET_CODE (X) == CONST_INT && INTVAL (X) < 0) \ + fprintf (FILE, "0xffffffff%08x", INTVAL (X)); \ else if (CODE == 'P' && GET_CODE (X) == CONST_INT) \ fprintf (FILE, "$%d", INTVAL (X) + 1); \ *************** *** 1228,1232 **** else if (GET_CODE (X) == MEM) \ output_address (XEXP (X, 0)); \ ! else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ { union { double d; int i[2]; } u; \ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ --- 1235,1243 ---- else if (GET_CODE (X) == MEM) \ output_address (XEXP (X, 0)); \ ! else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ ! { union { double d; int i[2]; } u; \ ! u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ ! fprintf (FILE, "$0f%.20e", u.d); } \ ! else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \ { union { double d; int i[2]; } u; \ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ diff -rc2N gcc-2.2.2/config/vax.md gcc-2.3.1/config/vax.md *** gcc-2.2.2/config/vax.md Thu Jun 11 00:59:54 1992 --- gcc-2.3.1/config/vax.md Thu Oct 8 15:32:08 1992 *************** *** 176,180 **** "@ clrq %0 ! movq %1,%0") ;; The VAX move instructions have space-time tradeoffs. On a microVAX --- 176,180 ---- "@ clrq %0 ! movq %D1,%0") ;; The VAX move instructions have space-time tradeoffs. On a microVAX *************** *** 334,342 **** }") ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it won't successfully combine with anything. ! (define_insn "movstrhi" [(set (match_operand:BLK 0 "general_operand" "=g") (match_operand:BLK 1 "general_operand" "g")) --- 334,355 ---- }") + ;; This is here to accept 4 arguments and pass the first 3 along + ;; to the movstrhi1 pattern that really does the work. + (define_expand "movstrhi" + [(set (match_operand:BLK 0 "general_operand" "=g") + (match_operand:BLK 1 "general_operand" "g")) + (use (match_operand:HI 2 "general_operand" "g")) + (match_operand 3 "" "")] + "" + " + emit_insn (gen_movstrhi1 (operands[0], operands[1], operands[2])); + DONE; + ") + ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it won't successfully combine with anything. ! (define_insn "movstrhi1" [(set (match_operand:BLK 0 "general_operand" "=g") (match_operand:BLK 1 "general_operand" "g")) *************** *** 517,520 **** --- 530,546 ---- addf3 %1,%2,%0") + /* The space-time-opcode tradeoffs for addition vary by model of VAX. + + On a VAX 3 "movab (r1)[r2],r3" is faster than "addl3 r1,r2,r3", + but it not faster on other models. + + "movab #(r1),r2" is usually shorter than "addl3 #,r1,r2", and is + faster on a VAX 3, but some VAXes (e.g. VAX 9000) will stall if + a register is used in an address too soon after it is set. + Compromise by using movab only when it is shorter than the add + or the base register in the address is one of sp, ap, and fp, + which are not modified very often. */ + + (define_insn "addsi3" [(set (match_operand:SI 0 "general_operand" "=g") *************** *** 535,539 **** if (GET_CODE (operands[2]) == CONST_INT && (unsigned) INTVAL (operands[2]) >= 64 ! && GET_CODE (operands[1]) == REG) return \"movab %c2(%1),%0\"; return \"addl2 %2,%0\"; --- 561,567 ---- if (GET_CODE (operands[2]) == CONST_INT && (unsigned) INTVAL (operands[2]) >= 64 ! && GET_CODE (operands[1]) == REG ! && ((INTVAL (operands[2]) < 32767 && INTVAL (operands[2]) > -32768) ! || REGNO (operands[1]) > 11)) return \"movab %c2(%1),%0\"; return \"addl2 %2,%0\"; *************** *** 541,555 **** if (rtx_equal_p (operands[0], operands[2])) return \"addl2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subl3 $%n2,%1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) INTVAL (operands[2]) >= 64 ! && GET_CODE (operands[1]) == REG) ! { ! if (push_operand (operands[0], SImode)) ! return \"pushab %c2(%1)\"; ! return \"movab %c2(%1),%0\"; ! } return \"addl3 %1,%2,%0\"; }") --- 569,595 ---- if (rtx_equal_p (operands[0], operands[2])) return \"addl2 %1,%0\"; + + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) < 32767 + && INTVAL (operands[2]) > -32768 + && GET_CODE (operands[1]) == REG + && push_operand (operands[0], SImode)) + return \"pushab %c2(%1)\"; + if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subl3 $%n2,%1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT && (unsigned) INTVAL (operands[2]) >= 64 ! && GET_CODE (operands[1]) == REG ! && ((INTVAL (operands[2]) < 32767 && INTVAL (operands[2]) > -32768) ! || REGNO (operands[1]) > 11)) ! return \"movab %c2(%1),%0\"; ! ! /* Add this if using gcc on a VAX 3xxx: ! if (REG_P (operands[1]) && REG_P (operands[2])) ! return \"movab (%1)[%2],%0\"; ! */ return \"addl3 %1,%2,%0\"; }") *************** *** 899,906 **** " { ! if (GET_CODE (operands[1]) == CONST_INT) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[1])); else ! operands[1] = expand_unop (SImode, one_cmpl_optab, operands[1], 0, 1); }") --- 939,956 ---- " { ! rtx op1 = operands[1]; ! ! /* If there is a constant argument, complement that one. */ ! if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (op1) != CONST_INT) ! { ! operands[1] = operands[2]; ! operands[2] = op1; ! op1 = operands[1]; ! } ! ! if (GET_CODE (op1) == CONST_INT) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (op1)); else ! operands[1] = expand_unop (SImode, one_cmpl_optab, op1, 0, 1); }") *************** *** 912,921 **** " { ! rtx op = operands[1]; ! if (GET_CODE (op) == CONST_INT) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! ((1 << 16) - 1) & ~INTVAL (op)); else ! operands[1] = expand_unop (HImode, one_cmpl_optab, op, 0, 1); }") --- 962,978 ---- " { ! rtx op1 = operands[1]; ! ! if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (op1) != CONST_INT) ! { ! operands[1] = operands[2]; ! operands[2] = op1; ! op1 = operands[1]; ! } ! ! if (GET_CODE (op1) == CONST_INT) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, 65535 & ~INTVAL (op1)); else ! operands[1] = expand_unop (HImode, one_cmpl_optab, op1, 0, 1); }") *************** *** 927,936 **** " { ! rtx op = operands[1]; ! if (GET_CODE (op) == CONST_INT) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, ! ((1 << 8) - 1) & ~INTVAL (op)); else ! operands[1] = expand_unop (QImode, one_cmpl_optab, op, 0, 1); }") --- 984,1000 ---- " { ! rtx op1 = operands[1]; ! ! if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (op1) != CONST_INT) ! { ! operands[1] = operands[2]; ! operands[2] = op1; ! op1 = operands[1]; ! } ! ! if (GET_CODE (op1) == CONST_INT) ! operands[1] = gen_rtx (CONST_INT, VOIDmode, 255 & ~INTVAL (op1)); else ! operands[1] = expand_unop (QImode, one_cmpl_optab, op1, 0, 1); }") *************** *** 1803,1807 **** "jmp (%0)") ! (define_insn "casesi" [(set (pc) (if_then_else (leu (minus:SI (match_operand:SI 0 "general_operand" "g") --- 1867,1893 ---- "jmp (%0)") ! ;; This is here to accept 5 arguments (as passed by expand_end_case) ! ;; and pass the first 4 along to the casesi1 pattern that really does the work. ! (define_expand "casesi" ! [(set (pc) ! (if_then_else (leu (minus:SI (match_operand:SI 0 "general_operand" "g") ! (match_operand:SI 1 "general_operand" "g")) ! (match_operand:SI 2 "general_operand" "g")) ! (plus:SI (sign_extend:SI ! (mem:HI ! (plus:SI (pc) ! (mult:SI (minus:SI (match_dup 0) ! (match_dup 1)) ! (const_int 2))))) ! (label_ref:SI (match_operand 3 "" ""))) ! (pc))) ! (match_operand 4 "" "")] ! "" ! " ! emit_insn (gen_casesi1 (operands[0], operands[1], operands[2], operands[3])); ! DONE; ! ") ! ! (define_insn "casesi1" [(set (pc) (if_then_else (leu (minus:SI (match_operand:SI 0 "general_operand" "g") diff -rc2N gcc-2.2.2/config/we32k.h gcc-2.3.1/config/we32k.h *** gcc-2.2.2/config/we32k.h Wed May 27 16:04:11 1992 --- gcc-2.3.1/config/we32k.h Fri Sep 11 01:06:59 1992 *************** *** 61,65 **** #define WORDS_BIG_ENDIAN 1 ! /* number of bits in an addressible storage unit */ #define BITS_PER_UNIT 8 --- 61,65 ---- #define WORDS_BIG_ENDIAN 1 ! /* number of bits in an addressable storage unit */ #define BITS_PER_UNIT 8 *************** *** 106,109 **** --- 106,112 ---- as actual integers */ #define PCC_BITFIELD_TYPE_MATTERS 1 + + /* Specify the size_t type. */ + #define SIZE_TYPE "unsigned int" /* Standard register usage. */ diff -rc2N gcc-2.2.2/config/we32k.md gcc-2.3.1/config/we32k.md *** gcc-2.2.2/config/we32k.md Mon May 4 19:11:31 1992 --- gcc-2.3.1/config/we32k.md Thu Sep 3 01:43:36 1992 *************** *** 1175,1179 **** (match_operand:SI 2 "general_operand" "mri"))) (set (pc) (if_then_else (gtu (cc0) (const_int 0)) ! (label_ref (match_operand 4 "" "")) (pc))) (set (match_dup 5) (ashift:SI (match_dup 5) --- 1175,1179 ---- (match_operand:SI 2 "general_operand" "mri"))) (set (pc) (if_then_else (gtu (cc0) (const_int 0)) ! (label_ref (match_dup 4)) (pc))) (set (match_dup 5) (ashift:SI (match_dup 5) diff -rc2N gcc-2.2.2/config/x-aix386 gcc-2.3.1/config/x-aix386 *** gcc-2.2.2/config/x-aix386 Sat Jan 18 02:42:17 1992 --- gcc-2.3.1/config/x-aix386 Mon Jul 27 23:06:22 1992 *************** *** 1,5 **** # There is an alloca in -lbsd, but it is limited to 32K ALLOCA = alloca.o - - # Is this right? - # INSTALL=cp --- 1,2 ---- diff -rc2N gcc-2.2.2/config/x-alpha gcc-2.3.1/config/x-alpha *** gcc-2.2.2/config/x-alpha --- gcc-2.3.1/config/x-alpha Fri Aug 14 15:13:47 1992 *************** *** 0 **** --- 1,2 ---- + RANLIB = ar ts + RANLIB_TEST = true diff -rc2N gcc-2.2.2/config/x-amix gcc-2.3.1/config/x-amix *** gcc-2.2.2/config/x-amix Sat Jun 13 17:42:37 1992 --- gcc-2.3.1/config/x-amix Tue Jul 21 14:02:35 1992 *************** *** 2,10 **** # (configure amiga-amix) - # Under SVR4, the ucb version of install is compatible, but not normally - # first in the shell search path, so specify it explicitly. - - INSTALL = /usr/ucb/install -c - # The Amiga ships with gcc installed, so use it as the default CC. --- 2,5 ---- *************** *** 31,40 **** mandir = /usr/man/1l manext = - - # Set up flags to use when compiling and linking enquire. - - ENQUIRE_CFLAGS = -DNO_SC -DNO_MEM -DNO_STDDEF -ansi - - # Use SVR4 version of fixincludes. - - FIXINCLUDES = fixinc.svr4 --- 26,27 ---- diff -rc2N gcc-2.2.2/config/x-dec-osf1 gcc-2.3.1/config/x-dec-osf1 *** gcc-2.2.2/config/x-dec-osf1 --- gcc-2.3.1/config/x-dec-osf1 Sat Oct 3 07:34:29 1992 *************** *** 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). We need to pass + # the -Wf,-XNg1500 option so the compiler can compile the + # G++ file cp-parse.c. Otherwise it complains about + # too many case statements. -Olimit is so the user + # can use -O2. Down with fixed size tables! + + CC = $(OLDCC) + OPT = -O1 + OLDCC = cc -Wf,-XNg1500 -Olimit 3000 $(OPT) + INSTALL = installbsd -c + + # The bison output files are machine-indep, + # so different flags for a particular machine are not useful. + #BISONFLAGS = -l diff -rc2N gcc-2.2.2/config/x-decrose gcc-2.3.1/config/x-decrose *** gcc-2.2.2/config/x-decrose Thu Jun 11 00:56:06 1992 --- gcc-2.3.1/config/x-decrose Sat Aug 15 11:15:17 1992 *************** *** 7,13 **** BUILD = CC = $(OLDCC) ! CLIB = -lbsd -lld ! X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) ! X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(XCFLAGS) CCLIBFLAGS = -O -pic-extern CPP_ABORT = # -Dabort=fancy_abort --- 7,13 ---- BUILD = CC = $(OLDCC) ! CLIB = -lld ! X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) $(X_DEFINES) ! X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(X_DEFINES) $(XCFLAGS) CCLIBFLAGS = -O -pic-extern CPP_ABORT = # -Dabort=fancy_abort *************** *** 24,29 **** OPT = -O2 PROFILE = ! SHLIB = -L${BUILD}/usr/ccs/lib # no shared libraries SYSTEM_INCLUDES = # -I${BUILD}/usr/include libdir = /usr/ccs --- 24,30 ---- OPT = -O2 PROFILE = ! SHLIB = -pic-none SYSTEM_INCLUDES = # -I${BUILD}/usr/include + X_DEFINES = -Dvfork=fork libdir = /usr/ccs diff -rc2N gcc-2.2.2/config/x-dpx2 gcc-2.3.1/config/x-dpx2 *** gcc-2.2.2/config/x-dpx2 --- gcc-2.3.1/config/x-dpx2 Mon Jul 27 22:57:33 1992 *************** *** 0 **** --- 1,16 ---- + # need this when using cc + ALLOCA = alloca.o + # avoid lossage assembling alloca. + ALLOCA_FLAGS=-S + ALLOCA_FINISH = $(AS) -o alloca.o alloca.s + # be sure not to confuse ./as with /bin/as + AS=`if [ x$(OLDCC) = x$(CC) ] ; then echo /bin/as; else echo $(GAS); fi` + GAS = gas + # + # as of gcc-2.2.1 gcc -g produces too many .stabd's for /bin/ld + # to link cc1plus, so use -g with /bin/cc, but -O with gcc + CFLAGS=`if [ x$(OLDCC) = x$(CC) ] ; then echo -g; else echo -O; fi` + # + CLIB=-lc_s -lld -lm + # tell CC whether we are a 200 or 300 + X_CFLAGS=-D_SYSV -D__DPX2__ `if [ -d /makesys/kernel/cf/ncl_mr ]; then echo -Dncl_mr=1; else echo -Dncl_el; fi` diff -rc2N gcc-2.2.2/config/x-elxsi gcc-2.3.1/config/x-elxsi *** gcc-2.2.2/config/x-elxsi --- gcc-2.3.1/config/x-elxsi Thu Oct 15 16:59:20 1992 *************** *** 0 **** --- 1,9 ---- + # Our make needs a little help... + MAKE=make + + # We don't support -g yet, so don't try and use it. + CFLAGS = + LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) + + # Hide xmalloc so that it does not conflict with the one in libc.a, Ick! + X_CFLAGS = -Dxmalloc=my_xmalloc diff -rc2N gcc-2.2.2/config/x-encrose gcc-2.3.1/config/x-encrose *** gcc-2.2.2/config/x-encrose Sat Jun 13 17:13:26 1992 --- gcc-2.3.1/config/x-encrose Sat Aug 15 11:15:16 1992 *************** *** 7,13 **** BUILD = CC = $(OLDCC) ! CLIB = -lbsd -lld ! X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) ! X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(XCFLAGS) CPP_ABORT = # -Dabort=fancy_abort CPPFLAGS = $(CPP_ABORT) $(SYSTEM_INCLUDES) --- 7,13 ---- BUILD = CC = $(OLDCC) ! CLIB = -lld ! X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) $(X_DEFINES) ! X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(X_DEFINES) $(XCFLAGS) CPP_ABORT = # -Dabort=fancy_abort CPPFLAGS = $(CPP_ABORT) $(SYSTEM_INCLUDES) *************** *** 25,28 **** --- 25,29 ---- SHLIB = -L${BUILD}/usr/ccs/lib # no shared libraries SYSTEM_INCLUDES = # -I${BUILD}/usr/include + X_DEFINES = -Dvfork=fork libdir = /usr/ccs diff -rc2N gcc-2.2.2/config/x-genix gcc-2.3.1/config/x-genix *** gcc-2.2.2/config/x-genix Sat Jun 13 17:41:53 1992 --- gcc-2.3.1/config/x-genix Sun Jun 28 10:04:35 1992 *************** *** 1,4 **** # Makefile modifications for compilation on Genix. - INSTALL=cp ALLOCA=alloca.o MALLOC = malloc.o --- 1,3 ---- diff -rc2N gcc-2.2.2/config/x-hp320g gcc-2.3.1/config/x-hp320g *** gcc-2.2.2/config/x-hp320g Sat Jun 13 17:38:26 1992 --- gcc-2.3.1/config/x-hp320g Sat Jul 4 14:49:56 1992 *************** *** 10,24 **** # Version 5 of HPUX had a compiler bug that made it crash with -g. # You must set CFLAGS to empty on version 5. - - # You must get alloca.c from GNU Emacs. - - # Control how libgcc.a is made. - LIBGCC1 = libgcc1.conv - - # Alas, we don't know where these programs can be found. - # We can only guess. - AR=/usr/local/gnubin/ar - RANLIB=/usr/local/gnubin/ranlib - RANLIB_TEST = [ -f /usr/local/gnubin/ranlib ] - - LIBCONVERT=/usr/local/bin/hpxt --- 10,11 ---- diff -rc2N gcc-2.2.2/config/x-i386isc gcc-2.3.1/config/x-i386isc *** gcc-2.2.2/config/x-i386isc Wed Jan 8 00:42:52 1992 --- gcc-2.3.1/config/x-i386isc Mon Jul 27 22:57:56 1992 *************** *** 1,4 **** CLIB = -lPW -lcposix - INSTALL = cp X_CFLAGS = -D_POSIX_SOURCE ENQUIRE_LDFLAGS = -posix $(LDFLAGS) --- 1,3 ---- diff -rc2N gcc-2.2.2/config/x-i386rose gcc-2.3.1/config/x-i386rose *** gcc-2.2.2/config/x-i386rose Tue Mar 17 10:42:51 1992 --- gcc-2.3.1/config/x-i386rose Sat Aug 15 11:15:17 1992 *************** *** 7,13 **** BUILD = CC = $(OLDCC) ! CLIB = -lbsd -lld ! X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) ! X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(XCFLAGS) CPP_ABORT = # -Dabort=fancy_abort CPPFLAGS = $(CPP_ABORT) $(SYSTEM_INCLUDES) --- 7,13 ---- BUILD = CC = $(OLDCC) ! CLIB = -lld ! X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) $(X_DEFINES) ! X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(X_DEFINES) $(XCFLAGS) CPP_ABORT = # -Dabort=fancy_abort CPPFLAGS = $(CPP_ABORT) $(SYSTEM_INCLUDES) *************** *** 22,27 **** OPT = -O PROFILE = ! SHLIB = -L${BUILD}/usr/ccs/lib # no shared libraries SYSTEM_INCLUDES = # -I${BUILD}/usr/include libdir = /usr/ccs --- 22,28 ---- OPT = -O PROFILE = ! SHLIB = -pic-none SYSTEM_INCLUDES = # -I${BUILD}/usr/include + X_DEFINES = -Dvfork=fork libdir = /usr/ccs diff -rc2N gcc-2.2.2/config/x-i386s4 gcc-2.3.1/config/x-i386s4 *** gcc-2.2.2/config/x-i386s4 --- gcc-2.3.1/config/x-i386s4 Wed Sep 2 02:16:00 1992 *************** *** 0 **** --- 1,10 ---- + RANLIB = : + RANLIB_TEST = false + CC = rcc $(RCCFLAGS) + OLDCC = rcc $(RCCFLAGS) + RCCFLAGS = -Dunix -Di386 -DM_UNIX -DM_I386 -DNULL=0 + CCLIBFLAGS = + CLIB = -lPW + + # Seems to be needed with SCO DEV3.2v4. + X_CFLAGS = -D__STDC__=0 diff -rc2N gcc-2.2.2/config/x-i386sco gcc-2.3.1/config/x-i386sco *** gcc-2.2.2/config/x-i386sco Wed Mar 25 17:11:24 1992 --- gcc-2.3.1/config/x-i386sco Wed Sep 2 02:16:37 1992 *************** *** 1,9 **** - INSTALL=cp RANLIB = : RANLIB_TEST = false ! CC = rcc ! OLDCC = rcc CCLIBFLAGS = - RCCFLAGS = -Dunix -Di386 -DM_UNIX -DM_I386 - XCFLAGS = $(RCCFLAGS) CLIB = -lPW --- 1,7 ---- RANLIB = : RANLIB_TEST = false ! CC = rcc $(RCCFLAGS) ! OLDCC = rcc $(RCCFLAGS) ! RCCFLAGS = -Dunix -Di386 -DM_UNIX -DM_I386 -DNULL=0 CCLIBFLAGS = CLIB = -lPW diff -rc2N gcc-2.2.2/config/x-i386v gcc-2.3.1/config/x-i386v *** gcc-2.2.2/config/x-i386v Wed Jul 31 20:58:04 1991 --- gcc-2.3.1/config/x-i386v Mon Jul 27 22:59:34 1992 *************** *** 1,2 **** CLIB=-lPW - INSTALL=cp --- 1 ---- diff -rc2N gcc-2.2.2/config/x-i860v3 gcc-2.3.1/config/x-i860v3 *** gcc-2.2.2/config/x-i860v3 Sun Dec 8 22:59:59 1991 --- gcc-2.3.1/config/x-i860v3 Mon Jul 27 22:59:42 1992 *************** *** 1,2 **** - INSTALL=cp ALLOCA=alloca.o --- 1 ---- diff -rc2N gcc-2.2.2/config/x-i860v4 gcc-2.3.1/config/x-i860v4 *** gcc-2.2.2/config/x-i860v4 Sat Mar 14 00:17:01 1992 --- gcc-2.3.1/config/x-i860v4 Mon Jul 27 22:59:56 1992 *************** *** 1,4 **** - INSTALL=cp - # The svr4 reference port for the i860 contains an alloca.o routine # in /usr/ucblib/libucb.a, but we can't just try to get that by --- 1,2 ---- diff -rc2N gcc-2.2.2/config/x-iris gcc-2.3.1/config/x-iris *** gcc-2.2.2/config/x-iris Fri Jun 12 10:34:17 1992 --- gcc-2.3.1/config/x-iris Tue Oct 27 18:02:28 1992 *************** *** 24,28 **** # Show we need to use the C version of ALLOCA ALLOCA = alloca.o - - # Iris install isn't BSD - INSTALL = cp --- 24,25 ---- diff -rc2N gcc-2.2.2/config/x-linux gcc-2.3.1/config/x-linux *** gcc-2.2.2/config/x-linux --- gcc-2.3.1/config/x-linux Tue Oct 27 18:02:26 1992 *************** *** 0 **** --- 1,5 ---- + X_CFLAGS=-DPOSIX + # we are native. + prefix=/usr + # no object c, why bother. + LANGUAGES = c c++ proto diff -rc2N gcc-2.2.2/config/x-m88kdgux gcc-2.3.1/config/x-m88kdgux *** gcc-2.2.2/config/x-m88kdgux Sat Jun 13 17:39:13 1992 --- gcc-2.3.1/config/x-m88kdgux Sun Jun 28 10:06:00 1992 *************** *** 1,5 **** CC = /bin/gcc BISONFLAGS = -l - INSTALL = cp X_CFLAGS = -D_M88KBCS_TARGET INSTALL_HEADERS = --- 1,4 ---- diff -rc2N gcc-2.2.2/config/x-m88kdolph gcc-2.3.1/config/x-m88kdolph *** gcc-2.2.2/config/x-m88kdolph Sat Jun 13 17:40:50 1992 --- gcc-2.3.1/config/x-m88kdolph Sun Jun 28 10:06:22 1992 *************** *** 1,4 **** - INSTALL = cp - # Green Hills C on Dolphin UNIX System V/88 Release 3.2 Version 3.5/5.60 does # not provide alloca. --- 1,2 ---- diff -rc2N gcc-2.2.2/config/x-m88kv4 gcc-2.3.1/config/x-m88kv4 *** gcc-2.2.2/config/x-m88kv4 Sat Jun 13 17:39:37 1992 --- gcc-2.3.1/config/x-m88kv4 Sun Jun 28 10:08:56 1992 *************** *** 1,4 **** - INSTALL = cp - # Problems in early version of the assembler have been fixed (-DNO_BUGS). # There are peculiar problems with the include files that require __STDC__ --- 1,2 ---- diff -rc2N gcc-2.2.2/config/x-ncr3000 gcc-2.3.1/config/x-ncr3000 *** gcc-2.2.2/config/x-ncr3000 Sat Mar 28 23:25:37 1992 --- gcc-2.3.1/config/x-ncr3000 Mon Sep 21 03:07:36 1992 *************** *** 17,31 **** # The rest is just x-i386v4. ! # The svr4 reference port for the i386 contains an alloca.o routine ! # in /usr/ucblib/libucb.a, but we can't just try to get that by ! # setting CLIB to /usr/ucblib/libucb.a because (unfortunately) ! # there are a lot of other routines in libucb.a which are supposed ! # to be the Berkeley versions of library routines normally found in ! # libc.a and many of these Berkeley versions are badly broken. Thus, ! # if we try to link programs with libucb.a before libc.a, those ! # programs tend to crash. To avoid this, we link with libc.a *before* ! # linking with libucb.a. ! CLIB=-lc /usr/ucblib/libucb.a # We used to build all stages *without* shared libraries because that may make --- 17,26 ---- # The rest is just x-i386v4. ! # Some versions of SVR4 have an alloca in /usr/ucblib/libucb.a, and if we are ! # careful to link that in after libc we can use it, but since newer versions of ! # SVR4 are dropping libucb, it is better to just use the portable C version for ! # bootstrapping. Do this by defining ALLOCA. ! ALLOCA = alloca.o # We used to build all stages *without* shared libraries because that may make *************** *** 37,42 **** # CCLIBFLAGS=-Bstatic -dn -g # GCC_CFLAGS=-static -g -O2 -B./ - - INSTALL=cp - - FIXINCLUDES=fixinc.svr4 --- 32,33 ---- diff -rc2N gcc-2.2.2/config/x-next gcc-2.3.1/config/x-next *** gcc-2.2.2/config/x-next --- gcc-2.3.1/config/x-next Thu Oct 15 04:15:07 1992 *************** *** 0 **** --- 1,3 ---- + # Make assignments for compiling on NeXT with their compiler version. + CC=cc -traditional-cpp + OLDCC=cc -traditional-cpp diff -rc2N gcc-2.2.2/config/x-pa gcc-2.3.1/config/x-pa *** gcc-2.2.2/config/x-pa --- gcc-2.3.1/config/x-pa Thu Sep 17 14:52:08 1992 *************** *** 0 **** --- 1 ---- + CC=/usr/local/gcc -DUSE_C_ALLOCA -D__inline= diff -rc2N gcc-2.2.2/config/x-pa-hpux gcc-2.3.1/config/x-pa-hpux *** gcc-2.2.2/config/x-pa-hpux Mon Apr 6 10:18:13 1992 --- gcc-2.3.1/config/x-pa-hpux Mon Jul 27 23:00:20 1992 *************** *** 1,3 **** ALLOCA=alloca.o - ALLOCA_FLAGS = -c -Demacs - ALLOCA_FINISH = --- 1 ---- diff -rc2N gcc-2.2.2/config/x-rs6000 gcc-2.3.1/config/x-rs6000 *** gcc-2.2.2/config/x-rs6000 Wed Mar 11 18:56:28 1992 --- gcc-2.3.1/config/x-rs6000 Fri Jul 3 16:55:30 1992 *************** *** 5,12 **** ALLOCA=alloca.o - # We can't use -S to compile alloca - ALLOCA_FLAGS=-c - ALLOCA_FINISH= - # For some reason, we need -lm for cc1. # We need -lld for collect2 (actually this only matters --- 5,8 ---- diff -rc2N gcc-2.2.2/config/x-rs6k-mach gcc-2.3.1/config/x-rs6k-mach *** gcc-2.2.2/config/x-rs6k-mach Thu Apr 16 22:03:53 1992 --- gcc-2.3.1/config/x-rs6k-mach Fri Jul 3 16:55:42 1992 *************** *** 4,11 **** ALLOCA=alloca.o - # We can't use -S to compile alloca - ALLOCA_FLAGS=-c - ALLOCA_FINISH= - # For some reason, we need -lm for cc1. CLIB=-lm --- 4,7 ---- diff -rc2N gcc-2.2.2/config/x-sparcv4 gcc-2.3.1/config/x-sparcv4 *** gcc-2.2.2/config/x-sparcv4 Thu Jun 11 00:44:23 1992 --- gcc-2.3.1/config/x-sparcv4 Sun Jul 5 16:41:37 1992 *************** *** 1,3 **** X_CFLAGS=-DSVR4 - INSTALL=cp ALLOCA=alloca.o --- 1,2 ---- diff -rc2N gcc-2.2.2/config/x-svr4 gcc-2.3.1/config/x-svr4 *** gcc-2.2.2/config/x-svr4 --- gcc-2.3.1/config/x-svr4 Mon Sep 21 03:07:32 1992 *************** *** 0 **** --- 1,6 ---- + # Some versions of SVR4 have an alloca in /usr/ucblib/libucb.a, and if we are + # careful to link that in after libc we can use it, but since newer versions of + # SVR4 are dropping libucb, it is better to just use the portable C version for + # bootstrapping. Do this by defining ALLOCA. + + ALLOCA = alloca.o diff -rc2N gcc-2.2.2/config/x-xenix gcc-2.3.1/config/x-xenix *** gcc-2.2.2/config/x-xenix Tue Nov 26 16:23:52 1991 --- gcc-2.3.1/config/x-xenix Mon Jul 27 23:02:25 1992 *************** *** 1,2 **** OLDCC = rcc -DM_XENIX -DM_UNIX -DM_COFF - INSTALL=cp --- 1 ---- diff -rc2N gcc-2.2.2/config/xm-aix386.h gcc-2.3.1/config/xm-aix386.h *** gcc-2.2.2/config/xm-aix386.h Fri May 31 15:40:04 1991 --- gcc-2.3.1/config/xm-aix386.h Sun Oct 11 08:53:29 1992 *************** *** 50,54 **** #define bcmp(a,b,c) memcmp (a,b,c) #ifdef __GNUC__ ! #define alloca(n) __builtin_alloca(n) #endif --- 50,58 ---- #define bcmp(a,b,c) memcmp (a,b,c) + /* If compiled with GNU C, use the built-in alloca. */ + #undef alloca #ifdef __GNUC__ ! #define alloca __builtin_alloca ! #else ! #define USE_C_ALLOCA #endif diff -rc2N gcc-2.2.2/config/xm-alpha.h gcc-2.3.1/config/xm-alpha.h *** gcc-2.2.2/config/xm-alpha.h --- gcc-2.3.1/config/xm-alpha.h Mon Oct 26 07:47:49 1992 *************** *** 0 **** --- 1,61 ---- + /* Configuration for GNU C-compiler for DEC Alpha. + Copyright (C) 1990 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@nyu.edu). + + This file is part of GNU CC. + + GNU CC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GNU CC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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 64 + #define HOST_BITS_PER_LONGLONG 64 + + /* #define HOST_WORDS_BIG_ENDIAN */ + + /* 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 FAILURE_EXIT_CODE 2 + #define FATAL_EXIT_CODE 3 + + /* If compiled with GNU C, use the built-in alloca. */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #else + #define USE_C_ALLOCA + #endif + + /* Declare some functions needed for this machine. We don't want to + include these in the sources since other machines might define them + differently. */ + + #ifdef __STDC__ + extern void *malloc (), *realloc (), *sbrk (), *calloc (); + #else + extern char *malloc (), *realloc (), *sbrk (), *calloc (); + #endif + + #include "string.h" diff -rc2N gcc-2.2.2/config/xm-convex.h gcc-2.3.1/config/xm-convex.h *** gcc-2.2.2/config/xm-convex.h Sun Dec 1 01:04:53 1991 --- gcc-2.3.1/config/xm-convex.h Fri Oct 23 18:45:32 1992 *************** *** 44,47 **** --- 44,52 ---- #ifdef _POSIX_SOURCE + /* Convex ships /tmp as a separate file system - thus it + usually has more free space than /usr/tmp */ + + #define P_tmpdir "/tmp/" + /* Un-hide names hidden in Posix include files. */ diff -rc2N gcc-2.2.2/config/xm-elxsi.h gcc-2.3.1/config/xm-elxsi.h *** gcc-2.2.2/config/xm-elxsi.h --- gcc-2.3.1/config/xm-elxsi.h Thu Oct 15 16:59:46 1992 *************** *** 0 **** --- 1,42 ---- + /* Configuration for GNU C-compiler for Elxsi. + Copyright (C) 1987 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 1, 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. */ + + /* #defines that need visibility everywhere. */ + #define FALSE 0 + #define TRUE 1 + + /* target machine dependencies. + tm.h is a symbolic link to the actual target specific file. */ + #include "tm.h" + + /* 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 + + /* Arguments to use with `exit'. */ + #define SUCCESS_EXIT_CODE 0 + #define FATAL_EXIT_CODE 33 + + /* If compiled with GNU C, use the built-in alloca */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #endif + diff -rc2N gcc-2.2.2/config/xm-hp320.h gcc-2.3.1/config/xm-hp320.h *** gcc-2.2.2/config/xm-hp320.h Wed Apr 29 20:32:58 1992 --- gcc-2.3.1/config/xm-hp320.h Mon Jul 27 23:02:38 1992 *************** *** 1,4 **** ! /* #define USG */ ! #include "xm-m68k.h" --- 1,4 ---- ! /* USG is needed to prevent trying to use getrusage and getwd. */ ! #define USG #include "xm-m68k.h" diff -rc2N gcc-2.2.2/config/xm-i38v4.h gcc-2.3.1/config/xm-i38v4.h *** gcc-2.2.2/config/xm-i38v4.h Sun Dec 8 22:45:35 1991 --- gcc-2.3.1/config/xm-i38v4.h Sun Oct 11 08:53:11 1992 *************** *** 3,4 **** --- 3,12 ---- #include "xm-i386.h" #include "xm-svr4.h" + + /* If compiled with GNU C, use the built-in alloca. */ + #undef alloca + #ifdef __GNUC__ + #define alloca __builtin_alloca + #else + #define USE_C_ALLOCA + #endif diff -rc2N gcc-2.2.2/config/xm-linux.h gcc-2.3.1/config/xm-linux.h *** gcc-2.2.2/config/xm-linux.h --- gcc-2.3.1/config/xm-linux.h Thu Oct 1 16:12:09 1992 *************** *** 0 **** --- 1,20 ---- + /* Configuration for GCC for Intel i386 running Linux. + * + * Written by H.J. Lu (hlu@eecs.wsu.edu) + */ + + #include "xm-i386.h" + #include "xm-svr3.h" + + #undef BSTRING + #define BSTRING + #undef bcmp + #undef bcopy + #undef bzero + #undef index + #undef rindex + + #undef malloc(n) + #define malloc(n) malloc ((n) ? (n) : 1) + #undef calloc(n,e) + #define calloc(n,e) calloc (((n) ? (n) : 1), ((e) ? (e) : 1)) diff -rc2N gcc-2.2.2/config/xm-m88kv3.h gcc-2.3.1/config/xm-m88kv3.h *** gcc-2.2.2/config/xm-m88kv3.h Mon Oct 21 15:03:54 1991 --- gcc-2.3.1/config/xm-m88kv3.h Wed Jun 24 00:16:49 1992 *************** *** 1,4 **** /* Configuration for GNU C-compiler. ! Motorola m88100 running the AT&T/Unisoft/Motorla V.3 reference port. Copyright (C) 1990 Free Software Foundation, Inc. --- 1,4 ---- /* Configuration for GNU C-compiler. ! Motorola m88100 running the AT&T/Unisoft/Motorola V.3 reference port. Copyright (C) 1990 Free Software Foundation, Inc. diff -rc2N gcc-2.2.2/config/xm-mips.h gcc-2.3.1/config/xm-mips.h *** gcc-2.2.2/config/xm-mips.h Thu Jun 11 00:47:31 1992 --- gcc-2.3.1/config/xm-mips.h Sat Sep 26 18:38:42 1992 *************** *** 75,79 **** /* Say if we have vprintf. BSD Mips targets probably don't have vfprintf. */ ! #if defined(__OSF1__) || defined(__OSF__) #define HAVE_VFPRINTF #define HAVE_PUTENV --- 75,79 ---- /* Say if we have vprintf. BSD Mips targets probably don't have vfprintf. */ ! #if defined(__OSF1__) || defined(__OSF__) || defined(__osf__) #define HAVE_VFPRINTF #define HAVE_PUTENV diff -rc2N gcc-2.2.2/config/xm-pa.h gcc-2.3.1/config/xm-pa.h *** gcc-2.2.2/config/xm-pa.h Wed May 6 15:31:25 1992 --- gcc-2.3.1/config/xm-pa.h Wed Oct 14 10:37:56 1992 *************** *** 24,27 **** --- 24,28 ---- #if defined(SHL_MAGIC) #define hpux8 1 + #define HAVE_VPRINTF #endif diff -rc2N gcc-2.2.2/config/xm-spc-sol2.h gcc-2.3.1/config/xm-spc-sol2.h *** gcc-2.2.2/config/xm-spc-sol2.h --- gcc-2.3.1/config/xm-spc-sol2.h Sat Jul 4 23:35:18 1992 *************** *** 0 **** --- 1,6 ---- + #include "xm-spcv4.h" + + /* If not compiled with GNU C, include the system's header. */ + #ifndef __GNUC__ + #include + #endif diff -rc2N gcc-2.2.2/config/xm-spcv4.h gcc-2.3.1/config/xm-spcv4.h *** gcc-2.2.2/config/xm-spcv4.h Thu Jun 11 00:45:18 1992 --- gcc-2.3.1/config/xm-spcv4.h Thu Jul 23 02:09:05 1992 *************** *** 51,52 **** --- 51,56 ---- #include "xm-svr4.h" + + #ifndef __GNUC__ + #define ONLY_INT_FIELDS + #endif diff -rc2N gcc-2.2.2/config/xm-umips.h gcc-2.3.1/config/xm-umips.h *** gcc-2.2.2/config/xm-umips.h Thu Jun 11 00:47:44 1992 --- gcc-2.3.1/config/xm-umips.h Mon Oct 19 10:59:02 1992 *************** *** 32,33 **** --- 32,37 ---- #define bzero(a,b) memset((a),0,(b)) #define bcmp(a,b,c) memcmp((a),(b),(c)) + + #define rindex strrchr + #define index strchr + diff -rc2N gcc-2.2.2/config/xm-vax-vms.h gcc-2.3.1/config/xm-vax-vms.h *** gcc-2.2.2/config/xm-vax-vms.h Sat Mar 14 00:17:03 1992 --- gcc-2.3.1/config/xm-vax-vms.h Thu Aug 20 15:23:20 1992 *************** *** 48,53 **** #define X_OK 1 #define F_OK 0 - - #define unlink delete #endif --- 48,51 ---- *************** *** 101,105 **** else { \ strcpy(BUFF, NAME); \ ! strcat(t, "_gxref"); \ } --- 99,103 ---- else { \ strcpy(BUFF, NAME); \ ! strcat(BUFF, "_gxref"); \ } *************** *** 116,118 **** --- 114,162 ---- #define FILE_NAME_JOINER "" + + #ifdef VAXC + /* Customizations/kludges for building with DEC's VAX C compiler + rather than GCC. */ + #define NO_SYS_PARAMS_H /* don't have */ + #define NO_STAB_H /* don't have */ + #define USE_C_ALLOCA /* using alloca.c */ + #define QSORT_WORKAROUND /* do not use VAXCRTL's qsort */ + + /* use ANSI/SYSV style byte manipulation routines instead of BSD ones */ + #define bcopy(s,d,n) memcpy((d),(s),(n)) + #define bzero(d,n) memset((d),0,(n)) + #define bcmp(l,r,n) memcmp((l),(r),(n)) + #define index strchr + #define rindex strrchr + + /* rename all too-long external symbol names to avoid warnings */ + #define check_for_full_enumeration_handling check_for_full_enum_handling + #define current_function_contains_functions curfunc_contains_functions + #define current_function_epilogue_delay_list curfunc_epilogue_delay_list + #define current_function_has_nonlocal_label curfunc_has_nonlocal_label + #define current_function_internal_arg_pointer curfunc_internal_arg_pointer + #define current_function_outgoing_args_size curfunc_outgoing_args_size + #define current_function_pretend_args_size curfunc_pretend_args_size + #define current_function_returns_pcc_struct curfunc_returns_pcc_struct + #define current_function_returns_pointer curfunc_returns_pointer + #define current_function_uses_const_pool curfunc_uses_const_pool + #define current_function_uses_pic_offset_table curfunc_uses_pic_offset_table + #define expand_start_loop_continue_elsewhere expnd_start_loop_cont_elsewhere + #define flag_schedule_insns_after_reload flag_sched_insns_after_reload + #define maybe_building_objc_message_expr maybe_building_objc_msg_expr + #define reg_overlap_mentioned_for_reload_p reg_overlap_mtnd_for_reload_p + #define reposition_prologue_and_epilogue_notes repos_prolog_and_epilog_notes + #define rtx_equal_function_value_matters rtx_equal_func_value_matters + #define set_new_first_and_last_label_num set_new_first_and_last_lbl_num + #define thread_prologue_and_epilogue_insns thread_prolog_and_epilog_insns + #endif + /* We need to avoid the library qsort routine, due to a serious bug + in VAXCRTL. (Sorting anything with size that's not a multiple of 4 + after having previously sorted something that was a multiple of 4 + can produce wrong results and result in data corruption.) We'll + use our own substitute (in vax.c) instead. */ + /* #define QSORT_WORKAROUND */ + #ifdef QSORT_WORKAROUND + #define qsort not_qsort + #endif diff -rc2N gcc-2.2.2/config.sub gcc-2.3.1/config.sub *** gcc-2.2.2/config.sub Tue Jun 2 15:37:40 1992 --- gcc-2.3.1/config.sub Thu Oct 15 17:05:53 1992 *************** *** 82,86 **** # Some are omitted here because they have special meanings below. tahoe | i[34]86 | i860 | m68k | m68000 | m88k | ns32k | arm | pyramid \ ! | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 | we32k) basic_machine=$basic_machine-unknown ;; --- 82,87 ---- # Some are omitted here because they have special meanings below. tahoe | i[34]86 | i860 | m68k | m68000 | m88k | ns32k | arm | pyramid \ ! | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \ ! | alpha | we32k) basic_machine=$basic_machine-unknown ;; *************** *** 90,94 **** | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ ! | hppa1.0-* | hppa1.1-* | we32k-*) ;; # Recognize the various machine names and aliases which stand --- 91,95 ---- | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ ! | hppa1.0-* | hppa1.1-* | alpha-* | we32k-*) ;; # Recognize the various machine names and aliases which stand *************** *** 114,117 **** --- 115,130 ---- os=-isc ;; + i486v32) + basic_machine=i486-unknown + os=-sysv32 + ;; + i486-sco* | i486sco | sco) + basic_machine=i486-unknown + os=-sco3.2v2 + ;; + i486-isc* | isc) + basic_machine=i486-unknown + os=-isc + ;; i386v4*) basic_machine=i386-unknown *************** *** 126,129 **** --- 139,146 ---- os=-sysv ;; + i486v) + basic_machine=i486-unknown + os=-sysv + ;; spur) basic_machine=spur-unknown *************** *** 162,165 **** --- 179,186 ---- basic_machine=m68k-crds ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; encore | umax | mmax) basic_machine=ns32k-encore *************** *** 320,324 **** amigaunix | amix) basic_machine=m68k-cbm ! os=-amix ;; cray | ymp) --- 341,345 ---- amigaunix | amix) basic_machine=m68k-cbm ! os=-sysv4 ;; cray | ymp) *************** *** 455,461 **** -bsd* | -sysv* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos* | -hpux* \ ! | -unos* | -osf* | -luna* | -dgux* | -solari* | -sym* | -amix* \ | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \ ! | -nindy* | -vxworks* | -ebmon* | -hds* | -m88kbcs*) ;; -osfrose*) --- 476,483 ---- -bsd* | -sysv* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos* | -hpux* \ ! | -unos* | -osf* | -luna* | -dgux* | -solari* | -sym* \ | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \ ! | -nindy* | -vxworks* | -ebmon* | -hds* | -m88kbcs* \ ! | -riscos* | -linux* ) ;; -osfrose*) *************** *** 465,468 **** --- 487,493 ---- os=-osf ;; + -utek*) + os=-bsd + ;; -dynix*) os=-bsd *************** *** 546,550 **** os=-genix ;; ! i386-*) os=-sco3.2v2 ;; --- 571,575 ---- os=-genix ;; ! i[34]86-*) os=-sco3.2v2 ;; diff -rc2N gcc-2.2.2/configure gcc-2.3.1/configure *** gcc-2.2.2/configure Thu Jun 11 15:46:42 1992 --- gcc-2.3.1/configure Sun Nov 1 03:25:32 1992 *************** *** 23,27 **** # preparation for compiling gcc. # ! # Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] TARGET # # If configure succeeds, it leaves its status in config.status. --- 23,37 ---- # preparation for compiling gcc. # ! # Options: --srcdir=DIR specifies directory where sources are. ! # --host=HOST specifies host configuration. ! # --target=TARGET specifies target configuration. ! # --build=TARGET specifies configuration of machine you are ! # using to compile GCC. ! # --prefix=DIR specifies directory to install in. ! # --exec-prefix=DIR specifies directory to install executables in. ! # --with-gnu-ld arrange to work with GNU ld. ! # --with-gnu-as arrange to work with GAS. ! # --with-stabs arrange to use stabs instead of host debug format. ! # --nfp assume system has no FPU. # # If configure succeeds, it leaves its status in config.status. *************** *** 43,46 **** --- 53,61 ---- host= + # Default prefix to /usr/local. + prefix=/usr/local + # Default is to let the Makefile set exec_prefix from $(prefix) + exec_prefix='$(prefix)' + remove=rm hard_link=ln *************** *** 56,79 **** #symbolic_link="echo ln -s" for arg in $*; do ! # Handle -srcdir, etc, with space between it and argument. ! if [ x$next_srcdir = xyes ] ! then srcdir=$arg; next_srcdir=; ! # Handle -host, etc, with space between it and argument. ! else if [ x$next_host = xyes ] ! then host=$arg; next_host=; ! else if [ x$next_target = xyes ] ! then target=$arg; next_target=; ! else case $arg in -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*) srcdir=`echo $arg | sed 's/-*s[a-z]*=//'` ;; - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s) - next_srcdir=yes - ;; -host | --host | --hos | --ho | --h) ! next_host=yes ;; -host=* | --host=* | --hos=* | --ho=* | --h=*) --- 71,115 ---- #symbolic_link="echo ln -s" + target= + host= + build= + for arg in $*; do ! case $next_arg in ! --srcdir) ! srcdir=$arg ! next_arg= ! ;; ! --host) ! host=$arg ! next_arg= ! ;; ! --target) ! target=$arg ! next_arg= ! ;; ! --build) ! build=$arg ! next_arg= ! ;; ! --prefix) ! prefix=$arg ! next_arg= ! ;; ! --exec-prefix) ! exec_prefix=$arg ! next_arg= ! ;; ! *) case $arg in + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s) + next_arg=--srcdir + ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*) srcdir=`echo $arg | sed 's/-*s[a-z]*=//'` ;; -host | --host | --hos | --ho | --h) ! next_arg=--host ;; -host=* | --host=* | --hos=* | --ho=* | --h=*) *************** *** 81,89 **** ;; -target | --target | --targe | --targ | --tar | --ta | --t) ! next_target=yes ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target=`echo $arg | sed 's/-*t[a-z]*=//'` ;; -with-gnu-ld | --with-gnu-ld | --with-gnu-l) gnu_ld=yes --- 117,146 ---- ;; -target | --target | --targe | --targ | --tar | --ta | --t) ! next_arg=--target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target=`echo $arg | sed 's/-*t[a-z]*=//'` ;; + -build | --build | --buil | --bui | --bu | --b) + next_arg=--build + ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) + build=`echo $arg | sed 's/-*b[a-z]*=//'` + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + next_arg=--prefix + ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=`echo $arg | sed 's/-*p[a-z]*=//'` + ;; + -exec-prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre \ + | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e) + next_arg=--exec-prefix + ;; + -exec-prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* \ + | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* \ + | --exe=* | --ex=* | --e=*) + exec_prefix=`echo $arg | sed 's/-*e[-a-z]*=//'` + ;; -with-gnu-ld | --with-gnu-ld | --with-gnu-l) gnu_ld=yes *************** *** 95,98 **** --- 152,161 ---- nfp=yes ;; + -with-stabs | -with-stab | -with-sta | -with-st | -with-s \ + | --with-stabs | --with-stab | --with-sta | --with-st | --with-s \ + | -stabs | -stab | -sta | -st \ + | --stabs | --stab | --sta | --st) + stabs=yes + ;; -with-* | --with-*) ;; #ignored -x | --x) ;; # ignored *************** *** 110,114 **** ;; esac ! fi; fi; fi done --- 173,177 ---- ;; esac ! esac done *************** *** 145,154 **** then echo "No target specified." 1>&2 ! echo "Usage: $progname [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] TARGET" 1>&2 ! echo -n "Where HOST and TARGET are something like " 1>&2 ! echo "\`vax', \`sun3', \`encore', etc." 1>&2 if [ -r config.status ] then ! cat config.status 1>&2 fi exit 1 --- 208,220 ---- then echo "No target specified." 1>&2 ! ! echo "\ ! Usage: `basename $progname` [--host=HOST] [--build=BUILD] ! [--prefix=DIR] [--exec-pref=DIR] ! [--with-gnu-as] [--with-gnu-ld] [--with-stabs] [--nfp] TARGET" 1>&2 ! echo "Where HOST, TARGET and BUILD are three-part configuration names " 1>&2 if [ -r config.status ] then ! tail +2 config.status 1>&2 fi exit 1 *************** *** 160,177 **** host=$target fi host_xm_file= host_xmake_file= host_broken_install= # Decode the host machine, then the target machine. # For the host machine, we save the xm_file variable as host_xm_file; # then we decode the target machine and forget everything else # that came from the host machine. ! for machine in $host $target; do - # Validate the spec, and canonicalize it. - machine=`$srcdir/config.sub $machine` || exit 1 - cpu_type= xm_file= --- 226,251 ---- host=$target fi + # If $build was not specified, use $host. + if [ x$build = x ] + then + build=$host + fi + build_xm_file= host_xm_file= host_xmake_file= host_broken_install= + # Validate the specs, and canonicalize them. + canon_build=`$srcdir/config.sub $build` || exit 1 + canon_host=`$srcdir/config.sub $host` || exit 1 + canon_target=`$srcdir/config.sub $target` || exit 1 + # Decode the host machine, then the target machine. # For the host machine, we save the xm_file variable as host_xm_file; # then we decode the target machine and forget everything else # that came from the host machine. ! for machine in $canon_build $canon_host $canon_target; do cpu_type= xm_file= *************** *** 183,188 **** --- 257,266 ---- # Set this to force installation and use of collect2. use_collect2= + # Set this to override the default target model. + target_cpu_default= # Set this to force use of install.sh. broken_install= + # Set this to control which fixincludes program to use. + fixincludes=fixincludes case $machine in *************** *** 210,215 **** ;; vax-*-vms*) # vaxen running VMS ! xm_file=xm-vms.h ! tm_file=vms.h ;; vax-*-sysv*) # vaxen running system V --- 288,293 ---- ;; vax-*-vms*) # vaxen running VMS ! xm_file=xm-vax-vms.h ! tm_file=vax-vms.h ;; vax-*-sysv*) # vaxen running system V *************** *** 225,229 **** # tm_file=tahoe.h # ;; ! i386-*-osfrose*) # 386 using OSF/rose tm_file=i386rose.h xmake_file=x-i386rose --- 303,307 ---- # tm_file=tahoe.h # ;; ! i[34]86-*-osfrose*) # 386 using OSF/rose tm_file=i386rose.h xmake_file=x-i386rose *************** *** 231,235 **** use_collect2=yes ;; ! i386-sequent-bsd*) # 80386 from Sequent xm_file=xm-i386.h use_collect2=yes --- 309,313 ---- use_collect2=yes ;; ! i[34]86-sequent-bsd*) # 80386 from Sequent xm_file=xm-i386.h use_collect2=yes *************** *** 241,276 **** fi ;; ! i386-*-bsd*) xm_file=xm-i386.h tm_file=i386bsd.h ! tmake_file=t-libc-ok use_collect2=yes ;; ! i386-*-mach*) xm_file=xm-i386.h tm_file=i386mach.h ! tmake_file=t-libc-ok use_collect2=yes ;; ! i386-*-sco3.2v4*) # 80386 running SCO 3.2v4 system xm_file=xm-i386sco.h tm_file=i386sco4.h ! xmake_file=x-i386sco tmake_file=t-i386sco ;; ! i386-*-sco*) # 80386 running SCO system xm_file=xm-i386sco.h tm_file=i386sco.h xmake_file=x-i386sco tmake_file=t-i386sco ;; ! i386-*-isc*) # 80386 running ISC system xm_file=xm-i386isc.h - tm_file=i386isc.h xmake_file=x-i386isc ! tmake_file=t-i386isc ;; ! i386-ibm-aix*) # IBM PS/2 running AIX ! tm_file=aix386.h xm_file=xm-aix386.h xmake_file=x-aix386 --- 319,369 ---- fi ;; ! i[34]86-*-bsd*) xm_file=xm-i386.h tm_file=i386bsd.h ! # tmake_file=t-libc-ok use_collect2=yes ;; ! i[34]86-*-mach*) xm_file=xm-i386.h tm_file=i386mach.h ! # tmake_file=t-libc-ok use_collect2=yes ;; ! i[34]86-*-sco3.2v4*) # 80386 running SCO 3.2v4 system xm_file=xm-i386sco.h tm_file=i386sco4.h ! xmake_file=x-i386s4 tmake_file=t-i386sco + broken_install=yes ;; ! i[34]86-*-sco*) # 80386 running SCO system xm_file=xm-i386sco.h tm_file=i386sco.h xmake_file=x-i386sco tmake_file=t-i386sco + broken_install=yes ;; ! i[34]86-*-isc*) # 80386 running ISC system xm_file=xm-i386isc.h xmake_file=x-i386isc ! if [ x$gas = xyes ] ! then ! tm_file=i386iscgas.h ! tmake_file=t-i386iscgas ! else ! tm_file=i386isc.h ! tmake_file=t-i386isc ! fi ! broken_install=yes ;; ! i[34]86-ibm-aix*) # IBM PS/2 running AIX ! if [ x$gas = xyes ] ! then ! tm_file=aix386.h ! else ! tm_file=aix386ng.h ! use_collect2=yes ! fi xm_file=xm-aix386.h xmake_file=x-aix386 *************** *** 282,292 **** use_collect2=yes ;; ! i386-*-sysv4*) # Intel 80386's running system V.4 xm_file=xm-i38v4.h - xmake_file=x-i386v4 tm_file=i386v4.h tmake_file=t-svr4 ;; ! i386-*-sysv*) # Intel 80386's running system V xm_file=xm-i386v.h xmake_file=x-i386v --- 375,400 ---- use_collect2=yes ;; ! i[34]86-*-linux*) # Intel 80386's running Linux ! cpu_type=i386 ! xm_file=xm-linux.h ! xmake_file=x-linux ! tm_file=i386linux.h ! broken_install=yes ! ;; ! i486-ncr-sysv4*) # NCR 3000 - i486 running system V.4 ! cpu_type=i386 ! xm_file=xm-i38v4.h ! xmake_file=x-ncr3000 ! tm_file=i386v4.h ! tmake_file=t-svr4 ! ;; ! i[34]86-*-sysv4*) # Intel 80386's running system V.4 ! cpu_type=i386 xm_file=xm-i38v4.h tm_file=i386v4.h tmake_file=t-svr4 + xmake_file=x-svr4 ;; ! i[34]86-*-sysv*) # Intel 80386's running system V xm_file=xm-i386v.h xmake_file=x-i386v *************** *** 294,315 **** if [ x$gas = xyes ] then ! tm_file=i386gas.h else tm_file=i386v.h fi ;; ! i486-ncr-sysv4*) # NCR 3000 - i486 running system V.4 ! cpu_type=i386 ! xm_file=xm-i38v4.h ! xmake_file=x-ncr3000 ! tm_file=i486v4.h ! tmake_file=t-svr4 ! ;; ! i486-*-sysv4*) # Intel 80486's running system V.4 ! cpu_type=i386 ! xm_file=xm-i38v4.h ! xmake_file=x-i386v4 ! tm_file=i486v4.h ! tmake_file=t-svr4 ;; i860-*-sysv3*) --- 402,419 ---- if [ x$gas = xyes ] then ! if [ x$stabs = xyes ] ! then ! tm_file=i386gstabs.h ! else ! tm_file=i386gas.h ! fi else tm_file=i386v.h fi ;; ! i860-*-mach*) ! xm_file=xm-i860.h ! tm_file=i860mach.h ! tmake_file=t-libc-ok ;; i860-*-sysv3*) *************** *** 345,348 **** --- 449,457 ---- use_collect2=yes ;; + elxsi-elxsi-*) + tm_file=elxsi.h + xm_file=xm-elxsi.h + use_collect2=yes + ;; sparc-*-sunos4*) tm_file=sparc.h *************** *** 359,369 **** xmake_file=x-sparcv4 ;; ! sparc-*-solaris2*) ! xm_file=xm-spcv4.h tm_file=spc-sol2.h ! tmake_file=t-svr4 xmake_file=x-sparcv4 ;; ! m68k-*-amix*) # Commodore variant of V.4. tm_file=amix.h xm_file=xm-amix.h --- 468,479 ---- xmake_file=x-sparcv4 ;; ! sparc-*-solaris2* | sparc-*-sunos5*) ! xm_file=xm-spc-sol2.h tm_file=spc-sol2.h ! tmake_file=t-sol2 xmake_file=x-sparcv4 + fixincludes=fixinc.svr4 ;; ! m68k-cbm-sysv4*) # Commodore variant of V.4. tm_file=amix.h xm_file=xm-amix.h *************** *** 374,379 **** m68k-*-sysv4*) # Motorola m68k's running system V.4 tm_file=m68kv4.h ! xm_file=xm-m68kv4.h ! xmake_file=x-m68kv4 tmake_file=t-svr4 header_files=math-68881.h --- 484,488 ---- m68k-*-sysv4*) # Motorola m68k's running system V.4 tm_file=m68kv4.h ! xm_file=xm-m68kv.h tmake_file=t-svr4 header_files=math-68881.h *************** *** 384,397 **** tm_file=dpx2g.h else tm_file=dpx2.h fi xm_file=xm-m68kv.h ! # is this cool ? ! if [ -d /makesys/kernel/cf/ncl_mr ]; then ! xmake_file=x-dpx2300 ! elif [ -d /makesys/kernel/cf/ncl_el ]; then ! xmake_file=x-dpx2200 ! fi ! xmake_file=${xmake_file:-x-dpx2300} use_collect2=yes header_files=math-68881.h --- 493,502 ---- tm_file=dpx2g.h else + echo dpx2 supported only with GAS 1>&2 + exit 1 tm_file=dpx2.h fi xm_file=xm-m68kv.h ! xmake_file=x-dpx2 use_collect2=yes header_files=math-68881.h *************** *** 402,405 **** --- 507,511 ---- xm_file=xm-next.h tmake_file=t-next + xmake_file=x-next use_collect2=yes header_files=math-68881.h *************** *** 415,419 **** header_files=math-68881.h ;; ! m68k-sun-sunos*) # For Sunos 4 (the default). if [ x$nfp = xyes ] then --- 521,525 ---- header_files=math-68881.h ;; ! m68k-sun-sunos*) # For SunOS 4 (the default). if [ x$nfp = xyes ] then *************** *** 441,444 **** --- 547,551 ---- then xmake_file=x-hp320g + tmake_file=t-hp320g tm_file=hp320g.h else *************** *** 465,469 **** header_files=math-68881.h ;; ! m68k-sony-bsd*) xm_file=xm-m68k.h if [ x$gas = xyes ] --- 572,587 ---- header_files=math-68881.h ;; ! m68k-sony-newsos3*) ! xm_file=xm-m68k.h ! if [ x$gas = xyes ] ! then ! tm_file=news3gas.h ! else ! tm_file=news3.h ! fi ! use_collect2=yes ! header_files=math-68881.h ! ;; ! m68k-sony-bsd* | m68k-sony-newsos*) xm_file=xm-m68k.h if [ x$gas = xyes ] *************** *** 506,509 **** --- 624,634 ---- header_files=math-68881.h ;; + m68k-plexus-sysv*) + cpu_type=m68k + tm_file=plexus.h + use_collect2=yes + xm_file=xm-m68kv.h + header_files=math-68881.h + ;; m68k-ncr-sysv*) # NCR Tower 32 SVR3 tm_file=tower-as.h *************** *** 592,595 **** --- 717,721 ---- # xmake_file=x-genix # tm_file=genix.h + # broken_install=yes # use_collect2=yes # ;; *************** *** 598,601 **** --- 724,737 ---- use_collect2=yes ;; + ns32k-tek6100-bsd*) + tm_file=tek6100.h + broken_install=yes + use_collect2=yes + ;; + ns32k-tek6200-bsd*) + tm_file=tek6200.h + broken_install=yes + use_collect2=yes + ;; ns32k-pc532-mach*) tm_file=pc532-mach.h *************** *** 614,617 **** --- 750,754 ---- tm_file=m88kdgux.h xmake_file=x-m88kdgux + broken_install=yes ;; m88k-*-sysv4*) *************** *** 628,632 **** tm_file=m88kv3.h xm_file=xm-m88kv3.h - xmake_file=x-m88kv3 ;; # This hasn't been upgraded to GCC 2. --- 765,768 ---- *************** *** 663,667 **** ;; mips-sgi-irix4*) # Mostly like a MIPS. ! tm_file=iris4.h xm_file=xm-irix4.h broken_install=yes --- 799,807 ---- ;; mips-sgi-irix4*) # Mostly like a MIPS. ! if [ x$stabs = xyes ]; then ! tm_file=iris4g.h ! else ! tm_file=iris4.h ! fi xm_file=xm-irix4.h broken_install=yes *************** *** 670,674 **** ;; mips-sgi-*) # Mostly like a MIPS. ! tm_file=iris.h xm_file=xm-iris.h broken_install=yes --- 810,818 ---- ;; mips-sgi-*) # Mostly like a MIPS. ! if [ x$stabs = xyes ]; then ! tm_file=irisgdb.h ! else ! tm_file=iris.h ! fi xm_file=xm-iris.h broken_install=yes *************** *** 677,681 **** ;; mips-dec-ultrix*) # Decstation. ! tm_file=decstatn.h tmake_file=t-decstatn xmake_file=x-decstatn --- 821,829 ---- ;; mips-dec-ultrix*) # Decstation. ! if [ x$stabs = xyes ]; then ! tm_file=decstabs.h ! else ! tm_file=decstatn.h ! fi tmake_file=t-decstatn xmake_file=x-decstatn *************** *** 689,700 **** ;; mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL ! tm_file=dec-osf1.h ! xmake_file=x-mips tmake_file=t-decstatn use_collect2=yes ;; ! mips-sony-bsd*) # Sony NEWS 3600 or risc/news. ! tm_file=mips-news.h ! xm_file=xm-mipsbsdn.h use_collect2=yes ;; --- 837,856 ---- ;; mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL ! if [ x$stabs = xyes ]; then ! tm_file=dec-gosf1.h ! else ! tm_file=dec-osf1.h ! fi ! xmake_file=x-dec-osf1 tmake_file=t-decstatn use_collect2=yes ;; ! mips-sony-bsd* | mips-sony-newsos*) # Sony NEWS 3600 or risc/news. ! if [ x$stabs = xyes ]; then ! tm_file=mips-gnews.h ! else ! tm_file=mips-news.h ! fi ! xm_file=xm-mips.h use_collect2=yes ;; *************** *** 702,727 **** # That is based on svr4. # t-svr4 is not right because this system doesn't use ELF. ! tm_file=mips-n5.h xm_file=xm-mipsnews.h use_collect2=yes ;; ! mips-*-bsd*) # BSD 4.3 variant of MIPS system. ! tm_file=mips-bsd.h use_collect2=yes ;; ! mips-*-sysv4*) # MIPS System V.4. ! tm_file=mips-svr4.h xm_file=xm-umips.h xmake_file=x-mipsv use_collect2=yes ;; ! mips-*-sysv*) # MIPS System V. ! tm_file=mips-sysv.h xm_file=xm-umips.h xmake_file=x-mipsv use_collect2=yes ;; ! mips-mips-*) # Default MIPS environment. ! tm_file=mips.h use_collect2=yes ;; --- 858,939 ---- # That is based on svr4. # t-svr4 is not right because this system doesn't use ELF. ! if [ x$stabs = xyes ]; then ! tm_file=mips-gn5.h ! else ! tm_file=mips-n5.h ! fi xm_file=xm-mipsnews.h use_collect2=yes ;; ! mips-*riscos[56789]bsd* | mips-*riscos[56789]-bsd*) ! if [ x$stabs = xyes ]; then # MIPS BSD 4.3, RISC-OS 5.0 ! tm_file=mips-5gbsd.h ! else ! tm_file=mips-5bsd.h ! fi ! use_collect2=yes ! ;; ! mips-*-bsd* | mips-*riscosbsd* | mips-*riscos[1234]bsd* \ ! | mips-*riscos-bsd* | mips-*riscos[1234]-bsd*) ! if [ x$stabs = xyes ]; then # MIPS BSD 4.3, RISC-OS 4.0 ! tm_file=mips-gbsd.h ! else ! tm_file=mips-bsd.h ! fi use_collect2=yes ;; ! mips-*riscos[56789]sysv4* | mips-*riscos[56789]-sysv4*) ! if [ x$stabs = xyes ]; then # MIPS System V.4., RISC-OS 5.0 ! tm_file=mips-5gsvr4.h ! else ! tm_file=mips-5svr4.h ! fi ! xm_file=xm-umips.h ! xmake_file=x-mipsv ! ;; ! mips-*-sysv4* | mips-*riscos[1234]sysv4* | mips-*riscossysv4* \ ! | mips-*riscos[1234]-sysv4* | mips-*riscos-sysv4*) ! if [ x$stabs = xyes ]; then # MIPS System V.4. RISC-OS 4.0 ! tm_file=mips-gsvr4.h ! else ! tm_file=mips-svr4.h ! fi ! xm_file=xm-umips.h ! xmake_file=x-mipsv ! ;; ! mips-*riscos[56789]sysv* | mips-*-riscos[56788]-sysv*) ! if [ x$stabs = xyes ]; then # MIPS System V.3, RISC-OS 5.0 ! tm_file=mips-5gsysv.h ! else ! tm_file=mips-5sysv.h ! fi xm_file=xm-umips.h xmake_file=x-mipsv use_collect2=yes ;; ! mips-*-sysv* | mips-*riscossysv* | mips-*riscos-sysv*) ! if [ x$stabs = xyes ]; then # MIPS System V.3, RISC-OS 4.0 ! tm_file=mips-gsysv.h ! else ! tm_file=mips-sysv.h ! fi xm_file=xm-umips.h xmake_file=x-mipsv use_collect2=yes ;; ! mips-*riscos[56789]*) # Default MIPS RISC-OS 5.0. ! if [ x$stabs = xyes ]; then ! tm_file=mips-5gdb.h ! else ! tm_file=mips-5.h ! fi ! use_collect2=yes ! ;; ! mips-*-*) # Default MIPS RISC-OS 4.0. ! if [ x$stabs = xyes ]; then ! tm_file=mips-gdb.h ! else ! tm_file=mips.h ! fi use_collect2=yes ;; *************** *** 772,775 **** --- 984,989 ---- xm_file=xm-pa.h tm_file=pa1.h + xmake_file=x-pa + tmake_file=t-pa use_collect2=yes ;; *************** *** 778,781 **** --- 992,997 ---- xm_file=xm-pa.h tm_file=pa.h + xmake_file=x-pa + tmake_file=t-pa use_collect2=yes ;; *************** *** 784,787 **** --- 1000,1004 ---- xm_file=xm-pa.h xmake_file=x-pa-hpux + tmake_file=t-libc-ok if [ x$gas = xyes ] then *************** *** 797,800 **** --- 1014,1018 ---- xm_file=xm-pa.h xmake_file=x-pa-hpux + tmake_file=t-libc-ok if [ x$gas = xyes ] then *************** *** 810,818 **** use_collect2=yes ;; i960-*-*) # Default i960 environment. use_collect2=yes ;; *) ! echo "Configuration $machine not recognized" 1>&2 exit 1 ;; --- 1028,1041 ---- use_collect2=yes ;; + alpha-*-osf*) + cpu_type=alpha + broken_install=yes + use_collect2=yes + ;; i960-*-*) # Default i960 environment. use_collect2=yes ;; *) ! echo "Configuration $machine not supported" 1>&2 exit 1 ;; *************** *** 821,825 **** --- 1044,1050 ---- case $machine in *-*-sysv4*) + fixincludes=fixinc.svr4 xmake_try_sysv=x-sysv + broken_install=yes ;; *-*-sysv*) *************** *** 828,831 **** --- 1053,1063 ---- esac + # Distinguish i386 from i486. + case $machine in + i486-*-*) + target_cpu_default=2 + ;; + esac + # No need for collect2 if we have the GNU linker. case x$gnu_ld in *************** *** 840,855 **** fi # Save data on host machine in vars host_xm_file and host_xmake_file. if [ x$pass1done = x ] then ! if [ x$xm_file = x ]; then host_xm_file=xm-$cpu_type.h ! else host_xm_file=$xm_file ! fi ! if [ x$xmake_file = x ] ! then xmake_file=x-$cpu_type fi - host_xmake_file=$xmake_file - host_broken_install=$broken_install pass1done=yes fi done --- 1072,1096 ---- fi + # Save data on machine being used to compile GCC in build_xm_file. # Save data on host machine in vars host_xm_file and host_xmake_file. if [ x$pass1done = x ] then ! if [ x$xm_file = x ]; then build_xm_file=xm-$cpu_type.h ! else build_xm_file=$xm_file fi pass1done=yes + else + if [ x$pass2done = x ] + then + if [ x$xm_file = x ]; then host_xm_file=xm-$cpu_type.h + else host_xm_file=$xm_file + fi + if [ x$xmake_file = x ] + then xmake_file=x-$cpu_type + fi + host_xmake_file=$xmake_file + host_broken_install=$broken_install + pass2done=yes + fi fi done *************** *** 877,882 **** # Set up the list of links to be made. # $links is the list of link names, and $files is the list of names to link to. ! files="$host_xm_file $tm_file $md_file $out_file $xm_file" ! links="config.h tm.h md aux-output.c tconfig.h" # Make the links. --- 1118,1123 ---- # Set up the list of links to be made. # $links is the list of link names, and $files is the list of names to link to. ! files="$host_xm_file $tm_file $md_file $out_file $xm_file $build_xm_file" ! links="config.h tm.h md aux-output.c tconfig.h hconfig.h" # Make the links. *************** *** 934,938 **** then rm -f Makefile.xx ! sed -e "/####/ r ${srcdir}/config/${host_xmake_file}" Makefile.tem > Makefile.xx echo "Merged ${host_xmake_file}." rm -f Makefile.tem --- 1175,1179 ---- then rm -f Makefile.xx ! sed -e "/####host/ r ${srcdir}/config/${host_xmake_file}" Makefile.tem > Makefile.xx echo "Merged ${host_xmake_file}." rm -f Makefile.tem *************** *** 951,955 **** else rm -f Makefile.xx ! sed 's|^INSTALL = .*|INSTALL = $(srcdir)/install.sh -c|' Makefile.tem > Makefile.xx rm -f Makefile.tem mv Makefile.xx Makefile.tem --- 1192,1197 ---- else rm -f Makefile.xx ! abssrcdir=`cd ${srcdir}; pwd` ! sed "s|^INSTALL = .*|INSTALL = ${abssrcdir}/install.sh -c|" Makefile.tem > Makefile.xx rm -f Makefile.tem mv Makefile.xx Makefile.tem *************** *** 980,988 **** fi # Conditionalize the makefile for this target machine. if [ -f ${srcdir}/config/${tmake_file} ] then rm -f Makefile.xx ! sed -e "/####/ r ${srcdir}/config/${tmake_file}" Makefile.tem > Makefile.xx echo "Merged ${tmake_file}." rm -f Makefile.tem --- 1222,1242 ---- fi + # Add -DTARGET_CPU_DEFAULT for toplev.c if system wants one. + # This substitutes for lots of *.h files. + if [ x$target_cpu_default = x ] + then true + else + rm -f Makefile.xx + (echo "MAYBE_TARGET_DEFAULT = -DTARGET_CPU_DEFAULT=$target_cpu_default")\ + | cat - Makefile.tem > Makefile.xx + rm -f Makefile.tem + mv Makefile.xx Makefile.tem + fi + # Conditionalize the makefile for this target machine. if [ -f ${srcdir}/config/${tmake_file} ] then rm -f Makefile.xx ! sed -e "/####target/ r ${srcdir}/config/${tmake_file}" Makefile.tem > Makefile.xx echo "Merged ${tmake_file}." rm -f Makefile.tem *************** *** 996,1006 **** # Remove all formfeeds, since some Makes get confused by them. ! # Also arrange to give the variables `target' and `host_xmake_file' ! # and `tmake_file' the same values in the Makefile ! # that they have in this script. rm -f Makefile.xx sed -e "s/ //" -e "s/^target=.*$/target=${target}/" \ -e "s|^xmake_file=.*$|xmake_file=${host_xmake_file}|" \ -e "s|^tmake_file=.*$|tmake_file=${tmake_file}|" \ Makefile.tem > Makefile.xx rm -f Makefile.tem --- 1250,1263 ---- # Remove all formfeeds, since some Makes get confused by them. ! # Also arrange to give the variables `target', `host_xmake_file', ! # `tmake_file', `prefix', `exec_prefix' and `FIXINCLUDES' ! # values in the Makefile from the values they have in this script. rm -f Makefile.xx sed -e "s/ //" -e "s/^target=.*$/target=${target}/" \ -e "s|^xmake_file=.*$|xmake_file=${host_xmake_file}|" \ -e "s|^tmake_file=.*$|tmake_file=${tmake_file}|" \ + -e "s|^prefix[ ]*=.*|prefix = $prefix|" \ + -e "s|^exec_prefix[ ]*=.*|exec_prefix = $exec_prefix|" \ + -e "s|^FIXINCLUDES[ ]*=.*|FIXINCLUDES = $fixincludes|" \ Makefile.tem > Makefile.xx rm -f Makefile.tem *************** *** 1013,1021 **** then rm -f Makefile ! mv Makefile.tem Makefile else rm -f Makefile echo "CROSS=-DCROSS_COMPILE" > Makefile ! sed -e "/####/ r ${srcdir}/cross-make" Makefile.tem >> Makefile rm -f Makefile.tem Makefile.xx fi --- 1270,1287 ---- then rm -f Makefile ! if [ x$host = x$build ] ! then ! mv Makefile.tem Makefile ! else ! # When build gcc with cross-compiler, we need to fix a ! # few things. ! echo "build= $build" > Makefile ! sed -e "/####build/ r ${srcdir}/build-make" Makefile.tem >> Makefile ! rm -f Makefile.tem Makefile.xx ! fi else rm -f Makefile echo "CROSS=-DCROSS_COMPILE" > Makefile ! sed -e "/####cross/ r ${srcdir}/cross-make" Makefile.tem >> Makefile rm -f Makefile.tem Makefile.xx fi *************** *** 1025,1029 **** if [ xx${vint} != xx ] then ! vintmsg =" (vint)" fi --- 1291,1295 ---- if [ xx${vint} != xx ] then ! vintmsg=" (vint)" fi *************** *** 1033,1043 **** # GCC was configured as follows: ${srcdir}/configure" $arguments > config.status chmod a+x config.status ! if [ x$host = x$target ] then ! echo "Links are now set up for target $target." else ! echo "Links are now set up for host $host and target $target." fi --- 1299,1310 ---- # GCC was configured as follows: ${srcdir}/configure" $arguments > config.status + echo echo host=$canon_host target=$canon_target build=$canon_build >> config.status chmod a+x config.status ! if [ x$canon_host = x$canon_target ] then ! echo "Links are now set up for target $canon_target." else ! echo "Links are now set up for host $canon_host and target $canon_target." fi diff -rc2N gcc-2.2.2/configure.bat gcc-2.3.1/configure.bat *** gcc-2.2.2/configure.bat Sun May 3 17:43:10 1992 --- gcc-2.3.1/configure.bat Tue Oct 13 00:14:07 1992 *************** *** 1,7 **** @echo off ! echo Configuring gcc-2.1 for go32 rem This batch file assumes a unix-type "sed" program update config\xm-i386dos.h config.h update config\i386gas.h tm.h update config\i386.md md --- 1,8 ---- @echo off ! echo Configuring GCC for go32 rem This batch file assumes a unix-type "sed" program update config\xm-i386dos.h config.h + update config\xm-i386dos.h hconfig.h update config\i386gas.h tm.h update config\i386.md md *************** *** 9,13 **** echo # Makefile generated by "configure.bat"> Makefile ! echo all.dos: cccp cc1 cc1plus cc1obj gcc>> Makefile if exist config.sed del config.sed --- 10,14 ---- echo # Makefile generated by "configure.bat"> Makefile ! echo all.dos: cccp cc1 cc1plus cc1obj xgcc>> Makefile if exist config.sed del config.sed diff -rc2N gcc-2.2.2/cp-call.c gcc-2.3.1/cp-call.c *** gcc-2.2.2/cp-call.c Thu Jun 11 00:10:40 1992 --- gcc-2.3.1/cp-call.c Tue Oct 6 19:28:51 1992 *************** *** 34,39 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); extern void sorry (); --- 34,37 ---- *************** *** 356,361 **** if (codel == REFERENCE_TYPE) { ! ttl = TYPE_MAIN_VARIANT (TREE_TYPE (ttl)); if (form == OFFSET_TYPE) { --- 354,369 ---- if (codel == REFERENCE_TYPE) { ! ttl = TREE_TYPE (ttl); + /* When passing a non-const argument into a const reference, + dig it a little, so a non-const reference is preferred over + this one. (mrs) */ + if (TREE_READONLY (ttl) && ! TREE_READONLY (parm)) + penalty = 2; + else + penalty = 0; + + ttl = TYPE_MAIN_VARIANT (ttl); + if (form == OFFSET_TYPE) { *************** *** 375,380 **** { /* Can reference be built up? */ ! if (ttl == intype) ! return 0; else penalty = 2; --- 383,402 ---- { /* Can reference be built up? */ ! if (ttl == intype && penalty == 0) { ! /* Becuase the READONLY bits are not always in the type, ! this extra check is necessary. The problem should ! be fixed someplace else, and this extra code removed. ! ! Also, if type if a reference, the readonly bits could ! either be in the outer type (with reference) or on the ! inner type (the thing being referenced). (mrs) */ ! if (TREE_READONLY (parm) ! && ! (TYPE_READONLY (type) ! || (TREE_CODE (type) == REFERENCE_TYPE ! && TYPE_READONLY (TREE_TYPE (type))))) ! penalty = 2; ! else ! return 0; ! } else penalty = 2; *************** *** 565,568 **** --- 587,597 ---- harshness = convert_harshness (TREE_VALUE (ttf), TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta)); + /* Don't include the cost to convert the first parameter, as we know it + is the instance pointer that we know will be converted by itself + later. It could point to a derived class. */ + if (strike_index == 0 && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE + && !DECL_STATIC_FUNCTION_P (function)) + harshness = 0; + cp->harshness[strike_index] = harshness; if (EVIL_HARSHNESS (harshness) *************** *** 731,734 **** --- 760,766 ---- /* Const member functions get a small penalty because defaulting to const is less useful than defaulting to non-const. */ + /* This is bogus, it does not correspond to anything in the ARM. + This code will be fixed when this entire section is rewritten + to conform to the ARM. (mrs) */ if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) { *************** *** 898,902 **** /* Don't complain if next best is from base class. */ tree f2 = cp[i].function; - tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2)); if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE --- 930,933 ---- *************** *** 906,909 **** --- 937,941 ---- { #if 0 + tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2)); /* For LUCID. */ if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1)) *************** *** 917,920 **** --- 949,953 ---- /* Ensure that there's nothing ambiguous about these two fns. */ + int identical = 1; for (index = 0; index < len; index++) { *************** *** 927,931 **** --- 960,974 ---- if (cp[i].harshness[index] < cp[best].harshness[index]) goto ret0; + /* If any single one it diffent, then the whole is + not identical. */ + if (cp[i].harshness[index] != cp[best].harshness[index]) + identical = 0; } + + /* If we can't tell the difference between the two, it + is ambiguous. */ + if (identical) + goto ret0; + /* If we made it to here, it means we're satisfied that BEST is still best. */ *************** *** 1010,1014 **** && ! DERIVED_FROM_P (base1, newbase)) { - char *buf = (char *)alloca (8192); error_with_aggr_type (basetype, "ambiguous request for function from distinct base classes of type `%s'"); error ("first candidate is `%s'", --- 1053,1056 ---- *************** *** 1162,1170 **** /* Check to see if we really have a reference to an instance variable with `operator()()' overloaded. */ - #if 1 field = IDENTIFIER_CLASS_VALUE (name); - #else - field = identifier_class_value (name); - #endif if (field == NULL_TREE) --- 1204,1208 ---- *************** *** 1197,1201 **** /* Check to see if this is not really a reference to an instance variable with `operator()()' overloaded. */ ! field = lookup_field (basetype_path, name, 1); /* This can happen if the reference was ambiguous --- 1235,1239 ---- /* Check to see if this is not really a reference to an instance variable with `operator()()' overloaded. */ ! field = lookup_field (basetype_path, name, 1, 0); /* This can happen if the reference was ambiguous *************** *** 1387,1391 **** error_with_aggr_type (TREE_TYPE (decl), "type `%s' has no destructor"); return build_delete (TREE_TYPE (decl), decl, integer_two_node, ! LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, 1); } --- 1425,1430 ---- error_with_aggr_type (TREE_TYPE (decl), "type `%s' has no destructor"); return build_delete (TREE_TYPE (decl), decl, integer_two_node, ! LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, ! 0, 0); } *************** *** 1481,1487 **** int constp, volatilep; - /* Know if this is explicit destructor call. */ - int dtor_specd = 0; - #ifdef GATHER_STATISTICS n_build_method_call++; --- 1520,1523 ---- *************** *** 1494,1497 **** --- 1530,1551 ---- return error_mark_node; + /* This is the logic that magically deletes the second argument to + operator delete, if it is not needed. */ + if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2) + { + tree save_last = TREE_CHAIN (parms); + tree result; + /* get rid of unneeded argument */ + TREE_CHAIN (parms) = NULL_TREE; + result = build_method_call (instance, name, parms, basetype_path, + (LOOKUP_SPECULATIVELY|flags) + &~LOOKUP_COMPLAIN); + /* If it works, return it. */ + if (result && result != error_mark_node) + return build_method_call (instance, name, parms, basetype_path, flags); + /* If it doesn't work, two argument delete must work */ + TREE_CHAIN (parms) = save_last; + } + #if 0 /* C++ 2.1 does not allow this, but ANSI probably will. */ *************** *** 2194,2197 **** --- 2248,2254 ---- if (ever_seen == 0) { + if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN)) + == LOOKUP_SPECULATIVELY) + return NULL_TREE; if (flags & LOOKUP_GLOBAL) error ("no global or member function `%s' defined", err_name); *************** *** 2338,2346 **** { if (flags & LOOKUP_COMPLAIN) ! error (TREE_PRIVATE (function) ! ? "%s `%s' is private" ! : "%s `%s' is from private base class", ! name_kind, ! lang_printable_name (function)); return error_mark_node; } --- 2395,2405 ---- { if (flags & LOOKUP_COMPLAIN) ! error_with_file_and_line (DECL_SOURCE_FILE (function), ! DECL_SOURCE_LINE (function), ! TREE_PRIVATE (function) ! ? "%s `%s' is private" ! : "%s `%s' is from private base class", ! name_kind, ! lang_printable_name (function)); return error_mark_node; } *************** *** 2348,2356 **** { if (flags & LOOKUP_COMPLAIN) ! error (TREE_PROTECTED (function) ! ? "%s `%s' is protected" ! : "%s `%s' has protected visibility from this point", ! name_kind, ! lang_printable_name (function)); return error_mark_node; } --- 2407,2417 ---- { if (flags & LOOKUP_COMPLAIN) ! error_with_file_and_line (DECL_SOURCE_FILE (function), ! DECL_SOURCE_LINE (function), ! TREE_PROTECTED (function) ! ? "%s `%s' is protected" ! : "%s `%s' has protected visibility from this point", ! name_kind, ! lang_printable_name (function)); return error_mark_node; } *************** *** 2468,2471 **** --- 2529,2535 ---- && TREE_OPERAND (TREE_OPERAND (instance_ptr, 0), 0) == instance) ; + /* The call to `convert_pointer_to' may return error_mark_node. */ + else if (TREE_CODE (instance_ptr) == ERROR_MARK) + return instance_ptr; else if (instance == NULL_TREE || TREE_CODE (instance) != INDIRECT_REF *************** *** 2649,2653 **** if (TREE_CODE (function) == FUNCTION_DECL) { ! if (TREE_INLINE (function)) function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); else --- 2713,2717 ---- if (TREE_CODE (function) == FUNCTION_DECL) { ! if (DECL_INLINE (function)) function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); else *************** *** 2929,2935 **** --- 2993,3006 ---- tree name; char *err_name; + /* Initialize name for error reporting. */ if (TREE_CODE (functions) == TREE_LIST) name = TREE_PURPOSE (functions); + else if (TREE_CODE (functions) == ADDR_EXPR) + /* Since the implicit `operator new' and `operator delete' functions + are set up to have IDENTIFIER_GLOBAL_VALUEs that are unary ADDR_EXPRs + by default_conversion(), we must compensate for that here by + using the name of the ADDR_EXPR's operand. */ + name = DECL_NAME (TREE_OPERAND (functions, 0)); else name = DECL_NAME (functions); diff -rc2N gcc-2.2.2/cp-class.c gcc-2.3.1/cp-class.c *** gcc-2.2.2/cp-class.c Thu Jun 11 00:19:32 1992 --- gcc-2.3.1/cp-class.c Thu Sep 24 21:48:03 1992 *************** *** 38,44 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - extern struct obstack permanent_obstack; --- 38,41 ---- *************** *** 98,103 **** tree current_lang_name; - tree minus_one_node; - /* When layout out an aggregate type, the size of the basetypes (virtual and non-virtual) is passed to layout_record --- 95,98 ---- *************** *** 116,157 **** int n_inner_fields_searched = 0; - #if 0 - /* Make sure that the tag NAME is defined *in the current binding level* - at least as a forward reference. - CODE says which kind of tag NAME ought to be. - - Not used for C++. Not maintained. */ - - tree - start_struct (code, name) - enum tree_code code; - tree name; - { - /* If there is already a tag defined at this binding level - (as a forward reference), just return it. */ - register tree ref = 0; - - if (name != 0) - ref = lookup_tag (code, name, current_binding_level, 1); - if (ref && TREE_CODE (ref) == code) - { - if (TYPE_FIELDS (ref)) - error ((code == UNION_TYPE ? "redefinition of `union %s'" - : "redefinition of `struct %s'"), - IDENTIFIER_POINTER (name)); - - return ref; - } - - /* Otherwise create a forward-reference just so the tag is in scope. */ - - ref = make_lang_type (code); - /* Must re-synch this with xref_tag if you are going to use it. */ - assert (0); - pushtag (name, ref); - return ref; - } - #endif - /* Virtual baseclass things. */ tree --- 111,114 ---- *************** *** 488,492 **** { TREE_PUBLIC (decl) = 1; ! TREE_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type); } } --- 445,449 ---- { TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type); } } *************** *** 495,499 **** TREE_PUBLIC (decl) = 1; if (write_virtuals < 0) ! TREE_EXTERNAL (decl) = 1; } } --- 452,456 ---- TREE_PUBLIC (decl) = 1; if (write_virtuals < 0) ! DECL_EXTERNAL (decl) = 1; } } *************** *** 662,671 **** tree virtuals, base_fndecl; { ! int i = (HOST_BITS_PER_INT >= BITS_PER_WORD #ifdef VTABLE_USES_MASK && 0 #endif ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) ! & (((unsigned)1<<(BITS_PER_WORD-1))-1)) : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))); --- 619,628 ---- tree virtuals, base_fndecl; { ! int i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD #ifdef VTABLE_USES_MASK && 0 #endif ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) ! & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1)) : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))); *************** *** 729,733 **** #ifndef VTABLE_USES_MASK vindex = build_int_2 (TREE_INT_CST_LOW (vindex) ! & ~((unsigned)1 << (BITS_PER_WORD -1)), 0); #endif TREE_VALUE (TREE_CHAIN (elts)) = vindex; --- 686,691 ---- #ifndef VTABLE_USES_MASK vindex = build_int_2 (TREE_INT_CST_LOW (vindex) ! & ~((unsigned HOST_WIDE_INT) 1 ! << (BITS_PER_WORD -1)), 0); #endif TREE_VALUE (TREE_CHAIN (elts)) = vindex; *************** *** 791,795 **** number of different vtables which must be maintained. */ ! if (! DERIVED_FROM_P (base, base_context)) continue; --- 749,757 ---- number of different vtables which must be maintained. */ ! /* In this case, we need to know whether BASE is derived ! from BASE_CONTEXT in any case, even the case where the ! derivation is ambiguous. */ ! int distance = get_base_distance (base, base_context, 0, 0); ! if (distance < 0 && distance != -2) continue; *************** *** 947,951 **** tree vfn = build1 (ADDR_EXPR, ptr_type_node, x); TREE_CONSTANT (vfn) = 1; ! TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type); /* If the virtual function is a redefinition of a prior one, --- 909,916 ---- tree vfn = build1 (ADDR_EXPR, ptr_type_node, x); TREE_CONSTANT (vfn) = 1; ! ! /* current_class_type may be NULL_TREE in case of error. */ ! if (current_class_type) ! TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type); /* If the virtual function is a redefinition of a prior one, *************** *** 975,979 **** if (i >= 256 || index_table[i] == 0) { ! index = build_int_2 (((unsigned)1 << (BITS_PER_WORD - 1)) | i, ~0); if (i < 256) index_table[i] = index; --- 940,945 ---- if (i >= 256 || index_table[i] == 0) { ! index = build_int_2 (((unsigned HOST_WIDE_INT) 1 ! << (BITS_PER_WORD - 1)) | i, ~0); if (i < 256) index_table[i] = index; *************** *** 987,993 **** pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals); } ! /* Happens if declared twice in class. We will give error ! later. */ ! else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST) return pending_virtuals; else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) --- 953,960 ---- pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals); } ! /* Happens if declared twice in class or we're not in a class definition. ! We will give error later or we've already given it. */ ! else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST ! || current_class_type == NULL_TREE) return pending_virtuals; else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) *************** *** 1919,1922 **** --- 1886,1895 ---- for (x = *testp; x; x = DECL_CHAIN (x)) { + if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR]) + { + /* ANSI C++ June 5 1992 WP 12.5.5.1 */ + error_with_decl (fn_fields, "operator delete cannot be overloaded"); + error_with_decl (x, "previous declaration here"); + } if (DECL_ASSEMBLER_NAME (fn_fields) == DECL_ASSEMBLER_NAME (x)) { *************** *** 1965,1969 **** } if (nonprivate_method == 0) ! warning ("all class member functions are private"); } --- 1938,1943 ---- } if (nonprivate_method == 0) ! warning ("all member functions in class `%s' are private", ! TYPE_NAME_STRING (t)); } *************** *** 2082,2085 **** --- 2056,2084 ---- /* Pretend we haven't defined this type. */ + + /* All of the component_decl's were TREE_CHAINed together in the parser. + finish_struct_methods walks these chains and assembles all methods with + the same base name into DECL_CHAINs. Now we don't need the parser chains + anymore, so we unravel them. + */ + /* + * This used to be in finish_struct, but it turns out that the + * TREE_CHAIN is used by dbxout_type_methods and perhaps some other things... + */ + if (CLASSTYPE_METHOD_VEC(t)) + { + tree tv = CLASSTYPE_METHOD_VEC(t); + int i, len = TREE_VEC_LENGTH (tv); + for (i = 0; i < len; i++) + { + tree unchain = TREE_VEC_ELT (tv, i); + while(unchain != NULL_TREE) + { + TREE_CHAIN (unchain) = NULL_TREE; + unchain = DECL_CHAIN(unchain); + } + } + } + if (TYPE_LANG_SPECIFIC (t)) { *************** *** 2219,2223 **** DECL_SOURCE_FILE (name) = input_filename; ! DECL_SOURCE_LINE (name) = lineno; name = DECL_NAME (name); } --- 2218,2228 ---- DECL_SOURCE_FILE (name) = input_filename; ! /* For TYPE_DECL that are not typedefs (those marked with a line number ! of zero, we don't want to mark them as real typedefs. If this fails ! one needs to make sure real typedefs have a previous line number, ! even if it is wrong, that way the below will fill in the right line ! number. (mrs) */ ! if (DECL_SOURCE_LINE (name)) ! DECL_SOURCE_LINE (name) = lineno; name = DECL_NAME (name); } *************** *** 2369,2372 **** --- 2374,2378 ---- && TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE) { + #if 0 /* @@ Um. This doesn't seem to be handled properly, at least in my PT test cases. Not sure if it's really *************** *** 2376,2384 **** t = TYPE_IDENTIFIER (TREE_TYPE (x)); if (d == t) continue; ! assert (IDENTIFIER_TEMPLATE (t) != NULL_TREE); ! t = DECL_NAME (TREE_PURPOSE (IDENTIFIER_TEMPLATE (t))); ! assert (t == d); ! continue; ! } if (TREE_CODE (x) == FUNCTION_DECL) --- 2382,2399 ---- t = TYPE_IDENTIFIER (TREE_TYPE (x)); if (d == t) continue; ! if (IDENTIFIER_TEMPLATE (t)) ! { ! t = DECL_NAME (TREE_PURPOSE (IDENTIFIER_TEMPLATE (t))); ! assert (t == d); ! continue; ! } ! else if (IDENTIFIER_CLASS_VALUE (t)) ! assert (TREE_TYPE (DECL_NAME (d)) == TREE_TYPE (DECL_NAME (TREE_TYPE (t)))); ! else ! abort (); ! #endif ! continue; ! } ! if (TREE_CODE (x) == FUNCTION_DECL) *************** *** 2447,2473 **** } - /* Perform error checking that did not get done in grokdeclarator. */ - if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) - { - error_with_decl (x, "field `%s' invalidly declared function type"); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) - { - error_with_decl (x, "field `%s' invalidly declared method type"); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) - { - error_with_decl (x, "field `%s' invalidly declared offset type"); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } /* If this is of reference type, check if it needs an init. */ ! if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE && DECL_INITIAL (x) == 0) ref_sans_init = 1; /* When this goes into scope, it will be a non-local reference. */ ! TREE_NONLOCAL (x) = 1; if (TREE_CODE (x) == FIELD_DECL) --- 2462,2497 ---- } /* If this is of reference type, check if it needs an init. */ ! if (TREE_CODE (x) != TYPE_DECL ! && TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE && DECL_INITIAL (x) == 0) ref_sans_init = 1; + /* ``A local class cannot have static data members.'' ARM 9.4 */ + if (current_function_decl && TREE_STATIC (x)) + error_with_decl (x, "field `%s' in local class cannot be static"); + /* When this goes into scope, it will be a non-local reference. */ ! DECL_NONLOCAL (x) = 1; ! ! /* Perform error checking that did not get done in grokdeclarator. */ ! if (TREE_CODE (x) == FIELD_DECL || TREE_CODE (x) == VAR_DECL) ! { ! if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) ! { ! error_with_decl (x, "field `%s' invalidly declared function type"); ! TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); ! } ! else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) ! { ! error_with_decl (x, "field `%s' invalidly declared method type"); ! TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); ! } ! else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) ! { ! error_with_decl (x, "field `%s' invalidly declared offset type"); ! TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); ! } ! } if (TREE_CODE (x) == FIELD_DECL) *************** *** 2515,2519 **** } } ! else if (TREE_STATIC (x) && TREE_CODE (t) == UNION_TYPE) /* Unions cannot have static members. */ error_with_decl (x, "field `%s' declared static in union"); --- 2539,2543 ---- } } ! else if (TREE_CODE (x) == VAR_DECL && TREE_CODE (t) == UNION_TYPE) /* Unions cannot have static members. */ error_with_decl (x, "field `%s' declared static in union"); *************** *** 2521,2525 **** if (! fields) fields = x; DECL_FIELD_CONTEXT (x) = t; ! DECL_CLASS_CONTEXT (x) = t; DECL_FIELD_SIZE (x) = 0; --- 2545,2551 ---- if (! fields) fields = x; DECL_FIELD_CONTEXT (x) = t; ! /* We could be making an extern "C" function a friend. */ ! if (DECL_LANG_SPECIFIC (x)) ! DECL_CLASS_CONTEXT (x) = t; DECL_FIELD_SIZE (x) = 0; *************** *** 2730,2734 **** tree ctor; ! for (ctor = TREE_VEC_ELT (method_vec, 0); ctor; ctor = DECL_CHAIN (ctor)) if (! TREE_PRIVATE (ctor)) --- 2756,2761 ---- tree ctor; ! for (ctor = TREE_VEC_ELT (method_vec, 0); ! ctor; ctor = DECL_CHAIN (ctor)) if (! TREE_PRIVATE (ctor)) *************** *** 2762,2765 **** --- 2789,2795 ---- change the type when we know what it should be. */ vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t), ptr_type_node); + /* If you change any of the below, take a look at all the + other VFIELD_BASEs and VTABLE_BASEs in the code, and change + them too. */ DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE); CLASSTYPE_VFIELD (t) = vfield; *************** *** 2888,2893 **** tree base_context = DECL_CLASS_CONTEXT (base_fndecl); tree binfo = NULL_TREE, these_virtuals; ! unsigned i = (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) ! & (((unsigned)1<<(BITS_PER_WORD-1))-1)); if (TYPE_USES_VIRTUAL_BASECLASSES (context)) --- 2918,2924 ---- tree base_context = DECL_CLASS_CONTEXT (base_fndecl); tree binfo = NULL_TREE, these_virtuals; ! unsigned HOST_WIDE_INT i ! = (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) ! & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1)); if (TYPE_USES_VIRTUAL_BASECLASSES (context)) *************** *** 2986,2990 **** { tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0); - tree basetype = BINFO_TYPE (binfo); /* This class contributes nothing new to the virtual function --- 3017,3020 ---- *************** *** 3127,3130 **** --- 3157,3163 ---- change the type when we know what it should be. */ vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t), ptr_type_node); + /* If you change any of the below, take a look at all the + other VFIELD_BASEs and VTABLE_BASEs in the code, and change + them too. */ DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE); CLASSTYPE_VFIELD (t) = vfield; *************** *** 3134,3137 **** --- 3167,3171 ---- DECL_FCONTEXT (vfield) = t; DECL_FIELD_SIZE (vfield) = 0; + DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); y = tree_last (fields); if (y) *************** *** 3208,3215 **** { if (DECL_BIT_FIELD (x) ! && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE ! && ((unsigned)TREE_INT_CST_LOW (DECL_SIZE (x)) ! < TYPE_PRECISION (integer_type_node))) ! TREE_TYPE (x) = integer_type_node; } --- 3242,3248 ---- { if (DECL_BIT_FIELD (x) ! && C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x))) ! TREE_TYPE (x) = TREE_UNSIGNED (TREE_TYPE (x)) ! ? unsigned_type_node : integer_type_node; } *************** *** 3273,3277 **** tree vtbl_ptr = build_decl (VAR_DECL, get_identifier (VPTR_NAME), TREE_TYPE (vfield)); ! TREE_REGDECL (vtbl_ptr) = 1; CLASSTYPE_VTBL_PTR (t) = vtbl_ptr; } --- 3306,3310 ---- tree vtbl_ptr = build_decl (VAR_DECL, get_identifier (VPTR_NAME), TREE_TYPE (vfield)); ! DECL_REGISTER (vtbl_ptr) = 1; CLASSTYPE_VTBL_PTR (t) = vtbl_ptr; } *************** *** 3292,3296 **** CLASSTYPE_VFIELD (t) = vfield; } ! if (extra_warnings && TYPE_HAS_DESTRUCTOR (t) && DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE) warning ("class `%s' has virtual functions but non-virtual destructor", --- 3325,3329 ---- CLASSTYPE_VFIELD (t) = vfield; } ! if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t) && DECL_VINDEX (TREE_VEC_ELT (method_vec, 0)) == NULL_TREE) warning ("class `%s' has virtual functions but non-virtual destructor", *************** *** 3351,3358 **** only output it if we would output the enclosing type. */ if (DECL_CONTEXT (TYPE_NAME (t)) ! && TREE_CODE (DECL_CONTEXT (TYPE_NAME (t))) == RECORD_TYPE) DECL_IGNORED_P (TYPE_NAME (t)) = TREE_ASM_WRITTEN (TYPE_NAME (t)); #endif /* If the type has methods, we want to think about cutting down the amount of symbol table stuff we output. The value stored in --- 3384,3392 ---- only output it if we would output the enclosing type. */ if (DECL_CONTEXT (TYPE_NAME (t)) ! && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (TYPE_NAME (t)))) == 't') DECL_IGNORED_P (TYPE_NAME (t)) = TREE_ASM_WRITTEN (TYPE_NAME (t)); #endif + #if 0 /* but we NEED all those types! --Chip */ /* If the type has methods, we want to think about cutting down the amount of symbol table stuff we output. The value stored in *************** *** 3379,3382 **** --- 3413,3417 ---- else if (CLASSTYPE_INTERFACE_ONLY (t)) DECL_IGNORED_P (TYPE_NAME (t)) = 1; + #endif /* never --Chip */ /* Finish debugging output for this type. */ *************** *** 3516,3520 **** /* Keep these values lying around. */ - minus_one_node = build_int_2 (-1, 0); the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node); base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node); --- 3551,3554 ---- diff -rc2N gcc-2.2.2/cp-cvt.c gcc-2.3.1/cp-cvt.c *** gcc-2.2.2/cp-cvt.c Thu Jun 11 00:22:01 1992 --- gcc-2.3.1/cp-cvt.c Thu Sep 24 21:48:12 1992 *************** *** 204,212 **** value we have to begin with is in ARG. ! FLAGS controls how we manage visibility checking. */ static tree ! build_up_reference (type, arg, flags) tree type, arg; ! int flags; { tree rval, targ; --- 204,213 ---- value we have to begin with is in ARG. ! FLAGS controls how we manage visibility checking. ! CHECKCONST controls if we report error messages on const subversion. */ static tree ! build_up_reference (type, arg, flags, checkconst) tree type, arg; ! int flags, checkconst; { tree rval, targ; *************** *** 248,252 **** tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1); TREE_HAS_CONSTRUCTOR (targ) = 0; ! return build_up_reference (type, temp, flags); } /* Let &* cancel out to simplify resulting code. --- 249,253 ---- tree temp = build_cplus_new (argtype, TREE_OPERAND (targ, 0), 1); TREE_HAS_CONSTRUCTOR (targ) = 0; ! return build_up_reference (type, temp, flags, 1); } /* Let &* cancel out to simplify resulting code. *************** *** 288,298 **** on the d parameter. The below could have been avoided, if the flags ! were down in the tree, not sure why they are not. */ /* The below code may have to be propagated to other parts of this switch. */ if (TREE_READONLY (targ) && !TREE_READONLY (arg) && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL) ! && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE) { TREE_READONLY (arg) = TREE_READONLY (targ); } --- 289,301 ---- on the d parameter. The below could have been avoided, if the flags ! were down in the tree, not sure why they are not. (mrs) */ /* The below code may have to be propagated to other parts of this switch. */ if (TREE_READONLY (targ) && !TREE_READONLY (arg) && (TREE_CODE (arg) == PARM_DECL || TREE_CODE (arg) == VAR_DECL) ! && TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE ! && (TYPE_READONLY (target_type) && checkconst)) { + arg = copy_node (arg); TREE_READONLY (arg) = TREE_READONLY (targ); } *************** *** 354,359 **** --- 357,399 ---- { error ("address of `this' not available"); + #if 0 + /* This code makes the following core dump the compiler on a sun4, + if the code below is used. + + class e_decl; + class a_decl; + typedef a_decl* a_ref; + + class a_s { + public: + a_s(); + void* append(a_ref& item); + }; + class a_decl { + public: + a_decl (e_decl *parent); + a_s generic_s; + a_s decls; + e_decl* parent; + }; + + class e_decl { + public: + e_decl(); + a_s implementations; + }; + + void foobar(void *); + + a_decl::a_decl(e_decl *parent) { + parent->implementations.append(this); + } + */ + TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */ put_var_into_stack (targ); + #else + return error_mark_node; + #endif break; } *************** *** 361,365 **** case VAR_DECL: case CONST_DECL: ! if (TREE_REGDECL (targ) && !TREE_ADDRESSABLE (targ)) warning ("address needed to build reference for `%s', which is declared `register'", IDENTIFIER_POINTER (DECL_NAME (targ))); --- 401,405 ---- case VAR_DECL: case CONST_DECL: ! if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)) warning ("address needed to build reference for `%s', which is declared `register'", IDENTIFIER_POINTER (DECL_NAME (targ))); *************** *** 374,378 **** { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1), ! LOOKUP_PROTECT); rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1)); --- 414,418 ---- { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1), ! LOOKUP_PROTECT, checkconst); rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1)); *************** *** 384,388 **** { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0), ! LOOKUP_PROTECT); rval = build (COMPOUND_EXPR, type, arg, real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0)); --- 424,428 ---- { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0), ! LOOKUP_PROTECT, checkconst); rval = build (COMPOUND_EXPR, type, arg, real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0)); *************** *** 393,402 **** return build (COND_EXPR, type, TREE_OPERAND (targ, 0), ! build_up_reference (type, TREE_OPERAND (targ, 1), LOOKUP_PROTECT), ! build_up_reference (type, TREE_OPERAND (targ, 2), LOOKUP_PROTECT)); case WITH_CLEANUP_EXPR: return build (WITH_CLEANUP_EXPR, type, ! build_up_reference (type, TREE_OPERAND (targ, 0), LOOKUP_PROTECT), 0, TREE_OPERAND (targ, 2)); --- 433,445 ---- return build (COND_EXPR, type, TREE_OPERAND (targ, 0), ! build_up_reference (type, TREE_OPERAND (targ, 1), ! LOOKUP_PROTECT, checkconst), ! build_up_reference (type, TREE_OPERAND (targ, 2), ! LOOKUP_PROTECT, checkconst)); case WITH_CLEANUP_EXPR: return build (WITH_CLEANUP_EXPR, type, ! build_up_reference (type, TREE_OPERAND (targ, 0), ! LOOKUP_PROTECT, checkconst), 0, TREE_OPERAND (targ, 2)); *************** *** 474,479 **** done_but_maybe_warn: ! if (TREE_READONLY (arg) ! && ! TYPE_READONLY (target_type)) readonly_warning_or_error (arg, "conversion to reference"); --- 517,521 ---- done_but_maybe_warn: ! if (checkconst && TREE_READONLY (arg) && ! TYPE_READONLY (target_type)) readonly_warning_or_error (arg, "conversion to reference"); *************** *** 495,498 **** --- 537,541 ---- If it is ERROR_MARK_NODE, it means the conversion is implicit, and that temporaries may be created. + Make sure the use of user-defined conversion operators is un-ambiguous. Otherwise, DECL is a _DECL node which can be used in error reporting. */ tree *************** *** 600,604 **** if (decl == error_mark_node) flags |= LOOKUP_PROTECTED_OK; ! return build_up_reference (reftype, expr, flags); } --- 643,647 ---- if (decl == error_mark_node) flags |= LOOKUP_PROTECTED_OK; ! return build_up_reference (reftype, expr, flags, decl!=NULL_TREE); } *************** *** 606,610 **** if (TYPE_HAS_CONSTRUCTOR (type)) { ! tree init = build_method_call (NULL_TREE, TYPE_IDENTIFIER (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), LOOKUP_NORMAL); tree rval; --- 649,655 ---- if (TYPE_HAS_CONSTRUCTOR (type)) { ! tree init = build_method_call (NULL_TREE, constructor_name (type), ! build_tree_list (NULL_TREE, expr), ! TYPE_BINFO (type), LOOKUP_NORMAL); tree rval; *************** *** 614,623 **** if (decl == error_mark_node) flags |= LOOKUP_PROTECTED_OK; ! return build_up_reference (reftype, rval, flags); } assert (form != OFFSET_TYPE); ! error ("cannot convert to a reference type"); return error_mark_node; --- 659,671 ---- if (decl == error_mark_node) flags |= LOOKUP_PROTECTED_OK; ! return build_up_reference (reftype, rval, flags, decl!=NULL_TREE); } assert (form != OFFSET_TYPE); ! /* This is in two pieces for now, because pointer to first becomes ! invalid once type_as_string is called again. */ ! error ("cannot convert type `%s'", type_as_string (intype)); ! error (" to type `%s'", type_as_string (reftype)); return error_mark_node; *************** *** 688,692 **** register tree tem = make_node (REAL_CST); TREE_TYPE (tem) = type; ! TREE_REAL_CST (tem) = 0; return tem; } --- 736,740 ---- register tree tem = make_node (REAL_CST); TREE_TYPE (tem) = type; ! TREE_REAL_CST (tem) = REAL_VALUE_ATOF ("0.0"); return tem; } *************** *** 737,741 **** } ! if (outprec >= inprec) return build1 (NOP_EXPR, type, expr); --- 785,802 ---- } ! /* If we are widening the type, put in an explicit conversion. ! Similarly if we are not changing the width. However, if this is ! a logical operation that just returns 0 or 1, we can change the ! type of the expression (see below). */ ! ! if (TREE_CODE_CLASS (ex_form) == '<' ! || ex_form == TRUTH_AND_EXPR || ex_form == TRUTH_ANDIF_EXPR ! || ex_form == TRUTH_OR_EXPR || ex_form == TRUTH_ORIF_EXPR ! || ex_form == TRUTH_NOT_EXPR) ! { ! TREE_TYPE (expr) = type; ! return expr; ! } ! else if (outprec >= inprec) return build1 (NOP_EXPR, type, expr); *************** *** 832,841 **** /* Don't do unsigned arithmetic where signed was wanted, or vice versa. ! Exception: if the original operands were unsigned ! then can safely do the work as unsigned. And we may need to do it as unsigned if we truncate to the original size. */ ! typex = ((TREE_UNSIGNED (TREE_TYPE (expr)) ! || TREE_UNSIGNED (TREE_TYPE (arg0))) ? unsigned_type (typex) : signed_type (typex)); return convert (type, --- 893,908 ---- /* Don't do unsigned arithmetic where signed was wanted, or vice versa. ! Exception 1: if we will eventually truncate ! the result, then do the work as unsigned; ! this can prevent unnecessary sign-extension. ! Exception 2: if either of the original operands were ! unsigned then can safely do the work as unsigned. And we may need to do it as unsigned if we truncate to the original size. */ ! typex = (((outprec <= TYPE_PRECISION (typex) ! && TREE_UNSIGNED (type)) ! || TREE_UNSIGNED (TREE_TYPE (expr)) ! || TREE_UNSIGNED (TREE_TYPE (arg0)) ! || TREE_UNSIGNED (TREE_TYPE (arg1))) ? unsigned_type (typex) : signed_type (typex)); return convert (type, *************** *** 849,868 **** break; - case EQ_EXPR: - case NE_EXPR: - case GT_EXPR: - case GE_EXPR: - case LT_EXPR: - case LE_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_NOT_EXPR: - /* If we want result of comparison converted to a byte, - we can just regard it as a byte, since it is 0 or 1. */ - TREE_TYPE (expr) = type; - return expr; - case NEGATE_EXPR: case BIT_NOT_EXPR: --- 916,919 ---- *************** *** 884,888 **** /* Don't do unsigned arithmetic where signed was wanted, or vice versa. */ ! typex = (TREE_UNSIGNED (TREE_TYPE (expr)) ? unsigned_type (typex) : signed_type (typex)); return convert (type, --- 935,941 ---- /* Don't do unsigned arithmetic where signed was wanted, or vice versa. */ ! typex = (((outprec <= TYPE_PRECISION (typex) ! && TREE_UNSIGNED (type)) ! || TREE_UNSIGNED (TREE_TYPE (expr))) ? unsigned_type (typex) : signed_type (typex)); return convert (type, *************** *** 927,931 **** /* Don't do unsigned arithmetic where signed was wanted, or vice versa. */ ! typex = (TREE_UNSIGNED (TREE_TYPE (expr)) ? unsigned_type (typex) : signed_type (typex)); return convert (type, --- 980,986 ---- /* Don't do unsigned arithmetic where signed was wanted, or vice versa. */ ! typex = (((outprec <= TYPE_PRECISION (typex) ! && TREE_UNSIGNED (type)) ! || TREE_UNSIGNED (TREE_TYPE (expr))) ? unsigned_type (typex) : signed_type (typex)); return convert (type, *************** *** 935,938 **** --- 990,1000 ---- convert (typex, arg2)))); } + else + /* It is sometimes worthwhile + to push the narrowing down through the conditional. */ + return fold (build (COND_EXPR, type, + TREE_OPERAND (expr, 0), + convert (type, TREE_OPERAND (expr, 1)), + convert (type, TREE_OPERAND (expr, 2)))); } } *************** *** 980,983 **** --- 1042,1046 ---- tree type, expr; char **msgp; + int protect; { tree basetype = type; *************** *** 1174,1178 **** fntype = TREE_TYPE (function); ! if (TREE_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL) function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); else --- 1237,1241 ---- fntype = TREE_TYPE (function); ! if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL) function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); else *************** *** 1196,1200 **** { register tree intype = TREE_TYPE (expr); - register enum tree_code form = TREE_CODE (intype); tree ptr_type; tree type, rval; --- 1259,1262 ---- *************** *** 1288,1293 **** register enum tree_code code = TREE_CODE (type); ! if (type == TREE_TYPE (expr) || TREE_CODE (expr) == ERROR_MARK) return expr; if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; --- 1350,1358 ---- register enum tree_code code = TREE_CODE (type); ! if (type == TREE_TYPE (expr) ! || TREE_CODE (expr) == ERROR_MARK) return expr; + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold (build1 (NOP_EXPR, type, expr)); if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) return error_mark_node; *************** *** 1362,1366 **** if (TYPE_HAS_CONSTRUCTOR (type)) { ! tree rval = build_method_call (NULL_TREE, TYPE_IDENTIFIER (type), build_tree_list (NULL_TREE, e), TYPE_BINFO (type), conversion ? LOOKUP_NO_CONVERSION : 0); --- 1427,1431 ---- if (TYPE_HAS_CONSTRUCTOR (type)) { ! tree rval = build_method_call (NULL_TREE, constructor_name (type), build_tree_list (NULL_TREE, e), TYPE_BINFO (type), conversion ? LOOKUP_NO_CONVERSION : 0); *************** *** 1415,1419 **** { tree rval; ! tree init = build_method_call (NULL_TREE, TYPE_IDENTIFIER (type), build_tree_list (NULL_TREE, e), TYPE_BINFO (type), LOOKUP_NORMAL); if (init == error_mark_node) { --- 1480,1486 ---- { tree rval; ! tree init = build_method_call (NULL_TREE, constructor_name (type), ! build_tree_list (NULL_TREE, e), ! TYPE_BINFO (type), LOOKUP_NORMAL); if (init == error_mark_node) { *************** *** 1487,1491 **** flags = LOOKUP_NORMAL; ! rval = build_method_call (first_arg, typename, NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) { --- 1554,1559 ---- flags = LOOKUP_NORMAL; ! rval = build_method_call (first_arg, constructor_name (typename), ! NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) { *************** *** 1497,1501 **** { expr = build_up_reference (build_reference_type (TREE_TYPE (expr)), expr, ! LOOKUP_COMPLAIN); TREE_VALUE (TREE_OPERAND (rval, 1)) = build_unary_op (ADDR_EXPR, expr, 0); } --- 1565,1569 ---- { expr = build_up_reference (build_reference_type (TREE_TYPE (expr)), expr, ! LOOKUP_COMPLAIN, 1); TREE_VALUE (TREE_OPERAND (rval, 1)) = build_unary_op (ADDR_EXPR, expr, 0); } *************** *** 1614,1618 **** else flags = LOOKUP_NORMAL; ! rval = build_method_call (first_arg, typename, NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) { --- 1682,1687 ---- else flags = LOOKUP_NORMAL; ! rval = build_method_call (first_arg, constructor_name (typename), ! NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) { *************** *** 1625,1632 **** if (IS_AGGR_TYPE (type)) { ! tree init = build_method_call (NULL_TREE, TYPE_IDENTIFIER (type), build_tree_list (NULL_TREE, rval), NULL_TREE, LOOKUP_NORMAL); tree temp = build_cplus_new (type, init, 1); return build_up_reference (TYPE_REFERENCE_TO (type), temp, ! LOOKUP_COMPLAIN); } return convert (xtype, rval); --- 1694,1703 ---- if (IS_AGGR_TYPE (type)) { ! tree init = build_method_call (NULL_TREE, ! constructor_name (type), ! build_tree_list (NULL_TREE, rval), NULL_TREE, LOOKUP_NORMAL); tree temp = build_cplus_new (type, init, 1); return build_up_reference (TYPE_REFERENCE_TO (type), temp, ! LOOKUP_COMPLAIN, 1); } return convert (xtype, rval); diff -rc2N gcc-2.2.2/cp-decl.c gcc-2.3.1/cp-decl.c *** gcc-2.2.2/cp-decl.c Thu Jun 11 00:14:00 1992 --- gcc-2.3.1/cp-decl.c Sat Oct 17 17:46:06 1992 *************** *** 30,33 **** --- 30,34 ---- #include "config.h" #include "tree.h" + #include "rtl.h" #include "flags.h" #include "cp-tree.h" *************** *** 40,46 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - extern struct obstack permanent_obstack; --- 41,44 ---- *************** *** 132,135 **** --- 130,142 ---- } while (0) + /* These are defined in their respective cp-* files. */ + extern void init_search_processing (); + extern void init_class_processing (); + extern void init_init_processing (); + extern void init_exception_processing (); + extern void init_gc_processing (); + extern void init_cadillac (); + + /* static */ void grokclassfn (); /* static */ tree grokoptypename (); *************** *** 147,152 **** static void expand_static_init (); static void deactivate_exception_cleanups (); void adjust_type_value (); - static void push_overload_decl_1 (); tree finish_table (); --- 154,159 ---- static void expand_static_init (); static void deactivate_exception_cleanups (); + static void revert_static_member_fn (); void adjust_type_value (); tree finish_table (); *************** *** 188,191 **** --- 195,208 ---- tree long_double_type_node; + tree intQI_type_node; + tree intHI_type_node; + tree intSI_type_node; + tree intDI_type_node; + + tree unsigned_intQI_type_node; + tree unsigned_intHI_type_node; + tree unsigned_intSI_type_node; + tree unsigned_intDI_type_node; + /* a VOID_TYPE node, and the same, packaged in a TREE_LIST. */ *************** *** 290,301 **** tree abort_fndecl; /* If original DECL_RESULT of current function was a register, but due to being an addressable named return value, would up on the stack, this variable holds the named return value's original location. */ ! struct rtx_def *original_result_rtx; /* Sequence of insns which represents base initialization. */ ! struct rtx_def *base_init_insns; /* C++: Keep these around to reduce calls to `get_identifier'. --- 307,320 ---- tree abort_fndecl; + extern rtx cleanup_label, return_label; + /* If original DECL_RESULT of current function was a register, but due to being an addressable named return value, would up on the stack, this variable holds the named return value's original location. */ ! rtx original_result_rtx; /* Sequence of insns which represents base initialization. */ ! rtx base_init_insns; /* C++: Keep these around to reduce calls to `get_identifier'. *************** *** 387,394 **** --- 406,415 ---- static tree shadowed_labels; + #if 0 /* Not needed by C++ */ /* Nonzero when store_parm_decls is called indicates a varargs function. Value not meaningful after store_parm_decls. */ static int c_function_varargs; + #endif /* The FUNCTION_DECL for the function currently being compiled, *************** *** 413,416 **** --- 434,442 ---- tree current_function_return_value; + /* Nonzero means warn about multiple (redundant) decls for the same single + variable or function. */ + + extern int warn_redundant_decls; + /* Set to nonzero by `grokdeclarator' for a function whose return type is defaulted, if warnings for this are desired. */ *************** *** 451,454 **** --- 477,484 ---- int current_function_obstack_usage; + + /* Flag used when debugging cp-spew.c */ + + extern int spew_debug; /* Allocate a level of searching. */ *************** *** 541,544 **** --- 571,578 ---- tree blocks; + /* The BLOCK node for this level, if one has been preallocated. + If 0, the BLOCK is allocated (if needed) when the level is popped. */ + tree this_block; + /* The binding level which this one is contained in (inherits from). */ struct binding_level *level_chain; *************** *** 574,578 **** unsigned accept_any : 1; ! /* Three bits left for this word. */ #if PARANOID --- 608,619 ---- unsigned accept_any : 1; ! /* Nonzero if this level is for completing a template class definition ! inside a binding level that temporarily binds the parameters. This ! means that definitions here should not be popped off when unwinding ! this binding level. (Not actually implemented this way, ! unfortunately.) */ ! unsigned pseudo_global : 1; ! ! /* Two bits left for this word. */ #if PARANOID *************** *** 617,621 **** static int n; if (++n < 3) ! return 1; assert (global_binding_level != 0); assert (current_binding_level != 0); --- 658,662 ---- static int n; if (++n < 3) ! return; assert (global_binding_level != 0); assert (current_binding_level != 0); *************** *** 635,639 **** assert (global_binding_level->depth == 0); assert (global_binding_level->level_chain == 0); ! return 1; } --- 676,680 ---- assert (global_binding_level->depth == 0); assert (global_binding_level->level_chain == 0); ! return; } *************** *** 652,655 **** --- 693,697 ---- push_binding_level (newlevel, tag_transparent, keep) struct binding_level *newlevel; + int tag_transparent, keep; { binding_levels_sane(); *************** *** 658,662 **** #ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); ! fprintf (stderr, "pushing binding level %x\n", newlevel); #endif *newlevel = clear_binding_level; --- 700,706 ---- #ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); ! fprintf (stderr, "pushing binding level "); ! fprintf (stderr, HOST_PTR_PRINTF, newlevel); ! fprintf (stderr, "\n"); #endif *newlevel = clear_binding_level; *************** *** 692,699 **** #ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); ! fprintf (stderr, "popping binding level %x\n", current_binding_level); #endif if (global_binding_level) ! assert (current_binding_level != global_binding_level); /* Pop the current level, and free the structure for reuse. */ { --- 736,749 ---- #ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); ! fprintf (stderr, "popping binding level "); ! fprintf (stderr, HOST_PTR_PRINTF, current_binding_level); ! fprintf (stderr, "\n"); #endif if (global_binding_level) ! { ! /* cannot pop a level, if there are none left to pop. */ ! if (current_binding_level == global_binding_level) ! my_friendly_abort (123); ! } /* Pop the current level, and free the structure for reuse. */ { *************** *** 741,746 **** kept_level_p () { ! return (current_binding_level->keep ! || current_binding_level->names != 0); } --- 791,799 ---- kept_level_p () { ! return (current_binding_level->blocks != 0 ! || current_binding_level->keep ! || current_binding_level->names != 0 ! || (current_binding_level->tags != 0 ! && !current_binding_level->tag_transparent)); } *************** *** 782,785 **** --- 835,850 ---- } + void + declare_pseudo_global_level () + { + current_binding_level->pseudo_global = 1; + } + + int + pseudo_global_level_p () + { + return current_binding_level->pseudo_global; + } + /* Enter a new binding level. If TAG_TRANSPARENT is nonzero, do so only for the name space of variables, *************** *** 833,842 **** current_binding_level->keep = 2; clear_last_expr (); ! #if 0 ! /* Don't call push_momentary here! It will cause cleanups ! to be allocated on the momentary obstack, and they ! will be overwritten by the next statement. */ ! push_momentary (); ! #endif expand_start_bindings (0); } --- 898,906 ---- current_binding_level->keep = 2; clear_last_expr (); ! ! /* Note we don't call push_momentary() here. Otherwise, it would cause ! cleanups to be allocated on the momentary obstack, and they will be ! overwritten by the next statement. */ ! expand_start_bindings (0); } *************** *** 881,884 **** --- 945,949 ---- tree block = 0; tree decl; + int block_previously_created; #ifdef DEBUG_CP_BINDING_LEVELS *************** *** 951,957 **** create a BLOCK to record them for the life of this function. */ ! if (keep == 1 || functionbody > 0) ! block = build_block (keep ? decls : 0, keep ? tags : 0, ! subblocks, 0, 0); /* In each subblock, record that this is its superior. */ --- 1016,1032 ---- create a BLOCK to record them for the life of this function. */ ! block = 0; ! block_previously_created = (current_binding_level->this_block != 0); ! if (block_previously_created) ! block = current_binding_level->this_block; ! else if (keep == 1 || functionbody) ! block = make_node (BLOCK); ! if (block != 0) ! { ! BLOCK_VARS (block) = decls; ! BLOCK_TYPE_TAGS (block) = tags; ! BLOCK_SUBBLOCKS (block) = subblocks; ! remember_end_note (block); ! } /* In each subblock, record that this is its superior. */ *************** *** 969,973 **** /* If the ident. was used or addressed via a local extern decl, don't forget that fact. */ ! if (TREE_EXTERNAL (link)) { if (TREE_USED (link)) --- 1044,1048 ---- /* If the ident. was used or addressed via a local extern decl, don't forget that fact. */ ! if (DECL_EXTERNAL (link)) { if (TREE_USED (link)) *************** *** 997,1000 **** --- 1072,1082 ---- if (functionbody) { + /* If this is the top level block of a function, + the vars are the function's parameters. + Don't leave them in the BLOCK because they are + found in the FUNCTION_DECL instead. */ + + BLOCK_VARS (block) = 0; + /* Clear out the definitions of all label names, since their scopes end here. */ *************** *** 1002,1016 **** for (link = named_labels; link; link = TREE_CHAIN (link)) { ! if (DECL_SOURCE_LINE (TREE_VALUE (link)) == 0) { error ("label `%s' used somewhere above but not defined", ! IDENTIFIER_POINTER (DECL_NAME (TREE_VALUE (link)))); /* Avoid crashing later. */ ! define_label (input_filename, 1, DECL_NAME (TREE_VALUE (link))); } ! else if (warn_unused && !TREE_USED (TREE_VALUE (link))) ! warning_with_decl (TREE_VALUE (link), "label `%s' defined but not used"); ! SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)), 0); } --- 1084,1105 ---- for (link = named_labels; link; link = TREE_CHAIN (link)) { ! register tree label = TREE_VALUE (link); ! ! if (DECL_INITIAL (label) == 0) { error ("label `%s' used somewhere above but not defined", ! IDENTIFIER_POINTER (DECL_NAME (label))); /* Avoid crashing later. */ ! define_label (input_filename, 1, DECL_NAME (label)); } ! else if (warn_unused && !TREE_USED (label)) ! warning_with_decl (label, "label `%s' defined but not used"); ! SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), 0); ! ! /* Put the labels into the "variables" of the ! top-level block, so debugger can see them. */ ! TREE_CHAIN (label) = BLOCK_VARS (block); ! BLOCK_VARS (block) = label; } *************** *** 1038,1053 **** pop_binding_level (); ! if (functionbody > 0) { ! DECL_INITIAL (current_function_decl) = block; ! /* If this is the top level block of a function, ! the vars are the function's parameters. ! Don't leave them in the BLOCK because they are ! found in the FUNCTION_DECL instead. */ ! BLOCK_VARS (block) = 0; } - else if (block) - current_binding_level->blocks - = chainon (current_binding_level->blocks, block); /* If we did not make a block for the level just exited, any blocks made for inner levels --- 1127,1138 ---- pop_binding_level (); ! if (functionbody) ! DECL_INITIAL (current_function_decl) = block; ! else if (block) { ! if (!block_previously_created) ! current_binding_level->blocks ! = chainon (current_binding_level->blocks, block); } /* If we did not make a block for the level just exited, any blocks made for inner levels *************** *** 1082,1085 **** --- 1167,1207 ---- } + /* Delete the node BLOCK from the current binding level. + This is used for the block inside a stmt expr ({...}) + so that the block can be reinserted where appropriate. */ + + void + delete_block (block) + tree block; + { + tree t; + if (current_binding_level->blocks == block) + current_binding_level->blocks = TREE_CHAIN (block); + for (t = current_binding_level->blocks; t;) + { + if (TREE_CHAIN (t) == block) + TREE_CHAIN (t) = TREE_CHAIN (block); + else + t = TREE_CHAIN (t); + } + TREE_CHAIN (block) = NULL; + /* Clear TREE_USED which is always set by poplevel. + The flag is set again if insert_block is called. */ + TREE_USED (block) = 0; + } + + /* Insert BLOCK at the end of the list of subblocks of the + current binding level. This is used when a BIND_EXPR is expanded, + to handle the BLOCK node inside the BIND_EXPR. */ + + void + insert_block (block) + tree block; + { + TREE_USED (block) = 1; + current_binding_level->blocks + = chainon (current_binding_level->blocks, block); + } + /* Add BLOCK to the current list of blocks for this binding contour. */ void *************** *** 1091,1094 **** --- 1213,1226 ---- } + /* Set the BLOCK node for the innermost scope + (the one we are currently in). */ + + void + set_block (block) + register tree block; + { + current_binding_level->this_block = block; + } + /* Do a pushlevel for class declarations. */ void *************** *** 1158,1162 **** #ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); ! fprintf (stderr, "popping class binding level %x\n", level); memset (level, 0x69, sizeof (*level)); debug_bindings_indentation -= 4; --- 1290,1296 ---- #ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); ! fprintf (stderr, "popping class binding level "); ! fprintf (stderr, HOST_PTR_PRINTF, level); ! fprintf (stderr, "\n"); memset (level, 0x69, sizeof (*level)); debug_bindings_indentation -= 4; *************** *** 1180,1185 **** tree t; int i = 0, len; ! fprintf (stderr, " blocks=%x n_incomplete=%d parm_flag=%d keep=%d", ! lvl->blocks, lvl->n_incomplete, lvl->parm_flag, lvl->keep); if (lvl->tag_transparent) fprintf (stderr, " tag-transparent"); --- 1314,1321 ---- tree t; int i = 0, len; ! fprintf (stderr, " blocks="); ! fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks); ! fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d", ! lvl->n_incomplete, lvl->parm_flag, lvl->keep); if (lvl->tag_transparent) fprintf (stderr, " tag-transparent"); *************** *** 1305,1309 **** for (level = stack; level != global_binding_level; level = level->level_chain) { ! fprintf (stderr, "binding level %x\n", level); print_binding_level (level); } --- 1441,1447 ---- for (level = stack; level != global_binding_level; level = level->level_chain) { ! fprintf (stderr, "binding level "); ! fprintf (stderr, HOST_PTR_PRINTF, level); ! fprintf (stderr, "\n"); print_binding_level (level); } *************** *** 1314,1320 **** { struct binding_level *b; ! fprintf (stderr, "current_binding_level=%8x\n", current_binding_level); ! fprintf (stderr, "class_binding_level= %8x\n", class_binding_level); ! fprintf (stderr, "global_binding_level= %8x\n", global_binding_level); if (class_binding_level) { --- 1452,1462 ---- { struct binding_level *b; ! fprintf (stderr, "current_binding_level="); ! fprintf (stderr, HOST_PTR_PRINTF, current_binding_level); ! fprintf (stderr, "\nclass_binding_level="); ! fprintf (stderr, HOST_PTR_PRINTF, class_binding_level); ! fprintf (stderr, "\nglobal_binding_level="); ! fprintf (stderr, HOST_PTR_PRINTF, global_binding_level); ! fprintf (stderr, "\n"); if (class_binding_level) { *************** *** 1584,1587 **** --- 1726,1734 ---- } + if (b == global_binding_level) + b->tags = perm_tree_cons (name, type, b->tags); + else + b->tags = saveable_tree_cons (name, type, b->tags); + if (name) { *************** *** 1591,1599 **** TYPE_NAME (type) = name; - if (b == global_binding_level) - b->tags = perm_tree_cons (name, type, b->tags); - else - b->tags = saveable_tree_cons (name, type, b->tags); - /* Do C++ gratuitous typedefing. */ if (IDENTIFIER_TYPE_VALUE (name) != type --- 1738,1741 ---- *************** *** 1619,1622 **** --- 1761,1766 ---- d = build_decl (TYPE_DECL, name, type); #endif + /* mark the binding layer marker as internal. (mrs) */ + DECL_SOURCE_LINE (d) = 0; set_identifier_type_value (name, type); } *************** *** 1629,1632 **** --- 1773,1777 ---- again--pushdecl is only for pushing new decls. */ if (! ANON_AGGRNAME_P (name) + && TYPE_NAME (type) && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL || lookup_name (name, 1) != TYPE_NAME (type))) *************** *** 1679,1702 **** CLASSTYPE_TAGS (current_class_type) = b->tags; } ! if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) ! /* Use the canonical TYPE_DECL for this node. */ ! TYPE_STUB_DECL (type) = TYPE_NAME (type); ! else ! { ! /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE ! will be the tagged type we just added to the current ! binding level. This fake NULL-named TYPE_DECL node helps ! dwarfout.c to know when it needs to output a a ! representation of a tagged type, and it also gives us a ! convenient place to record the "scope start" address for ! the tagged type. */ #if 0 /* not yet, should get fixed properly later */ ! TYPE_STUB_DECL (type) = pushdecl (make_type_decl (NULL, type)); #else ! TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL, type)); #endif - } } } --- 1824,1847 ---- CLASSTYPE_TAGS (current_class_type) = b->tags; } + } ! if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) ! /* Use the canonical TYPE_DECL for this node. */ ! TYPE_STUB_DECL (type) = TYPE_NAME (type); ! else ! { ! /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE ! will be the tagged type we just added to the current ! binding level. This fake NULL-named TYPE_DECL node helps ! dwarfout.c to know when it needs to output a ! representation of a tagged type, and it also gives us a ! convenient place to record the "scope start" address for ! the tagged type. */ #if 0 /* not yet, should get fixed properly later */ ! TYPE_STUB_DECL (type) = pushdecl (make_type_decl (NULL, type)); #else ! TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL, type)); #endif } } *************** *** 1721,1725 **** clear_anon_tags () { ! register struct binding_level *b = current_binding_level; register tree tags; static int last_cnt = 0; --- 1866,1870 ---- clear_anon_tags () { ! register struct binding_level *b; register tree tags; static int last_cnt = 0; *************** *** 1729,1733 **** return; ! while (b->tag_transparent) b = b->level_chain; tags = b->tags; while (tags) --- 1874,1880 ---- return; ! b = current_binding_level; ! while (b->tag_transparent) ! b = b->level_chain; tags = b->tags; while (tags) *************** *** 1763,1778 **** is METHOD_TYPE. Change that to FUNCTION_TYPE, and proceed. */ ! if (TREE_CODE (f1) == METHOD_TYPE ! && DECL_STATIC_FUNCTION_P (olddecl)) ! { ! tree n1; ! p1 = TREE_CHAIN (p1); ! n1 = build_function_type (TREE_TYPE (f1), p1); ! n1 = build_type_variant (n1, TYPE_READONLY (f1), TYPE_VOLATILE (f1)); ! n1 = build_exception_variant (TYPE_METHOD_BASETYPE (f1), n1, TYPE_RAISES_EXCEPTIONS (f1)); ! TREE_TYPE (newdecl) = n1; ! f1 = n1; ! DECL_STATIC_FUNCTION_P (newdecl) = 1; ! } /* Here we must take care of the case where new default parameters are specified. Also, warn if an old --- 1910,1919 ---- is METHOD_TYPE. Change that to FUNCTION_TYPE, and proceed. */ ! if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl)) ! revert_static_member_fn (&f1, &newdecl, &p1); ! else if (TREE_CODE (f2) == METHOD_TYPE ! && DECL_STATIC_FUNCTION_P (newdecl)) ! revert_static_member_fn (&f2, &olddecl, &p2); ! /* Here we must take care of the case where new default parameters are specified. Also, warn if an old *************** *** 1816,1821 **** { extern struct obstack permanent_obstack; ! int types_match; ! int new_is_definition; if (TREE_CODE (olddecl) == TREE_LIST --- 1957,1965 ---- { extern struct obstack permanent_obstack; ! unsigned olddecl_uid = DECL_UID (olddecl); ! int olddecl_friend = 0, types_match; ! int new_defines_function; ! register unsigned saved_old_decl_uid; ! register int saved_old_decl_friend_p; if (TREE_CODE (olddecl) == TREE_LIST *************** *** 1859,1863 **** } else ! types_match = decls_match (newdecl, olddecl); if ((TREE_TYPE (newdecl) && TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK) --- 2003,2011 ---- } else ! { ! if (TREE_CODE (olddecl) != TREE_LIST) ! olddecl_friend = DECL_LANG_SPECIFIC (olddecl) && DECL_FRIEND_P (olddecl); ! types_match = decls_match (newdecl, olddecl); ! } if ((TREE_TYPE (newdecl) && TREE_CODE (TREE_TYPE (newdecl)) == ERROR_MARK) *************** *** 1954,1961 **** } ! if (type == float_type_node ! || (TREE_CODE (type) == INTEGER_TYPE ! && (TYPE_PRECISION (type) ! < TYPE_PRECISION (integer_type_node)))) { error ("An argument type that has a default promotion"); --- 2102,2107 ---- } ! if (TYPE_MAIN_VARIANT (type) == float_type_node ! || C_PROMOTING_INTEGER_TYPE_P (type)) { error ("An argument type that has a default promotion"); *************** *** 2005,2009 **** if (DECL_NAME (olddecl) != NULL_TREE) error_with_decl (olddecl, ! "here is the previous declaration of `%s'"); } else if (TREE_CODE (olddecl) == FUNCTION_DECL --- 2151,2158 ---- if (DECL_NAME (olddecl) != NULL_TREE) error_with_decl (olddecl, ! (DECL_INITIAL (olddecl) ! && current_binding_level == global_binding_level) ! ? "`%s' previously defined here" ! : "`%s' previously declared here"); } else if (TREE_CODE (olddecl) == FUNCTION_DECL *************** *** 2044,2052 **** } Thing; */ assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl)); } ! new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL ! && DECL_INITIAL (newdecl) != 0); /* Copy all the DECL_... slots specified in the new decl --- 2193,2213 ---- } Thing; */ + #if 0 assert (DECL_IGNORED_P (olddecl) == DECL_IGNORED_P (newdecl)); + #endif } ! /* Special handling ensues if new decl is a function definition. */ ! new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL ! && DECL_INITIAL (newdecl) != 0); ! ! /* Optionally warn about more than one declaration for the same name, ! but don't warn about a function declaration followed by a definition. */ ! if (warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 ! && !(new_defines_function && DECL_INITIAL (olddecl) == 0)) ! { ! warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope"); ! warning_with_decl (olddecl, "previous declaration of `%s'"); ! } /* Copy all the DECL_... slots specified in the new decl *************** *** 2061,2065 **** if (TREE_CODE (newdecl) == VAR_DECL) ! DECL_EXTERNAL (newdecl) |= DECL_EXTERNAL (olddecl); /* Do this after calling `common_type' so that default parameters don't confuse us. */ --- 2222,2226 ---- if (TREE_CODE (newdecl) == VAR_DECL) ! DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); /* Do this after calling `common_type' so that default parameters don't confuse us. */ *************** *** 2127,2134 **** /* Merge the storage class information. */ ! if (TREE_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); ! TREE_EXTERNAL (newdecl) = TREE_EXTERNAL (olddecl); /* For functions, static overrides non-static. */ --- 2288,2295 ---- /* Merge the storage class information. */ ! if (DECL_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); ! DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); /* For functions, static overrides non-static. */ *************** *** 2149,2168 **** { TREE_STATIC (olddecl) = TREE_STATIC (newdecl); - TREE_EXTERNAL (olddecl) = 0; /* A `const' which was not declared `extern' and is in static storage is invisible. */ if (TREE_CODE (newdecl) == VAR_DECL && TREE_READONLY (newdecl) && TREE_STATIC (newdecl) ! && ! DECL_EXTERNAL (newdecl)) TREE_PUBLIC (newdecl) = 0; TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); } /* If either decl says `inline', this fn is inline, unless its definition was passed already. */ ! TREE_INLINE (olddecl) |= TREE_INLINE (newdecl); if (TREE_CODE (newdecl) == FUNCTION_DECL) { ! if (new_is_definition) /* If defining a function declared with other language linkage, use the previously declared language linkage. */ --- 2310,2331 ---- { TREE_STATIC (olddecl) = TREE_STATIC (newdecl); /* A `const' which was not declared `extern' and is in static storage is invisible. */ if (TREE_CODE (newdecl) == VAR_DECL && TREE_READONLY (newdecl) && TREE_STATIC (newdecl) ! && ! DECL_THIS_EXTERN (newdecl)) TREE_PUBLIC (newdecl) = 0; TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); } + /* If either decl says `inline', this fn is inline, unless its definition was passed already. */ ! if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0) ! DECL_INLINE (olddecl) = 1; ! DECL_INLINE (newdecl) = DECL_INLINE (olddecl); if (TREE_CODE (newdecl) == FUNCTION_DECL) { ! if (new_defines_function) /* If defining a function declared with other language linkage, use the previously declared language linkage. */ *************** *** 2205,2208 **** --- 2368,2379 ---- #endif + /* We are about to copy the contexts of newdecl into olddecl, so save a + few tidbits of information from olddecl that we may need to restore + after the copying takes place. */ + + saved_old_decl_uid = DECL_UID (olddecl); + saved_old_decl_friend_p + = DECL_LANG_SPECIFIC (olddecl) ? DECL_FRIEND_P (olddecl) : 0; + if (TREE_CODE (newdecl) == FUNCTION_DECL) { *************** *** 2222,2226 **** DECL_MAIN_VARIANT (newdecl) = olddecl; DECL_LANG_SPECIFIC (olddecl) = ol; ! bcopy (nl, ol, sizeof (struct lang_decl)); obstack_free (&permanent_obstack, newdecl); --- 2393,2397 ---- DECL_MAIN_VARIANT (newdecl) = olddecl; DECL_LANG_SPECIFIC (olddecl) = ol; ! bcopy ((char *)nl, (char *)ol, sizeof (struct lang_decl)); obstack_free (&permanent_obstack, newdecl); *************** *** 2250,2253 **** --- 2421,2434 ---- } + DECL_UID (olddecl) = olddecl_uid; + if (olddecl_friend) + DECL_FRIEND_P (olddecl) = 1; + + /* Restore some pieces of information which were originally in olddecl. */ + + DECL_UID (olddecl) = saved_old_decl_uid; + if (DECL_LANG_SPECIFIC (olddecl)) + DECL_FRIEND_P (olddecl) |= saved_old_decl_friend_p; + return 1; } *************** *** 2319,2322 **** --- 2500,2509 ---- #endif + /* Don't change DECL_CONTEXT of virtual methods. */ + if (x != current_function_decl + && (TREE_CODE (x) != FUNCTION_DECL + || !DECL_VIRTUAL_P (x))) + DECL_CONTEXT (x) = current_function_decl; + #if 0 /* not yet, should get fixed properly later */ /* For functions and class static data, we currently look up the encoded *************** *** 2344,2353 **** if (t != 0) { - tree cntxt = t; if (TREE_CODE (t) == PARM_DECL) { if (DECL_CONTEXT (t) == NULL_TREE) fatal ("parse errors have confused me too much"); - cntxt = DECL_CONTEXT (t); } file = DECL_SOURCE_FILE (t); --- 2531,2538 ---- *************** *** 2378,2382 **** a variable `extern const' and then later `const'. */ if (!flag_traditional && TREE_PUBLIC (name) ! && ! TREE_PUBLIC (x) && ! TREE_EXTERNAL (x) && ! TREE_INLINE (x)) { /* Due to interference in memory reclamation (X may be --- 2563,2567 ---- a variable `extern const' and then later `const'. */ if (!flag_traditional && TREE_PUBLIC (name) ! && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) && ! DECL_INLINE (x)) { /* Due to interference in memory reclamation (X may be *************** *** 2438,2447 **** /* Multiple external decls of the same identifier ought to match. */ ! if (TREE_EXTERNAL (x) && IDENTIFIER_GLOBAL_VALUE (name) != 0 ! && (TREE_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))) /* We get warnings about inline functions where they are defined. Avoid duplicate warnings where they are used. */ ! && !TREE_INLINE (x)) { if (! comptypes (TREE_TYPE (x), --- 2623,2632 ---- /* Multiple external decls of the same identifier ought to match. */ ! if (DECL_EXTERNAL (x) && IDENTIFIER_GLOBAL_VALUE (name) != 0 ! && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name)) || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))) /* We get warnings about inline functions where they are defined. Avoid duplicate warnings where they are used. */ ! && !DECL_INLINE (x)) { if (! comptypes (TREE_TYPE (x), *************** *** 2457,2461 **** /* In PCC-compatibility mode, extern decls of vars with no current decl take effect at top level no matter where they are. */ ! if (flag_traditional && TREE_EXTERNAL (x) && lookup_name (name, 0) == 0) b = global_binding_level; --- 2642,2646 ---- /* In PCC-compatibility mode, extern decls of vars with no current decl take effect at top level no matter where they are. */ ! if (flag_traditional && DECL_EXTERNAL (x) && lookup_name (name, 0) == 0) b = global_binding_level; *************** *** 2470,2474 **** A `const' which was not declared `extern' is invisible. */ if (TREE_CODE (x) == VAR_DECL ! && TREE_READONLY (x) && ! DECL_EXTERNAL (x)) TREE_PUBLIC (x) = 0; --- 2655,2659 ---- A `const' which was not declared `extern' is invisible. */ if (TREE_CODE (x) == VAR_DECL ! && TREE_READONLY (x) && ! DECL_THIS_EXTERN (x)) TREE_PUBLIC (x) = 0; *************** *** 2483,2487 **** --- 2668,2680 ---- || t == NULL_TREE || TREE_CODE (t) == TYPE_DECL) + #if 0 + /* This has not be thoroughly tested yet. */ + /* It allows better dwarf debugging. */ + IDENTIFIER_GLOBAL_VALUE (name) + = TREE_CODE_CLASS (TREE_CODE (x)) == 'd' + ? x : build_decl (TYPE_DECL, NULL, TREE_TYPE (x)); + #else IDENTIFIER_GLOBAL_VALUE (name) = x; + #endif /* Don't forget if the function was used via an implicit decl. */ *************** *** 2507,2511 **** if (TREE_PUBLIC (name) && TREE_CODE (x) != TYPE_DECL ! && ! TREE_PUBLIC (x) && ! TREE_EXTERNAL (x)) { if (IDENTIFIER_IMPLICIT_DECL (name)) --- 2700,2704 ---- if (TREE_PUBLIC (name) && TREE_CODE (x) != TYPE_DECL ! && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x)) { if (IDENTIFIER_IMPLICIT_DECL (name)) *************** *** 2525,2531 **** /* If this is an extern function declaration, see if we ! have a global definition for the function. */ if (oldlocal == 0 ! && TREE_EXTERNAL (x) && !TREE_INLINE (x) && oldglobal != 0 && TREE_CODE (x) == FUNCTION_DECL --- 2718,2724 ---- /* If this is an extern function declaration, see if we ! have a global definition or declaration for the function. */ if (oldlocal == 0 ! && DECL_EXTERNAL (x) && !DECL_INLINE (x) && oldglobal != 0 && TREE_CODE (x) == FUNCTION_DECL *************** *** 2534,2544 **** /* We have one. Their types must agree. */ if (! comptypes (TREE_TYPE (x), TREE_TYPE (oldglobal), 1)) ! warning_with_decl (x, "local declaration of `%s' doesn't match global one"); ! /* If the global one is inline, make the local one inline. */ ! else if (TREE_INLINE (oldglobal) ! || DECL_BUILT_IN (oldglobal) ! || (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 ! && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0)) ! IDENTIFIER_LOCAL_VALUE (name) = oldglobal; } /* If we have a local external declaration, --- 2727,2754 ---- /* We have one. Their types must agree. */ if (! comptypes (TREE_TYPE (x), TREE_TYPE (oldglobal), 1)) ! warning_with_decl (x, "extern declaration of `%s' doesn't match global one"); ! else ! { ! /* Inner extern decl is inline if global one is. ! Copy enough to really inline it. */ ! if (DECL_INLINE (oldglobal)) ! { ! DECL_INLINE (x) = DECL_INLINE (oldglobal); ! DECL_INITIAL (x) = DECL_INITIAL (oldglobal); ! DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal); ! DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal); ! } ! /* Inner extern decl is built-in if global one is. */ ! if (DECL_BUILT_IN (oldglobal)) ! { ! DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal); ! DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal)); ! } ! /* Keep the arg types from a file-scope fcn defn. */ ! if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 ! && DECL_INITIAL (oldglobal) ! && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0) ! TREE_TYPE (x) = TREE_TYPE (oldglobal); ! } } /* If we have a local external declaration, *************** *** 2547,2551 **** if (oldlocal == 0 && oldglobal == 0 ! && TREE_EXTERNAL (x) && TREE_PUBLIC (x)) { --- 2757,2761 ---- if (oldlocal == 0 && oldglobal == 0 ! && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { *************** *** 2557,2566 **** /* Warn if shadowing an argument at the top level of the body. */ ! else if (oldlocal != 0 && !TREE_EXTERNAL (x) && TREE_CODE (oldlocal) == PARM_DECL && TREE_CODE (x) != PARM_DECL) { - extern struct rtx_def *cleanup_label; - /* Go to where the parms should be and see if we find them there. */ --- 2767,2774 ---- /* Warn if shadowing an argument at the top level of the body. */ ! else if (oldlocal != 0 && !DECL_EXTERNAL (x) && TREE_CODE (oldlocal) == PARM_DECL && TREE_CODE (x) != PARM_DECL) { /* Go to where the parms should be and see if we find them there. */ *************** *** 2575,2581 **** } /* Maybe warn if shadowing something else. */ ! else if (warn_shadow && !TREE_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ ! && !DECL_IGNORED_P (x) /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) --- 2783,2789 ---- } /* Maybe warn if shadowing something else. */ ! else if (warn_shadow && !DECL_EXTERNAL (x) /* No shadow warnings for internally generated vars. */ ! && DECL_SOURCE_LINE (x) != 0 /* No shadow warnings for vars made for inlining. */ && ! DECL_FROM_INLINE (x)) *************** *** 2629,2633 **** TREE_CHAIN (x) = b->names; b->names = x; ! assert (b != global_binding_level || TREE_PERMANENT (x)); return x; --- 2837,2842 ---- TREE_CHAIN (x) = b->names; b->names = x; ! if (! (b != global_binding_level || TREE_PERMANENT (x))) ! my_friendly_abort (124); return x; *************** *** 2858,2862 **** && ! flag_traditional && (glob == 0 || TREE_PERMANENT (glob) == 1) ! && !global_bindings_p ()) overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget); glob = tree_cons (orig_name, decl, glob); --- 3067,3072 ---- && ! flag_traditional && (glob == 0 || TREE_PERMANENT (glob) == 1) ! && !global_bindings_p () ! && !pseudo_global_level_p ()) overloads_to_forget = tree_cons (orig_name, glob, overloads_to_forget); glob = tree_cons (orig_name, decl, glob); *************** *** 2893,2897 **** decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type); ! TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; --- 3103,3107 ---- decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type); ! DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; *************** *** 2946,2951 **** /* However, defining once as extern inline and a second time in another way is ok. */ ! && !(TREE_INLINE (olddecl) && TREE_EXTERNAL (olddecl) ! && !(TREE_INLINE (newdecl) && TREE_EXTERNAL (newdecl)))) { if (DECL_NAME (olddecl) == NULL_TREE) --- 3156,3161 ---- /* However, defining once as extern inline and a second time in another way is ok. */ ! && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl) ! && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl)))) { if (DECL_NAME (olddecl) == NULL_TREE) *************** *** 2960,2964 **** /* Objects declared at top level: */ /* If at least one is a reference, it's ok. */ ! if (TREE_EXTERNAL (newdecl) || TREE_EXTERNAL (olddecl)) return 0; /* Reject two definitions. */ --- 3170,3174 ---- /* Objects declared at top level: */ /* If at least one is a reference, it's ok. */ ! if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl)) return 0; /* Reject two definitions. */ *************** *** 2976,2980 **** /* Reject two definitions, and reject a definition together with an external reference. */ ! if (!(TREE_EXTERNAL (newdecl) && TREE_EXTERNAL (olddecl))) return "redeclaration of `%s'"; return 0; --- 3186,3190 ---- /* Reject two definitions, and reject a definition together with an external reference. */ ! if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))) return "redeclaration of `%s'"; return 0; *************** *** 3319,3322 **** --- 3529,3533 ---- void set_current_level_tags_transparency (tags_transparent) + int tags_transparent; { current_binding_level->tag_transparent = tags_transparent; *************** *** 3536,3539 **** --- 3747,3751 ---- lookup_name (name, prefer_type) tree name; + int prefer_type; { register tree val; *************** *** 3554,3558 **** if we are presently defining a type. We are presently only interested in TYPE_DECLs. */ ! val = lookup_field (current_class_type, name, 0); if (val == error_mark_node) return val; --- 3766,3770 ---- if we are presently defining a type. We are presently only interested in TYPE_DECLs. */ ! val = lookup_field (current_class_type, name, 0, prefer_type==-1); if (val == error_mark_node) return val; *************** *** 3561,3564 **** --- 3773,3778 ---- } if (val == NULL_TREE) + val = lookup_nested_field (name); + if (val == NULL_TREE) val = IDENTIFIER_GLOBAL_VALUE (name); } *************** *** 3645,3649 **** tdecl = pushdecl (build_decl (TYPE_DECL, tname, type)); #endif - DECL_IGNORED_P (TYPE_NAME (type)) = 0; set_identifier_type_value (tname, NULL_TREE); if ((int) rid_index < (int) RID_MAX) --- 3859,3862 ---- *************** *** 3836,3839 **** --- 4049,4070 ---- record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node); + /* These are types that type_for_size and type_for_mode use. */ + intQI_type_node = make_signed_type (8); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node)); + intHI_type_node = make_signed_type (16); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node)); + intSI_type_node = make_signed_type (32); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node)); + intDI_type_node = make_signed_type (64); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); + unsigned_intQI_type_node = make_unsigned_type (8); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); + unsigned_intHI_type_node = make_unsigned_type (16); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node)); + unsigned_intSI_type_node = make_unsigned_type (32); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node)); + unsigned_intDI_type_node = make_unsigned_type (64); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node)); + float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; *************** *** 3854,3863 **** layout_type (long_double_type_node); - wchar_type_node - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE))); - wchar_type_size = TYPE_PRECISION (wchar_type_node); - signed_wchar_type_node = type_for_size (wchar_type_size, 0); - unsigned_wchar_type_node = type_for_size (wchar_type_size, 1); - integer_zero_node = build_int_2 (0, 0); TREE_TYPE (integer_zero_node) = integer_type_node; --- 4085,4088 ---- *************** *** 3901,3907 **** int_array_type_node = build_array_type (integer_type_node, unsigned_char_type_node); - /* This is for wide string constants. */ - wchar_array_type_node - = build_array_type (wchar_type_node, unsigned_char_type_node); /* This is just some anonymous class type. Nobody should ever --- 4126,4129 ---- *************** *** 3992,3996 **** distinguish an index value into a virtual function table from an address. */ ! vtbl_mask = build_int_2 (~(VINDEX_MAX - 1), -1); #endif --- 4214,4218 ---- distinguish an index value into a virtual function table from an address. */ ! vtbl_mask = build_int_2 (~((HOST_WIDE_INT) VINDEX_MAX - 1), -1); #endif *************** *** 4001,4006 **** record_builtin_type (RID_MAX, 0, vtbl_type_node); ! builtin_function ("__builtin_constant_p", ! build_function_type (integer_type_node, endlink), BUILT_IN_CONSTANT_P, 0); --- 4223,4227 ---- record_builtin_type (RID_MAX, 0, vtbl_type_node); ! builtin_function ("__builtin_constant_p", int_ftype_int, BUILT_IN_CONSTANT_P, 0); *************** *** 4025,4028 **** --- 4246,4251 ---- builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, 0); builtin_function ("__builtin_fsqrt", double_ftype_double, BUILT_IN_FSQRT, 0); + builtin_function ("__builtin_sin", double_ftype_double, BUILT_IN_SIN, 0); + builtin_function ("__builtin_cos", double_ftype_double, BUILT_IN_COS, 0); #if 0 /* This does not work well with libg++. */ *************** *** 4031,4035 **** builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, 0); #endif ! builtin_function ("__builtin_saveregs", default_function_type, BUILT_IN_SAVEREGS, 0); #ifdef EXPAND_BUILTIN_VARARGS --- 4254,4259 ---- builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, 0); #endif ! builtin_function ("__builtin_saveregs", ! build_function_type (ptr_type_node, NULL_TREE), BUILT_IN_SAVEREGS, 0); #ifdef EXPAND_BUILTIN_VARARGS *************** *** 4098,4101 **** --- 4322,4341 ---- TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; + /* This is special for C++ so functions can be overloaded. */ + wchar_type_node + = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE))); + wchar_type_size = TYPE_PRECISION (wchar_type_node); + signed_wchar_type_node = make_signed_type (wchar_type_size); + unsigned_wchar_type_node = make_unsigned_type (wchar_type_size); + wchar_type_node + = TREE_UNSIGNED (wchar_type_node) + ? unsigned_wchar_type_node + : signed_wchar_type_node; + record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node); + + /* This is for wide string constants. */ + wchar_array_type_node + = build_array_type (wchar_type_node, unsigned_char_type_node); + /* This is a hack that should go away when we deliver the real gc code. */ *************** *** 4336,4340 **** { tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type); ! TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; --- 4576,4580 ---- { tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type); ! DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; *************** *** 4433,4441 **** && ANON_AGGRNAME_P (TYPE_NAME (t))) || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL ! && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))) ! && TYPE_FIELDS (t)) { ! tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, NULL_TREE); ! finish_anon_union (decl); } else if (ok_code == RECORD_TYPE --- 4673,4687 ---- && ANON_AGGRNAME_P (TYPE_NAME (t))) || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL ! && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))) { ! /* ANSI C++ June 5 1992 WP 9.5.3. Anonymous unions may not have ! function members. */ ! if (TYPE_FIELDS (t)) ! { ! tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, NULL_TREE); ! finish_anon_union (decl); ! } ! else ! error ("anonymous union cannot have a function member"); } else if (ok_code == RECORD_TYPE *************** *** 4507,4517 **** tree raises; { ! register tree decl = grokdeclarator (declarator, declspecs, ! NORMAL, initialized, raises); register tree type, tem; tree context; int init_written = initialized; if (decl == NULL_TREE) return decl; --- 4753,4772 ---- tree raises; { ! register tree decl; register tree type, tem; tree context; + extern int have_extern_spec; + extern int used_extern_spec; int init_written = initialized; + /* This should only be done once on the top most decl. */ + if (have_extern_spec && !used_extern_spec) + { + declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs); + used_extern_spec = 1; + } + + decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises); if (decl == NULL_TREE) return decl; *************** *** 4546,4550 **** push_obstacks_nochange (); ! context = DECL_LANG_SPECIFIC (decl) ? DECL_CLASS_CONTEXT (decl) : NULL_TREE; if (processing_template_decl) --- 4801,4808 ---- push_obstacks_nochange (); ! context ! = (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl)) ! ? DECL_CLASS_CONTEXT (decl) ! : DECL_CONTEXT (decl); if (processing_template_decl) *************** *** 4583,4588 **** TREE_PUBLIC (d) = TREE_PUBLIC (decl) = 0; TREE_STATIC (d) = TREE_STATIC (decl); ! TREE_EXTERNAL (d) = (TREE_EXTERNAL (decl) ! && !(context && !DECL_EXTERNAL (decl))); DECL_TEMPLATE_RESULT (d) = decl; DECL_OVERLOADED (d) = 1; --- 4841,4846 ---- TREE_PUBLIC (d) = TREE_PUBLIC (decl) = 0; TREE_STATIC (d) = TREE_STATIC (decl); ! DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) ! && !(context && !DECL_THIS_EXTERN (decl))); DECL_TEMPLATE_RESULT (d) = decl; DECL_OVERLOADED (d) = 1; *************** *** 4593,4599 **** { /* If it was not explicitly declared `extern', ! revoke any previous claims of TREE_EXTERNAL. */ ! if (DECL_EXTERNAL (decl) == 0) ! TREE_EXTERNAL (decl) = 0; if (DECL_LANG_SPECIFIC (decl)) DECL_IN_AGGR_P (decl) = 0; --- 4851,4857 ---- { /* If it was not explicitly declared `extern', ! revoke any previous claims of DECL_EXTERNAL. */ ! if (DECL_THIS_EXTERN (decl) == 0) ! DECL_EXTERNAL (decl) = 0; if (DECL_LANG_SPECIFIC (decl)) DECL_IN_AGGR_P (decl) = 0; *************** *** 4654,4658 **** && TREE_CODE (decl) != TYPE_DECL && TREE_CODE (decl) != TEMPLATE_DECL ! && IS_AGGR_TYPE (type) && ! TREE_EXTERNAL (decl)) { if (TYPE_SIZE (type) == 0) --- 4912,4916 ---- && TREE_CODE (decl) != TYPE_DECL && TREE_CODE (decl) != TEMPLATE_DECL ! && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl)) { if (TYPE_SIZE (type) == 0) *************** *** 4680,4687 **** { if (current_binding_level != global_binding_level ! && TREE_EXTERNAL (decl)) warning ("declaration of `%s' has `extern' and is initialized", IDENTIFIER_POINTER (DECL_NAME (decl))); ! TREE_EXTERNAL (decl) = 0; if (current_binding_level == global_binding_level) TREE_STATIC (decl) = 1; --- 4938,4945 ---- { if (current_binding_level != global_binding_level ! && DECL_EXTERNAL (decl)) warning ("declaration of `%s' has `extern' and is initialized", IDENTIFIER_POINTER (DECL_NAME (decl))); ! DECL_EXTERNAL (decl) = 0; if (current_binding_level == global_binding_level) TREE_STATIC (decl) = 1; *************** *** 4745,4749 **** if (DECL_CONTEXT (result) != NULL_TREE) { ! tree type, classname, tmpl; type = DECL_CONTEXT (result); assert (TREE_CODE (type) == UNINSTANTIATED_P_TYPE); --- 5003,5007 ---- if (DECL_CONTEXT (result) != NULL_TREE) { ! tree type; type = DECL_CONTEXT (result); assert (TREE_CODE (type) == UNINSTANTIATED_P_TYPE); *************** *** 4912,4930 **** init = default_conversion (init); } ! if (IS_AGGR_TYPE_2 (TREE_TYPE (type), TREE_TYPE (init)) ! && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)), ! TYPE_MAIN_VARIANT (TREE_TYPE (init)), 0)) ! { ! /* ``a reference to a plain T can only be initialized with a plain T.'' */ ! if ((!TYPE_READONLY (TREE_TYPE (type)) && !TYPE_VOLATILE (TREE_TYPE (type))) ! && TREE_READONLY (init)) ! errstr = "cannot initialize a reference to T with a const T"; ! if ((!TYPE_READONLY (TREE_TYPE (type)) && !TYPE_VOLATILE (TREE_TYPE (type))) ! && TREE_THIS_VOLATILE (init)) ! errstr = "cannot initialize a reference to T with a volatile T"; ! } ! else if (TREE_CODE (TREE_TYPE (type)) == TREE_CODE (TREE_TYPE (init))) { ! init = convert (TREE_TYPE (type), init); } else if (init != error_mark_node --- 5170,5199 ---- init = default_conversion (init); } ! if (TREE_CODE (TREE_TYPE (type)) == TREE_CODE (TREE_TYPE (init))) { ! if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (type)), ! TYPE_MAIN_VARIANT (TREE_TYPE (init)), 0)) ! { ! /* This section implements ANSI C++ June 5 1992 WP 8.4.3.5. */ ! ! /* A reference to a volatile T cannot be initialized with ! a const T, and vice-versa. */ ! if (TYPE_VOLATILE (TREE_TYPE (type)) && TREE_READONLY (init)) ! errstr = "cannot initialize a reference to a volatile T with a const T"; ! else if (TYPE_READONLY (TREE_TYPE (type)) && TREE_THIS_VOLATILE (init)) ! errstr = "cannot initialize a reference to a const T with a volatile T"; ! /* A reference to a plain T can be initialized only with ! a plain T. */ ! else if (!TYPE_VOLATILE (TREE_TYPE (type)) ! && !TYPE_READONLY (TREE_TYPE (type))) ! { ! if (TREE_READONLY (init)) ! errstr = "cannot initialize a reference to T with a const T"; ! else if (TREE_THIS_VOLATILE (init)) ! errstr = "cannot initialize a reference to T with a volatile T"; ! } ! } ! else ! init = convert (TREE_TYPE (type), init); } else if (init != error_mark_node *************** *** 5130,5134 **** DECL_INITIAL (decl) = init = 0; } ! if (IS_AGGR_TYPE (type)) { if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type) --- 5399,5403 ---- DECL_INITIAL (decl) = init = 0; } ! if (IS_AGGR_TYPE (type) && DECL_NAME (decl)) { if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type) *************** *** 5140,5147 **** GNU_xref_decl (current_function_decl, decl); rest_of_decl_compilation (decl, 0, ! current_binding_level == global_binding_level, 0); goto finish_end; } ! if (IS_AGGR_TYPE (type) && CLASSTYPE_DECLARED_EXCEPTION (type)) { finish_exception_decl (NULL_TREE, decl); --- 5409,5417 ---- GNU_xref_decl (current_function_decl, decl); rest_of_decl_compilation (decl, 0, ! DECL_CONTEXT (decl) == NULL, 0); goto finish_end; } ! if (type != error_mark_node && IS_AGGR_TYPE (type) ! && CLASSTYPE_DECLARED_EXCEPTION (type)) { finish_exception_decl (NULL_TREE, decl); *************** *** 5176,5180 **** } ! if (! TREE_EXTERNAL (decl) && TREE_READONLY (decl) && TYPE_NEEDS_CONSTRUCTING (type)) { --- 5446,5450 ---- } ! if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl) && TYPE_NEEDS_CONSTRUCTING (type)) { *************** *** 5208,5212 **** else if (init != 0 && DECL_INITIAL (decl) == 0) init = 0; ! else if (TREE_EXTERNAL (decl)) ; else if (TREE_CODE (type) == REFERENCE_TYPE) --- 5478,5482 ---- else if (init != 0 && DECL_INITIAL (decl) == 0) init = 0; ! else if (DECL_EXTERNAL (decl)) ; else if (TREE_CODE (type) == REFERENCE_TYPE) *************** *** 5218,5222 **** GNU_xref_decl (current_function_decl, decl); ! if (TREE_CODE (decl) == FIELD_DECL || TREE_EXTERNAL (decl)) ; else if (TREE_CODE (decl) == CONST_DECL) --- 5488,5492 ---- GNU_xref_decl (current_function_decl, decl); ! if (TREE_CODE (decl) == FIELD_DECL || DECL_EXTERNAL (decl)) ; else if (TREE_CODE (decl) == CONST_DECL) *************** *** 5332,5336 **** && TREE_STATIC (decl) && TREE_PUBLIC (decl) ! && ! TREE_EXTERNAL (decl) && TREE_CODE (decl) == VAR_DECL && TYPE_NEEDS_CONSTRUCTING (type) --- 5602,5606 ---- && TREE_STATIC (decl) && TREE_PUBLIC (decl) ! && ! DECL_EXTERNAL (decl) && TREE_CODE (decl) == VAR_DECL && TYPE_NEEDS_CONSTRUCTING (type) *************** *** 5344,5352 **** else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (type) != REFERENCE_TYPE && TREE_CODE_CLASS (TREE_CODE (type)) == 't' && (TYPE_READONLY (type) || TREE_READONLY (decl))) { if (! TREE_STATIC (decl)) ! error_with_decl (decl, "uninitialized const `%s'"); } --- 5614,5632 ---- else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (type) != REFERENCE_TYPE + #if 0 + /* const int a; should get this error. (mrs) */ && TREE_CODE_CLASS (TREE_CODE (type)) == 't' + #endif && (TYPE_READONLY (type) || TREE_READONLY (decl))) { + /* ``Unless explicitly declared extern, a const object does not have + external linkage and must be initialized. ($8.4; $12.1)'' ARM 7.1.6 */ + #if 0 + /* What is this for? (mrs) */ if (! TREE_STATIC (decl)) ! #endif ! { ! error_with_decl (decl, "uninitialized const `%s'"); ! } } *************** *** 5369,5374 **** /* Even if pedantic, an external linkage array may have incomplete type at first. */ ! ? pedantic && TREE_EXTERNAL (decl) ! : !TREE_EXTERNAL (decl)); tree initializer = init ? init : DECL_INITIAL (decl); int failure = complete_array_type (type, initializer, do_default); --- 5649,5654 ---- /* Even if pedantic, an external linkage array may have incomplete type at first. */ ! ? pedantic && DECL_EXTERNAL (decl) ! : !DECL_EXTERNAL (decl)); tree initializer = init ? init : DECL_INITIAL (decl); int failure = complete_array_type (type, initializer, do_default); *************** *** 5382,5386 **** error_with_decl (decl, "array size missing in `%s'"); else if (!pedantic && TREE_STATIC (decl)) ! TREE_EXTERNAL (decl) = 1; } --- 5662,5666 ---- error_with_decl (decl, "array size missing in `%s'"); else if (!pedantic && TREE_STATIC (decl)) ! DECL_EXTERNAL (decl) = 1; } *************** *** 5401,5409 **** Otherwise, let it through, but if it is not `extern' then it may cause an error message later. */ ! if (!TREE_EXTERNAL (decl) || DECL_INITIAL (decl) != 0) error_with_decl (decl, "storage size of `%s' isn't known"); init = 0; } ! else if (!TREE_EXTERNAL (decl) && DECL_SIZE (decl) == 0) { /* An automatic variable with an incomplete type: --- 5681,5689 ---- Otherwise, let it through, but if it is not `extern' then it may cause an error message later. */ ! if (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl) != 0) error_with_decl (decl, "storage size of `%s' isn't known"); init = 0; } ! else if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == 0) { /* An automatic variable with an incomplete type: *************** *** 5412,5424 **** TREE_TYPE (decl) = error_mark_node; } ! else if (!TREE_EXTERNAL (decl) && IS_AGGR_TYPE (ttype)) /* Let debugger know it should output info for this type. */ note_debug_info_needed (ttype); ! if ((TREE_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != 0 && ! TREE_CONSTANT (DECL_SIZE (decl))) error_with_decl (decl, "storage size of `%s' isn't constant"); ! if (!TREE_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)) { int yes = suspend_momentary (); --- 5692,5704 ---- TREE_TYPE (decl) = error_mark_node; } ! else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype)) /* Let debugger know it should output info for this type. */ note_debug_info_needed (ttype); ! if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) && DECL_SIZE (decl) != 0 && ! TREE_CONSTANT (DECL_SIZE (decl))) error_with_decl (decl, "storage size of `%s' isn't constant"); ! if (!DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)) { int yes = suspend_momentary (); *************** *** 5496,5500 **** && ! TREE_SIDE_EFFECTS (decl) && ! TREE_PUBLIC (decl) ! && ! TREE_EXTERNAL (decl) && ! TYPE_NEEDS_DESTRUCTOR (type) && DECL_MODE (decl) != BLKmode) --- 5776,5780 ---- && ! TREE_SIDE_EFFECTS (decl) && ! TREE_PUBLIC (decl) ! && ! DECL_EXTERNAL (decl) && ! TYPE_NEEDS_DESTRUCTOR (type) && DECL_MODE (decl) != BLKmode) *************** *** 5504,5508 **** If something later should take its address, we can always give it legitimate RTL at that time. */ ! DECL_RTL (decl) = (struct rtx_def *)gen_reg_rtx (DECL_MODE (decl)); store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0); TREE_ASM_WRITTEN (decl) = 1; --- 5784,5788 ---- If something later should take its address, we can always give it legitimate RTL at that time. */ ! DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0); TREE_ASM_WRITTEN (decl) = 1; *************** *** 5512,5516 **** /* Keep GCC from complaining that this variable is defined but never used. */ ! DECL_FROM_INLINE (decl) = 1; /* If this is a static const, change its apparent linkage if it belongs to a #pragma interface. */ --- 5792,5796 ---- /* Keep GCC from complaining that this variable is defined but never used. */ ! TREE_USED (decl) = 1; /* If this is a static const, change its apparent linkage if it belongs to a #pragma interface. */ *************** *** 5520,5524 **** { TREE_STATIC (decl) = 0; ! TREE_EXTERNAL (decl) = 1; } else --- 5800,5804 ---- { TREE_STATIC (decl) = 0; ! DECL_EXTERNAL (decl) = 1; } else *************** *** 5548,5552 **** ) { ! TREE_EXTERNAL (decl) = 1; make_decl_rtl (decl, asmspec, 1); } --- 5828,5832 ---- ) { ! DECL_EXTERNAL (decl) = 1; make_decl_rtl (decl, asmspec, 1); } *************** *** 5596,5602 **** *argp = parmtypes; fndecl = build_decl (FUNCTION_DECL, fnname, type); ! TREE_EXTERNAL (fndecl) = TREE_EXTERNAL (decl); TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl); ! TREE_INLINE (fndecl) = TREE_INLINE (decl); /* Keep G++ from thinking this function is unused. It is only used to speed up search in name space. */ --- 5876,5882 ---- *argp = parmtypes; fndecl = build_decl (FUNCTION_DECL, fnname, type); ! DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl); TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl); ! DECL_INLINE (fndecl) = DECL_INLINE (decl); /* Keep G++ from thinking this function is unused. It is only used to speed up search in name space. */ *************** *** 5615,5619 **** } } ! else if (TREE_EXTERNAL (decl)) ; else if (TREE_STATIC (decl) && type != error_mark_node) --- 5895,5899 ---- } } ! else if (DECL_EXTERNAL (decl)) ; else if (TREE_STATIC (decl) && type != error_mark_node) *************** *** 5622,5625 **** --- 5902,5908 ---- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE) expand_static_init (decl, init); + else if (TYPE_NEEDS_DESTRUCTOR (type)) + static_aggregates = perm_tree_cons (NULL_TREE, decl, + static_aggregates); /* Make entry in appropriate vector. */ *************** *** 5690,5693 **** --- 5973,5977 ---- tree context = DECL_CONTEXT (decl); if (context + && TREE_CODE_CLASS (TREE_CODE (context)) == 't' && (TREE_CODE (decl) == VAR_DECL /* We also have a pushclass done that we need to undo here *************** *** 5887,5890 **** --- 6171,6178 ---- } decl = build_lang_decl (FUNCTION_DECL, declarator, type); + /* propagate volatile out from type to decl */ + if (TYPE_VOLATILE (type)) + TREE_THIS_VOLATILE (decl) = 1; + /* should probably propagate const out from type to decl I bet (mrs) */ if (staticp) { *************** *** 5893,5897 **** DECL_CLASS_CONTEXT (decl) = ctype; } ! TREE_EXTERNAL (decl) = 1; if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) { --- 6181,6185 ---- DECL_CLASS_CONTEXT (decl) = ctype; } ! DECL_EXTERNAL (decl) = 1; if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) { *************** *** 5900,5903 **** --- 6188,6222 ---- } + /* Only two styles of delete's are valid. */ + if (declarator == ansi_opname[(int) DELETE_EXPR]) + { + tree args = TYPE_ARG_TYPES (type); + int style1, style2; + + if (ctype && args && TREE_CODE (type) == METHOD_TYPE) + /* remove this */ + args = TREE_CHAIN (args); + + style1 = type_list_equal (args, + tree_cons (NULL_TREE, ptr_type_node, + void_list_node)); + style2 = style1 != 0 ? 0 : + type_list_equal (args, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, sizetype, + void_list_node))); + + if (ctype == NULL_TREE) + { + if (! style1) + /* ANSI C++ June 5 1992 WP 12.5.5.2 */ + error ("global operator delete must be declared as taking a single argument of type void*"); + } + else + if (! style1 && ! style2) + /* ANSI C++ June 5 1992 WP 12.5.4.1 */ + error ("operator delete cannot be overloaded"); + } + /* Caller will do the rest of this. */ if (check < 0) *************** *** 5948,5952 **** if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) ! grok_op_properties (decl); if (ctype != NULL_TREE && check) --- 6267,6271 ---- if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) ! grok_op_properties (decl, virtualp); if (ctype != NULL_TREE && check) *************** *** 6036,6039 **** --- 6355,6363 ---- IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; if (ctype && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) + /* If this function is derived from a template, don't + make it public. This shouldn't be here, but there's + no good way to override the interface pragmas for one + function or class only. Bletch. */ + && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (ctype)) == NULL_TREE && (write_virtuals == 2 || (write_virtuals == 3 *************** *** 6049,6053 **** tree ctype, type; tree declarator; ! int specbits; { tree decl; --- 6373,6377 ---- tree ctype, type; tree declarator; ! int specbits, initialized; { tree decl; *************** *** 6058,6062 **** can be initialized, the code will reach here. */ tree field = lookup_field (TYPE_OFFSET_BASETYPE (type), ! declarator, 0); if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) { --- 6382,6386 ---- can be initialized, the code will reach here. */ tree field = lookup_field (TYPE_OFFSET_BASETYPE (type), ! declarator, 0, 0); if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL) { *************** *** 6104,6109 **** if (specbits & (1 << (int) RID_EXTERN)) { ! DECL_EXTERNAL (decl) = 1; ! TREE_EXTERNAL (decl) = !initialized; } --- 6428,6433 ---- if (specbits & (1 << (int) RID_EXTERN)) { ! DECL_THIS_EXTERN (decl) = 1; ! DECL_EXTERNAL (decl) = !initialized; } *************** *** 6115,6119 **** TREE_PUBLIC (decl) = 1; TREE_STATIC (decl) = 1; ! TREE_EXTERNAL (decl) = !initialized; } /* At top level, either `static' or no s.c. makes a definition --- 6439,6443 ---- TREE_PUBLIC (decl) = 1; TREE_STATIC (decl) = 1; ! DECL_EXTERNAL (decl) = !initialized; } /* At top level, either `static' or no s.c. makes a definition *************** *** 6122,6126 **** { TREE_PUBLIC (decl) = !(specbits & (1 << (int) RID_STATIC)); ! TREE_STATIC (decl) = ! TREE_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ --- 6446,6450 ---- { TREE_PUBLIC (decl) = !(specbits & (1 << (int) RID_STATIC)); ! TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ *************** *** 6128,6132 **** { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; ! TREE_PUBLIC (decl) = TREE_EXTERNAL (decl); } return decl; --- 6452,6456 ---- { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; ! TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); } return decl; *************** *** 6216,6220 **** enum tree_code innermost_code = ERROR_MARK; int bitfield = 0; ! int variable_size = 0; /* Set this to error_mark_node for FIELD_DECLs we could not handle properly. All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */ --- 6540,6544 ---- enum tree_code innermost_code = ERROR_MARK; int bitfield = 0; ! int size_varies = 0; /* Set this to error_mark_node for FIELD_DECLs we could not handle properly. All FIELD_DECLs we build here have `init' put into their DECL_INITIAL. */ *************** *** 6613,6616 **** --- 6937,6950 ---- goto found; } + if (id == ridpointers[(int) RID_WCHAR]) + { + if (type) + error ("extraneous `__wchar_t' ignored"); + else + { + type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id)); + } + goto found; + } /* C++ aggregate types. */ if (IDENTIFIER_HAS_TYPE_VALUE (id)) *************** *** 6634,6638 **** pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); else if (longlong) ! warning ("`long long long' is too long for GCC"); else longlong = 1; --- 6968,6972 ---- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); else if (longlong) ! error ("`long long long' is too long for GCC"); else longlong = 1; *************** *** 6704,6708 **** && TYPE_SIZE (type) == NULL_TREE && ! ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)) ! && current_function_decl == NULL_TREE) { /* xref_tag will make friend class declarations look like --- 7038,7043 ---- && TYPE_SIZE (type) == NULL_TREE && ! ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)) ! && current_function_decl == NULL_TREE ! && decl_context != PARM) { /* xref_tag will make friend class declarations look like *************** *** 6721,6728 **** /* Long double is a special combination. */ ! if ((specbits & 1 << (int) RID_LONG) && type == double_type_node) { specbits &= ~ (1 << (int) RID_LONG); ! type = long_double_type_node; } --- 7056,7065 ---- /* Long double is a special combination. */ ! if ((specbits & 1 << (int) RID_LONG) ! && TYPE_MAIN_VARIANT (type) == double_type_node) { specbits &= ~ (1 << (int) RID_LONG); ! type = build_type_variant (long_double_type_node, TYPE_READONLY (type), ! TYPE_VOLATILE (type)); } *************** *** 6736,6740 **** if (TREE_CODE (type) == REAL_TYPE) error ("short, signed or unsigned invalid for `%s'", name); ! else if (TREE_CODE (type) != INTEGER_TYPE) error ("long, short, signed or unsigned invalid for `%s'", name); else if ((specbits & 1 << (int) RID_LONG) --- 7073,7077 ---- if (TREE_CODE (type) == REAL_TYPE) error ("short, signed or unsigned invalid for `%s'", name); ! else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node) error ("long, short, signed or unsigned invalid for `%s'", name); else if ((specbits & 1 << (int) RID_LONG) *************** *** 6884,6887 **** --- 7221,7226 ---- pi[--i] = 0; DECL_LANG_SPECIFIC (loc_typedecl) = (struct lang_decl *) pi; + /* This poplevel conflicts with the popclass over in + grokdeclarator. See ``This popclass conflicts'' */ poplevel (0, 0, 0); *************** *** 6915,6933 **** else { ! error ((decl_context == FIELD ! ? "storage class specified for structure field `%s'" ! : (decl_context == PARM ! ? "storage class specified for parameter `%s'" ! : "storage class specified for typename")), ! name); specbits &= ~ ((1 << (int) RID_REGISTER) | (1 << (int) RID_AUTO) | (1 << (int) RID_EXTERN)); } } ! else if (specbits & 1 << (int) RID_EXTERN && initialized) { ! /* `extern' with initialization is invalid if not at top level. */ ! if (current_binding_level != global_binding_level) ! warning ("non-global `%s' initialized and declared `extern'", name); } else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag --- 7254,7279 ---- else { ! if (decl_context == FIELD) ! { ! tree tmp = TREE_OPERAND (declarator, 0); ! register int op = IDENTIFIER_OPNAME_P (tmp); ! error ("storage class specified for %s `%s'", ! op ? "member operator" : "structure field", ! op ? operator_name_string (tmp) : name); ! } ! else ! error ((decl_context == PARM ! ? "storage class specified for parameter `%s'" ! : "storage class specified for typename"), name); specbits &= ~ ((1 << (int) RID_REGISTER) | (1 << (int) RID_AUTO) | (1 << (int) RID_EXTERN)); } } ! else if (specbits & 1 << (int) RID_EXTERN && initialized && !funcdef_flag) { ! if (current_binding_level == global_binding_level) ! warning ("`%s' initialized and declared `extern'", name); ! else ! error ("`%s' has both `extern' and initializer", name); } else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag *************** *** 7023,7027 **** /* Check for some types that there cannot be arrays of. */ ! if (type == void_type_node) { error ("declaration of `%s' as array of voids", name); --- 7369,7373 ---- /* Check for some types that there cannot be arrays of. */ ! if (TYPE_MAIN_VARIANT (type) == void_type_node) { error ("declaration of `%s' as array of voids", name); *************** *** 7086,7089 **** --- 7432,7439 ---- dont_grok_size: itype = build_binary_op (MINUS_EXPR, size, integer_one_node); + /* Make sure the array size remains visibly nonconstant + even if it is (eg) a const variable with known value. */ + size_varies = 1; + itype = variable_size (itype); itype = build_index_type (itype); } *************** *** 7161,7166 **** --- 7511,7529 ---- if (flags == DTOR_FLAG) { + /* ANSI C++ June 5 1992 WP 12.4.1. A destructor may + not be declared const or volatile. A destructor + may not be static. */ if (staticp == 2) error ("destructor cannot be static member function"); + if (TYPE_READONLY (type)) + { + error ("destructors cannot be declared `const'"); + return NULL_TREE; + } + if (TYPE_VOLATILE (type)) + { + error ("destructors cannot be declared `volatile'"); + return NULL_TREE; + } if (decl_context == FIELD) { *************** *** 7168,7173 **** "destructor for alien class `%s' cannot be a member")) return NULL_TREE; - if (TYPE_HAS_DESTRUCTOR (ctype)) - error_with_aggr_type (ctype, "class `%s' already has destructor defined"); } } --- 7531,7534 ---- *************** *** 7201,7206 **** } } ! else /* its a constructor. */ { if (staticp == 2) error ("constructor cannot be static member function"); --- 7562,7570 ---- } } ! else /* it's a constructor. */ { + /* ANSI C++ June 5 1992 WP 12.1.2. A constructor may + not be declared const or volatile. A constructor may + not be virtual. A constructor may not be static. */ if (staticp == 2) error ("constructor cannot be static member function"); *************** *** 7210,7213 **** --- 7574,7587 ---- virtualp = 0; } + if (TYPE_READONLY (type)) + { + error ("constructors cannot be declared `const'"); + return NULL_TREE; + } + if (TYPE_VOLATILE (type)) + { + error ("constructors cannot be declared `volatile'"); + return NULL_TREE; + } if (specbits & ~((1 << (int) RID_INLINE)|(1 << (int) RID_STATIC))) error ("return value type specifier for constructor ignored"); *************** *** 7240,7245 **** /* Traditionally, declaring return type float means double. */ ! if (flag_traditional && type == float_type_node) ! type = double_type_node; /* Construct the function type and go to the next --- 7614,7624 ---- /* Traditionally, declaring return type float means double. */ ! if (flag_traditional ! && TYPE_MAIN_VARIANT (type) == float_type_node) ! { ! type = build_type_variant (double_type_node, ! TYPE_READONLY (type), ! TYPE_VOLATILE (type)); ! } /* Construct the function type and go to the next *************** *** 7448,7451 **** --- 7827,7833 ---- up appropriate member types. */ tree sname = TREE_OPERAND (declarator, 1); + /* Destructors can have their visibilities changed as well. */ + if (TREE_CODE (sname) == BIT_NOT_EXPR) + sname = TREE_OPERAND (sname, 0); if (TREE_COMPLEXITY (declarator) == 0) *************** *** 7457,7460 **** --- 7839,7844 ---- { TREE_COMPLEXITY (declarator) -= 1; + /* This popclass conflicts with the poplevel over in + grokdeclarator. See ``This poplevel conflicts'' */ popclass (1); } *************** *** 7476,7483 **** goto done_scoping; - /* Destructors can have their visibilities changed as well. */ - if (TREE_CODE (sname) == BIT_NOT_EXPR) - sname = TREE_OPERAND (sname, 0); - if (TREE_CODE (sname) == IDENTIFIER_NODE) { --- 7860,7863 ---- *************** *** 7485,7489 **** basetype :: member . */ ! if (ctype == current_class_type || friendp) if (TREE_CODE (type) == FUNCTION_TYPE) type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), --- 7865,7869 ---- basetype :: member . */ ! if (TYPE_MAIN_VARIANT (ctype) == current_class_type || friendp) if (TREE_CODE (type) == FUNCTION_TYPE) type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), *************** *** 7492,7496 **** type = build_offset_type (ctype, type); else if (TYPE_SIZE (ctype) != 0 ! || (specbits & (1<<(int)RID_TYPEDEF))) { tree t; --- 7872,7876 ---- type = build_offset_type (ctype, type); else if (TYPE_SIZE (ctype) != 0 ! || (specbits & (1<<(int)RID_TYPEDEF))) { tree t; *************** *** 7498,7504 **** this code is used for i.e., typedef int A::M; M *pm; */ ! if (decl_context == FIELD) { ! t = lookup_field (ctype, sname, 0); if (t) { --- 7878,7886 ---- this code is used for i.e., typedef int A::M; M *pm; */ ! if (decl_context == FIELD && funcdef_flag == 0) { ! /* The code in here should only be used to build ! stuff that will be grokked as visibility decls. */ ! t = lookup_field (ctype, sname, 0, 0); if (t) { *************** *** 7543,7547 **** { enum tree_code c; - tree t; if (TREE_CODE (type) == FUNCTION_TYPE) { --- 7925,7928 ---- *************** *** 7717,7721 **** { /* A friendly class? */ ! make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); type = void_type_node; } --- 8098,8106 ---- { /* A friendly class? */ ! if (current_class_type) ! make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); ! else ! error("trying to make class `%s' a friend of global scope", ! TYPE_NAME_STRING (type)); type = void_type_node; } *************** *** 7744,7748 **** a better error message can be made later. */ ! if (type == void_type_node && decl_context != PARM) { if (declarator != NULL_TREE --- 8129,8133 ---- a better error message can be made later. */ ! if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM) { if (declarator != NULL_TREE *************** *** 7805,7809 **** { /* Transfer const-ness of reference into that of type pointed to. */ ! type = build_reference_type (type, constp, volatilep); constp = volatilep = 0; } --- 8190,8194 ---- { /* Transfer const-ness of reference into that of type pointed to. */ ! type = build_type_variant (build_reference_type (type), constp, volatilep); constp = volatilep = 0; } *************** *** 7817,7825 **** DECL_ARG_TYPE (decl) = type; ! if (type == float_type_node) ! DECL_ARG_TYPE (decl) = double_type_node; ! else if (TREE_CODE (type) == INTEGER_TYPE ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) ! DECL_ARG_TYPE (decl) = integer_type_node; } else if (decl_context == FIELD) --- 8202,8226 ---- DECL_ARG_TYPE (decl) = type; ! if (TYPE_MAIN_VARIANT (type) == float_type_node) ! DECL_ARG_TYPE (decl) = build_type_variant (double_type_node, ! TYPE_READONLY (type), ! TYPE_VOLATILE (type)); ! else if (C_PROMOTING_INTEGER_TYPE_P (type)) ! { ! tree argtype; ! ! /* Retain unsignedness if traditional or if not really ! getting wider. */ ! if (TREE_UNSIGNED (type) ! && (flag_traditional ! || TYPE_PRECISION (type) ! == TYPE_PRECISION (integer_type_node))) ! argtype = unsigned_type_node; ! else ! argtype = integer_type_node; ! DECL_ARG_TYPE (decl) = build_type_variant (argtype, ! TYPE_READONLY (type), ! TYPE_VOLATILE (type)); ! } } else if (decl_context == FIELD) *************** *** 7837,7840 **** --- 8238,8260 ---- if (ctype == NULL_TREE) ctype = current_class_type; + + if (ctype == NULL_TREE) + { + register int op = IDENTIFIER_OPNAME_P (declarator); + error ("can't make %s `%s' into a method -- not in a class", + op ? "operator" : "function", + op ? operator_name_string (declarator) : IDENTIFIER_POINTER (declarator)); + return void_type_node; + } + + /* ``A union may [ ... ] not [ have ] virtual functions.'' + ARM 9.5 */ + if (virtualp && TREE_CODE (ctype) == UNION_TYPE) + { + error ("function `%s' declared virtual inside a union", + IDENTIFIER_POINTER (declarator)); + return void_type_node; + } + /* Don't convert type of operators new and delete to METHOD_TYPE; they remain FUNCTION_TYPEs. */ *************** *** 7846,7852 **** } decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0); ! TREE_INLINE (decl) = inlinep; if ((specbits & (1 << (int) RID_EXTERN)) ! || (ctype != NULL_TREE && funcdef_flag >= 0)) TREE_PUBLIC (decl) = 1; } --- 8266,8275 ---- } decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0); ! DECL_INLINE (decl) = inlinep; if ((specbits & (1 << (int) RID_EXTERN)) ! || (ctype != NULL_TREE && funcdef_flag >= 0) ! || (friendp ! && !(specbits & (1 << (int) RID_STATIC)) ! && !(specbits & (1 << (int) RID_INLINE)))) TREE_PUBLIC (decl) = 1; } *************** *** 7854,7858 **** { decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0); ! TREE_INLINE (decl) = inlinep; /* All method decls are public. */ TREE_PUBLIC (decl) = 1; --- 8277,8281 ---- { decl = grokfndecl (ctype, type, declarator, virtualp, flags, quals, raises, friendp ? -1 : 0); ! DECL_INLINE (decl) = inlinep; /* All method decls are public. */ TREE_PUBLIC (decl) = 1; *************** *** 7931,7935 **** /* In class context, static means public visibility. */ TREE_PUBLIC (decl) = 1; ! TREE_EXTERNAL (decl) = !initialized; } else --- 8354,8358 ---- /* In class context, static means public visibility. */ TREE_PUBLIC (decl) = 1; ! DECL_EXTERNAL (decl) = !initialized; } else *************** *** 7983,7995 **** if (ctype == NULL_TREE) DECL_ASSEMBLER_NAME (decl) = declarator; ! if (staticp == 1 && TREE_CODE (type) == METHOD_TYPE) { ! error_with_decl (decl, "cannot declare member function `%s' to have static linkage"); ! staticp = 0; ! specbits &= ~(1 << (int)RID_STATIC); } ! /* Record presence of `static'. In C++, `inline' is like `static'. */ ! TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE))); /* Record presence of `inline', if it is reasonable. */ if (inlinep) --- 8406,8445 ---- if (ctype == NULL_TREE) DECL_ASSEMBLER_NAME (decl) = declarator; ! if (staticp == 1) { ! int illegal_static = 0; ! ! /* Don't allow a static member function in a class, and forbid declaring ! main to be static. */ ! if (TREE_CODE (type) == METHOD_TYPE) ! { ! error_with_decl (decl, ! "cannot declare member function `%s' to have static linkage"); ! illegal_static = 1; ! } ! else if (! was_overloaded ! && ! ctype ! && ! strcmp (IDENTIFIER_POINTER (original_name), "main")) ! { ! error ("cannot declare function `main' to have static linkage"); ! illegal_static = 1; ! } ! ! if (illegal_static) ! { ! staticp = 0; ! specbits &= ~(1 << (int)RID_STATIC); ! } } ! /* Record presence of `static'. In C++, `inline' is like `static'. ! Methods of classes should be public, unless we're dropping them ! into some other file, so we don't clear TREE_PUBLIC for them. */ ! TREE_PUBLIC (decl) ! = ((ctype ! && ! CLASSTYPE_INTERFACE_UNKNOWN (ctype) ! && ! CLASSTYPE_INTERFACE_ONLY (ctype)) ! || !(specbits & ((1 << (int) RID_STATIC) ! | (1 << (int) RID_INLINE)))); /* Record presence of `inline', if it is reasonable. */ if (inlinep) *************** *** 8005,8009 **** else /* Assume that otherwise the function can be inlined. */ ! TREE_INLINE (decl) = 1; if (specbits & (1 << (int) RID_EXTERN)) --- 8455,8459 ---- else /* Assume that otherwise the function can be inlined. */ ! DECL_INLINE (decl) = 1; if (specbits & (1 << (int) RID_EXTERN)) *************** *** 8030,8039 **** /* An uninitialized decl with `extern' is a reference. */ decl = grokvardecl (ctype, type, declarator, specbits, initialized); ! if (ctype && staticp == 1) { ! error ("cannot declare member `%s' to have static linkage", ! lang_printable_name (decl)); ! staticp = 0; ! specbits &= ~(1 << (int)RID_STATIC); } } --- 8480,8498 ---- /* An uninitialized decl with `extern' is a reference. */ decl = grokvardecl (ctype, type, declarator, specbits, initialized); ! if (ctype) { ! if (staticp == 1) ! { ! error ("cannot declare member `%s' to have static linkage", ! lang_printable_name (decl)); ! staticp = 0; ! specbits &= ~(1 << (int)RID_STATIC); ! } ! if (specbits & 1 << (int) RID_EXTERN) ! { ! error ("cannot explicitly declare member `%s' to have extern linkage", ! lang_printable_name (decl)); ! specbits &= ~(1 << (int)RID_EXTERN); ! } } } *************** *** 8043,8047 **** if (specbits & (1 << (int) RID_REGISTER)) ! TREE_REGDECL (decl) = 1; /* Record constancy and volatility. */ --- 8502,8506 ---- if (specbits & (1 << (int) RID_REGISTER)) ! DECL_REGISTER (decl) = 1; /* Record constancy and volatility. */ *************** *** 8252,8259 **** decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl), ! PARM, 0, NULL_TREE); ! if (! decl) continue; type = TREE_TYPE (decl); ! if (type == void_type_node) decl = void_type_node; else if (TREE_CODE (type) == METHOD_TYPE) --- 8711,8719 ---- decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl), ! PARM, init != NULL_TREE, NULL_TREE); ! if (! decl) ! continue; type = TREE_TYPE (decl); ! if (TYPE_MAIN_VARIANT (type) == void_type_node) decl = void_type_node; else if (TREE_CODE (type) == METHOD_TYPE) *************** *** 8310,8315 **** DECL_ARG_TYPE (decl) = TREE_TYPE (decl); #ifdef PROMOTE_PROTOTYPES ! if (TREE_CODE (type) == INTEGER_TYPE ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) DECL_ARG_TYPE (decl) = integer_type_node; #endif --- 8770,8774 ---- DECL_ARG_TYPE (decl) = TREE_TYPE (decl); #ifdef PROMOTE_PROTOTYPES ! if (C_PROMOTING_INTEGER_TYPE_P (type)) DECL_ARG_TYPE (decl) = integer_type_node; #endif *************** *** 8321,8324 **** --- 8780,8798 ---- if (TREE_CODE (init) == SAVE_EXPR) PARM_DECL_EXPR (init) = 1; + else if (TREE_CODE (init) == VAR_DECL) + { + if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init))) + { + /* ``Local variables may not be used in default + argument expressions.'' dpANSI C++ 8.2.6 */ + /* If extern int i; within a function is not + considered a local variable, then this code is + wrong. */ + error_with_decl (init, "local variable `%s' may not be used as a default argument"); + any_error = 1; + } + else if (TREE_READONLY_DECL_P (init)) + init = decl_constant_value (init); + } else init = require_instantiated_type (type, init, integer_zero_node); *************** *** 8394,8397 **** --- 8868,8879 ---- tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; + if (parmtypes && TREE_CHAIN (parmtypes) + && TREE_CODE (TREE_VALUE (TREE_CHAIN (parmtypes))) == REFERENCE_TYPE + && TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (TREE_VALUE (TREE_CHAIN (parmtypes))))) + { + parmtypes = TREE_CHAIN (parmtypes); + parmtype = TREE_VALUE (parmtypes); + } + if (TREE_CODE (parmtype) == REFERENCE_TYPE && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype) *************** *** 8425,8430 **** static void ! grok_op_properties (decl) tree decl; { tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); --- 8907,8913 ---- static void ! grok_op_properties (decl, virtualp) tree decl; + int virtualp; { tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); *************** *** 8434,8447 **** --- 8917,8943 ---- if (DECL_NAME (decl) == ansi_opname[(int) NEW_EXPR]) { + if (virtualp) + error ("`operator new' cannot be declared virtual"); + /* Take care of function decl if we had syntax errors. */ if (argtypes == NULL_TREE) TREE_TYPE (decl) = build_function_type (ptr_type_node, hash_tree_chain (integer_type_node, void_list_node)); + else + decl = coerce_new_type (TREE_TYPE (current_class_name), + TREE_TYPE (decl)); } else if (DECL_NAME (decl) == ansi_opname[(int) DELETE_EXPR]) { + if (virtualp) + error ("`operator delete' cannot be declared virtual"); + if (argtypes == NULL_TREE) TREE_TYPE (decl) = build_function_type (void_type_node, hash_tree_chain (ptr_type_node, void_list_node)); + else + decl = coerce_delete_type (TREE_TYPE (current_class_name), + TREE_TYPE (decl)); + } else *************** *** 8450,8455 **** else if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR]) { ! tree parmtypes = TREE_CHAIN (argtypes); ! tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; if (TREE_CODE (parmtype) == REFERENCE_TYPE --- 8946,8959 ---- else if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR]) { ! tree parmtypes; ! tree parmtype; ! ! if (argtypes == NULL_TREE) ! { ! error_with_decl (decl, "too few arguments to `%s'"); ! return; ! } ! parmtypes = TREE_CHAIN (argtypes); ! parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node; if (TREE_CODE (parmtype) == REFERENCE_TYPE *************** *** 8508,8512 **** ncp = get_identifier (buf); #ifdef SPEW_DEBUG ! printf("*** %s ***\n", IDENTIFIER_POINTER (ncp)); #endif #if 0 --- 9012,9017 ---- ncp = get_identifier (buf); #ifdef SPEW_DEBUG ! if (spew_debug) ! printf("*** %s ***\n", IDENTIFIER_POINTER (ncp)); #endif #if 0 *************** *** 8618,8622 **** /* Give the type a default layout like unsigned int to avoid crashing if it does not get defined. */ ! TYPE_MODE (ref) = SImode; TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); TREE_UNSIGNED (ref) = 1; --- 9123,9127 ---- /* Give the type a default layout like unsigned int to avoid crashing if it does not get defined. */ ! TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); TREE_UNSIGNED (ref) = 1; *************** *** 8791,8813 **** } ! /* Note that virtual baseclasses are shared in the lattice! */ ! if (via_virtual) ! { ! child = CLASSTYPE_VBINFO (basetype, via_public); ! if (child == NULL_TREE) ! { ! CLASSTYPE_VBINFO (basetype, via_public) = child ! = make_binfo (integer_zero_node, basetype, ! TYPE_BINFO_VTABLE (basetype), ! TYPE_BINFO_VIRTUALS (basetype), 0); ! } ! } ! else ! child = make_binfo (integer_zero_node, basetype, ! TYPE_BINFO_VTABLE (basetype), ! TYPE_BINFO_VIRTUALS (basetype), 0); ! TREE_VEC_ELT (binfos, i) = child; TREE_VIA_PUBLIC (child) = via_public; TREE_VIA_VIRTUAL (child) = via_virtual; --- 9296,9314 ---- } ! /* Note that the BINFO records which describe individual ! inheritances are *not* shared in the lattice! They ! cannot be shared because a given baseclass may be ! inherited with different `accessability' by different ! derived classes. (Each BINFO record describing an ! individual inheritance contains flags which say what ! the `accessability' of that particular inheritance is.) */ ! ! child = make_binfo (integer_zero_node, basetype, ! TYPE_BINFO_VTABLE (basetype), ! TYPE_BINFO_VIRTUALS (basetype), 0); ! TREE_VEC_ELT (binfos, i) = child; TREE_VIA_PUBLIC (child) = via_public; + TREE_VIA_PROTECTED (child) = 0; /* Not yet implemented. */ TREE_VIA_VIRTUAL (child) = via_virtual; *************** *** 8962,8968 **** { register tree pair; ! register long maxvalue = 0; ! register long minvalue = 0; ! register int i; TYPE_VALUES (enumtype) = values; --- 9463,9469 ---- { register tree pair; ! register HOST_WIDE_INT maxvalue = 0; ! register HOST_WIDE_INT minvalue = 0; ! register HOST_WIDE_INT i; TYPE_VALUES (enumtype) = values; *************** *** 8974,8978 **** /* Speed up the main loop by performing some precalculations */ ! int value = TREE_INT_CST_LOW (TREE_VALUE (values)); TREE_TYPE (TREE_VALUE (values)) = enumtype; minvalue = maxvalue = value; --- 9475,9479 ---- /* Speed up the main loop by performing some precalculations */ ! HOST_WIDE_INT value = TREE_INT_CST_LOW (TREE_VALUE (values)); TREE_TYPE (TREE_VALUE (values)) = enumtype; minvalue = maxvalue = value; *************** *** 9019,9023 **** --- 9520,9528 ---- /* Finish debugging output for this type. */ + #if 0 + /* @@ Do we ever generate generate ENUMERAL_TYPE nodes for which debugging + information should *not* be generated? I think not. */ if (! DECL_IGNORED_P (TYPE_NAME (enumtype))) + #endif rest_of_type_compilation (enumtype, global_bindings_p ()); *************** *** 9062,9070 **** /* Remove no-op casts from the value. */ ! while (value != 0 && TREE_CODE (value) == NOP_EXPR) ! { ! value = TREE_OPERAND (value, 0); ! shareable = 0; ! } /* Make up for hacks in cp-lex.c. */ --- 9567,9572 ---- /* Remove no-op casts from the value. */ ! if (value) ! STRIP_TYPE_NOPS (value); /* Make up for hacks in cp-lex.c. */ *************** *** 9120,9141 **** } ! if (b == 0) ! { ! tree name = TYPE_NAME (type); ! if (TREE_CODE (name) == TYPE_DECL) ! name = DECL_NAME (name); ! error ("class-local enum declaration `%s' is not in scope here", ! IDENTIFIER_POINTER (name)); ! } ! else if (b != class_binding_level) ! { ! #if 0 /* This is nothing we should warn about. */ ! warning ("class-local declaration for enumeral type `%s' found", ! IDENTIFIER_POINTER (TREE_PURPOSE (tag))); ! warning ("(probably missing '}' before that enum declaration)"); ! #endif ! return decl; ! } ! else if (TREE_ADDRESSABLE (tag)) return decl; else --- 9622,9626 ---- } ! if (b == 0 || (b != class_binding_level) || TREE_ADDRESSABLE (tag)) return decl; else *************** *** 9147,9150 **** --- 9632,9636 ---- /* Create a declaration for the enum value name. */ tree next = build_lang_field_decl (CONST_DECL, TREE_PURPOSE (values), type); + TREE_READONLY (next) = 1; DECL_INITIAL (next) = TREE_VALUE (values); TREE_CHAIN (next) = decl; *************** *** 9169,9174 **** For C++, we must first check whether that datum makes any sense. ! For example, "class A local_a(1,2);" means that variable local ! a is an aggregate of type A, which should have a constructor applied to it with the argument list [1, 2]. --- 9655,9660 ---- For C++, we must first check whether that datum makes any sense. ! For example, "class A local_a(1,2);" means that variable local_a ! is an aggregate of type A, which should have a constructor applied to it with the argument list [1, 2]. *************** *** 9187,9190 **** --- 9673,9679 ---- tree fntype; tree restype; + extern int have_extern_spec; + extern int used_extern_spec; + int doing_friend = 0; if (flag_handle_exceptions && EHS_decl == NULL_TREE) *************** *** 9209,9212 **** --- 9698,9708 ---- clear_temp_name (); + /* This should only be done once on the top most decl. */ + if (have_extern_spec && !used_extern_spec) + { + declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs); + used_extern_spec = 1; + } + if (pre_parsed_p) { *************** *** 9218,9225 **** ctype = TYPE_METHOD_BASETYPE (fntype); if ( !(DECL_VINDEX (decl1) && write_virtuals >= 2 && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype))) ! current_extern_inline = TREE_PUBLIC (decl1) && TREE_INLINE (decl1); raises = TYPE_RAISES_EXCEPTIONS (fntype); --- 9714,9733 ---- ctype = TYPE_METHOD_BASETYPE (fntype); + /* ANSI C++ June 5 1992 WP 11.4.5. A friend function defined in a + class is in the (lexical) scope of the class in which it is + defined. */ + if (!ctype && DECL_FRIEND_P (decl1)) + { + ctype = TREE_TYPE (TREE_CHAIN (decl1)); + if (TREE_CODE (ctype) != RECORD_TYPE) + ctype = NULL_TREE; + else + doing_friend = 1; + } + if ( !(DECL_VINDEX (decl1) && write_virtuals >= 2 && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype))) ! current_extern_inline = TREE_PUBLIC (decl1) && DECL_INLINE (decl1); raises = TYPE_RAISES_EXCEPTIONS (fntype); *************** *** 9241,9255 **** && ! CLASSTYPE_GOT_SEMICOLON (restype)) { ! error_with_aggr_type (restype, "semicolon missing after declaration of `%s'"); shadow_tag (build_tree_list (NULL_TREE, restype)); CLASSTYPE_GOT_SEMICOLON (restype) = 1; - if (TREE_CODE (fntype) == FUNCTION_TYPE) - fntype = build_function_type (integer_type_node, - TYPE_ARG_TYPES (fntype)); - else - fntype = build_cplus_method_type (build_type_variant (TYPE_METHOD_BASETYPE (fntype), TREE_READONLY (decl1), TREE_SIDE_EFFECTS (decl1)), - integer_type_node, - TYPE_ARG_TYPES (fntype)); - TREE_TYPE (decl1) = fntype; } --- 9749,9771 ---- && ! CLASSTYPE_GOT_SEMICOLON (restype)) { ! /* ?? Do we care about doing any of this for anonymous aggregate ! types? */ ! /* Give a warning if it isn't "struct {...} f () return x; {...}". ! If it is unnamed, it's likely the user meant it that way(?). ! Should this warning be conditionalized? */ ! tree typename = TYPE_IDENTIFIER (restype); ! if (! ANON_AGGRNAME_P (typename)) ! { ! static int warned; ! warning ("possibly missing semicolon after declaration of `%s'?", ! IDENTIFIER_POINTER (typename)); ! if (!warned) ! { ! warned = 1; ! warning ("(suggest separating class decl and function definition)"); ! } ! } shadow_tag (build_tree_list (NULL_TREE, restype)); CLASSTYPE_GOT_SEMICOLON (restype) = 1; } *************** *** 9260,9265 **** && DECL_CONTEXT (decl1) == NULL_TREE) { ! /* If this doesn't return an integer type, complain. */ ! if (TREE_CODE (TREE_TYPE (fntype)) != INTEGER_TYPE) { #if 0 --- 9776,9781 ---- && DECL_CONTEXT (decl1) == NULL_TREE) { ! /* If this doesn't return integer_type, complain. */ ! if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) { #if 0 *************** *** 9329,9340 **** { TREE_PUBLIC (decl1) = 1; ! TREE_EXTERNAL (decl1) = interface_only; } else /* This is a definition, not a reference. ! So normally clear TREE_EXTERNAL. However, `extern inline' acts like a declaration except for ! defining how to inline. So set TREE_EXTERNAL in that case. */ ! TREE_EXTERNAL (decl1) = current_extern_inline; /* Now see if this is the implementation of a function --- 9845,9856 ---- { TREE_PUBLIC (decl1) = 1; ! DECL_EXTERNAL (decl1) = interface_only; } else /* This is a definition, not a reference. ! So normally clear DECL_EXTERNAL. However, `extern inline' acts like a declaration except for ! defining how to inline. So set DECL_EXTERNAL in that case. */ ! DECL_EXTERNAL (decl1) = current_extern_inline; /* Now see if this is the implementation of a function *************** *** 9431,9464 **** { pushclass (ctype, 1); ! /* We know that this was set up by `grokclassfn'. ! We do not wait until `store_parm_decls', since evil ! parse errors may never get us to that point. Here ! we keep the consistency between `current_class_type' ! and `current_class_decl'. */ ! current_class_decl = last_function_parms; ! assert (TREE_CODE (current_class_decl) == PARM_DECL); ! if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE) ! { ! tree variant = TREE_TYPE (TREE_TYPE (current_class_decl)); ! if (CLASSTYPE_INST_VAR (ctype) == NULL_TREE) ! { ! /* Can't call build_indirect_ref here, because it has special ! logic to return C_C_D given this argument. */ ! C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl); ! CLASSTYPE_INST_VAR (ctype) = C_C_D; } else ! { ! C_C_D = CLASSTYPE_INST_VAR (ctype); ! /* `current_class_decl' is different for every ! function we compile. */ ! TREE_OPERAND (C_C_D, 0) = current_class_decl; ! } ! TREE_READONLY (C_C_D) = TYPE_READONLY (variant); ! TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (variant); ! TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (variant); } - else - C_C_D = current_class_decl; } else --- 9947,9987 ---- { pushclass (ctype, 1); ! ! /* If we're compiling a friend function, neither of the variables ! current_class_decl nor current_class_type will have values. */ ! if (! doing_friend) ! { ! /* We know that this was set up by `grokclassfn'. ! We do not wait until `store_parm_decls', since evil ! parse errors may never get us to that point. Here ! we keep the consistency between `current_class_type' ! and `current_class_decl'. */ ! current_class_decl = last_function_parms; ! assert (current_class_decl != NULL_TREE ! && TREE_CODE (current_class_decl) == PARM_DECL); ! if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE) ! { ! tree variant = TREE_TYPE (TREE_TYPE (current_class_decl)); ! if (CLASSTYPE_INST_VAR (ctype) == NULL_TREE) ! { ! /* Can't call build_indirect_ref here, because it has special ! logic to return C_C_D given this argument. */ ! C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl); ! CLASSTYPE_INST_VAR (ctype) = C_C_D; ! } ! else ! { ! C_C_D = CLASSTYPE_INST_VAR (ctype); ! /* `current_class_decl' is different for every ! function we compile. */ ! TREE_OPERAND (C_C_D, 0) = current_class_decl; ! } ! TREE_READONLY (C_C_D) = TYPE_READONLY (variant); ! TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (variant); ! TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (variant); } else ! C_C_D = current_class_decl; } } else *************** *** 9475,9481 **** /* 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; if (DECL_RESULT (decl1) == NULL_TREE) DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, restype); --- 9998,10013 ---- /* Promote the value to int before returning it. */ ! if (C_PROMOTING_INTEGER_TYPE_P (restype)) ! { ! /* It retains unsignedness if traditional or if it isn't ! really getting wider. */ ! if (TREE_UNSIGNED (restype) ! && (flag_traditional ! || TYPE_PRECISION (restype) ! == TYPE_PRECISION (integer_type_node))) ! restype = unsigned_type_node; ! else ! restype = integer_type_node; ! } if (DECL_RESULT (decl1) == NULL_TREE) DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, restype); *************** *** 9577,9581 **** #endif } ! else if (TREE_TYPE (parm) == void_type_node) error_with_decl (parm, "parameter `%s' declared void"); else --- 10109,10113 ---- #endif } ! else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node) error_with_decl (parm, "parameter `%s' declared void"); else *************** *** 9718,9725 **** /* If this named return value comes in a register, put it in a pseudo-register. */ ! if (TREE_REGDECL (decl)) { original_result_rtx = DECL_RTL (decl); ! DECL_RTL (decl) = (struct rtx_def *)gen_reg_rtx (DECL_MODE (decl)); } --- 10250,10257 ---- /* If this named return value comes in a register, put it in a pseudo-register. */ ! if (DECL_REGISTER (decl)) { original_result_rtx = DECL_RTL (decl); ! DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); } *************** *** 9810,9816 **** register tree fndecl = current_function_decl; tree fntype = TREE_TYPE (fndecl), ctype = NULL_TREE; ! struct rtx_def *head, *last_parm_insn, *mark; ! extern struct rtx_def *get_last_insn (); ! extern struct rtx_def *cleanup_label, *return_label; extern int sets_exception_throw_decl; /* Label to use if this function is supposed to return a value. */ --- 10342,10346 ---- register tree fndecl = current_function_decl; tree fntype = TREE_TYPE (fndecl), ctype = NULL_TREE; ! rtx head, last_parm_insn, mark; extern int sets_exception_throw_decl; /* Label to use if this function is supposed to return a value. */ *************** *** 9828,9834 **** } ! if (write_symbols != NO_DEBUG ! && (TREE_CODE (fntype) != METHOD_TYPE ! || ! DECL_IGNORED_P (TYPE_NAME (TYPE_METHOD_BASETYPE (fntype))))) { tree ttype = target_type (fntype); --- 10358,10362 ---- } ! if (write_symbols != NO_DEBUG && TREE_CODE (fntype) != METHOD_TYPE) { tree ttype = target_type (fntype); *************** *** 9857,9860 **** --- 10385,10389 ---- tree exprstmt, vfields; tree in_charge_node = lookup_name (in_charge_identifier, 0); + tree virtual_size; int ok_to_optimize_dtor = 0; *************** *** 9869,9873 **** whether `this' is NULL in some cases. */ mark = get_last_insn (); ! last_parm_insn = (struct rtx_def *)get_first_nonparm_insn (); if ((flag_this_is_variable & 1) == 0) --- 10398,10402 ---- whether `this' is NULL in some cases. */ mark = get_last_insn (); ! last_parm_insn = get_first_nonparm_insn (); if ((flag_this_is_variable & 1) == 0) *************** *** 9954,9966 **** TYPE_HAS_DESTRUCTOR (current_class_type) = 1; /* At the end, call delete if that's what's requested. */ if (TREE_GETS_DELETE (current_class_type)) /* This NOP_EXPR means we are in a static call context. */ ! exprstmt = build_method_call (build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), error_mark_node), ! ansi_opname[(int) DELETE_EXPR], ! build_tree_list (NULL_TREE, current_class_decl), ! NULL_TREE, LOOKUP_NORMAL); else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) ! exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0); else exprstmt = 0; --- 10483,10502 ---- TYPE_HAS_DESTRUCTOR (current_class_type) = 1; + virtual_size = c_sizeof (current_class_type); + /* At the end, call delete if that's what's requested. */ if (TREE_GETS_DELETE (current_class_type)) /* This NOP_EXPR means we are in a static call context. */ ! exprstmt = ! build_method_call ! (build1 (NOP_EXPR, ! TYPE_POINTER_TO (current_class_type), error_mark_node), ! ansi_opname[(int) DELETE_EXPR], ! tree_cons (NULL_TREE, current_class_decl, ! build_tree_list (NULL_TREE, virtual_size)), ! NULL_TREE, LOOKUP_NORMAL); else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) ! exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0, ! virtual_size); else exprstmt = 0; *************** *** 9981,9987 **** /* Dont execute destructor code if `this' is NULL. */ mark = get_last_insn (); ! last_parm_insn = (struct rtx_def *)get_first_nonparm_insn (); ! if (last_parm_insn == 0) last_parm_insn = mark; ! else last_parm_insn = (struct rtx_def *) previous_insn (last_parm_insn); /* Make all virtual function table pointers point to CURRENT_CLASS_TYPE's --- 10517,10525 ---- /* Dont execute destructor code if `this' is NULL. */ mark = get_last_insn (); ! last_parm_insn = get_first_nonparm_insn (); ! if (last_parm_insn == 0) ! last_parm_insn = mark; ! else ! last_parm_insn = previous_insn (last_parm_insn); /* Make all virtual function table pointers point to CURRENT_CLASS_TYPE's *************** *** 9992,9998 **** TREE_CHAIN (vfields); vfields = TREE_CHAIN (vfields)) ! expand_expr_stmt (build_virtual_init (binfo, ! VF_BASETYPE_VALUE (vfields), ! current_class_decl)); expand_expr_stmt (build_virtual_init (binfo, binfo, current_class_decl)); --- 10530,10544 ---- TREE_CHAIN (vfields); vfields = TREE_CHAIN (vfields)) ! { ! tree vf_decl = current_class_decl; ! /* ??? This may need to be a loop if there are multiple ! levels of replication. */ ! if (VF_BINFO_VALUE (vfields)) ! vf_decl = convert_pointer_to (VF_BINFO_VALUE (vfields), vf_decl); ! if (vf_decl != error_mark_node) ! expand_expr_stmt (build_virtual_init (binfo, ! VF_BASETYPE_VALUE (vfields), ! vf_decl)); ! } expand_expr_stmt (build_virtual_init (binfo, binfo, current_class_decl)); *************** *** 10009,10013 **** reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); if (! ok_to_optimize_dtor) ! expand_end_cond (); } else if (current_function_assigns_this) --- 10555,10559 ---- reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); if (! ok_to_optimize_dtor) ! expand_end_cond (); } else if (current_function_assigns_this) *************** *** 10032,10036 **** c_expand_return (current_class_decl); } ! else if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node && return_label != NULL) no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); --- 10578,10583 ---- c_expand_return (current_class_decl); } ! else if (TYPE_MAIN_VARIANT (TREE_TYPE ( ! DECL_RESULT (current_function_decl))) != void_type_node && return_label != NULL) no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); *************** *** 10059,10065 **** { tree cleanup, cleanup_deallocate; allocated_this = build_decl (VAR_DECL, NULL_TREE, ptr_type_node); ! TREE_REGDECL (allocated_this) = 1; DECL_INITIAL (allocated_this) = error_mark_node; expand_decl (allocated_this); --- 10606,10617 ---- { tree cleanup, cleanup_deallocate; + tree virtual_size; + + /* This is the size of the virtual object pointed to by + allocated_this. In this case, it is simple. */ + virtual_size = c_sizeof (current_class_type); allocated_this = build_decl (VAR_DECL, NULL_TREE, ptr_type_node); ! DECL_REGISTER (allocated_this) = 1; DECL_INITIAL (allocated_this) = error_mark_node; expand_decl (allocated_this); *************** *** 10068,10073 **** we are ready to bail out. */ cleanup = TREE_GETS_DELETE (current_class_type) ! ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this) ! : build_delete (TREE_TYPE (allocated_this), allocated_this, integer_three_node, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, 1, 0); cleanup_deallocate = build_modify_expr (current_class_decl, NOP_EXPR, integer_zero_node); --- 10620,10629 ---- we are ready to bail out. */ cleanup = TREE_GETS_DELETE (current_class_type) ! ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size) ! /* The size of allocated_this is wrong, and hence the ! second argument to operator delete will be wrong. */ ! : build_delete (TREE_TYPE (allocated_this), allocated_this, ! integer_three_node, ! LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, 1, 0); cleanup_deallocate = build_modify_expr (current_class_decl, NOP_EXPR, integer_zero_node); *************** *** 10093,10097 **** /* must keep the first insn safe. */ ! head = (struct rtx_def *)get_insns (); /* this note will come up to the top with us. */ --- 10649,10653 ---- /* must keep the first insn safe. */ ! head = get_insns (); /* this note will come up to the top with us. */ *************** *** 10122,10128 **** If optimization is enabled, last_parm_insn may move, so we don't hold on to it (across emit_base_init). */ ! last_parm_insn = (struct rtx_def *)get_first_nonparm_insn (); if (last_parm_insn == 0) last_parm_insn = mark; ! else last_parm_insn = (struct rtx_def *) previous_insn (last_parm_insn); if (mark != get_last_insn ()) --- 10678,10684 ---- If optimization is enabled, last_parm_insn may move, so we don't hold on to it (across emit_base_init). */ ! last_parm_insn = get_first_nonparm_insn (); if (last_parm_insn == 0) last_parm_insn = mark; ! else last_parm_insn = previous_insn (last_parm_insn); if (mark != get_last_insn ()) *************** *** 10282,10288 **** have declarations (from inline functions) that need to go into this function's blocks. */ ! assert (current_binding_level->parm_flag == 1); poplevel (1, 0, 1); /* So we can tell if jump_optimize sets it to 1. */ can_reach_end = 0; --- 10838,10849 ---- have declarations (from inline functions) that need to go into this function's blocks. */ ! if (current_binding_level->parm_flag != 1) ! my_friendly_abort (122); poplevel (1, 0, 1); + /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point + to the FUNCTION_DECL node itself. */ + BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; + /* So we can tell if jump_optimize sets it to 1. */ can_reach_end = 0; *************** *** 10294,10303 **** || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))) ! TREE_INLINE (fndecl) = 0; ! if (TREE_EXTERNAL (fndecl) /* This function is just along for the ride. If we can make it inline, that's great. Otherwise, just punt it. */ ! && (TREE_INLINE (fndecl) == 0 || flag_no_inline || function_cannot_inline_p (fndecl))) --- 10855,10864 ---- || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))) ! DECL_INLINE (fndecl) = 0; ! if (DECL_EXTERNAL (fndecl) /* This function is just along for the ride. If we can make it inline, that's great. Otherwise, just punt it. */ ! && (DECL_INLINE (fndecl) == 0 || flag_no_inline || function_cannot_inline_p (fndecl))) *************** *** 10305,10309 **** extern int rtl_dump_and_exit; int old_rtl_dump_and_exit = rtl_dump_and_exit; ! int inline_spec = TREE_INLINE (fndecl); /* This throws away the code for FNDECL. */ --- 10866,10870 ---- extern int rtl_dump_and_exit; int old_rtl_dump_and_exit = rtl_dump_and_exit; ! int inline_spec = DECL_INLINE (fndecl); /* This throws away the code for FNDECL. */ *************** *** 10311,10318 **** /* This throws away the memory of the code for FNDECL. */ if (flag_no_inline) ! TREE_INLINE (fndecl) = 0; rest_of_compilation (fndecl); rtl_dump_and_exit = old_rtl_dump_and_exit; ! TREE_INLINE (fndecl) = inline_spec; } else --- 10872,10879 ---- /* This throws away the memory of the code for FNDECL. */ if (flag_no_inline) ! DECL_INLINE (fndecl) = 0; rest_of_compilation (fndecl); rtl_dump_and_exit = old_rtl_dump_and_exit; ! DECL_INLINE (fndecl) = inline_spec; } else *************** *** 10337,10341 **** warning ("`volatile' function does return"); else if (warn_return_type && current_function_returns_null ! && TREE_TYPE (fntype) != void_type_node) { /* If this function returns non-void and control can drop through, --- 10898,10902 ---- warning ("`volatile' function does return"); else if (warn_return_type && current_function_returns_null ! && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node) { /* If this function returns non-void and control can drop through, *************** *** 10407,10412 **** /* Pass friends other than inline friend functions back. */ ! if (fndecl == void_type_node) ! return void_type_node; if (TREE_CODE (fndecl) != FUNCTION_DECL) --- 10968,10973 ---- /* Pass friends other than inline friend functions back. */ ! if (TYPE_MAIN_VARIANT (fndecl) == void_type_node) ! return fndecl; if (TREE_CODE (fndecl) != FUNCTION_DECL) *************** *** 10417,10421 **** { if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type) ! error_with_decl (fndecl, "`%s' is already defined in aggregate scope"); return void_type_node; } --- 10978,10983 ---- { if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type) ! error_with_decl (fndecl, "`%s' is already defined in class %s", ! TYPE_NAME_STRING (DECL_CONTEXT (fndecl))); return void_type_node; } *************** *** 10425,10429 **** whether it's needed, and whether an override exists. */ if (flag_default_inline && !processing_template_defn) ! TREE_INLINE (fndecl) = 1; /* We read in the parameters on the maybepermanent_obstack, --- 10987,10991 ---- whether it's needed, and whether an override exists. */ if (flag_default_inline && !processing_template_defn) ! DECL_INLINE (fndecl) = 1; /* We read in the parameters on the maybepermanent_obstack, *************** *** 10447,10451 **** grok_ctor_properties (current_class_type, fndecl); else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl))) ! grok_op_properties (fndecl); } --- 11009,11013 ---- grok_ctor_properties (current_class_type, fndecl); else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl))) ! grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl)); } *************** *** 10478,10485 **** register tree fndecl = decl; tree old_initial; register tree link; ! if (decl == void_type_node) return decl; --- 11040,11048 ---- register tree fndecl = decl; tree old_initial; + tree context = DECL_CONTEXT (fndecl); register tree link; ! if (TYPE_MAIN_VARIANT (decl) == void_type_node) return decl; *************** *** 10531,10535 **** --- 11094,11103 ---- DECL_INITIAL (fndecl) = old_initial; + #if 0 + /* tiemann would like this, but is causes String.cc to not compile. */ + if (DECL_FRIEND_P (fndecl) || DECL_CONTEXT (fndecl) != current_class_type) + #else if (DECL_FRIEND_P (fndecl)) + #endif { CLASSTYPE_INLINE_FRIENDS (current_class_type) *************** *** 10537,10540 **** --- 11105,11140 ---- decl = void_type_node; } + #if 0 + /* Work in progress, 9/17/92. */ + else if (context != current_class_type + && TREE_CHAIN (context) != NULL_TREE + && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl))) + { + /* Don't allow them to declare a function like this: + class A { + public: + class B { + public: + int f(); + }; + int B::f() {} + }; + + Note we can get in here if it's a friend (in which case we'll + avoid lots of nasty cruft), or it's a destructor. Compensate. + */ + tree tmp = DECL_ARGUMENTS (TREE_CHAIN (context)); + if (tmp + && TREE_CODE (tmp) == IDENTIFIER_NODE + && TREE_CHAIN (IDENTIFIER_GLOBAL_VALUE (tmp)) + && TREE_CODE (TREE_CHAIN (IDENTIFIER_GLOBAL_VALUE (tmp))) == TYPE_DECL) + { + error_with_decl (decl, + "qualified name used in declaration of `%s'"); + /* Make this node virtually unusable in the end. */ + TREE_CHAIN (decl) = NULL_TREE; + } + } + #endif #ifdef DEBUG_CP_BINDING_LEVELS *************** *** 10572,10575 **** --- 11172,11178 ---- { int toplevel = global_binding_level == current_binding_level; + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TREE_TYPE (TREE_TYPE (decl)) == type) + layout_type (TREE_TYPE (decl)); layout_decl (decl, 0); rest_of_decl_compilation (decl, 0, toplevel, 0); *************** *** 10581,10586 **** } } --current_binding_level->n_incomplete; - assert (current_binding_level->n_incomplete >= 0); } } --- 11184,11189 ---- } } + assert (current_binding_level->n_incomplete > 0); --current_binding_level->n_incomplete; } } *************** *** 10791,10795 **** decl = pushdecl (decl); ! TREE_REGDECL (decl) = 1; store_init_value (decl, addr); expand_decl (decl); --- 11394,11398 ---- decl = pushdecl (decl); ! DECL_REGISTER (decl) = 1; store_init_value (decl, addr); expand_decl (decl); *************** *** 10828,10830 **** --- 11431,11452 ---- b = b->level_chain; } + } + + /* Change a static member function definition into a FUNCTION_TYPE, instead + of the METHOD_TYPE that we create when it's originally parsed. */ + static void + revert_static_member_fn (fn, decl, argtypes) + tree *fn, *decl, *argtypes; + { + tree tmp, function = *fn; + + *argtypes = TREE_CHAIN (*argtypes); + tmp = build_function_type (TREE_TYPE (function), *argtypes); + tmp = build_type_variant (tmp, TYPE_READONLY (function), + TYPE_VOLATILE (function)); + tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp, + TYPE_RAISES_EXCEPTIONS (function)); + TREE_TYPE (*decl) = tmp; + *fn = tmp; + DECL_STATIC_FUNCTION_P (*decl) = 1; } diff -rc2N gcc-2.2.2/cp-decl2.c gcc-2.3.1/cp-decl2.c *** gcc-2.2.2/cp-decl2.c Thu Jun 11 00:18:13 1992 --- gcc-2.3.1/cp-decl2.c Thu Sep 24 21:48:49 1992 *************** *** 28,32 **** --- 28,34 ---- #include "config.h" + #include #include "tree.h" + #include "rtl.h" #include "flags.h" #include "cp-tree.h" *************** *** 35,40 **** #include "assert.h" - #define NULL 0 - extern tree grokdeclarator (); static void grok_function_init (); --- 37,40 ---- *************** *** 133,136 **** --- 133,141 ---- int warn_missing_prototypes; + /* Nonzero means warn about multiple (redundant) decls for the same single + variable or function. */ + + int warn_redundant_decls; + /* Warn about *printf or *scanf format/argument anomalies. */ *************** *** 153,156 **** --- 158,165 ---- int warn_enum_clash; + /* Non-zero means warn when declaring a class that has a non virtual + destructor, when it really ought to have a virtual one. */ + int warn_nonvdtor = 1; + /* Nonzero means `$' can be in an identifier. See cccp.c for reasons why this breaks some obscure ANSI C programs. */ *************** *** 312,324 **** flag_traditional = 1, dollars_in_ident = 1, flag_writable_strings = 1, flag_this_is_variable = 1; ! /* The +e options are for cfront compatibility. */ ! else if (p[0] == '+' && p[1] == 'e') { int old_write_virtuals = write_virtuals; ! if (p[2] == '1') write_virtuals = 1; ! else if (p[2] == '0') write_virtuals = -1; ! else if (p[2] == '2') write_virtuals = 2; else error ("invalid +e option"); --- 321,334 ---- flag_traditional = 1, dollars_in_ident = 1, flag_writable_strings = 1, flag_this_is_variable = 1; ! /* The +e options are for cfront compatibility. They come in as ! `-+eN', to kludge around gcc.c's argument handling. */ ! else if (p[0] == '-' && p[1] == '+' && p[2] == 'e') { int old_write_virtuals = write_virtuals; ! if (p[3] == '1') write_virtuals = 1; ! else if (p[3] == '0') write_virtuals = -1; ! else if (p[3] == '2') write_virtuals = 2; else error ("invalid +e option"); *************** *** 427,430 **** --- 437,442 ---- else if (!strcmp (p, "missing-prototypes")) warn_missing_prototypes = setting; + else if (!strcmp (p, "redundant-decls")) + warn_redundant_decls = setting; else if (!strcmp (p, "format")) warn_format = setting; *************** *** 444,450 **** { extra_warnings = setting; - warn_implicit = setting; explicit_warn_return_type = setting; warn_unused = setting; warn_switch = setting; warn_uninitialized = setting; --- 456,462 ---- { extra_warnings = setting; explicit_warn_return_type = setting; warn_unused = setting; + warn_implicit = setting; warn_switch = setting; warn_uninitialized = setting; *************** *** 518,521 **** --- 530,551 ---- } + /* This routine replaces cryptic DECL_NAMEs with readable DECL_NAMEs. + It leaves DECL_ASSEMBLER_NAMEs with the correct value. */ + /* This does not yet work with user defined conversion operators + It should. */ + static void + substitute_nice_name (decl) + tree decl; + { + if (DECL_NAME (decl) && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE) + { + extern char *decl_as_string (); + char *n = decl_as_string (DECL_NAME (decl)); + if (n[strlen (n) - 1] == ' ') + n[strlen (n) - 1] = 0; + DECL_NAME (decl) = get_identifier (n); + } + } + /* Classes overload their constituent function names automatically. When a function name is declared in a record structure, *************** *** 593,597 **** parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); DECL_ARG_TYPE (parm) = integer_type_node; ! TREE_REGDECL (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; --- 623,627 ---- parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); DECL_ARG_TYPE (parm) = integer_type_node; ! DECL_REGISTER (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; *************** *** 600,607 **** parm = build_decl (PARM_DECL, this_identifier, type); DECL_ARG_TYPE (parm) = type; /* We can make this a register, so long as we don't accidentally complain if someone tries to take its address. */ ! TREE_REGDECL (parm) = 1; #if 0 /* it is wrong to flag the object as readonly, when --- 630,639 ---- parm = build_decl (PARM_DECL, this_identifier, type); + /* Mark the artificial `this' parameter as "artificial". */ + DECL_SOURCE_LINE (parm) = 0; DECL_ARG_TYPE (parm) = type; /* We can make this a register, so long as we don't accidentally complain if someone tries to take its address. */ ! DECL_REGISTER (parm) = 1; #if 0 /* it is wrong to flag the object as readonly, when *************** *** 694,697 **** --- 726,738 ---- = build_decl_overload (fn_name, these_arg_types, 1 + DECL_CONSTRUCTOR_P (function)); + + #if 0 + /* This code is going into the compiler, but currently, it makes + libg++/src/Interger.cc not compile. The problem is that the nice name + winds up going into the symbol table, and conversion operations look + for the manged name. */ + substitute_nice_name (function); + #endif + #if 0 if (flags == TYPENAME_FLAG) *************** *** 845,849 **** if (TREE_CODE (value) == TYPE_DECL) { ! TREE_NONLOCAL (value) = 1; CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; pushdecl_class_level (value); --- 886,890 ---- if (TREE_CODE (value) == TYPE_DECL) { ! DECL_NONLOCAL (value) = 1; CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; pushdecl_class_level (value); *************** *** 853,857 **** if (DECL_IN_AGGR_P (value)) { ! error_with_decl (value, "`%s' is already defined in aggregate scope"); return void_type_node; } --- 894,899 ---- if (DECL_IN_AGGR_P (value)) { ! error_with_decl (value, "`%s' is already defined in the class %s", ! TYPE_NAME_STRING (DECL_CONTEXT (value))); return void_type_node; } *************** *** 906,910 **** || (TREE_STATIC (init) == 0 && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd' ! || TREE_EXTERNAL (init) == 0))) { error ("field initializer is not constant"); --- 948,952 ---- || (TREE_STATIC (init) == 0 && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd' ! || DECL_EXTERNAL (init) == 0))) { error ("field initializer is not constant"); *************** *** 926,930 **** if (TREE_STATIC (value)) { ! if (asmspec == 0) { tree name; --- 968,973 ---- if (TREE_STATIC (value)) { ! /* current_class_type can be NULL_TREE in case of error. */ ! if (asmspec == 0 && current_class_type) { tree name; *************** *** 1026,1030 **** if (DECL_IN_AGGR_P (value)) { ! error_with_decl (value, "`%s' is already defined in aggregate scope"); return void_type_node; } --- 1069,1074 ---- if (DECL_IN_AGGR_P (value)) { ! error_with_decl (value, "`%s' is already defined in the class %s", ! TYPE_NAME_STRING (DECL_CONTEXT (value))); return void_type_node; } *************** *** 1038,1057 **** } finish_decl (value, NULL_TREE, NULL_TREE, 0); - /* detect invalid field size. */ - if (TREE_CODE (width) == CONST_DECL) - width = DECL_INITIAL (width); - else if (TREE_READONLY_DECL_P (width)) - width = decl_constant_value (width); ! if (TREE_CODE (width) != INTEGER_CST) ! { ! error_with_decl (value, "structure field `%s' width not an integer constant"); ! DECL_INITIAL (value) = NULL; ! } ! else { ! DECL_INITIAL (value) = width; ! DECL_BIT_FIELD (value) = 1; } DECL_IN_AGGR_P (value) = 1; return value; --- 1082,1105 ---- } finish_decl (value, NULL_TREE, NULL_TREE, 0); ! if (width != error_mark_node) { ! /* detect invalid field size. */ ! if (TREE_CODE (width) == CONST_DECL) ! width = DECL_INITIAL (width); ! else if (TREE_READONLY_DECL_P (width)) ! width = decl_constant_value (width); ! if (TREE_CODE (width) != INTEGER_CST) ! { ! error_with_decl (value, "structure field `%s' width not an integer constant"); ! DECL_INITIAL (value) = NULL_TREE; ! } ! else ! { ! DECL_INITIAL (value) = width; ! DECL_BIT_FIELD (value) = 1; ! } } + DECL_IN_AGGR_P (value) = 1; return value; *************** *** 1102,1106 **** } ! /* Nope, we have a conversion operator to a scalar type. */ spec = declspecs; while (spec) --- 1150,1156 ---- } ! /* Nope, we have a conversion operator to a scalar type or something ! else, that includes things like constructor declarations for ! templates. */ spec = declspecs; while (spec) *************** *** 1112,1116 **** if (id == ridpointers[(int)RID_INT] || id == ridpointers[(int)RID_DOUBLE] ! || id == ridpointers[(int)RID_FLOAT]) { if (type_id) --- 1162,1167 ---- if (id == ridpointers[(int)RID_INT] || id == ridpointers[(int)RID_DOUBLE] ! || id == ridpointers[(int)RID_FLOAT] ! || id == ridpointers[(int)RID_WCHAR]) { if (type_id) *************** *** 1169,1172 **** --- 1220,1227 ---- error ("identifier for aggregate type conversion omitted"); } + else if (TREE_CODE_CLASS (TREE_CODE (id)) == 't') + { + error ("`operator' missing on conversion operator or tag missing from type"); + } else assert (0); *************** *** 1192,1195 **** --- 1247,1251 ---- } else return NULL_TREE; + found: decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE), *************** *** 1213,1217 **** if (DECL_IN_AGGR_P (decl)) { ! error_with_decl (decl, "`%s' already defined in aggregate scope"); return void_type_node; } --- 1269,1273 ---- if (DECL_IN_AGGR_P (decl)) { ! error_with_decl (decl, "`%s' already defined in the class "); return void_type_node; } *************** *** 1224,1228 **** if (DECL_CHAIN (decl)) { ! error_with_decl (decl, "function `%s' declared twice in aggregate"); return NULL_TREE; } --- 1280,1285 ---- if (DECL_CHAIN (decl)) { ! error_with_decl (decl, "function `%s' declared twice in class %s", ! TYPE_NAME_STRING (DECL_CONTEXT (decl))); return NULL_TREE; } *************** *** 1488,1492 **** setup_vtbl_ptr () { ! extern struct rtx_def *base_init_insns; if (base_init_insns == 0 --- 1545,1549 ---- setup_vtbl_ptr () { ! extern rtx base_init_insns; if (base_init_insns == 0 *************** *** 1494,1497 **** --- 1551,1588 ---- emit_base_init (current_class_type, 0); + #if 0 + /* This has something a little wrong with it. + + On a sun4, code like: + + be L6 + ld [%i0],%o1 + + is generated, when the below is used when -O4 is given. The delay + slot it filled with an instruction that is safe, when this isn't + used, like in: + + be L6 + sethi %hi(LC1),%o0 + ld [%i0],%o1 + + on code like: + + struct A { + virtual void print() { printf("xxx"); } + void f(); + }; + + void A::f() { + if (this) { + print(); + } else { + printf("0"); + } + } + + And that is why this is disabled for now. (mrs) + */ + if ((flag_this_is_variable & 1) == 0 && optimize *************** *** 1510,1513 **** --- 1601,1605 ---- } else + #endif current_vtable_decl = NULL_TREE; } *************** *** 1561,1565 **** char buf[sizeof (AUTO_TEMP_FORMAT) + 20]; tree decl; - int temp = 0; int toplev = global_bindings_p (); --- 1653,1656 ---- *************** *** 1606,1610 **** decl = build_decl (VAR_DECL, get_identifier (buf), type); TREE_USED (decl) = 1; ! TREE_REGDECL (decl) = 1; if (init) --- 1697,1701 ---- decl = build_decl (VAR_DECL, get_identifier (buf), type); TREE_USED (decl) = 1; ! DECL_REGISTER (decl) = 1; if (init) *************** *** 1635,1639 **** static, and must be laid out together. If the union is an anonymous union, we arrange for that ! as well. PUBLICP is nonzero if this union is not declared static. */ void --- 1726,1730 ---- static, and must be laid out together. If the union is an anonymous union, we arrange for that ! as well. PUBLIC_P is nonzero if this union is not declared static. */ void *************** *** 1646,1650 **** int public_p = TREE_PUBLIC (anon_union_decl); int static_p = TREE_STATIC (anon_union_decl); ! int external_p = TREE_EXTERNAL (anon_union_decl); if ((field = TYPE_FIELDS (type)) == NULL_TREE) --- 1737,1741 ---- int public_p = TREE_PUBLIC (anon_union_decl); int static_p = TREE_STATIC (anon_union_decl); ! int external_p = DECL_EXTERNAL (anon_union_decl); if ((field = TYPE_FIELDS (type)) == NULL_TREE) *************** *** 1661,1665 **** TREE_PUBLIC (decl) = public_p; TREE_STATIC (decl) = static_p; ! TREE_EXTERNAL (decl) = external_p; decl = pushdecl (decl); --- 1752,1756 ---- TREE_PUBLIC (decl) = public_p; TREE_STATIC (decl) = static_p; ! DECL_EXTERNAL (decl) = external_p; decl = pushdecl (decl); *************** *** 1707,1710 **** --- 1798,1802 ---- finish_table (name, type, init, publicp) tree name, type, init; + int publicp; { tree itype, atype, decl; *************** *** 1760,1764 **** { /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */ ! TREE_EXTERNAL (decl) = 1; TREE_STATIC (decl) = 0; init = 0; --- 1852,1856 ---- { /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */ ! DECL_EXTERNAL (decl) = 1; TREE_STATIC (decl) = 0; init = 0; *************** *** 1781,1784 **** --- 1873,1877 ---- char *name; tree fields[]; + int len; tree align_type; { *************** *** 1904,1908 **** tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); tree fn = TREE_OPERAND (fnaddr, 0); ! if (! TREE_EXTERNAL (fn) && ! TREE_ASM_WRITTEN (fn) && DECL_SAVED_INSNS (fn)) { --- 1997,2001 ---- tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); tree fn = TREE_OPERAND (fnaddr, 0); ! if (! DECL_EXTERNAL (fn) && ! TREE_ASM_WRITTEN (fn) && DECL_SAVED_INSNS (fn)) { *************** *** 1935,1939 **** write those functions out now. */ if (decl && write_virtuals >= 0 ! && ! TREE_EXTERNAL (decl) && (TREE_PUBLIC (decl) || TREE_USED (decl))) write_vtable_entries (decl); } --- 2028,2032 ---- write those functions out now. */ if (decl && write_virtuals >= 0 ! && ! DECL_EXTERNAL (decl) && (TREE_PUBLIC (decl) || TREE_USED (decl))) write_vtable_entries (decl); } *************** *** 1944,1948 **** { if (write_virtuals >= 0 ! && ! TREE_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) { extern tree the_null_vtable_entry; --- 2037,2041 ---- { if (write_virtuals >= 0 ! && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) { extern tree the_null_vtable_entry; *************** *** 2003,2011 **** finish_file () { - extern struct rtx_def *const0_rtx; extern int lineno; - extern struct _iob *asm_out_file; int start_time, this_time; - char *init_function_name; char *buf; --- 2096,2101 ---- *************** *** 2122,2126 **** expand_end_bindings (getdecls (), 1, 0); ! poplevel (1, 0, 1); pop_momentary (); --- 2212,2216 ---- expand_end_bindings (getdecls (), 1, 0); ! poplevel (1, 0, 0); pop_momentary (); *************** *** 2250,2254 **** expand_end_bindings (getdecls (), 1, 0); ! poplevel (1, 0, 1); pop_momentary (); --- 2340,2344 ---- expand_end_bindings (getdecls (), 1, 0); ! poplevel (1, 0, 0); pop_momentary (); *************** *** 2335,2339 **** type = build_function_type (void_type_node, NULL_TREE); decl = pushdecl (build_lang_decl (FUNCTION_DECL, get_identifier ("_Ztable_from_cfront"), type)); ! TREE_EXTERNAL (decl) = 1; finish_decl (decl, NULL_TREE, NULL_TREE, 0); expand_expr_stmt (build_function_call (decl, build_tree_list (NULL_TREE, zlink_table))); --- 2425,2429 ---- type = build_function_type (void_type_node, NULL_TREE); decl = pushdecl (build_lang_decl (FUNCTION_DECL, get_identifier ("_Ztable_from_cfront"), type)); ! DECL_EXTERNAL (decl) = 1; finish_decl (decl, NULL_TREE, NULL_TREE, 0); expand_expr_stmt (build_function_call (decl, build_tree_list (NULL_TREE, zlink_table))); *************** *** 2441,2445 **** tree decl = TREE_VALUE (pending_addressable_inlines); if (! TREE_ASM_WRITTEN (decl) ! && ! TREE_EXTERNAL (decl) && DECL_SAVED_INSNS (decl)) output_inline_function (decl); --- 2531,2535 ---- tree decl = TREE_VALUE (pending_addressable_inlines); if (! TREE_ASM_WRITTEN (decl) ! && ! DECL_EXTERNAL (decl) && DECL_SAVED_INSNS (decl)) output_inline_function (decl); *************** *** 2452,2455 **** --- 2542,2559 ---- We output them all ourselves, because each will be treated specially. */ + #if 1 + /* The reason for pushing garbage onto the global_binding_level is to + ensure that we can slice out _DECLs which pertain to virtual function + tables. If the last thing pushed onto the global_binding_level was a + virtual function table, then slicing it out would slice away all the + decls (i.e., we lose the head of the chain). + + There are several ways of getting the same effect, from changing the + way that iterators over the chain treat the elements that pertain to + virtual function tables, moving the implementation of this code to + cp-decl.c (where we can manipulate global_binding_level directly), + popping the garbage after pushing it and slicing away the vtable + stuff, or just leaving it alone. */ + /* Make last thing in global scope not be a virtual function table. */ #if 0 /* not yet, should get fixed properly later */ *************** *** 2458,2462 **** --- 2562,2569 ---- vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node); #endif + DECL_IGNORED_P (vars) = 1; + DECL_SOURCE_LINE (vars) = 0; pushdecl (vars); + #endif walk_vtables (finish_vtable_typedecl, finish_vtable_vardecl); diff -rc2N gcc-2.2.2/cp-dem.c gcc-2.3.1/cp-dem.c *** gcc-2.2.2/cp-dem.c Thu Jun 11 00:22:29 1992 --- gcc-2.3.1/cp-dem.c Mon Jul 6 23:41:15 1992 *************** *** 55,65 **** #ifdef USG #include - #include #else - #include #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n)) #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n)) - #define strchr index - #define strrchr rindex #endif --- 55,61 ---- *************** *** 277,281 **** } /* static data member */ ! else if (*type != '_' && (strchr (type, CPLUS_MARKER) != NULL)) { static_type = 1; --- 273,277 ---- } /* static data member */ ! else if (*type != '_' && (index (type, CPLUS_MARKER) != NULL)) { static_type = 1; diff -rc2N gcc-2.2.2/cp-edsel.c gcc-2.3.1/cp-edsel.c *** gcc-2.2.2/cp-edsel.c Thu Jun 11 00:23:01 1992 --- gcc-2.3.1/cp-edsel.c Sun Jun 28 06:12:46 1992 *************** *** 38,44 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - void init_cadillac (); --- 38,41 ---- diff -rc2N gcc-2.2.2/cp-except.c gcc-2.3.1/cp-except.c *** gcc-2.2.2/cp-except.c Thu Jun 11 00:23:12 1992 --- gcc-2.3.1/cp-except.c Thu Sep 17 20:01:20 1992 *************** *** 30,33 **** --- 30,34 ---- #include "config.h" #include "tree.h" + #include "rtl.h" #include "cp-tree.h" #include "flags.h" *************** *** 45,51 **** #endif - extern struct rtx_def *expand_expr (); - extern struct rtx_def *const0_rtx, *const1_rtx; - void init_exception_processing (); void init_exception_processing_1 (); --- 46,49 ---- *************** *** 66,71 **** /* The exception handler object for the given scope. */ tree current_exception_decl; ! struct rtx_def *current_exception_name_as_rtx; ! struct rtx_def *current_exception_parms_as_rtx; /* The ``object'' view of the current exception parameters. --- 64,69 ---- /* The exception handler object for the given scope. */ tree current_exception_decl; ! rtx current_exception_name_as_rtx; ! rtx current_exception_parms_as_rtx; /* The ``object'' view of the current exception parameters. *************** *** 88,92 **** /* Cached component refs to fields of `EHS_decl'. */ static tree EHS_prev, EHS_handler, EHS_parms, EHS_name; ! static struct rtx_def *EHS_parms_as_rtx, *EHS_name_as_rtx; /* The parameter names of this exception type. */ --- 86,90 ---- /* Cached component refs to fields of `EHS_decl'. */ static tree EHS_prev, EHS_handler, EHS_parms, EHS_name; ! static rtx EHS_parms_as_rtx, EHS_name_as_rtx; /* The parameter names of this exception type. */ *************** *** 398,405 **** TYPE_HAS_CONSTRUCTOR (t) = 1; grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, NULL_TREE); ! TREE_EXTERNAL (ctor) = 1; TREE_STATIC (ctor) = 1; TREE_PUBLIC (ctor) = 0; ! TREE_INLINE (ctor) = 1; make_decl_rtl (ctor, 0, 1); finish_decl (ctor, NULL_TREE, 0, 0); --- 396,403 ---- TYPE_HAS_CONSTRUCTOR (t) = 1; grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, NULL_TREE); ! DECL_EXTERNAL (ctor) = 1; TREE_STATIC (ctor) = 1; TREE_PUBLIC (ctor) = 0; ! DECL_INLINE (ctor) = 1; make_decl_rtl (ctor, 0, 1); finish_decl (ctor, NULL_TREE, 0, 0); *************** *** 774,777 **** --- 772,776 ---- tree ansi_exception_object_lookup (type) + tree type; { tree raise_id = cplus_exception_name (type); *************** *** 805,813 **** /* Allocate new exception of appropriate type, passing PARMS to its constructor. */ - tree cname, name; tree decl = ansi_exception_object_lookup (TREE_TYPE (exp)); tree xexp = exp; - tree raise_id; - if (in_try_block (1)) --- 804,809 ---- *************** *** 976,980 **** tree ex_ptr; tree ex_object = current_exception_object; ! struct rtx_def *ex_ptr_as_rtx; if (exceptions && TREE_CODE (exceptions) == IDENTIFIER_NODE) --- 972,976 ---- tree ex_ptr; tree ex_object = current_exception_object; ! rtx ex_ptr_as_rtx; if (exceptions && TREE_CODE (exceptions) == IDENTIFIER_NODE) *************** *** 1000,1004 **** expand_catch (error_mark_node); expand_raise (error_mark_node); ! emit_move_insn (EHS_name_as_rtx, current_exception_name_as_rtx, 0); store_expr (EHS_parms_as_rtx, current_exception_parms_as_rtx, 0); if (in_try_block (1) == 0) --- 996,1000 ---- expand_catch (error_mark_node); expand_raise (error_mark_node); ! emit_move_insn (EHS_name_as_rtx, current_exception_name_as_rtx); store_expr (EHS_parms_as_rtx, current_exception_parms_as_rtx, 0); if (in_try_block (1) == 0) *************** *** 1150,1154 **** TREE_STATIC (ctor) = 1; TREE_PUBLIC (ctor) = 1; ! TREE_EXTERNAL (ctor) = 1; grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0); grok_ctor_properties (EHS_type, ctor); --- 1146,1150 ---- TREE_STATIC (ctor) = 1; TREE_PUBLIC (ctor) = 1; ! DECL_EXTERNAL (ctor) = 1; grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0); grok_ctor_properties (EHS_type, ctor); *************** *** 1165,1169 **** TREE_STATIC (dtor) = 1; TREE_PUBLIC (dtor) = 1; ! TREE_EXTERNAL (dtor) = 1; grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0); finish_decl (pushdecl (dtor), 0, 0, 0); --- 1161,1165 ---- TREE_STATIC (dtor) = 1; TREE_PUBLIC (dtor) = 1; ! DECL_EXTERNAL (dtor) = 1; grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0); finish_decl (pushdecl (dtor), 0, 0, 0); *************** *** 1193,1197 **** will not be seen. */ EHS_decl = pushdecl (EHS_decl); ! TREE_EXTERNAL (EHS_decl) = 1; TREE_STATIC (EHS_decl) = 1; TREE_PUBLIC (EHS_decl) = 1; --- 1189,1193 ---- will not be seen. */ EHS_decl = pushdecl (EHS_decl); ! DECL_EXTERNAL (EHS_decl) = 1; TREE_STATIC (EHS_decl) = 1; TREE_PUBLIC (EHS_decl) = 1; diff -rc2N gcc-2.2.2/cp-gc.c gcc-2.3.1/cp-gc.c *** gcc-2.2.2/cp-gc.c Thu Jun 11 00:23:31 1992 --- gcc-2.3.1/cp-gc.c Sat Jul 11 22:57:17 1992 *************** *** 474,478 **** { tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); ! TREE_EXTERNAL (tdecl) = 1; TREE_PUBLIC (tdecl) = 1; tdecl = pushdecl_top_level (tdecl); --- 474,478 ---- { tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node); ! DECL_EXTERNAL (tdecl) = 1; TREE_PUBLIC (tdecl) = 1; tdecl = pushdecl_top_level (tdecl); *************** *** 504,508 **** || CLASSTYPE_INTERFACE_UNKNOWN (taggr)); TREE_STATIC (tdecl) = 1; ! TREE_EXTERNAL (tdecl) = 0; } else --- 504,508 ---- || CLASSTYPE_INTERFACE_UNKNOWN (taggr)); TREE_STATIC (tdecl) = 1; ! DECL_EXTERNAL (tdecl) = 0; } else *************** *** 514,518 **** else { ! TREE_EXTERNAL (tdecl) = 0; TREE_STATIC (tdecl) = 1; TREE_PUBLIC (tdecl) = (definition > 1); --- 514,518 ---- else { ! DECL_EXTERNAL (tdecl) = 0; TREE_STATIC (tdecl) = 1; TREE_PUBLIC (tdecl) = (definition > 1); *************** *** 520,524 **** } SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); ! if (!definition || TREE_EXTERNAL (tdecl)) { /* That's it! */ --- 520,524 ---- } SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0)); ! if (!definition || DECL_EXTERNAL (tdecl)) { /* That's it! */ *************** *** 673,677 **** else vindex = integer_zero_node; ! if (DECL_CONTEXT (decl)) vcontext = build_t_desc (DECL_CONTEXT (decl), 0); else --- 673,678 ---- 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 diff -rc2N gcc-2.2.2/cp-hash.h gcc-2.3.1/cp-hash.h *** gcc-2.2.2/cp-hash.h Thu Jun 11 00:34:34 1992 --- gcc-2.3.1/cp-hash.h Tue Aug 4 17:31:29 1992 *************** *** 4,13 **** struct resword { char *name; short token; enum rid rid;}; ! #define TOTAL_KEYWORDS 81 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 13 #define MIN_HASH_VALUE 4 ! #define MAX_HASH_VALUE 199 ! /* maximum key range = 196, duplicates = 0 */ #ifdef __GNUC__ --- 4,13 ---- struct resword { char *name; short token; enum rid rid;}; ! #define TOTAL_KEYWORDS 82 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 13 #define MIN_HASH_VALUE 4 ! #define MAX_HASH_VALUE 140 ! /* maximum key range = 137, duplicates = 0 */ #ifdef __GNUC__ *************** *** 21,37 **** static unsigned char asso_values[] = { ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, ! 200, 200, 200, 200, 200, 0, 200, 35, 1, 52, ! 53, 0, 5, 11, 44, 21, 200, 13, 35, 36, ! 21, 0, 9, 200, 30, 0, 8, 49, 5, 64, ! 0, 34, 200, 200, 200, 200, 200, 200, }; register int hval = len; --- 21,37 ---- static unsigned char asso_values[] = { ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, ! 141, 141, 141, 141, 141, 0, 141, 49, 3, 28, ! 28, 0, 5, 11, 32, 37, 141, 2, 24, 35, ! 51, 0, 19, 141, 23, 0, 8, 48, 0, 36, ! 0, 11, 141, 141, 141, 141, 141, 141, }; register int hval = len; *************** *** 80,179 **** {"typeof", TYPEOF, NORID,}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, ! {"private", VISSPEC, RID_PRIVATE,}, ! {"",}, {"__const", TYPE_QUAL, RID_CONST}, ! {"",}, {"typedef", SCSPEC, RID_TYPEDEF,}, {"",}, - {"extern", SCSPEC, RID_EXTERN,}, - {"if", IF, NORID,}, - {"",}, {"",}, - {"__signed__", TYPESPEC, RID_SIGNED}, - {"int", TYPESPEC, RID_INT,}, - {"template", TEMPLATE, NORID,}, - {"__extension__", EXTENSION, NORID}, {"raise", RAISE, NORID /* Extension */,}, {"raises", RAISES, NORID /* Extension */,}, - {"",}, - {"for", FOR, NORID,}, - {"auto", SCSPEC, RID_AUTO,}, - {"__attribute", ATTRIBUTE, NORID}, - {"__asm", ASM_KEYWORD, NORID}, - {"__attribute__", ATTRIBUTE, NORID}, - {"short", TYPESPEC, RID_SHORT,}, - {"__typeof__", TYPEOF, NORID}, - {"try", TRY, NORID /* Extension */,}, - {"__classof__", CLASSOF, NORID}, - {"__typeof", TYPEOF, NORID}, - {"inline", SCSPEC, RID_INLINE,}, - {"__classof", CLASSOF, NORID}, - {"__inline", SCSPEC, RID_INLINE}, - {"exception", AGGR, RID_EXCEPTION /* Extension */,}, - {"__inline__", SCSPEC, RID_INLINE}, - {"float", TYPESPEC, RID_FLOAT,}, - {"break", BREAK, NORID,}, {"do", DO, NORID,}, {"case", CASE, NORID,}, {"class", AGGR, RID_CLASS,}, - {"switch", SWITCH, NORID,}, {"delete", DELETE, NORID,}, {"double", TYPESPEC, RID_DOUBLE,}, ! {"long", TYPESPEC, RID_LONG,}, ! {"",}, ! {"struct", AGGR, RID_RECORD,}, {"friend", SCSPEC, RID_FRIEND,}, {"const", TYPE_QUAL, RID_CONST,}, {"static", SCSPEC, RID_STATIC,}, ! {"__alignof__", ALIGNOF, NORID}, ! {"operator", OPERATOR, NORID,}, {"classof", CLASSOF, NORID,}, ! {"__alignof", ALIGNOF, NORID}, {"",}, ! {"reraise", RERAISE, NORID /* Extension */,}, ! {"all", ALL, NORID /* Extension */,}, ! {"asm", ASM_KEYWORD, NORID,}, ! {"union", AGGR, RID_UNION,}, {"enum", ENUM, NORID,}, - {"throw", THROW, NORID /* Extension */,}, {"",}, {"__label__", LABEL, NORID}, {"signed", TYPESPEC, RID_SIGNED,}, {"",}, ! {"__signed", TYPESPEC, RID_SIGNED}, ! {"volatile", TYPE_QUAL, RID_VOLATILE,}, ! {"",}, {"",}, {"",}, ! {"protected", VISSPEC, RID_PROTECTED,}, {"new", NEW, NORID,}, {"register", SCSPEC, RID_REGISTER,}, ! {"virtual", SCSPEC, RID_VIRTUAL,}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, ! {"public", VISSPEC, RID_PUBLIC,}, ! {"",}, ! {"while", WHILE, NORID,}, ! {"",}, ! {"return", RETURN, NORID,}, ! {"",}, ! {"headof", HEADOF, NORID,}, {"",}, {"",}, {"default", DEFAULT, NORID,}, {"",}, {"",}, {"",}, ! {"void", TYPESPEC, RID_VOID,}, ! {"char", TYPESPEC, RID_CHAR,}, ! {"continue", CONTINUE, NORID,}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"overload", OVERLOAD, NORID,}, ! {"",}, {"",}, {"",}, {"",}, {"unsigned", TYPESPEC, RID_UNSIGNED,}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, {"",}, ! {"catch", CATCH, NORID,}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"dynamic", DYNAMIC, NORID,}, }; --- 80,171 ---- {"typeof", TYPEOF, NORID,}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, ! {"__typeof__", TYPEOF, NORID}, ! {"try", TRY, NORID /* Extension */,}, {"__const", TYPE_QUAL, RID_CONST}, ! {"__typeof", TYPEOF, NORID}, {"typedef", SCSPEC, RID_TYPEDEF,}, + {"private", VISSPEC, RID_PRIVATE,}, {"",}, {"raise", RAISE, NORID /* Extension */,}, {"raises", RAISES, NORID /* Extension */,}, {"do", DO, NORID,}, + {"for", FOR, NORID,}, {"case", CASE, NORID,}, {"class", AGGR, RID_CLASS,}, {"delete", DELETE, NORID,}, + {"__classof__", CLASSOF, NORID}, + {"short", TYPESPEC, RID_SHORT,}, {"double", TYPESPEC, RID_DOUBLE,}, ! {"__classof", CLASSOF, NORID}, {"friend", SCSPEC, RID_FRIEND,}, + {"__asm", ASM_KEYWORD, NORID}, {"const", TYPE_QUAL, RID_CONST,}, {"static", SCSPEC, RID_STATIC,}, ! {"template", TEMPLATE, NORID,}, ! {"if", IF, NORID,}, {"classof", CLASSOF, NORID,}, ! {"switch", SWITCH, NORID,}, ! {"__signed__", TYPESPEC, RID_SIGNED}, ! {"int", TYPESPEC, RID_INT,}, ! {"throw", THROW, NORID /* Extension */,}, ! {"long", TYPESPEC, RID_LONG,}, ! {"",}, {"",}, ! {"auto", SCSPEC, RID_AUTO,}, ! {"operator", OPERATOR, NORID,}, {"",}, ! {"__attribute", ATTRIBUTE, NORID}, ! {"extern", SCSPEC, RID_EXTERN,}, ! {"__attribute__", ATTRIBUTE, NORID}, ! {"break", BREAK, NORID,}, ! {"void", TYPESPEC, RID_VOID,}, ! {"",}, ! {"struct", AGGR, RID_RECORD,}, ! {"virtual", SCSPEC, RID_VIRTUAL,}, ! {"__extension__", EXTENSION, NORID}, ! {"while", WHILE, NORID,}, ! {"",}, ! {"float", TYPESPEC, RID_FLOAT,}, ! {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,}, ! {"",}, {"",}, ! {"headof", HEADOF, NORID,}, ! {"protected", VISSPEC, RID_PROTECTED,}, ! {"__signed", TYPESPEC, RID_SIGNED}, {"enum", ENUM, NORID,}, {"",}, + {"all", ALL, NORID /* Extension */,}, + {"public", VISSPEC, RID_PUBLIC,}, + {"char", TYPESPEC, RID_CHAR,}, + {"reraise", RERAISE, NORID /* Extension */,}, + {"inline", SCSPEC, RID_INLINE,}, + {"volatile", TYPE_QUAL, RID_VOLATILE,}, {"__label__", LABEL, NORID}, + {"",}, {"",}, {"signed", TYPESPEC, RID_SIGNED,}, + {"__alignof__", ALIGNOF, NORID}, + {"asm", ASM_KEYWORD, NORID,}, {"",}, ! {"__alignof", ALIGNOF, NORID}, {"new", NEW, NORID,}, {"register", SCSPEC, RID_REGISTER,}, ! {"continue", CONTINUE, NORID,}, ! {"catch", CATCH, NORID,}, ! {"",}, {"",}, {"",}, ! {"exception", AGGR, RID_EXCEPTION /* Extension */,}, {"",}, {"",}, {"default", DEFAULT, NORID,}, {"",}, {"",}, {"",}, ! {"union", AGGR, RID_UNION,}, ! {"",}, {"",}, {"",}, {"overload", OVERLOAD, NORID,}, ! {"",}, ! {"__inline", SCSPEC, RID_INLINE}, ! {"",}, ! {"__inline__", SCSPEC, RID_INLINE}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"unsigned", TYPESPEC, RID_UNSIGNED,}, ! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"return", RETURN, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, ! {"",}, {"",}, {"dynamic", DYNAMIC, NORID,}, }; diff -rc2N gcc-2.2.2/cp-init.c gcc-2.3.1/cp-init.c *** gcc-2.2.2/cp-init.c Thu Jun 11 00:24:40 1992 --- gcc-2.3.1/cp-init.c Thu Sep 24 21:48:59 1992 *************** *** 24,27 **** --- 24,28 ---- #include "config.h" #include "tree.h" + #include "rtl.h" #include "cp-tree.h" #include "flags.h" *************** *** 41,45 **** tree current_base_init_list, current_member_init_list; - void init_init_processing (); void emit_base_init (); void check_base_init (); --- 42,45 ---- *************** *** 47,52 **** void expand_member_init (); void expand_aggr_init (); - tree build_virtual_init (); - tree build_vbase_delete (); static void expand_aggr_init_1 (); --- 47,50 ---- *************** *** 69,75 **** static tree minus_one; - extern struct rtx_def *start_sequence (), *get_insns (), *get_last_insn (); - extern struct rtx_def *const0_rtx; - /* Set up local variable for this file. MUST BE CALLED AFTER INIT_DECL_PROCESSING. */ --- 67,70 ---- *************** *** 168,176 **** since we are technically at the PARM level of scope. ! Argument ASSIGNS_THIS_P is nonzero if the current function assigns ! `this' explicitly. We cannot get this value by checking ! `current_function_assigns_this', since it is set up after this ! function is called. (although I don't know if its really ! necessary to wait until afterward to do that.) Note that emit_base_init does *not* initialize virtual --- 163,170 ---- since we are technically at the PARM level of scope. ! Argument IMMEDIATELY, if zero, forces a new sequence to be generated ! to contain these new insns, so it can be emitted later. This sequence ! is saved in the global variable BASE_INIT_INSNS. Otherwise, the insns ! are emitted into the current sequence. Note that emit_base_init does *not* initialize virtual *************** *** 259,263 **** are recorded with this constructor, and they are used when this constructor is the top-level constructor called. */ ! if (! TREE_VIA_VIRTUAL (binfo) || pedantic) { /* Otherwise, if it is not an immediate base class, complain. */ --- 253,257 ---- are recorded with this constructor, and they are used when this constructor is the top-level constructor called. */ ! if (! TREE_VIA_VIRTUAL (binfo)) { /* Otherwise, if it is not an immediate base class, complain. */ *************** *** 288,292 **** && BINFO_BASETYPES (binfo) != NULL_TREE && TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1) ! binfo = BINFO_BASETYPE (binfo, 0); if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))) --- 282,291 ---- && BINFO_BASETYPES (binfo) != NULL_TREE && TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1) ! { ! /* ?? This should be fixed in RENO by forcing ! default constructors to exist. */ ! SET_BINFO_BASEINIT_MARKED (binfo); ! binfo = BINFO_BASETYPE (binfo, 0); ! } if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))) *************** *** 574,578 **** if (! immediately) { ! extern struct rtx_def *base_init_insns; do_pending_stack_adjust (); --- 573,577 ---- if (! immediately) { ! extern rtx base_init_insns; do_pending_stack_adjust (); *************** *** 620,624 **** binfo = TYPE_BINFO (type); } ! else my_friendly_abort (46); vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type)); --- 619,624 ---- binfo = TYPE_BINFO (type); } ! else ! my_friendly_abort (46); vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type)); *************** *** 918,922 **** try_member: ! field = lookup_field (type, name, 1); if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) --- 918,922 ---- try_member: ! field = lookup_field (type, name, 1, 0); if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) *************** *** 942,946 **** basetype = type; ! field = lookup_field (basetype, name, 0); if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name))) --- 942,946 ---- basetype = type; ! field = lookup_field (basetype, name, 0, 0); if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name))) *************** *** 1043,1047 **** This never calls operator=(). ! When initializing, nothing is CONST. */ void --- 1043,1054 ---- This never calls operator=(). ! When initializing, nothing is CONST. ! ! A default copy constructor may have to be used to perform the ! initialization. ! ! A constructor or a conversion operator may have to be used to ! perform the initialization, but not both, as it would be ambiguous. ! */ void *************** *** 1073,1077 **** } expand_vec_init (exp, exp, array_type_nelts (type), init, ! init && TREE_TYPE (init) == TREE_TYPE (exp)); TREE_READONLY (exp) = was_const; TREE_TYPE (exp) = type; --- 1080,1084 ---- } expand_vec_init (exp, exp, array_type_nelts (type), init, ! init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1)); TREE_READONLY (exp) = was_const; TREE_TYPE (exp) = type; *************** *** 1095,1098 **** --- 1102,1266 ---- } + static void + expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) + tree binfo; + tree true_exp, exp; + tree type; + tree init; + int alias_this; + int flags; + { + /* It fails because there may not be a constructor which takes + its own type as the first (or only parameter), but which does + take other types via a conversion. So, if the thing initializing + the expression is a unit element of type X, first try X(X&), + followed by initialization by X. If neither of these work + out, then look hard. */ + tree rval; + tree parms; + int xxref_init_possible; + + if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) + { + parms = init; + if (parms) init = TREE_VALUE (parms); + } + else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)) + { + convert_for_initialization (exp, type, init, 0, 0, 0, 0); + expand_expr_stmt (TREE_OPERAND (init, 0)); + return; + } + else parms = build_tree_list (NULL_TREE, init); + + if (TYPE_HAS_INIT_REF (type) + || init == NULL_TREE + || TREE_CHAIN (parms) != NULL_TREE) + xxref_init_possible = 0; + else + { + xxref_init_possible = LOOKUP_SPECULATIVELY; + flags &= ~LOOKUP_COMPLAIN; + } + + if (TYPE_USES_VIRTUAL_BASECLASSES (type)) + { + if (true_exp == exp) + parms = tree_cons (NULL_TREE, integer_one_node, parms); + else + parms = tree_cons (NULL_TREE, integer_zero_node, parms); + flags |= LOOKUP_HAS_IN_CHARGE; + } + rval = build_method_call (exp, constructor_name (type), + parms, binfo, flags|xxref_init_possible); + if (rval == NULL_TREE && xxref_init_possible) + { + /* It is an error to implement a default copy constructor if + (see ARM 12.8 for details) ... one case being if another + copy constructor already exists. */ + tree init_type = TREE_TYPE (init); + if (TREE_CODE (init_type) == REFERENCE_TYPE) + init_type = TREE_TYPE (init_type); + if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type) + || (IS_AGGR_TYPE (init_type) + && DERIVED_FROM_P (type, init_type))) + { + if (type == BINFO_TYPE (binfo) + && TYPE_USES_VIRTUAL_BASECLASSES (type)) + { + tree addr = build_unary_op (ADDR_EXPR, exp, 0); + expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE); + + expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, + exp, addr, 1)); + } + expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); + return; + } + else + rval = build_method_call (exp, constructor_name (type), parms, + binfo, flags); + } + + /* Private, protected, or otherwise unavailable. */ + if (rval == error_mark_node && (flags&LOOKUP_COMPLAIN)) + error_with_aggr_type (binfo, "in base initialization for class `%s'"); + /* A valid initialization using constructor. */ + else if (rval != error_mark_node && rval != NULL_TREE) + { + /* p. 222: if the base class assigns to `this', then that + value is used in the derived class. */ + if ((flag_this_is_variable & 1) && alias_this) + { + TREE_TYPE (rval) = TREE_TYPE (current_class_decl); + expand_assignment (current_class_decl, rval, 0, 0); + } + else + expand_expr_stmt (rval); + } + else if (parms && TREE_CHAIN (parms) == NULL_TREE) + { + /* If we are initializing one aggregate value + from another, and though there are constructors, + and none accept the initializer, just do a bitwise + copy. + + The above sounds wrong, ``If a class has any copy + constructor defined, the default copy constructor will + not be generated.'' 12.8 Copying Class Objects (mrs) + + @@ This should reject initializer which a constructor + @@ rejected on visibility gounds, but there is + @@ no way right now to recognize that case with + @@ just `error_mark_node'. */ + tree itype; + init = TREE_VALUE (parms); + itype = TREE_TYPE (init); + if (TREE_CODE (itype) == REFERENCE_TYPE) + { + init = convert_from_reference (init); + itype = TREE_TYPE (init); + } + itype = TYPE_MAIN_VARIANT (itype); + + /* This is currently how the default X(X&) constructor + is implemented. */ + if (comptypes (TYPE_MAIN_VARIANT (type), itype, 0)) + { + #if 0 + warning ("bitwise copy in initialization of type `%s'", + TYPE_NAME_STRING (type)); + #endif + rval = build (INIT_EXPR, type, exp, init); + expand_expr_stmt (rval); + } + else + { + error_with_aggr_type (binfo, "in base initialization for class `%s',"); + error_with_aggr_type (type, "invalid initializer to constructor for type `%s'"); + return; + } + } + else + { + if (init == NULL_TREE) + assert (parms == NULL_TREE); + if (parms == NULL_TREE && TREE_VIA_VIRTUAL (binfo)) + error_with_aggr_type (binfo, "virtual baseclass `%s' does not have default initializer"); + else + { + error_with_aggr_type (binfo, "in base initialization for class `%s',"); + /* This will make an error message for us. */ + build_method_call (exp, constructor_name (type), parms, binfo, + (TYPE_USES_VIRTUAL_BASECLASSES (type) + ? LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE + : LOOKUP_NORMAL)); + } + return; + } + /* Constructor has been called, but vtables may be for TYPE + rather than for FOR_TYPE. */ + } + /* This function is responsible for initializing EXP with INIT (if any). *************** *** 1173,1178 **** DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp); else ! DECL_RTL (TREE_OPERAND (init, 0)) ! = (struct rtx_def *)expand_expr (exp, 0, 0, 0); expand_expr_stmt (init); --- 1341,1345 ---- DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp); else ! DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, 0, 0, 0); expand_expr_stmt (init); *************** *** 1307,1312 **** /* See whether we can go through a type conversion operator. ! This wins over going through a constructor because we may be ! able to avoid an X(X&) constructor. */ if (TREE_CODE (init) != TREE_LIST) { --- 1474,1479 ---- /* See whether we can go through a type conversion operator. ! This wins over going through a non-existent constructor. If ! there is a constructor, it is ambiguous. */ if (TREE_CODE (init) != TREE_LIST) { *************** *** 1320,1324 **** if (rval) { ! expand_assignment (exp, rval, 0, 0); return; } --- 1487,1509 ---- if (rval) { ! /* See if there is a constructor for``type'' that takes a ! ``ttype''-typed object. */ ! tree parms = build_tree_list (NULL_TREE, init); ! tree as_cons = NULL_TREE; ! if (TYPE_HAS_CONSTRUCTOR (type)) ! as_cons = build_method_call (exp, constructor_name (type), ! parms, binfo, ! LOOKUP_SPECULATIVELY); ! if (as_cons != NULL_TREE && as_cons != error_mark_node) ! { ! tree name = TYPE_NAME (type); ! if (TREE_CODE (name) == TYPE_DECL) ! name = DECL_NAME (name); ! /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */ ! error ("ambiguity between conversion to `%s' and constructor", ! IDENTIFIER_POINTER (name)); ! } ! else ! expand_assignment (exp, rval, 0, 0); return; } *************** *** 1327,1478 **** } ! if (TYPE_HAS_CONSTRUCTOR (type)) ! { ! /* It fails because there may not be a constructor which takes ! its own type as the first (or only parameter), but which does ! take other types via a conversion. So, if the thing initializing ! the expression is a unit element of type X, first try X(X&), ! followed by initialization by X. If neither of these work ! out, then look hard. */ ! tree parms; ! int xxref_init_possible; ! ! if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) ! { ! parms = init; ! if (parms) init = TREE_VALUE (parms); ! } ! else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)) ! { ! convert_for_initialization (exp, type, init, 0, 0, 0, 0); ! expand_expr_stmt (TREE_OPERAND (init, 0)); ! return; ! } ! else parms = build_tree_list (NULL_TREE, init); ! ! if (TYPE_HAS_INIT_REF (type) ! || init == NULL_TREE ! || TREE_CHAIN (parms) != NULL_TREE) ! xxref_init_possible = 0; ! else ! { ! xxref_init_possible = LOOKUP_SPECULATIVELY; ! flags &= ~LOOKUP_COMPLAIN; ! } ! ! if (TYPE_USES_VIRTUAL_BASECLASSES (type)) ! { ! if (true_exp == exp) ! parms = tree_cons (NULL_TREE, integer_one_node, parms); ! else ! parms = tree_cons (NULL_TREE, integer_zero_node, parms); ! flags |= LOOKUP_HAS_IN_CHARGE; ! } ! rval = build_method_call (exp, constructor_name (type), ! parms, binfo, flags|xxref_init_possible); ! if (rval == NULL_TREE && xxref_init_possible) ! { ! tree init_type = TREE_TYPE (init); ! if (TREE_CODE (init_type) == REFERENCE_TYPE) ! init_type = TREE_TYPE (init_type); ! if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type) ! || (IS_AGGR_TYPE (init_type) ! && DERIVED_FROM_P (type, init_type))) ! { ! if (type == BINFO_TYPE (binfo) ! && TYPE_USES_VIRTUAL_BASECLASSES (type)) ! { ! tree addr = build_unary_op (ADDR_EXPR, exp, 0); ! expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE); ! ! expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, exp, addr, 1)); ! } ! expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); ! return; ! } ! else ! rval = build_method_call (exp, constructor_name (type), parms, ! binfo, flags); ! } ! ! /* Private, protected, or otherwise unavailable. */ ! if (rval == error_mark_node && (flags&LOOKUP_COMPLAIN)) ! error_with_aggr_type (binfo, "in base initialization for class `%s'"); ! /* A valid initialization using constructor. */ ! else if (rval != error_mark_node && rval != NULL_TREE) ! { ! /* p. 222: if the base class assigns to `this', then that ! value is used in the derived class. */ ! if ((flag_this_is_variable & 1) && alias_this) ! { ! TREE_TYPE (rval) = TREE_TYPE (current_class_decl); ! expand_assignment (current_class_decl, rval, 0, 0); ! } ! else ! expand_expr_stmt (rval); ! } ! else if (parms && TREE_CHAIN (parms) == NULL_TREE) ! { ! /* If we are initializing one aggregate value ! from another, and though there are constructors, ! and none accept the initializer, just do a bitwise ! copy. ! ! @@ The above sounds wrong, ``If a class has any copy ! @@ constructor defined, the default copy constructor will ! @@ not be generated.'' 12.8 Copying Class Objects -- mrs ! ! @@ This should reject initializer which a constructor ! @@ rejected on visibility gounds, but there is ! @@ no way right now to recognize that case with ! @@ just `error_mark_node'. */ ! tree itype; ! init = TREE_VALUE (parms); ! itype = TREE_TYPE (init); ! if (TREE_CODE (itype) == REFERENCE_TYPE) ! { ! init = convert_from_reference (init); ! itype = TREE_TYPE (init); ! } ! itype = TYPE_MAIN_VARIANT (itype); ! ! /* This is currently how the default X(X&) constructor ! is implemented. */ ! if (comptypes (TYPE_MAIN_VARIANT (type), itype, 0)) ! { ! #if 0 ! warning ("bitwise copy in initialization of type `%s'", ! TYPE_NAME_STRING (type)); ! #endif ! rval = build (INIT_EXPR, type, exp, init); ! expand_expr_stmt (rval); ! } ! else ! { ! error_with_aggr_type (binfo, "in base initialization for class `%s',"); ! error_with_aggr_type (type, "invalid initializer to constructor for type `%s'"); ! return; ! } ! } ! else ! { ! if (init == NULL_TREE) ! assert (parms == NULL_TREE); ! if (parms == NULL_TREE && TREE_VIA_VIRTUAL (binfo)) ! error_with_aggr_type (binfo, "virtual baseclass `%s' does not have default initializer"); ! else ! { ! error_with_aggr_type (binfo, "in base initialization for class `%s',"); ! /* This will make an error message for us. */ ! build_method_call (exp, constructor_name (type), parms, binfo, ! (TYPE_USES_VIRTUAL_BASECLASSES (type) ! ? LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE ! : LOOKUP_NORMAL)); ! } ! return; ! } ! /* Constructor has been called, but vtables may be for TYPE ! rather than for FOR_TYPE. */ ! } else if (TREE_CODE (type) == ARRAY_TYPE) { --- 1512,1523 ---- } ! /* Handle default copy constructors here, does not matter if there is ! a constructor or not. */ ! if (type == init_type && IS_AGGR_TYPE (type) ! && init && TREE_CODE (init) != TREE_LIST) ! expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags); ! /* Not sure why this is here... */ ! else if (TYPE_HAS_CONSTRUCTOR (type)) ! expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags); else if (TREE_CODE (type) == ARRAY_TYPE) { *************** *** 1483,1487 **** } else ! expand_recursive_init (binfo, true_exp, exp, init, CLASSTYPE_BASE_INIT_LIST (type), alias_this); } --- 1528,1533 ---- } else ! expand_recursive_init (binfo, true_exp, exp, init, ! CLASSTYPE_BASE_INIT_LIST (type), alias_this); } *************** *** 1683,1698 **** { basetype_path = NULL_TREE; ! decl = build1 (NOP_EXPR, ! TYPE_POINTER_TO (IDENTIFIER_TYPE_VALUE (cname)), ! error_mark_node); } else if (current_class_decl == 0) { dont_use_this = 1; ! decl = build1 (NOP_EXPR, ! TYPE_POINTER_TO (IDENTIFIER_TYPE_VALUE (cname)), ! error_mark_node); } - else decl = current_class_decl; if (t = lookup_fnfields (TYPE_BINFO (type), method_name, 0)) --- 1729,1745 ---- { basetype_path = NULL_TREE; ! decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node); } else if (current_class_decl == 0) { dont_use_this = 1; ! decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node); ! } ! else ! { ! decl = current_class_decl; ! if (TREE_TYPE (decl) != type) ! decl = convert (TYPE_POINTER_TO (type), decl); } if (t = lookup_fnfields (TYPE_BINFO (type), method_name, 0)) *************** *** 1700,1704 **** LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); if (TREE_CODE (name) == IDENTIFIER_NODE ! && (t = lookup_field (TYPE_BINFO (type), name, 1))) { if (t == error_mark_node) --- 1747,1751 ---- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL); if (TREE_CODE (name) == IDENTIFIER_NODE ! && (t = lookup_field (TYPE_BINFO (type), name, 1, 0))) { if (t == error_mark_node) *************** *** 1813,1817 **** fnfields = lookup_fnfields (TYPE_BINFO (type), name, 0); ! fields = lookup_field (type, name, 0); if (fields == error_mark_node) --- 1860,1864 ---- fnfields = lookup_fnfields (TYPE_BINFO (type), name, 0); ! fields = lookup_field (type, name, 0, 0); if (fields == error_mark_node) *************** *** 1827,1831 **** } else if (current_class_decl == 0) ! decl = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (cname)), error_mark_node); else decl = C_C_D; --- 1874,1878 ---- } else if (current_class_decl == 0) ! decl = build1 (NOP_EXPR, IDENTIFIER_TYPE_VALUE (cname), error_mark_node); else decl = C_C_D; *************** *** 1917,1921 **** error message. */ ! t = lookup_field (basetypes, name, 1); if (t == error_mark_node) --- 1964,1968 ---- error message. */ ! t = lookup_field (basetypes, name, 1, 0); if (t == error_mark_node) *************** *** 2211,2215 **** list will either be of aggregate type or error_mark_node. */ ! /* Tell if this function specified by FUNCTION_DECL can be a friend of type TYPE. Return nonzero if friend, zero otherwise. --- 2258,2262 ---- list will either be of aggregate type or error_mark_node. */ ! /* Tell if this function specified by DECL can be a friend of type TYPE. Return nonzero if friend, zero otherwise. *************** *** 2433,2439 **** /* 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. --- 2480,2490 ---- /* Main friend processor. This is large, and for modularity purposes, ! has been removed from grokdeclarator. It always returns `void_type_node'. ! That value is in turn returned by `grokdeclarator' into cp-parse.y which ! sees that `void_type_node' was returned when trying to grok some ! declaration (in this case a friend declaration) appearing within a ! classtype definition. cp-parse.y knows that `void_type_node' means ! that a friend declaration was grok'ed, and thus it avoids adding ! anything new to the list of members of the current class in such cases. CTYPE is the class this friend belongs to. *************** *** 2470,2475 **** do { ! if (TREE_TYPE (TREE_VALUE (previous_decl)) ! == TREE_TYPE (decl)) { previous_decl = TREE_VALUE (previous_decl); --- 2521,2525 ---- do { ! if (TREE_TYPE (TREE_VALUE (previous_decl)) == TREE_TYPE (decl)) { previous_decl = TREE_VALUE (previous_decl); *************** *** 2515,2521 **** --- 2565,2573 ---- make_decl_rtl (decl, NULL_TREE, 1); add_friend (current_class_type, decl); + /* decl = void_type_node; */ } else xref_friend (current_class_type, decl, ctype); + /* decl = void_type_node; */ DECL_FRIEND_P (decl) = 1; } *************** *** 2541,2545 **** else xref_friends (current_class_type, declarator, ctype); ! decl = void_type_node; } } --- 2593,2597 ---- else xref_friends (current_class_type, declarator, ctype); ! /* decl = void_type_node; */ } } *************** *** 2568,2572 **** TREE_GETS_DELETE (current_class_type) = 0; } ! decl = void_type_node; } /* A global friend. --- 2620,2624 ---- TREE_GETS_DELETE (current_class_type) = 0; } ! /* decl = void_type_node; */ } /* A global friend. *************** *** 2604,2607 **** --- 2656,2660 ---- TREE_OVERLOADED (declarator) = 1; decl = push_overloaded_decl (decl, 1); + /* decl = void_type_node; */ } else *************** *** 2632,2638 **** else make_friend_class (current_class_type, TREE_TYPE (decl)); ! decl = void_type_node; } ! return decl; } --- 2685,2691 ---- else make_friend_class (current_class_type, TREE_TYPE (decl)); ! /* decl = void_type_node; */ } ! return void_type_node; } *************** *** 2722,2725 **** --- 2775,2784 ---- not. + Note that build_new does nothing to assure that any special + alignment requirements of the type are met. Rather, it leaves + it up to malloc to do the right thing. Otherwise, folding to + the right alignment cal cause problems if the user tries to later + free the memory returned by `new'. + PLACEMENT is the `placement' list for user-defined operator new (). */ *************** *** 2734,2738 **** tree init1 = NULL_TREE, nelts; int has_call = 0, has_array = 0; ! tree alignment = NULL_TREE; tree pending_sizes = NULL_TREE; --- 2793,2797 ---- tree init1 = NULL_TREE, nelts; int has_call = 0, has_array = 0; ! tree pending_sizes = NULL_TREE; *************** *** 2800,2803 **** --- 2859,2868 ---- return error_mark_node; + /* ``A reference cannot be created by the new operator. A reference + is not an object (8.2.2, 8.4.3), so a pointer to it could not be + returned by new.'' ARM 5.3.3 */ + if (TREE_CODE (type) == REFERENCE_TYPE) + error ("new cannot be applied to a reference type"); + type = TYPE_MAIN_VARIANT (type); if (type == void_type_node) *************** *** 2879,2896 **** size = size_in_bytes (type); - #if 0 - /* This causes troubles when the user attempts to free the storage - returned by `new'. Bottom line: it's up to malloc to do the - right thing. */ - - /* If this type has special alignment requirements, deal with them here. */ - if (TYPE_ALIGN (type) > BITS_PER_WORD) - { - alignment = fold (build (MINUS_EXPR, integer_type_node, - c_alignof (type), integer_one_node)); - size = fold (build (PLUS_EXPR, integer_type_node, size, alignment)); - } - #endif - if (has_call) init = init1; --- 2944,2947 ---- *************** *** 2945,3050 **** #endif ! if (has_array) { ! if (placement) ! { ! error ("placement syntax invalid for arrays"); ! return error_mark_node; ! } ! if (TYPE_NEEDS_DESTRUCTOR (true_type)) ! { ! tree extra = BI_header_size; ! tree cookie, exp1, exp2; ! size = size_binop (PLUS_EXPR, size, extra); ! rval = build_builtin_call (ptr_type_node, BIN, ! build_tree_list (NULL_TREE, size)); ! rval = convert (string_type_node, rval); /* lets not add void* and ints */ ! rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra)); ! /* Store header info. */ ! cookie = build_indirect_ref (build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type), ! rval, extra), 0); ! exp1 = build (MODIFY_EXPR, void_type_node, ! build_component_ref (cookie, get_identifier ("nelts"), 0, 0), ! nelts); ! TREE_SIDE_EFFECTS (exp1) = 1; ! exp2 = build (MODIFY_EXPR, void_type_node, ! build_component_ref (cookie, get_identifier ("ptr_2comp"), 0, 0), ! build (MINUS_EXPR, ptr_type_node, integer_zero_node, rval)); ! TREE_SIDE_EFFECTS (exp2) = 1; ! rval = convert (build_pointer_type (true_type), rval); ! TREE_CALLS_NEW (rval) = 1; ! TREE_SIDE_EFFECTS (rval) = 1; ! rval = build_compound_expr (tree_cons (NULL_TREE, exp1, ! tree_cons (NULL_TREE, exp2, ! build_tree_list (NULL_TREE, rval)))); ! } else { ! rval = save_expr (build_builtin_call (build_pointer_type (true_type), ! BIN, ! build_tree_list (NULL_TREE, ! size))); } } else { ! if (TYPE_LANG_SPECIFIC (true_type) ! && (TREE_GETS_NEW (true_type) && !use_global_new)) ! rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL, ! TYPE_POINTER_TO (true_type), size, placement); ! else if (placement) { ! rval = build_opfncall (NEW_EXPR, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, ptr_type_node, size, placement); ! rval = convert (TYPE_POINTER_TO (true_type), rval); } ! else if (flag_this_is_variable > 0 ! && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) { ! if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) ! rval = NULL_TREE; ! else ! { ! error ("constructors take parameter lists"); ! return error_mark_node; ! } } ! else { ! rval = build_builtin_call (build_pointer_type (true_type), ! BIN, build_tree_list (NULL_TREE, size)); ! #if 0 ! /* See comment above as to why this is disabled. */ ! if (alignment) ! { ! rval = build (PLUS_EXPR, TYPE_POINTER_TO (true_type), rval, alignment); ! rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (true_type), ! rval, build1 (BIT_NOT_EXPR, integer_type_node, alignment)); ! } ! #endif ! TREE_CALLS_NEW (rval) = 1; ! TREE_SIDE_EFFECTS (rval) = 1; ! } ! /* We've figured out where the allocation is to go. ! If we're not eliding constructors, then if a constructor ! is defined, we must go through it. */ ! if ((rval == NULL_TREE || !flag_elide_constructors) ! && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) ! { ! /* Constructors are never virtual. */ ! int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL; ! ! if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) ! { ! init = tree_cons (NULL_TREE, integer_one_node, init); ! flags |= LOOKUP_HAS_IN_CHARGE; ! } ! rval = build_method_call (rval, constructor_name (true_type), ! init, NULL_TREE, flags); TREE_HAS_CONSTRUCTOR (rval) = 1; goto done; } } if (rval == error_mark_node) return error_mark_node; --- 2996,3110 ---- #endif ! /* Get a little extra space to store a couple of things before the new'ed ! array. */ ! if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type)) { ! tree extra = BI_header_size; ! size = size_binop (PLUS_EXPR, size, extra); ! } ! /* Allocate the object. */ ! if (TYPE_LANG_SPECIFIC (true_type) ! && (TREE_GETS_NEW (true_type) && !use_global_new)) ! rval = build_opfncall (NEW_EXPR, LOOKUP_NORMAL, ! TYPE_POINTER_TO (true_type), size, placement); ! else if (placement) ! { ! rval = build_opfncall (NEW_EXPR, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, ! ptr_type_node, size, placement); ! rval = convert (TYPE_POINTER_TO (true_type), rval); ! } ! else if (flag_this_is_variable > 0 ! && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) ! { ! if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) ! rval = NULL_TREE; else { ! error ("constructors take parameter lists"); ! return error_mark_node; } } else { ! rval = build_builtin_call (build_pointer_type (true_type), ! BIN, build_tree_list (NULL_TREE, size)); ! #if 0 ! /* See comment above as to why this is disabled. */ ! if (alignment) { ! rval = build (PLUS_EXPR, TYPE_POINTER_TO (true_type), rval, ! alignment); ! rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (true_type), ! rval, build1 (BIT_NOT_EXPR, integer_type_node, ! alignment)); } ! #endif ! TREE_CALLS_NEW (rval) = 1; ! TREE_SIDE_EFFECTS (rval) = 1; ! } ! ! /* if rval is NULL_TREE I don't have to allocate it, but are we totally ! sure we have some extra bytes in that case for the BI_header_size ! cookies? And how does that interact with the code below? (mrs) */ ! /* Finish up some magic for new'ed arrays */ ! if (has_array && TYPE_NEEDS_DESTRUCTOR (true_type) && rval != NULL_TREE) ! { ! tree extra = BI_header_size; ! tree cookie, exp1, exp2; ! rval = convert (ptr_type_node, rval); /* convert to void * first */ ! rval = convert (string_type_node, rval); /* lets not add void* and ints */ ! rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra)); ! /* Store header info. */ ! cookie = build_indirect_ref (build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type), ! rval, extra), 0); ! exp1 = build (MODIFY_EXPR, void_type_node, ! build_component_ref (cookie, get_identifier ("nelts"), 0, 0), ! nelts); ! TREE_SIDE_EFFECTS (exp1) = 1; ! exp2 = build (MODIFY_EXPR, void_type_node, ! build_component_ref (cookie, get_identifier ("ptr_2comp"), 0, 0), ! build (MINUS_EXPR, ptr_type_node, integer_zero_node, rval)); ! TREE_SIDE_EFFECTS (exp2) = 1; ! rval = convert (build_pointer_type (true_type), rval); ! TREE_CALLS_NEW (rval) = 1; ! TREE_SIDE_EFFECTS (rval) = 1; ! rval = build_compound_expr (tree_cons (NULL_TREE, exp1, ! tree_cons (NULL_TREE, exp2, ! build_tree_list (NULL_TREE, rval)))); ! } ! ! /* We've figured out where the allocation is to go. ! If we're not eliding constructors, then if a constructor ! is defined, we must go through it. */ ! if (!has_array && (rval == NULL_TREE || !flag_elide_constructors) ! && TYPE_HAS_CONSTRUCTOR (true_type) && init != void_type_node) ! { ! tree newrval; ! /* Constructors are never virtual. */ ! int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL; ! /* If a copy constructor might work, set things up so that we can ! try that after this. */ ! if (rval != NULL_TREE) ! flags = ~LOOKUP_COMPLAIN & (flags|LOOKUP_SPECULATIVELY); ! ! if (rval && TYPE_USES_VIRTUAL_BASECLASSES (true_type)) { ! init = tree_cons (NULL_TREE, integer_one_node, init); ! flags |= LOOKUP_HAS_IN_CHARGE; } ! newrval = build_method_call (rval, constructor_name (true_type), ! init, NULL_TREE, flags); ! if (newrval) { ! rval = newrval; TREE_HAS_CONSTRUCTOR (rval) = 1; goto done; } + /* Didn't find the constructor, maybe it is a call to a copy constructor + that we should implement. */ } + if (rval == error_mark_node) return error_mark_node; *************** *** 3056,3060 **** goto done; ! if (TYPE_NEEDS_CONSTRUCTING (type)) { extern tree static_aggregates; --- 3116,3121 ---- goto done; ! if (TYPE_NEEDS_CONSTRUCTING (type) ! || (has_call || init)) { extern tree static_aggregates; *************** *** 3111,3118 **** --- 3172,3183 ---- } } + #if 0 + /* It would seem that the above code handles this better than the code + below. (mrs) */ else if (has_call || init) { if (IS_AGGR_TYPE (type)) { + /* default copy constructor may be missing from the below. (mrs) */ error_with_aggr_type (type, "no constructor for type `%s'"); rval = error_mark_node; *************** *** 3122,3125 **** --- 3187,3191 ---- /* New 2.0 interpretation: `new int (10)' means allocate an int, and initialize it with 10. */ + init = build_c_cast (type, init); rval = build (COMPOUND_EXPR, TREE_TYPE (rval), *************** *** 3130,3133 **** --- 3196,3200 ---- } } + #endif done: if (pending_sizes) *************** *** 3215,3219 **** table. Return the result of the call to the ctor. */ import_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (type), import_ptr); ! return build_method_call (import_ptr, TYPE_IDENTIFIER (type), tree_cons (NULL_TREE, import_tmp, parms), NULL_TREE, LOOKUP_DYNAMIC); --- 3282,3286 ---- table. Return the result of the call to the ctor. */ import_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (type), import_ptr); ! return build_method_call (import_ptr, constructor_name (type), tree_cons (NULL_TREE, import_tmp, parms), NULL_TREE, LOOKUP_DYNAMIC); *************** *** 3287,3290 **** --- 3354,3358 ---- expand_vec_init (decl, base, maxindex, init, from_array) tree decl, base, maxindex, init; + int from_array; { tree rval; *************** *** 3376,3380 **** { if (decl == NULL_TREE ! || (init && TREE_TYPE (init) != TREE_TYPE (decl))) { sorry ("initialization of array from dissimilar array type"); --- 3444,3448 ---- { if (decl == NULL_TREE ! || (init && !comptypes (TREE_TYPE (init), TREE_TYPE (decl), 1))) { sorry ("initialization of array from dissimilar array type"); *************** *** 3456,3465 **** /* Free up storage of type TYPE, at address ADDR. - TYPE is a POINTER_TYPE. This does not call any destructors. */ tree ! build_x_delete (type, addr, use_global_delete) ! tree type, addr; int use_global_delete; { --- 3524,3542 ---- /* Free up storage of type TYPE, at address ADDR. + TYPE is a POINTER_TYPE and can be ptr_type_node for no special type + of pointer. + + VIRTUAL_SIZE is the ammount of storage that was allocated, and is + used as the second argument to operator delete. It can include + things like padding and magic size cookies. It has virtual in it, + because if you have a base pointer and you delete through a virtual + destructor, it should be the size of the dynamic object, not the + static object, see Free Store 12.5 ANSI C++ WP. + This does not call any destructors. */ tree ! build_x_delete (type, addr, use_global_delete, virtual_size) ! tree type, addr, virtual_size; int use_global_delete; { *************** *** 3469,3475 **** && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) && TREE_GETS_DELETE (TREE_TYPE (type))) ! rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr); else ! rval = build_builtin_call (void_type_node, BID, build_tree_list (NULL_TREE, addr)); return rval; } --- 3546,3555 ---- && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) && TREE_GETS_DELETE (TREE_TYPE (type))) ! rval = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, virtual_size); else ! rval = build_builtin_call (void_type_node, BID, ! tree_cons (NULL_TREE, addr, ! build_tree_list (NULL_TREE, ! virtual_size))); return rval; } *************** *** 3566,3573 **** if (! IS_AGGR_TYPE (type)) { if (maybe_adjust) addr = maybe_adjust_addr_for_delete (addr); return build_builtin_call (void_type_node, BID, ! build_tree_list (NULL_TREE, addr)); } if (TREE_SIDE_EFFECTS (addr)) --- 3646,3660 ---- if (! IS_AGGR_TYPE (type)) { + tree virtual_size; + + /* This is probably wrong. It should be the size of the virtual + object being deleted. */ + virtual_size = c_sizeof (type); + if (maybe_adjust) addr = maybe_adjust_addr_for_delete (addr); return build_builtin_call (void_type_node, BID, ! tree_cons (NULL_TREE, addr, ! build_tree_list (NULL_TREE, virtual_size))); } if (TREE_SIDE_EFFECTS (addr)) *************** *** 3610,3613 **** --- 3697,3706 ---- if (! TYPE_NEEDS_DESTRUCTOR (type)) { + tree virtual_size; + + /* This is probably wrong. It should be the size of the virtual object + being deleted. */ + virtual_size = c_sizeof (type); + if (auto_delete == integer_zero_node) return void_zero_node; *************** *** 3615,3621 **** addr = maybe_adjust_addr_for_delete (addr); if (TREE_GETS_DELETE (type) && !use_global_delete) ! return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr); return build_builtin_call (void_type_node, BID, ! build_tree_list (NULL_TREE, addr)); } parms = build_tree_list (NULL_TREE, addr); --- 3708,3715 ---- addr = maybe_adjust_addr_for_delete (addr); if (TREE_GETS_DELETE (type) && !use_global_delete) ! return build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, virtual_size); return build_builtin_call (void_type_node, BID, ! tree_cons (NULL_TREE, addr, ! build_tree_list (NULL_TREE, virtual_size))); } parms = build_tree_list (NULL_TREE, addr); *************** *** 3736,3740 **** else { ! expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr); if (expr == error_mark_node) return error_mark_node; --- 3830,3841 ---- else { ! tree virtual_size; ! ! /* This is probably wrong. It should be the size of the ! virtual object being deleted. */ ! virtual_size = c_sizeof (type); ! ! expr = build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, addr, ! virtual_size); if (expr == error_mark_node) return error_mark_node; *************** *** 3749,3756 **** || (TREE_VIA_VIRTUAL (child) == 0 && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (child)))) ! cond = build (COND_EXPR, void_type_node, ! build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node), ! build_builtin_call (void_type_node, BID, build_tree_list (NULL_TREE, addr)), ! void_zero_node); else cond = NULL_TREE; --- 3850,3867 ---- || (TREE_VIA_VIRTUAL (child) == 0 && ! TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (child)))) ! { ! tree virtual_size; ! ! /* This is probably wrong. It should be the size of the virtual ! object being deleted. */ ! virtual_size = c_sizeof (type); ! ! cond = build (COND_EXPR, void_type_node, ! build (BIT_AND_EXPR, integer_type_node, auto_delete, integer_one_node), ! build_builtin_call (void_type_node, BID, ! tree_cons (NULL_TREE, addr, ! build_tree_list (NULL_TREE, virtual_size))), ! void_zero_node); ! } else cond = NULL_TREE; *************** *** 3862,3866 **** tree ptype = TREE_TYPE (base); tree type; ! tree rval; /* Temporary variables used by the loop. */ tree tbase, size_exp, tbase_init; --- 3973,3977 ---- tree ptype = TREE_TYPE (base); tree type; ! tree virtual_size; /* Temporary variables used by the loop. */ tree tbase, size_exp, tbase_init; *************** *** 3914,3917 **** --- 4025,4030 ---- ptype = TYPE_POINTER_TO (type); + size_exp = size_in_bytes (type); + if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type)) { *************** *** 3920,3932 **** } ! size_exp = size_in_bytes (type); tbase = build_decl (VAR_DECL, NULL_TREE, ptype); tbase_init = build_modify_expr (tbase, NOP_EXPR, fold (build (PLUS_EXPR, ptype, base, ! size_binop (MULT_EXPR, ! size_exp, ! maxindex)))); ! TREE_REGDECL (tbase) = 1; controller = build (BIND_EXPR, void_type_node, tbase, 0, 0); TREE_SIDE_EFFECTS (controller) = 1; --- 4033,4045 ---- } ! /* The below is short by BI_header_size */ ! virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex)); ! tbase = build_decl (VAR_DECL, NULL_TREE, ptype); tbase_init = build_modify_expr (tbase, NOP_EXPR, fold (build (PLUS_EXPR, ptype, base, ! virtual_size))); ! DECL_REGISTER (tbase) = 1; controller = build (BIND_EXPR, void_type_node, tbase, 0, 0); TREE_SIDE_EFFECTS (controller) = 1; *************** *** 3941,3946 **** convert (ptr_type_node, base), BI_header_size)); body = build_tree_list (NULL_TREE, ! build_x_delete (ptr_type_node, base_tbd, 0)); body = build (COND_EXPR, void_type_node, build (BIT_AND_EXPR, integer_type_node, --- 4054,4062 ---- convert (ptr_type_node, base), BI_header_size)); + /* This is the real size */ + virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); body = build_tree_list (NULL_TREE, ! build_x_delete (ptr_type_node, base_tbd, 0, ! virtual_size)); body = build (COND_EXPR, void_type_node, build (BIT_AND_EXPR, integer_type_node, *************** *** 3980,3992 **** { tree base_tbd; if (loop == integer_zero_node) /* no header */ base_tbd = base; else ! base_tbd = convert (ptype, ! build_binary_op (MINUS_EXPR, ! convert (string_type_node, base), ! BI_header_size)); ! deallocate_expr = build_x_delete (ptr_type_node, base_tbd, 1); if (auto_delete_vec != integer_one_node) deallocate_expr = build (COND_EXPR, void_type_node, --- 4096,4117 ---- { tree base_tbd; + + /* The below is short by BI_header_size */ + virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex)); + if (loop == integer_zero_node) /* no header */ base_tbd = base; else ! { ! base_tbd = convert (ptype, ! build_binary_op (MINUS_EXPR, ! convert (string_type_node, base), ! BI_header_size)); ! /* True size with header. */ ! virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size); ! } ! deallocate_expr = build_x_delete (ptr_type_node, base_tbd, 1, ! virtual_size); if (auto_delete_vec != integer_one_node) deallocate_expr = build (COND_EXPR, void_type_node, diff -rc2N gcc-2.2.2/cp-input.c gcc-2.3.1/cp-input.c *** gcc-2.2.2/cp-input.c Thu Jun 11 00:24:50 1992 --- gcc-2.3.1/cp-input.c Thu Sep 17 20:01:37 1992 *************** *** 29,33 **** inlining). */ ! #include #include #include "obstack.h" --- 29,33 ---- inlining). */ ! #include "assert.h" #include #include "obstack.h" *************** *** 105,108 **** --- 105,109 ---- feed_input (str, len, delete) char *str; + int len; struct obstack *delete; { diff -rc2N gcc-2.2.2/cp-lex.c gcc-2.3.1/cp-lex.c *** gcc-2.2.2/cp-lex.c Thu Jun 11 00:25:49 1992 --- gcc-2.3.1/cp-lex.c Tue Oct 20 14:54:29 1992 *************** *** 1,3 **** ! /* Separate lexical analyzer for GNU C++. Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) --- 1,3 ---- ! /* Seperate lexical analyzer for GNU C++. Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) *************** *** 26,30 **** #include #include - #include #include "config.h" #include "input.h" --- 26,29 ---- *************** *** 35,40 **** #include "flags.h" #include "obstack.h" ! #include extern int errno; /* needed for VAX. */ extern jmp_buf toplevel; --- 34,47 ---- #include "flags.h" #include "obstack.h" ! #include "assert.h" ! ! #ifdef MULTIBYTE_CHARS ! #include ! #include ! #endif ! ! #ifndef errno extern int errno; /* needed for VAX. */ + #endif extern jmp_buf toplevel; *************** *** 42,48 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - extern struct obstack *expression_obstack, permanent_obstack; extern struct obstack *current_obstack, *saveable_obstack; --- 49,52 ---- *************** *** 56,69 **** #ifndef FILE_NAME_NONDIRECTORY #define FILE_NAME_NONDIRECTORY(X) \ ! (strrchr (X, '/') != 0 ? strrchr (X, '/') + 1 : X) #endif ! /* If you don't have strrchr, but instead have rindex, ! add your machine to this list, and send mail to ! tiemann@wheaties.ai.mit.edu. */ ! #if defined(sequent) || defined(convex) ! #define strrchr rindex ! #endif ! extern char *strrchr (); void extract_interface_info (); --- 60,69 ---- #ifndef FILE_NAME_NONDIRECTORY #define FILE_NAME_NONDIRECTORY(X) \ ! (rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X) #endif ! extern char *index (); ! extern char *rindex (); ! void extract_interface_info (); *************** *** 92,96 **** char **assignop_tab; - #define YYEMPTY -2 extern int yychar; /* the lookahead symbol */ extern YYSTYPE yylval; /* the semantic value of the */ --- 92,95 ---- *************** *** 233,242 **** /* lexical analyzer */ static int maxtoken; /* Current nominal length of token buffer. */ char *token_buffer; /* Pointer to token buffer. Actual allocated length is maxtoken + 2. */ - static int max_wide; /* Current nominal length of wide_buffer. */ - static int *wide_buffer; /* Pointer to wide-string buffer. - Actual allocated length is max_wide + 1. */ #define NORID RID_UNUSED --- 232,252 ---- /* lexical analyzer */ + /* File used for outputting assembler code. */ + extern FILE *asm_out_file; + + #ifndef WCHAR_TYPE_SIZE + #ifdef INT_TYPE_SIZE + #define WCHAR_TYPE_SIZE INT_TYPE_SIZE + #else + #define WCHAR_TYPE_SIZE BITS_PER_WORD + #endif + #endif + + /* Number of bytes in a wide character. */ + #define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT) + static int maxtoken; /* Current nominal length of token buffer. */ char *token_buffer; /* Pointer to token buffer. Actual allocated length is maxtoken + 2. */ #define NORID RID_UNUSED *************** *** 246,249 **** --- 256,262 ---- int check_newline (); + /* Nonzero tells yylex to ignore \ in string constants. */ + static int ignore_escape_flag = 0; + static int skip_white_space (); *************** *** 541,546 **** maxtoken = 40; token_buffer = (char *) xmalloc (maxtoken + 2); - max_wide = 40; - wide_buffer = (int *) xmalloc (max_wide + 1); ridpointers[(int) RID_INT] = get_identifier ("int"); --- 554,557 ---- *************** *** 597,600 **** --- 608,614 ---- /* C++ extensions. These are probably not correctly named. */ + ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t"); + SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR], + build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR])); class_type_node = build_int_2 (class_type, 0); TREE_TYPE (class_type_node) = class_type_node; *************** *** 845,849 **** /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */ ! if (strchr (s1, '.') || strchr (t1, '.')) continue; --- 859,863 ---- /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */ ! if (index (s1, '.') || index (t1, '.')) continue; *************** *** 883,887 **** else CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1; ! TREE_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type); TREE_PUBLIC (vars) = 1; } --- 897,901 ---- else CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1; ! DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type); TREE_PUBLIC (vars) = 1; } *************** *** 920,923 **** --- 934,938 ---- feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0); lineno = t->lineno; + #if 0 if (input_filename != t->filename) { *************** *** 926,929 **** --- 941,949 ---- extract_interface_info (); } + #else + input_filename = t->filename; + interface_unknown = t->interface == 1; + interface_only = t->interface == 0; + #endif yychar = PRE_PARSED_FUNCTION_DECL; } *************** *** 935,943 **** the `inline' state. */ && t->parm_vec == NULL_TREE) ! TREE_INLINE (t->fndecl) = 1; DECL_PENDING_INLINE_INFO (t->fndecl) = 0; } extern struct pending_input *to_be_restored; void --- 955,964 ---- the `inline' state. */ && t->parm_vec == NULL_TREE) ! DECL_INLINE (t->fndecl) = 1; DECL_PENDING_INLINE_INFO (t->fndecl) = 0; } extern struct pending_input *to_be_restored; + static int nextchar = -1; void *************** *** 958,966 **** * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're * hosed, feed back YYEMPTY. */ ! yychar = YYEMPTY; } ! else ! yychar = YYEMPTY; restore_pending_input (to_be_restored); to_be_restored = 0; --- 979,990 ---- * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're * hosed, feed back YYEMPTY. + * We also need to discard nextchar, since that may have gotten + * set as well. */ ! nextchar = -1; } ! yychar = YYEMPTY; ! if (to_be_restored == 0) ! my_friendly_abort (123); restore_pending_input (to_be_restored); to_be_restored = 0; *************** *** 979,986 **** the `inline' state. */ && i->parm_vec == NULL_TREE) ! TREE_INLINE (i->fndecl) = 1; DECL_PENDING_INLINE_INFO (i->fndecl) = 0; } ! extract_interface_info (); } --- 1003,1016 ---- the `inline' state. */ && i->parm_vec == NULL_TREE) ! DECL_INLINE (i->fndecl) = 1; DECL_PENDING_INLINE_INFO (i->fndecl) = 0; } ! if (i) ! { ! interface_unknown = i->interface == 1; ! interface_only = i->interface == 0; ! } ! else ! extract_interface_info (); } *************** *** 1021,1028 **** } - static int nextchar = -1; static int nextyychar = YYEMPTY; static YYSTYPE nextyylval; - static tree nextlastiddecl; struct pending_input { --- 1051,1056 ---- *************** *** 1139,1143 **** /* Assumption: In this (possibly) nested class sequence, only one name will have template parms. */ ! while (type) { tree decl = TYPE_NAME (type); --- 1167,1171 ---- /* Assumption: In this (possibly) nested class sequence, only one name will have template parms. */ ! while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't') { tree decl = TYPE_NAME (type); *************** *** 1161,1165 **** and we know no overrides will exist. Otherwise, we delay until end-of-file, to see if the definition is really required. */ ! if (TREE_INLINE (decl)) /* delay_to_eof == 0 */; else if (current_class_type && !interface_unknown) --- 1189,1193 ---- and we know no overrides will exist. Otherwise, we delay until end-of-file, to see if the definition is really required. */ ! if (DECL_INLINE (decl)) /* delay_to_eof == 0 */; else if (current_class_type && !interface_unknown) *************** *** 1250,1253 **** --- 1278,1284 ---- t->can_free = 1; t->deja_vu = 0; + t->interface = ((interface_unknown || processing_template_defn) + ? 1 + : (interface_only ? 0 : 2)); store_pending_inline (decl, t); } *************** *** 1475,1478 **** --- 1506,1512 ---- t->can_free = 0; t->deja_vu = 0; + t->interface = ((interface_unknown || processing_template_defn) + ? 1 + : (interface_only ? 0 : 2)); store_pending_inline (fn, t); /* We make this declaration private (static in the C sense). */ *************** *** 1482,1486 **** DECL_CLASS_CONTEXT (fn) = type; /* Show that this function was generated by the compiler. */ ! DECL_IGNORED_P (fn) = 1; return fn; } --- 1516,1520 ---- DECL_CLASS_CONTEXT (fn) = type; /* Show that this function was generated by the compiler. */ ! DECL_SOURCE_LINE (fn) = 0; return fn; } *************** *** 1777,1781 **** { char *main_filename = main_input_filename ? main_input_filename : input_filename; - char *tmp; while (c == ' ' || c == '\t') --- 1811,1814 ---- *************** *** 1816,1820 **** } } ! else if (main_input_filename == input_filename || ! strcmp (input_filename, main_filename)) { --- 1849,1854 ---- } } ! else if ((main_input_filename != 0 ! && ! strcmp (main_input_filename, input_filename)) || ! strcmp (input_filename, main_filename)) { *************** *** 1890,1898 **** && ((c = getch ()) == ' ' || c == '\t')) { ! /* Conditionally used. */ extern FILE *asm_out_file; ! ! if (pedantic) ! error ("ANSI C does not allow #ident"); /* Here we have just seen `#ident '. --- 1924,1931 ---- && ((c = getch ()) == ' ' || c == '\t')) { ! #ifdef ASM_OUTPUT_IDENT extern FILE *asm_out_file; ! #endif ! /* #ident. The pedantic warning is now in cccp.c. */ /* Here we have just seen `#ident '. *************** *** 1915,1921 **** } #ifdef ASM_OUTPUT_IDENT ! ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype)); #endif /* Skip the rest of this line. */ --- 1948,1958 ---- } + if (! flag_no_ident) + { #ifdef ASM_OUTPUT_IDENT ! ASM_OUTPUT_IDENT (asm_out_file, ! TREE_STRING_POINTER (yylval.ttype)); #endif + } /* Skip the rest of this line. */ *************** *** 1980,1984 **** --- 2017,2025 ---- /* More follows: it must be a string constant (filename). */ + /* Read the string constant, but don't treat \ as special. */ + ignore_escape_flag = 1; token = real_yylex (); + ignore_escape_flag = 0; + if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) { *************** *** 2153,2156 **** --- 2194,2198 ---- register int code; unsigned firstdig; + int nonnull; switch (c) *************** *** 2159,2162 **** --- 2201,2205 ---- code = 0; count = 0; + nonnull = 0; while (1) { *************** *** 2174,2183 **** if (c >= '0' && c <= '9') code += c - '0'; ! if (count == 0) ! firstdig = code; ! count++; } ! if (count == 0) error ("\\x used with no following hex digits"); else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) || ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4)) --- 2217,2233 ---- if (c >= '0' && c <= '9') code += c - '0'; ! if (code != 0 || count != 0) ! { ! if (count == 0) ! firstdig = code; ! count++; ! } ! nonnull = 1; } ! if (! nonnull) error ("\\x used with no following hex digits"); + else if (count == 0) + /* Digits are all 0's. Ok. */ + ; else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) || ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4)) *************** *** 2234,2243 **** case '{': case '[': return c; } ! if (c >= 040 && c <= 0177) ! warning ("unknown escape sequence `\\%c'", c); else ! warning ("unknown escape sequence: `\\' followed by char code 0x%x", c); return c; } --- 2284,2295 ---- case '{': case '[': + if (pedantic) + pedwarn ("unknown escape sequence `\\%c'", c); return c; } ! if (c >= 040 && c < 0177) ! pedwarn ("unknown escape sequence `\\%c'", c); else ! pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c); return c; } *************** *** 2308,2312 **** { /* Could be from one of the base classes. */ ! tree field = lookup_field (current_class_type, token, 1); if (field == 0) ; --- 2360,2364 ---- { /* Could be from one of the base classes. */ ! tree field = lookup_field (current_class_type, token, 1, 0); if (field == 0) ; *************** *** 2331,2334 **** --- 2383,2394 ---- if (!id || id == error_mark_node) { + if (id == error_mark_node && current_class_type != NULL_TREE) + { + id = lookup_nested_field (token); + /* In lookup_nested_field(), we marked this so we can gracefully + leave this whole mess. */ + if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node) + return id; + } if (yychar == '(' || yychar == LEFT_RIGHT) { *************** *** 2432,2438 **** int wide_flag = 0; int dollar_seen = 0; ! static tree typename_scope_in_progress; - relex: if (nextchar >= 0) c = nextchar, nextchar = -1; --- 2492,2497 ---- int wide_flag = 0; int dollar_seen = 0; ! int i; if (nextchar >= 0) c = nextchar, nextchar = -1; *************** *** 2468,2472 **** /* yylloc.first_line = lineno; */ - reswitch: switch (c) { --- 2527,2530 ---- *************** *** 2743,2749 **** int numdigits = 0; /* for multi-precision arithmetic, ! we store only 8 live bits in each short, ! giving us 64 bits of reliable precision */ ! short shorts[8]; int overflow = 0; --- 2801,2806 ---- int numdigits = 0; /* for multi-precision arithmetic, ! we store only 8 live bits in each short. */ ! short shorts[MAX_SHORTS]; int overflow = 0; *************** *** 2754,2758 **** *p++ = c; ! for (count = 0; count < 8; count++) shorts[count] = 0; --- 2811,2815 ---- *p++ = c; ! for (count = 0; count < MAX_SHORTS; count++) shorts[count] = 0; *************** *** 2855,2859 **** numdigits++; ! for (count = 0; count < 8; count++) { shorts[count] *= base; --- 2912,2916 ---- numdigits++; ! for (count = 0; count < MAX_SHORTS; count++) { shorts[count] *= base; *************** *** 2866,2871 **** } ! if (shorts[7] >= 1<<8 ! || shorts[7] < - (1 << 8)) overflow = TRUE; --- 2923,2928 ---- } ! if (shorts[MAX_SHORTS - 1] >= 1<<8 ! || shorts[MAX_SHORTS - 1] < - (1 << 8)) overflow = TRUE; *************** *** 2930,2934 **** set_float_handler (handler); value = REAL_VALUE_ATOF (token_buffer); ! set_float_handler (0); } #ifdef ERANGE --- 2987,2991 ---- set_float_handler (handler); value = REAL_VALUE_ATOF (token_buffer); ! set_float_handler (NULL); } #ifdef ERANGE *************** *** 2937,2941 **** char *p1 = token_buffer; /* Check for "0.0" and variants; ! Sunos 4 spuriously returns ERANGE for them. */ while (*p1 == '0') p1++; if (*p1 == '.') --- 2994,2998 ---- char *p1 = token_buffer; /* Check for "0.0" and variants; ! SunOS 4 spuriously returns ERANGE for them. */ while (*p1 == '0') p1++; if (*p1 == '.') *************** *** 2966,2970 **** f_seen = 1; type = float_type_node; ! value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value); } else if (c == 'l' || c == 'L') --- 3023,3027 ---- f_seen = 1; type = float_type_node; ! value = real_value_truncate (TYPE_MODE (type), value); } else if (c == 'l' || c == 'L') *************** *** 3005,3008 **** --- 3062,3066 ---- { tree type; + HOST_WIDE_INT high, low; int spec_unsigned = 0; int spec_long = 0; *************** *** 3052,3055 **** --- 3110,3117 ---- put_back (c); + /* ??? This code assumes that everything but long long is 32-bits. + Probably this code needs to be replaced with code similar + to that in c-lex.c, but I don't want to do it. -- RK. */ + if ((overflow || shorts[7] || shorts[6] || shorts[5] || shorts[4]) && !spec_long_long) *************** *** 3064,3075 **** /* This is simplified by the fact that our constant is always positive. */ ! yylval.ttype ! = (build_int_2 ! ((((long)shorts[3]<<24) + ((long)shorts[2]<<16) ! + ((long)shorts[1]<<8) + (long)shorts[0]), ! (spec_long_long ! ? (((long)shorts[7]<<24) + ((long)shorts[6]<<16) ! + ((long)shorts[5]<<8) + (long)shorts[4]) ! : 0))); #if 0 --- 3126,3138 ---- /* This is simplified by the fact that our constant is always positive. */ ! high = low = 0; ! ! for (i = 0; i < MAX_SHORTS / 2; i++) ! { ! high |= (HOST_WIDE_INT) shorts[i + MAX_SHORTS / 2] << (i * 8); ! low |= (HOST_WIDE_INT) shorts[i] << (i * 8); ! } ! ! yylval.ttype = build_int_2 (low, high); #if 0 *************** *** 3214,3224 **** { register int result = 0; ! register num_chars = 0; unsigned width = TYPE_PRECISION (char_type_node); int max_chars; ! if (wide_flag) width = TYPE_PRECISION (integer_type_node); ! ! max_chars = TYPE_PRECISION (integer_type_node) / width; while (1) --- 3277,3295 ---- { register int result = 0; ! register int num_chars = 0; unsigned width = TYPE_PRECISION (char_type_node); int max_chars; ! if (wide_flag) ! { ! width = WCHAR_TYPE_SIZE; ! #ifdef MULTIBYTE_CHARS ! max_chars = MB_CUR_MAX; ! #else ! max_chars = 1; ! #endif ! } ! else ! max_chars = TYPE_PRECISION (integer_type_node) / width; while (1) *************** *** 3238,3242 **** if (width < HOST_BITS_PER_INT && (unsigned) c >= (1 << width)) ! warning ("escape sequence out of range for character"); } else if (c == '\n') --- 3309,3313 ---- if (width < HOST_BITS_PER_INT && (unsigned) c >= (1 << width)) ! pedwarn ("escape sequence out of range for character"); } else if (c == '\n') *************** *** 3285,3304 **** || ((result >> (num_bits - 1)) & 1) == 0) yylval.ttype ! = build_int_2 (result & ((unsigned) ~0 >> (HOST_BITS_PER_INT - num_bits)), 0); else yylval.ttype ! = build_int_2 (result | ~((unsigned) ~0 >> (HOST_BITS_PER_INT - num_bits)), -1); ! TREE_TYPE (yylval.ttype) = char_type_node; } else { yylval.ttype = build_int_2 (result, 0); ! TREE_TYPE (yylval.ttype) = integer_type_node; } ! value = CONSTANT; break; } --- 3356,3396 ---- || ((result >> (num_bits - 1)) & 1) == 0) yylval.ttype ! = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0 >> (HOST_BITS_PER_INT - num_bits)), 0); else yylval.ttype ! = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0 >> (HOST_BITS_PER_INT - num_bits)), -1); ! if (num_chars<=1) ! TREE_TYPE (yylval.ttype) = char_type_node; ! else ! TREE_TYPE (yylval.ttype) = integer_type_node; } else { + #ifdef MULTIBYTE_CHARS + /* Set the initial shift state and convert the next sequence. */ + result = 0; + /* In all locales L'\0' is zero and mbtowc will return zero, + so don't use it. */ + if (num_chars > 1 + || (num_chars == 1 && token_buffer[1] != '\0')) + { + wchar_t wc; + (void) mbtowc (NULL, NULL, 0); + if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars) + result = wc; + else + warning ("Ignoring invalid multibyte character"); + } + #endif yylval.ttype = build_int_2 (result, 0); ! TREE_TYPE (yylval.ttype) = wchar_type_node; } ! ! value = CONSTANT; ! break; } *************** *** 3306,3310 **** string_constant: { - int *widep; register char *p; --- 3398,3401 ---- *************** *** 3312,3327 **** p = token_buffer + 1; - if (wide_flag) - widep = wide_buffer; - while (c != '"' && c >= 0) { ! if (c == '\\') { c = readescape (); if (c < 0) goto skipnewline; ! if (!wide_flag && c >= (1 << BITS_PER_UNIT)) ! warning ("escape sequence out of range for character"); } else if (c == '\n') --- 3403,3418 ---- p = token_buffer + 1; while (c != '"' && c >= 0) { ! /* ignore_escape_flag is set for reading the filename in #line. */ ! if (!ignore_escape_flag && c == '\\') { c = readescape (); if (c < 0) goto skipnewline; ! if (!wide_flag ! && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT ! && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node))) ! pedwarn ("escape sequence out of range for character"); } else if (c == '\n') *************** *** 3332,3354 **** } ! /* Store the char in C into the appropriate buffer. */ ! ! if (wide_flag) ! { ! if (widep == wide_buffer + max_wide) ! { ! int n = widep - wide_buffer; ! max_wide *= 2; ! wide_buffer = (int *) xrealloc (wide_buffer, max_wide + 1); ! widep = wide_buffer + n; ! } ! *widep++ = c; ! } ! else ! { ! if (p == token_buffer + maxtoken) ! p = extend_token_buffer (p); ! *p++ = c; ! } skipnewline: --- 3423,3429 ---- } ! if (p == token_buffer + maxtoken) ! p = extend_token_buffer (p); ! *p++ = c; skipnewline: *************** *** 3359,3362 **** --- 3434,3438 ---- } } + *p = 0; /* We have read the entire constant. *************** *** 3365,3381 **** if (wide_flag) { ! /* If this is a L"..." wide-string, make a vector ! of the ints in wide_buffer. */ ! *widep = 0; ! /* We have not implemented the case where `int' ! on the target and on the execution machine differ in size. */ ! assert (TYPE_PRECISION (integer_type_node) == sizeof (int) * BITS_PER_UNIT); ! yylval.ttype = build_string ((widep - wide_buffer + 1) * sizeof (int), ! (char *)wide_buffer); ! TREE_TYPE (yylval.ttype) = int_array_type_node; } else { - *p = 0; yylval.ttype = build_string (p - token_buffer, token_buffer + 1); TREE_TYPE (yylval.ttype) = char_array_type_node; --- 3441,3479 ---- if (wide_flag) { ! /* If this is a L"..." wide-string, convert the multibyte string ! to a wide character string. */ ! char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES); ! int len; ! ! #ifdef MULTIBYTE_CHARS ! len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer); ! if ((unsigned) len >= (p - token_buffer)) ! { ! warning ("Ignoring invalid multibyte string"); ! len = 0; ! } ! bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES); ! #else ! { ! union { long l; char c[sizeof (long)]; } u; ! int big_endian; ! char *wp, *cp; ! ! /* Determine whether host is little or big endian. */ ! u.l = 1; ! big_endian = u.c[sizeof (long) - 1]; ! wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0); ! ! bzero (widep, (p - token_buffer) * WCHAR_BYTES); ! for (cp = token_buffer + 1; cp < p; cp++) ! *wp = *cp, wp += WCHAR_BYTES; ! len = p - token_buffer - 1; ! } ! #endif ! yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep); ! TREE_TYPE (yylval.ttype) = wchar_array_type_node; } else { yylval.ttype = build_string (p - token_buffer, token_buffer + 1); TREE_TYPE (yylval.ttype) = char_array_type_node; *************** *** 3634,3638 **** { DECL_LANGUAGE (t) = lang_cplusplus; - #ifndef NO_AUTO_OVERLOAD if (code == FUNCTION_DECL && name != 0 --- 3732,3735 ---- diff -rc2N gcc-2.2.2/cp-lex.h gcc-2.3.1/cp-lex.h *** gcc-2.2.2/cp-lex.h Thu Jun 11 00:34:58 1992 --- gcc-2.3.1/cp-lex.h Tue Aug 4 17:31:40 1992 *************** *** 51,55 **** RID_VOLATILE, RID_INLINE, ! RID_NOALIAS, /* extensions */ --- 51,55 ---- RID_VOLATILE, RID_INLINE, ! RID_WCHAR, /* extensions */ diff -rc2N gcc-2.2.2/cp-method.c gcc-2.3.1/cp-method.c *** gcc-2.2.2/cp-method.c Thu Jun 11 00:26:27 1992 --- gcc-2.3.1/cp-method.c Tue Oct 20 14:37:35 1992 *************** *** 27,31 **** /* Handle method declarations. */ #include - #include #include "config.h" #include "tree.h" --- 27,30 ---- *************** *** 38,44 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - /* TREE_LIST of the current inline functions that need to be processed. */ --- 37,40 ---- *************** *** 91,105 **** } - /* Return a pointer to the end of the new text in INLINE_BUFFER. - We cannot use `fatal' or `error' in here because that - might cause an infinite loop. */ - static char * - new_text_len (s) - char *s; - { - while (*s++) ; - return s - 1; - } - tree make_anon_parm_name () --- 87,90 ---- *************** *** 184,189 **** { int old_p = 0; - int print_struct = 1; - tree name; if (t == NULL_TREE) --- 169,172 ---- *************** *** 462,466 **** { int old_p = 0; - int print_struct = 1; if (t == NULL_TREE) --- 445,448 ---- *************** *** 1136,1145 **** /* Same, but handtype a _TYPE. */ char * ! type_as_string (buf, typ) ! char *buf; tree typ; { int p = 0; - int spaces = 0; OB_INIT (); --- 1118,1125 ---- /* Same, but handtype a _TYPE. */ char * ! type_as_string (typ) tree typ; { int p = 0; OB_INIT (); *************** *** 1152,1155 **** --- 1132,1149 ---- } + /* A cross between type_as_string and fndecl_as_string. */ + char * + decl_as_string (decl) + tree decl; + { + OB_INIT (); + + dump_decl(decl); + + OB_FINISH (); + + return (char *)obstack_base (&scratch_obstack); + } + /* Move inline function definitions out of structure so that they can be processed normally. CNAME is the name of the class *************** *** 1162,1166 **** tree type, friend_list; { - tree cname = TYPE_IDENTIFIER (type); tree method = TYPE_METHODS (type); --- 1156,1159 ---- *************** *** 1218,1222 **** } ! /* Report a argument type mismatch between the best declared function we could find and the current argument list that we have. */ void --- 1211,1215 ---- } ! /* Report an argument type mismatch between the best declared function we could find and the current argument list that we have. */ void *************** *** 1362,1366 **** { int tindex = 0; - char *rval; while (typevec[tindex] != type) --- 1355,1358 ---- *************** *** 1413,1417 **** { assert (TREE_CODE (value) == INTEGER_CST); ! if (TYPE_MODE (value) == DImode) { if (tree_int_cst_lt (value, integer_zero_node)) --- 1405,1409 ---- { assert (TREE_CODE (value) == INTEGER_CST); ! if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT) { if (tree_int_cst_lt (value, integer_zero_node)) *************** *** 1421,1425 **** - TREE_INT_CST_HIGH (value)); } ! if (TREE_INT_CST_HIGH (value) != (TREE_INT_CST_LOW (value) >> 31)) { /* need to print a DImode value in decimal */ --- 1413,1418 ---- - TREE_INT_CST_HIGH (value)); } ! if (TREE_INT_CST_HIGH (value) ! != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) { /* need to print a DImode value in decimal */ *************** *** 1428,1432 **** /* else fall through to print in smaller mode */ } ! /* SImode or smaller */ icat (TREE_INT_CST_LOW (value)); return; --- 1421,1425 ---- /* else fall through to print in smaller mode */ } ! /* Wordsize or smaller */ icat (TREE_INT_CST_LOW (value)); return; *************** *** 1446,1450 **** } sprintf (bufp, "%e", val); ! bufp = strchr (bufp, 'e'); if (!bufp) strcat (digit_buffer, "e0"); --- 1439,1443 ---- } sprintf (bufp, "%e", val); ! bufp = (char *) index (bufp, 'e'); if (!bufp) strcat (digit_buffer, "e0"); *************** *** 1732,1782 **** case INTEGER_TYPE: parmtype = TYPE_MAIN_VARIANT (parmtype); ! switch (TYPE_MODE (parmtype)) { ! case TImode: ! if (parmtype == long_integer_type_node ! || parmtype == long_unsigned_type_node) ! OB_PUTC ('l'); ! else ! OB_PUTC ('q'); ! break; ! case DImode: ! if (parmtype == long_integer_type_node ! || parmtype == long_unsigned_type_node) ! OB_PUTC ('l'); ! else if (parmtype == integer_type_node ! || parmtype == unsigned_type_node) ! OB_PUTC ('i'); ! else if (parmtype == short_integer_type_node ! || parmtype == short_unsigned_type_node) ! OB_PUTC ('s'); ! else ! OB_PUTC ('x'); ! break; ! case SImode: ! if (parmtype == long_integer_type_node ! || parmtype == long_unsigned_type_node) ! OB_PUTC ('l'); ! else if (parmtype == short_integer_type_node ! || parmtype == short_unsigned_type_node) ! OB_PUTC ('s'); ! else ! OB_PUTC ('i'); ! break; ! case HImode: ! if (parmtype == integer_type_node ! || parmtype == unsigned_type_node) ! OB_PUTC ('i'); ! else ! OB_PUTC ('s'); ! break; ! case QImode: ! if (parmtype == signed_char_type_node) ! OB_PUTC ('S'); OB_PUTC ('c'); - break; - default: - my_friendly_abort (73); } break; --- 1725,1759 ---- case INTEGER_TYPE: parmtype = TYPE_MAIN_VARIANT (parmtype); ! if (parmtype == integer_type_node ! || parmtype == unsigned_type_node) ! OB_PUTC ('i'); ! else if (parmtype == long_integer_type_node ! || parmtype == long_unsigned_type_node) ! OB_PUTC ('l'); ! else if (parmtype == short_integer_type_node ! || parmtype == short_unsigned_type_node) ! OB_PUTC ('s'); ! else if (parmtype == signed_char_type_node) { ! OB_PUTC ('S'); OB_PUTC ('c'); } + else if (parmtype == char_type_node + || parmtype == unsigned_char_type_node) + OB_PUTC ('c'); + else if (parmtype == wchar_type_node) + OB_PUTC ('w'); + else if (parmtype == long_long_integer_type_node + || parmtype == long_long_unsigned_type_node) + OB_PUTC ('x'); + #if 0 + /* it would seem there is no way to enter these in source code, + yet. (mrs) */ + else if (parmtype == long_long_long_integer_type_node + || parmtype == long_long_long_unsigned_type_node) + OB_PUTC ('q'); + #endif + else + my_friendly_abort (73); break; *************** *** 1931,1934 **** --- 1908,1920 ---- && TREE_CHAIN (parms) == void_list_node) return get_identifier ("__builtin_delete"); + else if (dname == ansi_opname[(int) DELETE_EXPR] + && parms != NULL_TREE + && TREE_CODE (parms) == TREE_LIST + && TREE_VALUE (parms) == ptr_type_node + && TREE_CHAIN (parms) != NULL_TREE + && TREE_CODE (TREE_CHAIN (parms)) == TREE_LIST + && TREE_VALUE (TREE_CHAIN (parms)) == sizetype + && TREE_CHAIN (TREE_CHAIN (parms)) == void_list_node) + return get_identifier ("__builtin_delete"); OB_INIT (); *************** *** 2005,2010 **** tree type; { - int i = sizeof (T_DESC_FORMAT) - 1; - OB_INIT (); OB_PUTS (T_DESC_FORMAT); --- 1991,1994 ---- *************** *** 2107,2110 **** --- 2091,2095 ---- build_opfncall (code, flags, xarg1, xarg2, arg3) enum tree_code code; + int flags; tree xarg1, xarg2; tree arg3; *************** *** 2203,2207 **** fnname = ansi_opname[(int) DELETE_EXPR]; if (flags & LOOKUP_GLOBAL) ! return build_overload_call (fnname, build_tree_list (NULL_TREE, xarg1), flags & LOOKUP_COMPLAIN, 0); --- 2188,2194 ---- fnname = ansi_opname[(int) DELETE_EXPR]; if (flags & LOOKUP_GLOBAL) ! return build_overload_call (fnname, ! tree_cons (NULL_TREE, xarg1, ! build_tree_list (NULL_TREE, xarg2)), flags & LOOKUP_COMPLAIN, 0); *************** *** 2210,2215 **** || current_class_type != TYPE_MAIN_VARIANT (type1)) flags = LOOKUP_COMPLAIN; ! rval = build_method_call (build1 (NOP_EXPR, TREE_TYPE (xarg1), error_mark_node), ! fnname, build_tree_list (NULL_TREE, xarg1), NULL_TREE, flags); /* This happens when the user mis-declares `operator delete'. --- 2197,2204 ---- || current_class_type != TYPE_MAIN_VARIANT (type1)) flags = LOOKUP_COMPLAIN; ! rval = build_method_call (build1 (NOP_EXPR, TREE_TYPE (xarg1), ! error_mark_node), ! fnname, tree_cons (NULL_TREE, xarg1, ! build_tree_list (NULL_TREE, xarg2)), NULL_TREE, flags); /* This happens when the user mis-declares `operator delete'. *************** *** 2349,2353 **** else if (code == COND_EXPR) { ! parms = tree_cons (0, xarg2, build_tree_list (0, arg3)); rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags); } --- 2338,2342 ---- else if (code == COND_EXPR) { ! parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3)); rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags); } *************** *** 2404,2407 **** --- 2393,2397 ---- hack_identifier (value, name, yychar) tree value, name; + int yychar; { tree type; *************** *** 2487,2491 **** } ! if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && TREE_NONLOCAL (value)) { if (DECL_CLASS_CONTEXT (value) != current_class_type) --- 2477,2481 ---- } ! if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) { if (DECL_CLASS_CONTEXT (value) != current_class_type) *************** *** 2493,2499 **** tree path; enum visibility_type visibility; ! get_base_distance (DECL_CLASS_CONTEXT (value), ! current_class_type, 0, &path); visibility = compute_visibility (path, value); if (visibility != visibility_public) --- 2483,2492 ---- tree path; enum visibility_type visibility; + register tree context + = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value)) + ? DECL_CLASS_CONTEXT (value) + : DECL_CONTEXT (value); ! get_base_distance (context, current_class_type, 0, &path); visibility = compute_visibility (path, value); if (visibility != visibility_public) *************** *** 2508,2516 **** } } - if (TREE_CODE (value) == VAR_DECL && ! TREE_USED (value)) - { - assemble_external (value); - TREE_USED (value) = 1; - } return value; } --- 2501,2504 ---- *************** *** 2589,2593 **** int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN; ! assert (IS_AGGR_TYPE (TREE_TYPE (of))); assert (TREE_CODE (component) == TYPE_EXPR); --- 2577,2582 ---- int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN; ! if (of) ! assert (IS_AGGR_TYPE (TREE_TYPE (of))); assert (TREE_CODE (component) == TYPE_EXPR); diff -rc2N gcc-2.2.2/cp-parse.h gcc-2.3.1/cp-parse.h *** gcc-2.2.2/cp-parse.h Fri Jun 12 23:52:45 1992 --- gcc-2.3.1/cp-parse.h Fri Sep 18 02:43:39 1992 *************** *** 85,86 **** --- 85,87 ---- extern YYSTYPE yylval; + #define YYEMPTY -2 diff -rc2N gcc-2.2.2/cp-parse.y gcc-2.3.1/cp-parse.y *** gcc-2.2.2/cp-parse.y Thu Jun 11 00:33:04 1992 --- gcc-2.3.1/cp-parse.y Mon Oct 19 18:19:36 1992 *************** *** 41,45 **** %{ ! #ifdef GATHER_STATISTICS #undef YYDEBUG #define YYDEBUG 1 --- 41,45 ---- %{ ! #if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG) #undef YYDEBUG #define YYDEBUG 1 *************** *** 53,56 **** --- 53,57 ---- #include "tree.h" #include "input.h" + #include "flags.h" #include "cp-lex.h" #include "cp-tree.h" *************** *** 58,61 **** --- 59,63 ---- extern tree void_list_node; + extern struct obstack permanent_obstack; #ifndef errno *************** *** 84,89 **** /* Nonzero if we have an `extern "C"' acting as an extern specifier. */ ! ! static int have_extern_spec; void yyhook (); --- 86,91 ---- /* Nonzero if we have an `extern "C"' acting as an extern specifier. */ ! int have_extern_spec; ! int used_extern_spec; void yyhook (); *************** *** 240,244 **** %type after_type_declarator_no_typename %type maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers ! %type component_declarator0 scoped_id scoped_typename %type forhead.1 identifier_or_opname operator_name %type new delete object object_star aggr --- 242,246 ---- %type after_type_declarator_no_typename %type maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers ! %type component_declarator0 scoped_id scoped_typename scoped_base_class %type forhead.1 identifier_or_opname operator_name %type new delete object object_star aggr *************** *** 316,319 **** --- 318,322 ---- .hush_warning: { have_extern_spec = 1; + used_extern_spec = 0; $$ = NULL_TREE; } ; *************** *** 454,458 **** for them. */ if (pedantic) ! error ("ANSI C forbids data definition with no type or storage class"); else if (! flag_traditional && ! have_extern_spec) warning ("data definition has no type or storage class"); --- 457,461 ---- for them. */ if (pedantic) ! pedwarn ("ANSI C forbids data definition with no type or storage class"); else if (! flag_traditional && ! have_extern_spec) warning ("data definition has no type or storage class"); *************** *** 508,512 **** notype_initdecls ';' { if (pedantic) ! error ("ANSI C forbids data definition with no type or storage class"); else if (! flag_traditional && ! have_extern_spec) warning ("data definition has no type or storage class"); } --- 511,515 ---- notype_initdecls ';' { if (pedantic) ! pedwarn ("ANSI C forbids data definition with no type or storage class"); else if (! flag_traditional && ! have_extern_spec) warning ("data definition has no type or storage class"); } *************** *** 533,537 **** } | declmods ';' ! { error ("empty declaration"); } | typed_declspecs ';' { --- 536,540 ---- } | declmods ';' ! { pedwarn ("empty declaration"); } | typed_declspecs ';' { *************** *** 714,718 **** { store_return_init ($$, NULL_TREE); } | return_id '=' init ! { store_return_init ($$, $2); } | return_id '(' nonnull_exprlist ')' { store_return_init ($$, $3); } --- 717,721 ---- { store_return_init ($$, NULL_TREE); } | return_id '=' init ! { store_return_init ($$, $3); } | return_id '(' nonnull_exprlist ')' { store_return_init ($$, $3); } *************** *** 764,769 **** member_init: '(' nonnull_exprlist ')' { ! if (current_class_name && pedantic) ! pedwarn ("old style base class initialization; use `%s (...)'", IDENTIFIER_POINTER (current_class_name)); expand_member_init (C_C_D, NULL_TREE, $2); --- 767,772 ---- member_init: '(' nonnull_exprlist ')' { ! if (current_class_name && !flag_traditional) ! pedwarn ("ANSI C++ forbids old style base class initialization", IDENTIFIER_POINTER (current_class_name)); expand_member_init (C_C_D, NULL_TREE, $2); *************** *** 771,776 **** | LEFT_RIGHT { ! if (current_class_name && pedantic) ! pedwarn ("old style base class initialization; use `%s (...)'", IDENTIFIER_POINTER (current_class_name)); expand_member_init (C_C_D, NULL_TREE, void_type_node); --- 774,779 ---- | LEFT_RIGHT { ! if (current_class_name && !flag_traditional) ! pedwarn ("ANSI C++ forbids old style base class initialization", IDENTIFIER_POINTER (current_class_name)); expand_member_init (C_C_D, NULL_TREE, void_type_node); *************** *** 786,789 **** --- 789,796 ---- | template_type_name LEFT_RIGHT { expand_member_init (C_C_D, $$, void_type_node); } + | scoped_typename '(' nonnull_exprlist ')' + { expand_member_init (C_C_D, $$, $3); } + | scoped_typename LEFT_RIGHT + { expand_member_init (C_C_D, $$, void_type_node); } | scoped_id identifier '(' nonnull_exprlist ')' { *************** *** 840,847 **** --- 847,866 ---- template_type_name tmpl.1 template_instantiation { + extern tree template_type_seen_before_scope; + if ($3) $$ = $3; else if ($$ != error_mark_node) $$ = IDENTIFIER_TYPE_VALUE ($$); + /* This is a kludge: In order to detect nested types inside + * template classes, we have to tell the lexer that it should + * try to replace a following SCOPE token with the correct + * SCOPED_TYPENAME for the nested type. This SCOPED_TYPENAME + * token will be handled in the rule "scoped_typename". + * - niklas@appli.se */ + if (yychar == SCOPE) { + template_type_seen_before_scope = TYPE_IDENTIFIER ($$); + yychar = YYLEX; + } } ; *************** *** 850,853 **** --- 869,874 ---- PTYPENAME '<' template_arg_list '>' { $$ = lookup_template_class ($$, $3); } + | TYPENAME '<' template_arg_list '>' + { $$ = lookup_template_class ($$, $3); } ; *************** *** 902,906 **** /* Need to copy it to clear the chain pointer, and need to get it into permanent storage. */ - extern struct obstack permanent_obstack; assert (TREE_CODE (decl) == TYPE_DECL); push_obstacks (&permanent_obstack, &permanent_obstack); --- 923,926 ---- *************** *** 915,920 **** { extern void end_template_instantiation (); ! tree id, members; $$ = finish_struct ($3, $5, 0, 0); --- 935,941 ---- { extern void end_template_instantiation (); ! int old_interface = interface_unknown; + interface_unknown = 1; $$ = finish_struct ($3, $5, 0, 0); *************** *** 923,927 **** --- 944,952 ---- /* Now go after the methods & class data. */ + old_interface = interface_unknown; + interface_unknown = 1; instantiate_member_templates ($1); + interface_unknown = old_interface; + CLASSTYPE_GOT_SEMICOLON ($$) = 1; } ; *************** *** 1045,1055 **** --- 1070,1090 ---- | .scope new typename %prec '=' { $$ = build_new ($2, $3, NULL_TREE, $$); } + | .scope new '(' nonnull_exprlist ')' typename %prec '=' + { $$ = build_new ($4, $6, NULL_TREE, $$); } | .scope new typespec '(' nonnull_exprlist ')' { $$ = build_new ($2, $3, $5, $$); } + | .scope NEW '(' nonnull_exprlist ')' typespec '(' nonnull_exprlist ')' + { $$ = build_new ($4, $6, $8, $$); } | .scope new typespec LEFT_RIGHT { $$ = build_new ($2, $3, NULL_TREE, $$); } + | .scope NEW '(' nonnull_exprlist ')' typespec LEFT_RIGHT + { $$ = build_new ($4, $6, NULL_TREE, $$); } | .scope new typename '=' init %prec '=' { $$ = build_new ($2, $3, $5, $$); } + | .scope NEW '(' nonnull_exprlist ')' typename '=' init %prec '=' + { $$ = build_new ($4, $6, $8, $$); } + /* I am not going to add placement syntax to the below complex rules + because Ken says the syntax is illegal. (mrs) */ /* I'm not sure why this is disallowed. But since it is, and it doesn't seem difficult to catch it, let's give a message, so *************** *** 1058,1073 **** { tree absdcl, typename; - static int gave_warning = 0; illegal_new_array: absdcl = build_parse_node (ARRAY_REF, $5, $8); typename = build_decl_list ($4, absdcl); ! pedwarn ("array dimensions with parenthesized type is disallowed in standard C++"); ! if (!gave_warning) ! { ! gave_warning++; ! pedwarn (" (per grammar in Ellis & Stroustrup [1990], chapter 17)"); ! pedwarn (" try rewriting, perhaps with a typedef"); ! } $$ = build_new ($2, typename, NULL_TREE, $$); } --- 1093,1101 ---- { tree absdcl, typename; illegal_new_array: absdcl = build_parse_node (ARRAY_REF, $5, $8); typename = build_decl_list ($4, absdcl); ! pedwarn ("ANSI C++ forbids array dimensions with parenthesized type"); $$ = build_new ($2, typename, NULL_TREE, $$); } *************** *** 1076,1088 **** | .scope new '(' typed_typespecs absdcl ')' ! { ! $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); ! } | .scope new '(' nonempty_type_quals absdcl ')' { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } /* Unswallow a ':' which is probably meant for ?: expression. */ | .scope new TYPENAME_COLON ! { yyungetc (':', 1); ! $$ = build_new ($2, $3, NULL_TREE, $$); } | delete cast_expr %prec UNARY --- 1104,1119 ---- | .scope new '(' typed_typespecs absdcl ')' ! { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } ! | .scope NEW '(' nonnull_exprlist ')' '(' typed_typespecs absdcl ')' ! { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$); } | .scope new '(' nonempty_type_quals absdcl ')' { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$); } + | .scope NEW '(' nonnull_exprlist ')' '(' nonempty_type_quals absdcl ')' + { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$); } /* Unswallow a ':' which is probably meant for ?: expression. */ | .scope new TYPENAME_COLON ! { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$); } ! | .scope NEW '(' nonnull_exprlist ')' TYPENAME_COLON ! { yyungetc (':', 1); $$ = build_new ($4, $6, NULL_TREE, $$); } | delete cast_expr %prec UNARY *************** *** 1090,1096 **** tree type = TREE_TYPE (expr); ! if (integer_zerop (expr)) ! $$ = build1 (NOP_EXPR, void_type_node, expr); ! else if (TREE_CODE (type) != POINTER_TYPE) { error ("non-pointer type to `delete'"); --- 1121,1125 ---- tree type = TREE_TYPE (expr); ! if (TREE_CODE (type) != POINTER_TYPE) { error ("non-pointer type to `delete'"); *************** *** 1098,1113 **** break; } $$ = build_delete (type, expr, integer_three_node, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, ! TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)) ? $$ : 0, 1); } | delete '[' ']' cast_expr %prec UNARY { tree exp = stabilize_reference (convert_from_reference ($4)); ! tree elt_size = c_sizeof (TREE_TYPE (exp)); if (yychar == YYEMPTY) yychar = YYLEX; $$ = build_vec_delete (exp, NULL_TREE, elt_size, NULL_TREE, integer_one_node, integer_two_node); --- 1127,1164 ---- break; } + else if (integer_zerop (expr)) + { + /* ANSI C++ June 5 1992 WP 5.3.4. Deleting a pointer + with the value zero is legal and has no effect. */ + $$ = build1 (NOP_EXPR, void_type_node, expr); + break; + } + else if (TREE_READONLY (TREE_TYPE (type))) + { + error ("`const *' cannot be deleted"); + $$ = error_mark_node; + break; + } $$ = build_delete (type, expr, integer_three_node, LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, ! TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)), ! 0); } | delete '[' ']' cast_expr %prec UNARY { tree exp = stabilize_reference (convert_from_reference ($4)); ! tree type = TREE_TYPE (exp); ! tree elt_size = c_sizeof (type); if (yychar == YYEMPTY) yychar = YYLEX; + if (TREE_CODE (type) == POINTER_TYPE + && TREE_READONLY (TREE_TYPE (type))) + { + error ("`const *' cannot be deleted"); + $$ = error_mark_node; + break; + } $$ = build_vec_delete (exp, NULL_TREE, elt_size, NULL_TREE, integer_one_node, integer_two_node); *************** *** 1118,1127 **** integer_one_node); tree exp = stabilize_reference (convert_from_reference ($5)); ! tree elt_size = c_sizeof (TREE_TYPE (exp)); if (yychar == YYEMPTY) yychar = YYLEX; ! pedwarn ("use of array size with vector delete is anachronistic"); $$ = build_vec_delete (exp, maxindex, elt_size, NULL_TREE, integer_one_node, integer_two_node); --- 1169,1187 ---- integer_one_node); tree exp = stabilize_reference (convert_from_reference ($5)); ! tree type = TREE_TYPE (exp); ! tree elt_size = c_sizeof (type); if (yychar == YYEMPTY) yychar = YYLEX; ! if (! flag_traditional) ! pedwarn ("ANSI C++ forbids array size in vector delete"); ! if (TREE_CODE (type) == POINTER_TYPE ! && TREE_READONLY (TREE_TYPE (type))) ! { ! error ("`const *' cannot be deleted"); ! $$ = error_mark_node; ! break; ! } $$ = build_vec_delete (exp, maxindex, elt_size, NULL_TREE, integer_one_node, integer_two_node); *************** *** 1238,1242 **** else { ! $$ = lookup_name (op); if ($$ == NULL_TREE) { --- 1298,1302 ---- else { ! $$ = lookup_name (op, 0); if ($$ == NULL_TREE) { *************** *** 1268,1282 **** /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; - /* Make a BIND_EXPR for the BLOCK already made. */ $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp), NULL_TREE, rtl_exp, $3); } | primary '(' nonnull_exprlist ')' { /* [eichin:19911016.1902EST] */ - extern struct pending_template* pending_templates; $$ = build_x_function_call ($1, $3, current_class_decl); /* here we instantiate_class_template as needed... */ ! if (pending_templates) do_pending_templates (); } template_instantiate_some { if (TREE_CODE ($5) == CALL_EXPR --- 1328,1344 ---- /* The statements have side effects, so the group does. */ TREE_SIDE_EFFECTS (rtl_exp) = 1; /* 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); } | primary '(' nonnull_exprlist ')' { /* [eichin:19911016.1902EST] */ $$ = build_x_function_call ($1, $3, current_class_decl); /* here we instantiate_class_template as needed... */ ! do_pending_templates (); } template_instantiate_some { if (TREE_CODE ($5) == CALL_EXPR *************** *** 1288,1295 **** | primary LEFT_RIGHT { ! $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); ! if (TREE_CODE ($$) == CALL_EXPR ! && TREE_TYPE ($$) != void_type_node) ! $$ = require_complete_type ($$); } | primary '[' expr ']' --- 1350,1361 ---- | primary LEFT_RIGHT { ! if ($$ != error_mark_node) ! { ! $$ = build_x_function_call ($$, NULL_TREE, ! current_class_decl); ! if (TREE_CODE ($$) == CALL_EXPR ! && TREE_TYPE ($$) != void_type_node) ! $$ = require_complete_type ($$); ! } } | primary '[' expr ']' *************** *** 1410,1416 **** --- 1476,1485 ---- } #endif + #if 0 + /* type is not set! (mrs) */ if (type == error_mark_node) $$ = error_mark_node; else + #endif { if (id == ridpointers[(int) RID_CONST]) *************** *** 1418,1421 **** --- 1487,1492 ---- else if (id == ridpointers[(int) RID_VOLATILE]) type = build_type_variant (integer_type_node, 0, 1); + #if 0 + /* should not be able to get here (mrs) */ else if (id == ridpointers[(int) RID_FRIEND]) { *************** *** 1424,1427 **** --- 1495,1499 ---- break; } + #endif else my_friendly_abort (79); $$ = build_c_cast (type, build_compound_expr ($3)); *************** *** 1432,1435 **** --- 1504,1511 ---- | typespec LEFT_RIGHT { $$ = build_functional_cast ($$, NULL_TREE); } + | SCOPE typespec '(' nonnull_exprlist ')' + { $$ = build_functional_cast ($2, $4); } + | SCOPE typespec LEFT_RIGHT + { $$ = build_functional_cast ($2, NULL_TREE); } | SCOPE IDENTIFIER { *************** *** 1458,1463 **** } if (TREE_CODE ($$) == CONST_DECL) ! $$ = DECL_INITIAL ($$); ! /* XXX CHS - should we set TREE_USED of the constant? */ } | SCOPE operator_name --- 1534,1546 ---- } if (TREE_CODE ($$) == CONST_DECL) ! { ! /* XXX CHS - should we set TREE_USED of the constant? */ ! $$ = 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; ! } ! } | SCOPE operator_name *************** *** 1527,1531 **** { $$ = NULL_TREE; } | NEW '{' nonnull_exprlist '}' ! { $$ = $3; } | NEW DYNAMIC %prec EMPTY { $$ = void_type_node; } --- 1610,1617 ---- { $$ = NULL_TREE; } | NEW '{' nonnull_exprlist '}' ! { ! $$ = $3; ! pedwarn ("old style placement syntax, use () instead"); ! } | NEW DYNAMIC %prec EMPTY { $$ = void_type_node; } *************** *** 1656,1664 **** { $$ = build_decl_list (NULL_TREE, $$); } | SCSPEC ! { $$ = build_decl_list (NULL_TREE, $$); } | reserved_declspecs typespecqual_reserved { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | reserved_declspecs SCSPEC ! { $$ = decl_tree_cons (NULL_TREE, $2, $$); } ; --- 1742,1756 ---- { $$ = build_decl_list (NULL_TREE, $$); } | SCSPEC ! { if (extra_warnings) ! warning ("`%s' is not at beginning of declaration", ! IDENTIFIER_POINTER ($$)); ! $$ = build_decl_list (NULL_TREE, $$); } | reserved_declspecs typespecqual_reserved { $$ = decl_tree_cons (NULL_TREE, $2, $$); } | reserved_declspecs SCSPEC ! { if (extra_warnings) ! warning ("`%s' is not at beginning of declaration", ! IDENTIFIER_POINTER ($2)); ! $$ = decl_tree_cons (NULL_TREE, $2, $$); } ; *************** *** 1669,1679 **** declmods: TYPE_QUAL ! { $$ = IDENTIFIER_AS_LIST ($$); } | SCSPEC { $$ = IDENTIFIER_AS_LIST ($$); } | declmods TYPE_QUAL ! { $$ = hash_tree_chain ($2, $$); } | declmods SCSPEC ! { $$ = hash_tree_chain ($2, $$); } ; --- 1761,1777 ---- declmods: TYPE_QUAL ! { $$ = IDENTIFIER_AS_LIST ($$); ! TREE_STATIC ($$) = 1; } | SCSPEC { $$ = IDENTIFIER_AS_LIST ($$); } | declmods TYPE_QUAL ! { $$ = hash_tree_chain ($2, $$); ! TREE_STATIC ($$) = 1; } | declmods SCSPEC ! { if (extra_warnings && TREE_STATIC ($$)) ! warning ("`%s' is not at beginning of declaration", ! IDENTIFIER_POINTER ($2)); ! $$ = hash_tree_chain ($2, $$); ! TREE_STATIC ($$) = TREE_STATIC ($1); } ; *************** *** 1833,1837 **** } else ! $$ = tree_cons ($1, $3); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ --- 1931,1935 ---- } else ! $$ = tree_cons ($1, $3, NULL_TREE); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ *************** *** 1845,1849 **** } else ! $$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7))); } ; --- 1943,1947 ---- } else ! $$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7, NULL_TREE), NULL_TREE), NULL_TREE); } ; *************** *** 1919,1922 **** --- 2017,2022 ---- { int semi; + tree id; + #if 0 /* Need to rework class nesting in the *************** *** 1924,1930 **** --- 2024,2035 ---- shadow_tag (CLASSTYPE_AS_LIST ($$)); */ #endif + if (yychar == YYEMPTY) + yychar = YYLEX; semi = yychar == ';'; + /* finish_struct nukes this anyway; if + finish_exception does too, then it can go. */ if (semi) note_got_semicolon ($$); + if (TREE_CODE ($$) == ENUMERAL_TYPE) /* $$ = $1 from default rule. */; *************** *** 1937,1943 **** } else ! $$ = finish_struct ($$, $3, semi, semi); pop_obstacks (); if (! semi) check_for_missing_semicolon ($$); } --- 2042,2070 ---- } else ! { ! $$ = finish_struct ($$, $3, semi, semi); ! if (semi) note_got_semicolon ($$); ! } pop_obstacks (); + + id = TYPE_IDENTIFIER ($$); + if (IDENTIFIER_TEMPLATE (id)) + { + tree decl; + + /* I don't know if the copying of this TYPE_DECL is + * really needed. However, it's such a small per- + * formance penalty that the extra safety is a bargain. + * - niklas@appli.se + */ + push_obstacks (&permanent_obstack, &permanent_obstack); + decl = copy_node (lookup_name (id)); + if (DECL_LANG_SPECIFIC (decl)) + copy_lang_decl (decl); + pop_obstacks (); + undo_template_name_overload (id, 0); + pushdecl_top_level (decl); + } if (! semi) check_for_missing_semicolon ($$); } *************** *** 1965,1969 **** /* empty */ | ',' ! { if (pedantic) pedwarn ("comma at end of enumerator list"); } ; --- 2092,2097 ---- /* empty */ | ',' ! { if (pedantic) ! pedwarn ("ANSI C forbids comma at end of enumerator list"); } ; *************** *** 1998,2002 **** aggr2: current_aggr = $$; ! $$ = $2; } | aggr template_type_name ':' { yyungetc (':', 1); goto aggr2; } --- 2126,2131 ---- aggr2: current_aggr = $$; ! $$ = $2; ! overload_template_name ($$, 0); } | aggr template_type_name ':' { yyungetc (':', 1); goto aggr2; } *************** *** 2061,2072 **** --- 2190,2230 ---- $$ = NULL_TREE; else $$ = build_tree_list ((tree)visibility_default, $$); } + | scoped_base_class + { if (! is_aggr_typedef ($$, 1)) + $$ = NULL_TREE; + else $$ = build_tree_list ((tree)visibility_default, $$); } | base_class_visibility_list base_class.1 { if (! is_aggr_typedef ($2, 1)) $$ = NULL_TREE; else $$ = build_tree_list ((tree) $$, $2); } + | base_class_visibility_list scoped_base_class + { if (! is_aggr_typedef ($2, 1)) + $$ = NULL_TREE; + else $$ = build_tree_list ((tree) $$, $2); } ; + scoped_base_class: + base_class.1 SCOPED_TYPENAME + { + /* Kludge!!! See rule "template_type" and the code + * dealing with "template_type_seen_before_scope" in + * yylex(). */ + $$ = $2; + } + ; base_class.1: template_type_name tmpl.2 template_instantiation + { + extern tree template_type_seen_before_scope; + tree id = $3 ? TYPE_IDENTIFIER ($3) : $1; + + /* Check the rule template_type to get this... */ + if (yychar == YYEMPTY) + yychar = YYLEX; + if (yychar == SCOPE) { + template_type_seen_before_scope = id; + yychar = YYLEX; + } + } | identifier ; *************** *** 2164,2168 **** | component_decl_list ';' { if (pedantic) ! pedwarn ("extra semicolon in struct or union specified"); } ; --- 2322,2326 ---- | component_decl_list ';' { if (pedantic) ! pedwarn ("ANSI C forbids extra semicolons here"); } ; *************** *** 2186,2192 **** { /* handle anonymous unions */ ! if (CLASSTYPE_METHOD_VEC (t)) ! sorry ("methods in anonymous unions"); ! $$ = build_lang_field_decl (FIELD_DECL, NULL_TREE, t); } else if (TREE_CODE (t) == ENUMERAL_TYPE) --- 2344,2366 ---- { /* handle anonymous unions */ ! if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) ! $$ = build_lang_field_decl (FIELD_DECL, ! NULL_TREE, t); ! else ! { ! /* This is a local union decl with a name, but ! no components, I think this is the right thing ! to do. (mrs) */ ! #if 0 ! /* I copied this from below, it is probably ! needed, but I cannot prove that to myself ! right now, but if you find it is needed ! please turn it on. (mrs) */ ! if (TYPE_LANG_SPECIFIC (t) ! && CLASSTYPE_DECLARED_EXCEPTION (t)) ! shadow_tag ($$); ! #endif ! $$ = NULL_TREE; ! } } else if (TREE_CODE (t) == ENUMERAL_TYPE) *************** *** 2551,2554 **** --- 2725,2735 ---- scoped_typename: SCOPED_TYPENAME + | template_type SCOPED_TYPENAME + { + /* Kludge!!! See rule "template_type" and the code + * dealing with "template_type_seen_before_scope" in + * yylex(). */ + $$ = $2; + } /* | template_type SCOPE try_for_typename TYPENAME { *************** *** 2836,2840 **** if ($1) { ! register keep = $1 > 0; if (keep) expand_end_bindings (0, keep, 1); poplevel (keep, 1, 0); --- 3017,3021 ---- if ($1) { ! register int keep = $1 > 0; if (keep) expand_end_bindings (0, keep, 1); poplevel (keep, 1, 0); *************** *** 2913,2922 **** if (pedantic) ! { ! error ("ANSI C does not allow range expressions in switch statement"); ! value1 = error_mark_node; ! value2 = error_mark_node; ! break; ! } /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. Strip such NOP_EXPRs. */ --- 3094,3099 ---- if (pedantic) ! pedwarn ("ANSI C forbids range expressions in switch statement"); ! /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. Strip such NOP_EXPRs. */ *************** *** 3999,4002 **** --- 4176,4180 ---- print_parse_statistics () { + #ifdef GATHER_STATISTICS #if YYDEBUG != 0 int i; *************** *** 4040,4043 **** --- 4218,4222 ---- fprintf (stderr, "\n"); #endif + #endif } *************** *** 4062,4070 **** int value; { - #if YYDEBUG != 0 return yytname[YYTRANSLATE (value)]; - #else - return "YYDEBUG not defined."; - #endif } --- 4241,4245 ---- diff -rc2N gcc-2.2.2/cp-pt.c gcc-2.3.1/cp-pt.c *** gcc-2.2.2/cp-pt.c Thu Jun 11 00:27:17 1992 --- gcc-2.3.1/cp-pt.c Thu Sep 24 21:49:36 1992 *************** *** 31,35 **** #include "config.h" #include ! #include #include "obstack.h" --- 31,35 ---- #include "config.h" #include ! #include "assert.h" #include "obstack.h" *************** *** 52,59 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - static int unify (); void overload_template_name (), pop_template_decls (); --- 52,57 ---- #define obstack_chunk_free free static int unify (); + static void add_pending_template (); void overload_template_name (), pop_template_decls (); *************** *** 223,229 **** TREE_TYPE (decl) = TREE_TYPE (d2); TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = 0; ! TREE_EXTERNAL (decl) = (TREE_EXTERNAL (d2) && !(DECL_CLASS_CONTEXT (d2) ! && !DECL_EXTERNAL (d2))); } --- 221,227 ---- TREE_TYPE (decl) = TREE_TYPE (d2); TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = 0; ! DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2) && !(DECL_CLASS_CONTEXT (d2) ! && !DECL_THIS_EXTERN (d2))); } *************** *** 436,440 **** typename = IDENTIFIER_POINTER (TYPE_IDENTIFIER (arg)); else ! typename = type_as_string ((char *) 0, arg); cat (typename); continue; --- 434,438 ---- typename = IDENTIFIER_POINTER (TYPE_IDENTIFIER (arg)); else ! typename = type_as_string (arg); cat (typename); continue; *************** *** 461,465 **** if (TREE_CODE (arg) == INTEGER_CST) { ! if (TREE_INT_CST_HIGH (arg) != (((int)TREE_INT_CST_LOW (arg)) >> (HOST_BITS_PER_INT - 1))) { tree val = arg; --- 459,464 ---- if (TREE_CODE (arg) == INTEGER_CST) { ! if (TREE_INT_CST_HIGH (arg) ! != (TREE_INT_CST_LOW (arg) >> (HOST_BITS_PER_WIDE_INT - 1))) { tree val = arg; *************** *** 552,556 **** assert (TREE_CODE (d1) == IDENTIFIER_NODE); template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */ ! assert (TREE_CODE (template) == TEMPLATE_DECL); parmlist = DECL_TEMPLATE_PARMS (template); --- 551,560 ---- assert (TREE_CODE (d1) == IDENTIFIER_NODE); template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */ ! if (TREE_CODE (template) != TEMPLATE_DECL) ! { ! error ("Non-template type '%s' used as a template", ! IDENTIFIER_POINTER (d1)); ! return error_mark_node; ! } parmlist = DECL_TEMPLATE_PARMS (template); *************** *** 862,879 **** &TREE_VEC_ELT (parmvec, 0)); type = IDENTIFIER_TYPE_VALUE (id); - #if 0 - print_node_brief (stderr, "producing ", t2, 0); - print_node_brief (stderr, "\n\tfrom template ", tdecl, 0); - fprintf (stderr, "\n"); - #endif assert (type != 0); if (CLASSTYPE_INTERFACE_UNKNOWN (type)) { ! TREE_EXTERNAL (t2) = 0; TREE_PUBLIC (t2) = 0; } else { ! TREE_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type); TREE_PUBLIC (t2) = 1; } --- 866,878 ---- &TREE_VEC_ELT (parmvec, 0)); type = IDENTIFIER_TYPE_VALUE (id); assert (type != 0); if (CLASSTYPE_INTERFACE_UNKNOWN (type)) { ! DECL_EXTERNAL (t2) = 0; TREE_PUBLIC (t2) = 0; } else { ! DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type); TREE_PUBLIC (t2) = 1; } *************** *** 997,1000 **** --- 996,1015 ---- } + static int + list_eq (t1, t2) + tree t1, t2; + { + if (t1 == NULL_TREE) + return t2 == NULL_TREE; + if (t2 == NULL_TREE) + return 0; + /* Don't care if one declares its arg const and the other doesn't -- the + main variant of the arg type is all that matters. */ + if (TYPE_MAIN_VARIANT (TREE_VALUE (t1)) + != TYPE_MAIN_VARIANT (TREE_VALUE (t2))) + return 0; + return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2)); + } + static tree tsubst (t, args, nargs) *************** *** 1002,1009 **** { tree type; ! if (t == NULL_TREE) return t; type = TREE_TYPE (t); if (type && type != integer_type_node && type != void_type_node --- 1017,1027 ---- { tree type; ! if (t == NULL_TREE || t == error_mark_node) return t; type = TREE_TYPE (t); if (type + /* Minor optimization. + ?? Are these really the most frequent cases? Is the savings + significant? */ && type != integer_type_node && type != void_type_node *************** *** 1012,1017 **** TYPE_READONLY (type), TYPE_VOLATILE (type)); - if (type != TREE_TYPE (t)) - layout_type (t); switch (TREE_CODE (t)) { --- 1030,1033 ---- *************** *** 1053,1074 **** if (type == TREE_TYPE (t) ! && DECL_CONTEXT (t) == NULL_TREE) return t; fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs); result = tsubst (DECL_RESULT (t), args, nargs); ! if (DECL_CONTEXT (t)) { /* Look it up in that class, and return the decl node there, instead of creating a new one. */ ! tree ctx = tsubst (DECL_CONTEXT (t), args, nargs); ! tree methods = CLASSTYPE_METHOD_VEC (ctx); ! tree name = DECL_NAME (t); ! tree method; ! int n_methods = TREE_VEC_LENGTH (methods); int i, found = 0; r = NULL_TREE; ! if (DECL_CONTEXT (t) && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t)) name = constructor_name (ctx); --- 1069,1107 ---- if (type == TREE_TYPE (t) ! && (DECL_CONTEXT (t) == NULL_TREE ! || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')) return t; fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs); result = tsubst (DECL_RESULT (t), args, nargs); ! if (DECL_CONTEXT (t) != NULL_TREE ! && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't') { /* Look it up in that class, and return the decl node there, instead of creating a new one. */ ! tree ctx, methods, name, method; ! int n_methods; int i, found = 0; + name = DECL_NAME (t); + ctx = tsubst (DECL_CONTEXT (t), args, nargs); + methods = CLASSTYPE_METHOD_VEC (ctx); + if (methods == NULL_TREE) + /* No methods at all -- no way this one can match. */ + goto no_match; + n_methods = TREE_VEC_LENGTH (methods); + r = NULL_TREE; ! if (!strncmp (OPERATOR_TYPENAME_FORMAT, ! IDENTIFIER_POINTER (name), ! sizeof (OPERATOR_TYPENAME_FORMAT) - 1)) ! { ! /* Type-conversion operator. Reconstruct the name, in ! case it's the name of one of the template's parameters. */ ! name = build_typename_overload (TREE_TYPE (type)); ! } ! ! if (DECL_CONTEXT (t) != NULL_TREE ! && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't' && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t)) name = constructor_name (ctx); *************** *** 1088,1091 **** --- 1121,1161 ---- if (TREE_TYPE (method) != type) { + tree mtype = TREE_TYPE (method); + tree t1, t2; + + t1 = TYPE_ARG_TYPES (mtype); + t2 = TYPE_ARG_TYPES (type); + if (TREE_CODE (mtype) == FUNCTION_TYPE) + t2 = TREE_CHAIN (t2); + + if (list_eq (t1, t2)) + { + if (TREE_CODE (mtype) == FUNCTION_TYPE) + { + tree newtype; + newtype = build_function_type (TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + newtype = build_type_variant (newtype, + TYPE_READONLY (type), + TYPE_VOLATILE (type)); + type = newtype; + if (TREE_TYPE (type) != TREE_TYPE (mtype)) + goto maybe_bad_return_type; + } + else if (TYPE_METHOD_BASETYPE (mtype) + == TYPE_METHOD_BASETYPE (type)) + { + /* Types didn't match, but arg types and + `this' do match, so the return type is + all that should be messing it up. */ + maybe_bad_return_type: + if (TREE_TYPE (type) != TREE_TYPE (mtype)) + error ("inconsistent return types for method `%s' in class `%s'", + IDENTIFIER_POINTER (name), + IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx))); + } + r = method; + break; + } found = 1; continue; *************** *** 1107,1110 **** --- 1177,1181 ---- if (r == NULL_TREE) { + no_match: error (found ? "template for method `%s' doesn't match any in class `%s'" *************** *** 1118,1129 **** { r = DECL_NAME (t); ! r = build_decl_overload (r, TYPE_VALUES (type), ! DECL_CONTEXT (t) != NULL_TREE); ! r = build_lang_decl (FUNCTION_DECL, r, type); } TREE_PUBLIC (r) = TREE_PUBLIC (t); ! TREE_EXTERNAL (r) = TREE_EXTERNAL (t); TREE_STATIC (r) = TREE_STATIC (t); ! TREE_INLINE (r) = TREE_INLINE (t); DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t); DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t); --- 1189,1227 ---- { r = DECL_NAME (t); ! { ! tree decls, val; ! int got_it = 0; ! ! decls = IDENTIFIER_GLOBAL_VALUE (r); ! if (decls == NULL_TREE) ! /* no match */; ! else if (TREE_CODE (decls) == TREE_LIST) ! while (decls) ! { ! val = TREE_VALUE (decls); ! decls = TREE_CHAIN (decls); ! try_one: ! if (TREE_CODE (val) == FUNCTION_DECL ! && TREE_TYPE (val) == type) ! { ! got_it = 1; ! r = val; ! break; ! } ! } ! else ! { ! val = decls; ! decls = NULL_TREE; ! goto try_one; ! } ! if (!got_it) ! r = build_lang_decl (FUNCTION_DECL, r, type); ! } } TREE_PUBLIC (r) = TREE_PUBLIC (t); ! DECL_EXTERNAL (r) = DECL_EXTERNAL (t); TREE_STATIC (r) = TREE_STATIC (t); ! DECL_INLINE (r) = DECL_INLINE (t); DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t); DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t); *************** *** 1132,1136 **** DECL_ARGUMENTS (r) = fnargs; DECL_RESULT (r) = result; ! if (DECL_CONTEXT (t) == NULL_TREE) push_overloaded_decl_top_level (r, 0); return r; --- 1230,1235 ---- DECL_ARGUMENTS (r) = fnargs; DECL_RESULT (r) = result; ! if (DECL_CONTEXT (t) == NULL_TREE ! || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't') push_overloaded_decl_top_level (r, 0); return r; *************** *** 1246,1250 **** else if (context == NULL_TREE) { ! tree base = tsubst (TYPE_METHOD_BASETYPE (t), args, nargs); new_value = build_cplus_method_type (base, type, TREE_CHAIN (values)); --- 1345,1350 ---- else if (context == NULL_TREE) { ! tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), ! args, nargs); new_value = build_cplus_method_type (base, type, TREE_CHAIN (values)); *************** *** 1266,1271 **** } new_value = build_type_variant (new_value, ! TYPE_READONLY (new_value), ! TYPE_VOLATILE (new_value)); return new_value; } --- 1366,1371 ---- } new_value = build_type_variant (new_value, ! TYPE_READONLY (t), ! TYPE_VOLATILE (t)); return new_value; } *************** *** 1299,1303 **** IDENTIFIER_TYPE_VALUE (id); } ! return IDENTIFIER_TYPE_VALUE (id); } --- 1399,1405 ---- IDENTIFIER_TYPE_VALUE (id); } ! return build_type_variant (IDENTIFIER_TYPE_VALUE (id), ! TYPE_READONLY (t), ! TYPE_VOLATILE (t)); } *************** *** 1377,1380 **** --- 1479,1483 ---- p->len = t->length; p->fndecl = fndecl; + p->interface = 1; /* unknown */ } else *************** *** 1391,1395 **** /* do nothing */ } ! else if (TREE_INLINE (fndecl)) { DECL_PENDING_INLINE_INFO (fndecl) = p; --- 1494,1498 ---- /* do nothing */ } ! else if (DECL_INLINE (fndecl)) { DECL_PENDING_INLINE_INFO (fndecl) = p; *************** *** 1456,1460 **** if (!classlevel) ! pushlevel (1); t = xref_tag (tinfo->aggr, id, NULL_TREE); --- 1559,1566 ---- if (!classlevel) ! { ! pushlevel (1); ! declare_pseudo_global_level (); ! } t = xref_tag (tinfo->aggr, id, NULL_TREE); *************** *** 1511,1515 **** /* Restore the old parser input state. */ ! if (yychar == -2 /* YYEMPTY */) yychar = yylex (); if (yychar != END_OF_SAVED_INPUT) --- 1617,1621 ---- /* Restore the old parser input state. */ ! if (yychar == YYEMPTY) yychar = yylex (); if (yychar != END_OF_SAVED_INPUT) *************** *** 1526,1529 **** --- 1632,1639 ---- assert (t != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (t)) == 't'); CLASSTYPE_USE_TEMPLATE (t) = 2; + /* Always make methods of template classes static, until we've + got a decent scheme for handling them. The pragmas as they + are now are inadequate. */ + CLASSTYPE_INTERFACE_UNKNOWN (t) = 1; decl = IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (t1)); assert (TREE_CODE (decl) == TYPE_DECL); *************** *** 1627,1630 **** --- 1737,1742 ---- if (arg == error_mark_node) return 1; + if (arg == unknown_type_node) + return 1; #if 0 if (TREE_CODE (arg) == VAR_DECL) *************** *** 1680,1683 **** --- 1792,1797 ---- if (arg == error_mark_node) return 1; + if (arg == unknown_type_node) + return 1; if (arg == parm) return 0; *************** *** 1790,1794 **** case UNINSTANTIATED_P_TYPE: { ! tree a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg)); if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a)) /* different templates */ --- 1904,1915 ---- case UNINSTANTIATED_P_TYPE: { ! tree a; ! /* Unification of something that is not a template fails. (mrs) */ ! if (TYPE_NAME (arg) == 0) ! return 1; ! a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg)); ! /* Unification of something that is not a template fails. (mrs) */ ! if (a == 0) ! return 1; if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a)) /* different templates */ *************** *** 1798,1801 **** --- 1919,1926 ---- } + case RECORD_TYPE: + /* Unification of something that is not a template fails. (mrs) */ + return 1; + default: sorry ("use of `%s' in template type unification", *************** *** 1838,1842 **** Maybe both file contexts should be taken into account? */ context = DECL_CONTEXT (t); ! if (context) { /* If `unknown', we might want a static copy. --- 1963,1968 ---- Maybe both file contexts should be taken into account? */ context = DECL_CONTEXT (t); ! if (context != NULL_TREE ! && TREE_CODE_CLASS (TREE_CODE (context)) == 't') { /* If `unknown', we might want a static copy. *************** *** 1883,1886 **** --- 2009,2013 ---- } + struct pending_template { struct pending_template *next; *************** *** 1888,1893 **** }; ! ! struct pending_template* pending_templates; void --- 2015,2019 ---- }; ! static struct pending_template* pending_templates; void *************** *** 1908,1912 **** } ! int add_pending_template (pt) tree pt; --- 2034,2038 ---- } ! static void add_pending_template (pt) tree pt; diff -rc2N gcc-2.2.2/cp-ptree.c gcc-2.3.1/cp-ptree.c *** gcc-2.2.2/cp-ptree.c Thu Jun 11 00:27:23 1992 --- gcc-2.3.1/cp-ptree.c Mon Jul 6 18:37:56 1992 *************** *** 39,47 **** indent_to (file, indent + 3); if (DECL_MAIN_VARIANT (node)) ! fprintf (file, " decl-main-variant %x", DECL_MAIN_VARIANT (node)); if (DECL_PENDING_INLINE_INFO (node)) ! fprintf (file, " pending-inline-info %x", DECL_PENDING_INLINE_INFO (node)); if (DECL_TEMPLATE_INFO (node)) ! fprintf (file, " template-info %x", DECL_TEMPLATE_INFO (node)); } --- 39,56 ---- indent_to (file, indent + 3); if (DECL_MAIN_VARIANT (node)) ! { ! fprintf (file, " decl-main-variant "); ! fprintf (file, HOST_PTR_PRINTF, DECL_MAIN_VARIANT (node)); ! } if (DECL_PENDING_INLINE_INFO (node)) ! { ! fprintf (file, " pending-inline-info "); ! fprintf (file, HOST_PTR_PRINTF, DECL_PENDING_INLINE_INFO (node)); ! } if (DECL_TEMPLATE_INFO (node)) ! { ! fprintf (file, " template-info "); ! fprintf (file, HOST_PTR_PRINTF, DECL_TEMPLATE_INFO (node)); ! } } diff -rc2N gcc-2.2.2/cp-search.c gcc-2.3.1/cp-search.c *** gcc-2.2.2/cp-search.c Thu Jun 11 00:28:11 1992 --- gcc-2.3.1/cp-search.c Fri Sep 25 19:56:19 1992 *************** *** 34,40 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - void init_search (); extern struct obstack *current_obstack; --- 34,37 ---- *************** *** 442,445 **** --- 439,445 ---- if (TREE_CODE (parent) == TREE_VEC) parent = BINFO_TYPE (parent); + /* unions cannot participate in inheritance relationships */ + else if (TREE_CODE (parent) == UNION_TYPE) + return 0; else if (TREE_CODE (parent) != RECORD_TYPE) my_friendly_abort (89); *************** *** 892,896 **** { if (context == current_class_type ! || DERIVED_FROM_P (current_class_type, context)) PUBLIC_RETURN; else --- 892,896 ---- { if (context == current_class_type ! || DERIVED_FROM_P (context, current_class_type)) PUBLIC_RETURN; else *************** *** 1052,1060 **** /* Look for a field named NAME in an inheritance lattice dominated by XBASETYPE. PROTECT is zero if we can avoid computing visibility ! information, otherwise it is 1. */ tree ! lookup_field (xbasetype, name, protect) register tree xbasetype, name; ! int protect; { int head = 0, tail = 0; --- 1052,1061 ---- /* Look for a field named NAME in an inheritance lattice dominated by XBASETYPE. PROTECT is zero if we can avoid computing visibility ! information, otherwise it is 1. WANT_TYPE is 1 when we should only ! return TYPE_DECLs, if no TYPE_DECL can be found return NULL. */ tree ! lookup_field (xbasetype, name, protect, want_type) register tree xbasetype, name; ! int protect, want_type; { int head = 0, tail = 0; *************** *** 1115,1118 **** --- 1116,1122 ---- rval = lookup_field_1 (type, name); + if (rval && TREE_CODE (rval) != TYPE_DECL && want_type) + rval = NULL_TREE; + if (rval) { *************** *** 1232,1235 **** --- 1236,1243 ---- tree nval = lookup_field_1 (type, name); + if (nval && TREE_CODE (nval) != TYPE_DECL && want_type) + nval = NULL_TREE; + + if (nval && binfo != get_binfo (type, DECL_FIELD_CONTEXT (rval), 0)) *************** *** 1251,1254 **** --- 1259,1266 ---- { rval = lookup_field_1 (type, name); + + if (rval && TREE_CODE (rval) != TYPE_DECL && want_type) + rval = NULL_TREE; + if (rval) { *************** *** 1340,1343 **** --- 1352,1400 ---- } + /* If NAME is defined in an enclosing class, complain about it and + return the node. */ + tree + lookup_nested_field (name) + tree name; + { + register tree t; + + tree id = NULL_TREE; + if (TREE_CHAIN (current_class_type)) + { + /* Climb our way up the nested ladder, seeing if we're trying to + modify a field in an enclosing class. If so, we should only + be able to modify if it's static. */ + for (t = TREE_CHAIN (current_class_type); + t && DECL_CONTEXT (t); + t = TREE_CHAIN (DECL_CONTEXT (t))) + { + if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE) + break; + + /* N.B.: lookup_field will do the visibility checking for us */ + id = lookup_field (DECL_CONTEXT (t), name, 1, 0); + if (id == error_mark_node) + continue; + if (id != NULL_TREE) + { + if (! TREE_STATIC (id) && TREE_TYPE (id) != error_mark_node) + { + error ("assignment to non-static member `%s' of enclosing class `%s'", + lang_printable_name (id), + IDENTIFIER_POINTER (TYPE_IDENTIFIER + (DECL_CONTEXT (t)))); + /* Mark this for do_identifier(). It would otherwise + claim that the variable was undeclared. */ + TREE_TYPE (id) = error_mark_node; + } + break; + } + } + } + + return id; + } + /* TYPE is a class type. Return the index of the fields within the method vector with name NAME, or -1 is no such field exists. */ *************** *** 1717,1720 **** --- 1774,1778 ---- int tree_needs_constructor_p (binfo, i) tree binfo; + int i; { tree basetype; *************** *** 1840,1847 **** btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp)); ! if (instptr_type == NULL_TREE ! && compparms (TREE_CHAIN (btypes), dtypes, 3)) ! /* Caller knows to give error in this case. */ ! return tmp; if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes))) --- 1898,1908 ---- btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp)); ! if (instptr_type == NULL_TREE) ! { ! if (compparms (TREE_CHAIN (btypes), dtypes, 3)) ! /* Caller knows to give error in this case. */ ! return tmp; ! return NULL_TREE; ! } if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes))) *************** *** 2194,2199 **** tree binfo; { - extern tree pending_vtables; - tree t = BINFO_TYPE (binfo); --- 2255,2258 ---- *************** *** 2204,2208 **** CLASSTYPE_DEBUG_REQUESTED (t) = 1; ! /* If interface info is known, the value of DECL_IGNORED_P is correct. */ if (methods == 0 || ! CLASSTYPE_INTERFACE_UNKNOWN (t) --- 2263,2267 ---- CLASSTYPE_DEBUG_REQUESTED (t) = 1; ! /* If interface info is known, the value of (?@@?) is correct. */ if (methods == 0 || ! CLASSTYPE_INTERFACE_UNKNOWN (t) *************** *** 2453,2457 **** tree type = BINFO_TYPE (binfo); tree these_vbase_types = CLASSTYPE_VBASECLASSES (type); - tree basetype; if (these_vbase_types) --- 2512,2515 ---- diff -rc2N gcc-2.2.2/cp-spew.c gcc-2.3.1/cp-spew.c *** gcc-2.2.2/cp-spew.c Thu Jun 11 00:28:35 1992 --- gcc-2.3.1/cp-spew.c Thu Sep 24 21:49:49 1992 *************** *** 20,24 **** ! /* This file is the type analyzer for GNU C++. */ #include "config.h" --- 20,25 ---- ! /* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG ! when compiling cp-parse.c and cp-spew.c. */ #include "config.h" *************** *** 31,35 **** #include "flags.h" #include "obstack.h" ! #include /* This takes a token stream that hasn't decided much about types and --- 32,36 ---- #include "flags.h" #include "obstack.h" ! #include "assert.h" /* This takes a token stream that hasn't decided much about types and *************** *** 65,71 **** int first_token; - /* #define SPEW_DEBUG */ #ifdef SPEW_DEBUG ! static int spew_debug = 0; static int yylex_ctr = 0; static int debug_yychar (); --- 66,71 ---- int first_token; #ifdef SPEW_DEBUG ! int spew_debug = 0; static int yylex_ctr = 0; static int debug_yychar (); *************** *** 75,78 **** --- 75,85 ---- static char follows_identifier[END_OF_SAVED_INPUT+1]; + /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name + * of the last template_type parsed in cp-parse.y if it is followed by a + * scope operator. It will be reset inside the next invocation of yylex(). + * This is used for recognizing nested types inside templates. + * - niklas@appli.se */ + tree template_type_seen_before_scope; + /* Initialize token_obstack. Called once, from init_lex. */ void *************** *** 81,85 **** static char *chars_following_identifier = ".+-|/%^!?:"; short *ps; - char *pc; static short toks_follow_ids[] = { POINTSAT_LEFT_RIGHT, ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE, --- 88,91 ---- *************** *** 91,95 **** THROW, ANSI_TRY, ANSI_THROW, EXTERN_LANG_STRING, ALL, END_OF_SAVED_INPUT, -1 }; - static char *chars_following_typename = "("; static short toks_follow_types[] = { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL, --- 97,100 ---- *************** *** 232,241 **** obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token)); ! tmp = (char *)alloca ((num_tokens () + (n-first_token)) ! * sizeof (struct token)); ! /* This move does not rely on the system being able to handle ! overlapping moves. */ ! bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token)); ! bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token)); first_token = 0; } --- 237,249 ---- obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token)); ! if (old_token_count) ! { ! tmp = (char *)alloca ((num_tokens () + (n-first_token)) ! * sizeof (struct token)); ! /* This move does not rely on the system being able to handle ! overlapping moves. */ ! bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token)); ! bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token)); ! } first_token = 0; } *************** *** 277,282 **** { struct token tmp_token; ! tree t2; ! tree dk, trrr; retry: --- 285,289 ---- { struct token tmp_token; ! tree trrr; retry: *************** *** 289,296 **** #endif /* if we've got tokens, send them */ if (num_tokens()) { - tree tmp; tmp_token= *nth_token(0); --- 296,327 ---- #endif + /* This is a kludge for recognizing nested types in templates */ + if (template_type_seen_before_scope) + { + shift_tokens (2); /* Sync in hack_more_ids (yes, it's ugly) */ + nth_token (1)->yychar = SCOPE; + yylval.ttype = hack_more_ids (0, template_type_seen_before_scope); + template_type_seen_before_scope = 0; + if (!yylval.ttype) + { + /* Sync back again, leaving SCOPE on the token stream, because we + * failed to substitute the original SCOPE token with a + * SCOPED_TYPENAME. See rule "template_type" in cp-parse.y */ + consume_token (); + } + else + { + yychar = SCOPED_TYPENAME; + #ifdef SPEW_DEBUG + if (spew_debug) + debug_yychar(yychar); + #endif + return yychar; + } + } + /* if we've got tokens, send them */ if (num_tokens()) { tmp_token= *nth_token(0); *************** *** 475,480 **** { #if 0 ! t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype); ! if (t2) { tmp_token.yylval.ttype = t2; --- 506,511 ---- { #if 0 ! tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype); ! if (t2 != NULL_TREE) { tmp_token.yylval.ttype = t2; *************** *** 599,603 **** tb = resolve_scope_to_name (NULL_TREE, ta); ! if (tb) { if (nth_token (2)->yychar == OPERATOR) --- 630,634 ---- tb = resolve_scope_to_name (NULL_TREE, ta); ! if (tb != NULL_TREE) { if (nth_token (2)->yychar == OPERATOR) *************** *** 739,742 **** --- 770,778 ---- return exp_decl; + /* If we see a id&, or id&) the we are probably in an argument list. */ + if (ch=='&' + && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')')) + return type_decl; + /* Look for the first identifier or other distinguishing token we find in the next several tokens. */ *************** *** 926,930 **** val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype); type = resolve_scope_to_name (NULL_TREE, val); ! if (! type) return NULL_TREE; consume_token (); --- 962,966 ---- val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype); type = resolve_scope_to_name (NULL_TREE, val); ! if (type == NULL_TREE) return NULL_TREE; consume_token (); *************** *** 1005,1017 **** #ifdef SPEW_DEBUG ! ! /* ! * debug_yychar takes a yychar (token number) value and prints its ! * name. This only works if cp-tab.c is compiled with YYDEBUG != 0. ! */ static int debug_yychar (yy) int yy; { extern char *debug_yytranslate (); --- 1041,1050 ---- #ifdef SPEW_DEBUG ! /* debug_yychar takes a yychar (token number) value and prints its name. */ static int debug_yychar (yy) int yy; { + /* In cp-parse.y: */ extern char *debug_yytranslate (); diff -rc2N gcc-2.2.2/cp-tree.c gcc-2.3.1/cp-tree.c *** gcc-2.2.2/cp-tree.c Thu Jun 11 00:29:24 1992 --- gcc-2.3.1/cp-tree.c Thu Sep 24 21:49:56 1992 *************** *** 31,35 **** /* Return nonzero if REF is an lvalue valid for this language. Lvalues can be assigned, unless they have TREE_READONLY. ! Lvalues can have their address taken, unless they have TREE_REGDECL. */ int --- 31,35 ---- /* Return nonzero if REF is an lvalue valid for this language. Lvalues can be assigned, unless they have TREE_READONLY. ! Lvalues can have their address taken, unless they have DECL_REGISTER. */ int *************** *** 92,95 **** --- 92,102 ---- return 1; break; + + case ADDR_EXPR: + /* ANSI C++ June 5 1992 WP 5.4.14. The result of a cast to a + reference is an lvalue. */ + if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) + return 1; + break; } return 0; *************** *** 180,184 **** /* Recursively perform a preorder search EXP for CALL_EXPRs, making ! copies where they are found. Retuns a deep copy all nodes transitively containing CALL_EXPRs. */ --- 187,191 ---- /* Recursively perform a preorder search EXP for CALL_EXPRs, making ! copies where they are found. Returns a deep copy all nodes transitively containing CALL_EXPRs. */ *************** *** 200,222 **** return copy_node (exp); switch (TREE_CODE_CLASS (code)) { - case 'x': /* something random, like an identifier. */ - case 't': /* a type node */ default: abort (); case 'c': /* a constant */ case 'd': /* A decl node */ return exp; ! case 'e': /* a expression */ case 's': /* an expression with side effects */ ! for (i = tree_code_length[(int) code]; i >= 0; i--) { t1 = break_out_calls (TREE_OPERAND (exp, i)); if (t1 != TREE_OPERAND (exp, i)) { ! if (changed == 0) exp = copy_node (exp); TREE_OPERAND (exp, i) = t1; --- 207,251 ---- return copy_node (exp); + /* Don't try and defeat a save_expr, as it should only be done once. */ + if (code == SAVE_EXPR) + return exp; + switch (TREE_CODE_CLASS (code)) { default: abort (); case 'c': /* a constant */ + case 't': /* a type node */ + case 'x': /* something random, like an identifier or an ERROR_MARK. */ + return exp; + case 'd': /* A decl node */ + t1 = break_out_calls (DECL_INITIAL (exp)); + if (t1 != DECL_INITIAL (exp)) + { + exp = copy_node (exp); + DECL_INITIAL (exp) = t1; + } + return exp; + + case 'b': /* A block node */ + { + /* Don't know how to handle these correctly yet. Must do a + break_out_calls on all DECL_INITIAL values for local variables, + and also break_out_calls on all sub-blocks and sub-statements. */ + abort (); + } return exp; ! case 'e': /* an expression */ ! case 'r': /* a reference */ case 's': /* an expression with side effects */ ! for (i = tree_code_length[(int) code] - 1; i >= 0; i--) { t1 = break_out_calls (TREE_OPERAND (exp, i)); if (t1 != TREE_OPERAND (exp, i)) { ! if (changed++ == 0) exp = copy_node (exp); TREE_OPERAND (exp, i) = t1; *************** *** 230,234 **** if (t2 != TREE_OPERAND (exp, 1)) changed = 1; - case 'r': /* a reference */ case '1': /* a unary arithmetic expression */ t1 = break_out_calls (TREE_OPERAND (exp, 0)); --- 259,262 ---- *************** *** 301,305 **** { register tree t; - tree ptype = build_pointer_type (basetype); int hashcode; --- 329,332 ---- *************** *** 366,370 **** tree offset; { - tree t = BINFO_TYPE (binfo); tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; --- 393,396 ---- *************** *** 380,384 **** int j; tree child_binfos = BINFO_BASETYPES (child); - tree basetype = BINFO_TYPE (child); tree delta; --- 406,409 ---- *************** *** 561,567 **** #ifdef STRUCTURE_SIZE_BOUNDARY ! int record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec)); #else ! int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); #endif --- 586,592 ---- #ifdef STRUCTURE_SIZE_BOUNDARY ! unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec)); #else ! unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec)); #endif *************** *** 571,575 **** If VAR_SIZE is null, the size is just CONST_SIZE. Naturally we try to avoid using VAR_SIZE. */ ! register int const_size = 0; register tree var_size = 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; --- 596,600 ---- If VAR_SIZE is null, the size is just CONST_SIZE. Naturally we try to avoid using VAR_SIZE. */ ! register unsigned const_size = 0; register tree var_size = 0; int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; *************** *** 590,593 **** --- 615,626 ---- TREE_VIA_PUBLIC (child) = 1; TREE_VIA_VIRTUAL (child) = 0; + + /* Should handle this better so that + + class A; + class B: private A { virtual void F(); }; + + does not dump core when compiled. */ + my_friendly_abort (121); continue; } *************** *** 598,602 **** if (TREE_VIA_VIRTUAL (child)) { - tree binfo; int j; char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype) --- 631,634 ---- *************** *** 622,625 **** --- 654,660 ---- decl = build_lang_decl (FIELD_DECL, get_identifier (name), build_pointer_type (basetype)); + /* If you change any of the below, take a look at all the + other VFIELD_BASEs and VTABLE_BASEs in the code, and change + them too. */ DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE); DECL_VIRTUAL_P (decl) = 1; *************** *** 627,634 **** DECL_CLASS_CONTEXT (decl) = rec; DECL_FCONTEXT (decl) = basetype; TREE_CHAIN (decl) = vbase_decls; vbase_decls = decl; ! if (TYPE_HAS_DESTRUCTOR (basetype) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) { --- 662,672 ---- DECL_CLASS_CONTEXT (decl) = rec; DECL_FCONTEXT (decl) = basetype; + DECL_FIELD_SIZE (decl) = 0; + DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node); TREE_CHAIN (decl) = vbase_decls; + BINFO_VPTR_FIELD (child) = decl; vbase_decls = decl; ! if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) { *************** *** 653,657 **** offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT); ! if (TYPE_HAS_DESTRUCTOR (basetype) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) { --- 691,695 ---- offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT); ! if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE) { *************** *** 1003,1007 **** tree chain; { ! tree binfo = make_tree_vec (5); tree old_binfo = TYPE_BINFO (type); tree last; --- 1041,1045 ---- tree chain; { ! tree binfo = make_tree_vec (6); tree old_binfo = TYPE_BINFO (type); tree last; *************** *** 1012,1018 **** TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type); ! TREE_VEC_ELT (binfo, 1) = offset; ! TREE_VEC_ELT (binfo, 2) = vtable; ! TREE_VEC_ELT (binfo, 3) = virtuals; last = binfo; --- 1050,1057 ---- TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type); ! BINFO_OFFSET (binfo) = offset; ! BINFO_VTABLE (binfo) = vtable; ! BINFO_VIRTUALS (binfo) = virtuals; ! BINFO_VPTR_FIELD (binfo) = NULL_TREE; last = binfo; *************** *** 1661,1670 **** const char *string; const char *expression; ! int line; const char *filename; #else char *string; char *expression; ! int line; char *filename; #endif --- 1700,1709 ---- const char *string; const char *expression; ! unsigned line; const char *filename; #else char *string; char *expression; ! unsigned line; char *filename; #endif *************** *** 1695,1699 **** tree type; { - tree index_type = TYPE_DOMAIN (type); tree sz = array_type_nelts_top (type); type = TREE_TYPE (type); --- 1734,1737 ---- diff -rc2N gcc-2.2.2/cp-tree.h gcc-2.3.1/cp-tree.h *** gcc-2.2.2/cp-tree.h Thu Jun 11 00:34:03 1992 --- gcc-2.3.1/cp-tree.h Thu Sep 24 21:50:06 1992 *************** *** 28,32 **** #endif #if PARANOID ! #include #endif --- 28,32 ---- #endif #if PARANOID ! #include "assert.h" #endif *************** *** 121,124 **** --- 121,126 ---- ((struct lang_identifier *)(NODE))->x->error_locus = (VALUE)) + #define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE) + /* Nonzero if this identifier is the prefix for a mangled C++ operator name. */ #define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2(NODE) *************** *** 140,149 **** /* in cp-typeck.c */ ! extern tree build_component_ref(), build_conditional_expr(); ! extern tree build_x_compound_expr (), build_compound_expr(); ! extern tree build_unary_op(), build_binary_op(), build_function_call(); extern tree build_binary_op_nodefault (); ! extern tree build_indirect_ref(), build_array_ref(), build_c_cast(); ! extern tree build_modify_expr(); extern tree c_sizeof (), c_alignof (); extern tree store_init_value (); --- 142,151 ---- /* in cp-typeck.c */ ! extern tree build_component_ref (), build_conditional_expr (); ! extern tree build_x_compound_expr (), build_compound_expr (); ! extern tree build_unary_op (), build_binary_op (), build_function_call (); extern tree build_binary_op_nodefault (); ! extern tree build_indirect_ref (), build_array_ref (), build_c_cast (); ! extern tree build_modify_expr (); extern tree c_sizeof (), c_alignof (); extern tree store_init_value (); *************** *** 151,154 **** --- 153,157 ---- extern tree c_expand_start_case (); extern tree default_conversion (); + extern int comptypes (), compparms (), compexcepttypes (); /* Given two integer or real types, return the type for their sum. *************** *** 213,216 **** --- 216,223 ---- extern tree shorten_compare (); + + /* Prepare expr to be an argument of a TRUTH_NOT_EXPR, + or validate its data type for an `if' or `while' statement or ?..: exp. */ + extern tree truthvalue_conversion (); extern tree double_type_node, long_double_type_node, float_type_node; *************** *** 225,228 **** --- 232,239 ---- extern tree wchar_array_type_node; extern tree wchar_type_node, signed_wchar_type_node, unsigned_wchar_type_node; + extern tree intQI_type_node, unsigned_intQI_type_node; + extern tree intHI_type_node, unsigned_intHI_type_node; + extern tree intSI_type_node, unsigned_intSI_type_node; + extern tree intDI_type_node, unsigned_intDI_type_node; extern int current_function_returns_value; *************** *** 255,258 **** --- 266,273 ---- extern int flag_gnu_binutils; + /* Nonzero means ignore `#ident' directives. */ + + extern int flag_no_ident; + /* Nonzero means warn about implicit declarations. */ *************** *** 288,291 **** --- 303,311 ---- extern int warn_cast_qual; + /* Nonzero means warn about non virtual destructors in classes that have + virtual functions. */ + + extern int warn_nonvdtor; + /* Nonzero means do some things the same way PCC does. */ *************** *** 296,305 **** extern int flag_signed_bitfields; ! /* 2 means write out only specific virtual function tables and give them (C) public visibility. 1 means write out virtual function tables and give them (C) public visibility. 0 means write out virtual function tables and give them ! (C) static visibility. -1 means declare virtual function tables extern. */ --- 316,327 ---- extern int flag_signed_bitfields; ! /* 3 means write out only virtuals function tables `defined' ! in this implementation file. ! 2 means write out only specific virtual function tables and give them (C) public visibility. 1 means write out virtual function tables and give them (C) public visibility. 0 means write out virtual function tables and give them ! (C) static visibility (default). -1 means declare virtual function tables extern. */ *************** *** 544,556 **** #define TREE_NONLOCAL_FLAG(NODE) (TREE_LANG_FLAG_0 (NODE)) - /* Ditto, for `private' declarations. */ - #define TREE_VIA_PRIVATE(NODE) ((NODE)->common.private_flag) - - /* Nonzero for TREE_LIST node means that the path to the - base class is via a `protected' declaration, which preserves - protected fields from the base class as protected. - OVERLOADED. */ - #define TREE_VIA_PROTECTED(NODE) ((NODE)->common.static_flag) - /* Nonzero for a _CLASSTYPE node which we know to be private. */ #define TYPE_PRIVATE_P(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.private_attr) --- 566,569 ---- *************** *** 1076,1079 **** --- 1089,1103 ---- #define C_TYPEDEF_EXPLICITLY_SIGNED(exp) DECL_LANG_FLAG_1 ((exp)) + /* Nonzero if the type T promotes to itself. + ANSI C states explicitly the list of types that promote; + in particular, short promotes to int even if they have the same width. */ + #define C_PROMOTING_INTEGER_TYPE_P(t) \ + (TREE_CODE ((t)) == INTEGER_TYPE \ + && (TYPE_MAIN_VARIANT (t) == char_type_node \ + || TYPE_MAIN_VARIANT (t) == signed_char_type_node \ + || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \ + || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ + || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) + /* Mark which labels are explicitly declared. These may be shadowed, and may be referenced from nested functions. */ *************** *** 1126,1130 **** /* Nonzero for VAR_DECL node means that `external' was specified in its declaration. */ ! #define DECL_EXTERNAL(NODE) (DECL_LANG_FLAG_2(NODE)) /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */ --- 1150,1154 ---- /* Nonzero for VAR_DECL node means that `external' was specified in its declaration. */ ! #define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE)) /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */ *************** *** 1225,1229 **** extern tree build_member_type (); extern tree build_push_scope (); ! extern tree vtable_entry_type; extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node; --- 1249,1253 ---- extern tree build_member_type (); extern tree build_push_scope (); ! extern void finish_builtin_type (); extern tree vtable_entry_type; extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node; *************** *** 1300,1303 **** --- 1324,1328 ---- extern tree binfo_or_else (); extern void my_friendly_abort (); + extern void error_with_aggr_type (); /* in tree.c */ *************** *** 1311,1315 **** extern tree build_cplus_method_type (); extern tree build_classtype_variant (); ! extern tree hash_tree_cons (), hash_tree_chain (); extern tree list_hash_lookup_or_cons (); extern tree layout_basetypes (); --- 1336,1340 ---- extern tree build_cplus_method_type (); extern tree build_classtype_variant (); ! extern tree hash_tree_cons (), hash_tree_chain (), hash_chainon (); extern tree list_hash_lookup_or_cons (); extern tree layout_basetypes (); *************** *** 1330,1333 **** --- 1355,1359 ---- extern tree cplus_expand_start_catch (); extern tree cplus_expand_end_try (); + extern void finish_exception_decl (); /* in cp-class.c */ *************** *** 1345,1352 **** extern tree build_method_call (), build_overload_call (); extern tree build_type_pathname (); ! extern tree start_method (), start_type_method (); extern tree finish_method (); ! extern tree lookup_field (), lookup_fnfields (); void pushclass (), popclass (), pushclasstype (); --- 1371,1378 ---- extern tree build_method_call (), build_overload_call (); extern tree build_type_pathname (); ! extern tree start_method (); extern tree finish_method (); ! extern tree lookup_field (), lookup_nested_field (), lookup_fnfields (); void pushclass (), popclass (), pushclasstype (); *************** *** 1381,1384 **** --- 1407,1411 ---- extern tree get_member_function (); extern tree build_member_call (), build_offset_ref (); + extern tree build_virtual_init (); extern int current_function_assigns_this; *************** *** 1392,1402 **** #define OPERATOR_TYPENAME_FORMAT "__op" ! /* Cannot use '$' up front, because this confuses gdb. ! Note that any format of this kind *must* make the ! format for `this' lexicographically less than any other ! parameter name, i.e. "$this" is less than anything else can be. Note that all forms in which the '$' is significant are long enough ! for direct indexing. */ /* Define NO_DOLLAR_IN_LABEL in your favorite tm file if your assembler --- 1419,1429 ---- #define OPERATOR_TYPENAME_FORMAT "__op" ! /* Cannot use '$' up front, because this confuses gdb ! (names beginning with '$' are gdb-local identifiers). Note that all forms in which the '$' is significant are long enough ! for direct indexing (meaning that if we know there is a '$' ! at a particular location, we can index into the string at ! any other location that provides distinguishing characters). */ /* Define NO_DOLLAR_IN_LABEL in your favorite tm file if your assembler *************** *** 1406,1410 **** #define JOINER '$' ! #define THIS_NAME "$t" #define VPTR_NAME "$v" #define THROW_NAME "$eh_throw" --- 1433,1437 ---- #define JOINER '$' ! #define THIS_NAME "this" #define VPTR_NAME "$v" #define THROW_NAME "$eh_throw" *************** *** 1433,1437 **** #define JOINER '.' ! #define THIS_NAME ".t" #define VPTR_NAME ".v" #define THROW_NAME ".eh_throw" --- 1460,1464 ---- #define JOINER '.' ! #define THIS_NAME "this" #define VPTR_NAME ".v" #define THROW_NAME ".eh_throw" *************** *** 1551,1554 **** --- 1578,1582 ---- unsigned int can_free : 1; /* free this after we're done with it? */ unsigned int deja_vu : 1; /* set iff we don't want to see it again. */ + unsigned int interface : 2; /* 0=interface 1=unknown 2=implementation */ }; *************** *** 1682,1689 **** /* in cp-init.c */ extern tree resolve_offset_ref (); /* in cp-lex.c */ extern char *operator_name_string (); ! extern tree build_opid (); extern tree do_identifier (); --- 1710,1718 ---- /* in cp-init.c */ extern tree resolve_offset_ref (); + extern tree build_vbase_delete (); /* in cp-lex.c */ extern char *operator_name_string (); ! extern void compiler_error_with_decl (); extern tree build_opid (); extern tree do_identifier (); *************** *** 1706,1709 **** --- 1735,1739 ---- extern tree build_vbase_pointer (), build_vbase_path (); extern tree lookup_fnfield (), next_baselink (); + extern tree build_vbase_vtables_init (); extern tree get_binfo (); *************** *** 1756,1759 **** --- 1786,1793 ---- #define UNKNOWN_TYPE LANG_TYPE + + /* in cp-xref.c */ + extern void GNU_xref_start_scope (); + extern void GNU_xref_end_scope (); /* -- end of C++ */ diff -rc2N gcc-2.2.2/cp-type2.c gcc-2.3.1/cp-type2.c *** gcc-2.2.2/cp-type2.c Thu Jun 11 00:29:57 1992 --- gcc-2.3.1/cp-type2.c Tue Oct 13 22:02:43 1992 *************** *** 287,290 **** --- 287,291 ---- one day, maybe it will be. (mrs) */ + /* Last used: 124 */ void my_friendly_abort(i) *************** *** 298,302 **** fatal ("please fix above errors, and try recompiling."); else ! fatal ("internal compiler error %d, please report", i); } --- 299,306 ---- fatal ("please fix above errors, and try recompiling."); else ! { ! error ("Internal compiler error %d.", i); ! fatal ("Please report this to `bug-g++@prep.ai.mit.edu'."); ! } } *************** *** 468,475 **** if (pedantic && TREE_CODE (value) == CONSTRUCTOR) { ! if (! TREE_CONSTANT (value)) ! warning ("aggregate initializer is not constant"); ! else if (! TREE_STATIC (value)) ! warning ("aggregate initializer uses complicated arithmetic"); } } --- 472,477 ---- if (pedantic && TREE_CODE (value) == CONSTRUCTOR) { ! if (! TREE_CONSTANT (value) || ! TREE_STATIC (value)) ! pedwarn ("ANSI C forbids non-constant aggregate initializer expressions"); } } *************** *** 508,513 **** } ! if (init == error_mark_node) ! return init; /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ --- 510,516 ---- } ! if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST ! && TREE_VALUE (init) == error_mark_node)) ! return error_mark_node; /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ *************** *** 551,555 **** pedwarn ("ANSI C forbids initializing array from array expression"); if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE)) ! pedwarn ("single-expression nonscalar initializer has braces"); if (TREE_CODE (element) == CONST_DECL) element = DECL_INITIAL (element); --- 554,558 ---- pedwarn ("ANSI C forbids initializing array from array expression"); if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE)) ! pedwarn ("ANSI C forbids single nonscalar initializer with braces"); if (TREE_CODE (element) == CONST_DECL) element = DECL_INITIAL (element); *************** *** 642,648 **** = TREE_INT_CST_LOW (TYPE_SIZE (type)); size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; ! /* Subtract 1 because it's ok to ignore the terminating null char ! that is counted in the length of the constant. */ ! if (size < TREE_STRING_LENGTH (string) - 1) warning ("initializer-string for array of chars is too long"); } --- 645,653 ---- = TREE_INT_CST_LOW (TYPE_SIZE (type)); size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; ! /* In C it is ok to subtract 1 from the length of the string ! because it's ok to ignore the terminating null char that is ! counted in the length of the constant, but in C++ this would ! be invalid. */ ! if (size < TREE_STRING_LENGTH (string)) warning ("initializer-string for array of chars is too long"); } *************** *** 742,746 **** if (elts) ! tail = *elts; else tail = CONSTRUCTOR_ELTS (init); --- 747,755 ---- if (elts) ! { ! if (extra_warnings) ! warning ("aggregate has a partly bracketed initializer"); ! tail = *elts; ! } else tail = CONSTRUCTOR_ELTS (init); *************** *** 955,959 **** { /* We have some work to do. */ ! struct type_chain { tree type; struct type_chain *next; } *chain = 0, *head = 0; orig_ref = ref = build_unary_op (ADDR_EXPR, datum, 0); while (TREE_CODE (types) == SCOPE_REF) --- 964,968 ---- { /* We have some work to do. */ ! struct type_chain { tree type; struct type_chain *next; } *chain = 0, *head = 0, scratch; orig_ref = ref = build_unary_op (ADDR_EXPR, datum, 0); while (TREE_CODE (types) == SCOPE_REF) *************** *** 973,977 **** return error_mark_node; ! head = (struct type_chain *)alloca (sizeof (struct type_chain)); head->type = IDENTIFIER_TYPE_VALUE (types); head->next = chain; --- 982,986 ---- return error_mark_node; ! head = &scratch; head->type = IDENTIFIER_TYPE_VALUE (types); head->next = chain; *************** *** 1163,1167 **** tree expr_as_conversion = NULL_TREE; ! if (parms == error_mark_node) return error_mark_node; --- 1172,1176 ---- tree expr_as_conversion = NULL_TREE; ! if (exp == error_mark_node || parms == error_mark_node) return error_mark_node; *************** *** 1336,1340 **** #if 0 /* mrs Mar 12, 1992 I claim that if it is a constructor, it is ! impossible to be a expr_as_method, without being a constructor call. */ if (expr_as_method --- 1345,1349 ---- #if 0 /* mrs Mar 12, 1992 I claim that if it is a constructor, it is ! impossible to be an expr_as_method, without being a constructor call. */ if (expr_as_method *************** *** 1350,1353 **** --- 1359,1363 ---- else if (expr_as_conversion && expr_as_conversion != error_mark_node) { + /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */ error ("ambiguity between conversion to `%s' and constructor", IDENTIFIER_POINTER (name)); *************** *** 1408,1412 **** { register tree values = TYPE_VALUES (type); ! register int intval = TREE_INT_CST_LOW (value); assert (TREE_CODE (type) == ENUMERAL_TYPE); --- 1418,1422 ---- { register tree values = TYPE_VALUES (type); ! register HOST_WIDE_INT intval = TREE_INT_CST_LOW (value); assert (TREE_CODE (type) == ENUMERAL_TYPE); diff -rc2N gcc-2.2.2/cp-typeck.c gcc-2.3.1/cp-typeck.c *** gcc-2.2.2/cp-typeck.c Thu Jun 11 00:31:13 1992 --- gcc-2.3.1/cp-typeck.c Thu Sep 24 21:50:31 1992 *************** *** 35,38 **** --- 35,39 ---- #include #include "tree.h" + #include "rtl.h" #include "cp-tree.h" #include "flags.h" *************** *** 56,59 **** --- 57,62 ---- extern void readonly_warning_or_error (); + extern rtx original_result_rtx; + /* Return the target type of TYPE, which meas return T for: T*, T&, T[], T (...), and otherwise, just T. */ *************** *** 151,154 **** --- 154,159 ---- /* Return the common type of two parameter lists. + We assume that comptypes has already been done and returned 1; + if that isn't so, this may crash. As an optimization, free the space we allocate if the parameter *************** *** 352,364 **** /* Save space: see if the result is identical to one of the args. */ ! if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2)) return t1; ! if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1)) return t2; /* Simple way if one arg fails to specify argument types. */ ! if (TYPE_ARG_TYPES (t1) == 0) { ! rval = build_function_type (valtype, TYPE_ARG_TYPES (t2)); if (raises = TYPE_RAISES_EXCEPTIONS (t2)) rval = build_exception_variant (NULL_TREE, rval, raises); --- 357,369 ---- /* Save space: see if the result is identical to one of the args. */ ! if (valtype == TREE_TYPE (t1) && ! p2) return t1; ! if (valtype == TREE_TYPE (t2) && ! p1) return t2; /* Simple way if one arg fails to specify argument types. */ ! if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node) { ! rval = build_function_type (valtype, p2); if (raises = TYPE_RAISES_EXCEPTIONS (t2)) rval = build_exception_variant (NULL_TREE, rval, raises); *************** *** 366,372 **** } raises = TYPE_RAISES_EXCEPTIONS (t1); ! if (TYPE_ARG_TYPES (t2) == 0) { ! rval = build_function_type (valtype, TYPE_ARG_TYPES (t1)); if (raises) rval = build_exception_variant (NULL_TREE, rval, raises); --- 371,377 ---- } raises = TYPE_RAISES_EXCEPTIONS (t1); ! if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node) { ! rval = build_function_type (valtype, p1); if (raises) rval = build_exception_variant (NULL_TREE, rval, raises); *************** *** 441,444 **** --- 446,450 ---- register int (*cmp)(); tree t1, t2; + int strict; { tree d1 = TYPE_DOMAIN (t1); *************** *** 913,921 **** return 0; ! if (type == float_type_node) return 0; ! if (TREE_CODE (type) == INTEGER_TYPE ! && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) return 0; } --- 919,929 ---- return 0; ! if (TYPE_MAIN_VARIANT (type) == float_type_node) ! return 0; ! ! if (type == 0) return 0; ! if (C_PROMOTING_INTEGER_TYPE_P (type)) return 0; } *************** *** 931,945 **** tree type; { ! type = TYPE_MAIN_VARIANT (type); ! if (type == signed_char_type_node || type == char_type_node) return unsigned_char_type_node; ! if (type == integer_type_node) return unsigned_type_node; ! if (type == short_integer_type_node) return short_unsigned_type_node; ! if (type == long_integer_type_node) return long_unsigned_type_node; ! if (type == long_long_integer_type_node) return long_long_unsigned_type_node; return type; --- 939,953 ---- tree type; { ! tree type1 = TYPE_MAIN_VARIANT (type); ! if (type1 == signed_char_type_node || type1 == char_type_node) return unsigned_char_type_node; ! if (type1 == integer_type_node) return unsigned_type_node; ! if (type1 == short_integer_type_node) return short_unsigned_type_node; ! if (type1 == long_integer_type_node) return long_unsigned_type_node; ! if (type1 == long_long_integer_type_node) return long_long_unsigned_type_node; return type; *************** *** 952,964 **** tree type; { ! if (type == unsigned_char_type_node || type == char_type_node) return signed_char_type_node; ! if (type == unsigned_type_node) return integer_type_node; ! if (type == short_unsigned_type_node) return short_integer_type_node; ! if (type == long_unsigned_type_node) return long_integer_type_node; ! if (type == long_long_unsigned_type_node) return long_long_integer_type_node; return type; --- 960,974 ---- tree type; { ! tree type1 = TYPE_MAIN_VARIANT (type); ! ! if (type1 == unsigned_char_type_node || type1 == char_type_node) return signed_char_type_node; ! if (type1 == unsigned_type_node) return integer_type_node; ! if (type1 == short_unsigned_type_node) return short_integer_type_node; ! if (type1 == long_unsigned_type_node) return long_integer_type_node; ! if (type1 == long_long_unsigned_type_node) return long_long_integer_type_node; return type; *************** *** 998,1002 **** { if (pedantic || warn_pointer_arith) ! pedwarn ("sizeof applied to a function type"); return size_int (1); } --- 1008,1012 ---- { if (pedantic || warn_pointer_arith) ! pedwarn ("ANSI C forbids taking the sizeof a function type"); return size_int (1); } *************** *** 1004,1008 **** { if (pedantic || warn_pointer_arith) ! pedwarn ("sizeof applied to a method type"); return size_int (1); } --- 1014,1018 ---- { if (pedantic || warn_pointer_arith) ! pedwarn ("ANSI C forbids taking the sizeof a method type"); return size_int (1); } *************** *** 1010,1014 **** { if (pedantic || warn_pointer_arith) ! pedwarn ("sizeof applied to a void type"); return size_int (1); } --- 1020,1024 ---- { if (pedantic || warn_pointer_arith) ! pedwarn ("ANSI C forbids taking the sizeof a void type"); return size_int (1); } *************** *** 1130,1144 **** exp = TREE_OPERAND (exp, 0); ! if (code == ENUMERAL_TYPE ! || (code == INTEGER_TYPE ! && (TYPE_PRECISION (type) ! < TYPE_PRECISION (integer_type_node)))) ! { ! /* Traditionally, unsignedness is preserved in default promotions. */ ! if (flag_traditional && TREE_UNSIGNED (type)) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } ! if (flag_traditional && type == float_type_node) return convert (double_type_node, exp); if (code == VOID_TYPE) --- 1140,1165 ---- exp = TREE_OPERAND (exp, 0); ! /* Normally convert enums to int, ! but convert wide enums to something wider. */ ! if (code == ENUMERAL_TYPE) ! { ! type = type_for_size (MAX (TYPE_PRECISION (type), ! TYPE_PRECISION (integer_type_node)), ! (flag_traditional && TREE_UNSIGNED (type))); ! return convert (type, exp); ! } ! ! if (C_PROMOTING_INTEGER_TYPE_P (type)) ! { ! /* Traditionally, unsignedness is preserved in default promotions. ! Otherwise, retain unsignedness if really not getting bigger. */ ! if (TREE_UNSIGNED (type) ! && (flag_traditional ! || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) return convert (unsigned_type_node, exp); return convert (integer_type_node, exp); } ! if (flag_traditional ! && TYPE_MAIN_VARIANT (type) == float_type_node) return convert (double_type_node, exp); if (code == VOID_TYPE) *************** *** 1304,1315 **** case COMPOUND_EXPR: { ! tree op1 = build_component_ref (TREE_OPERAND (datum, 1), component, ! basetype_path, protect); ! pedantic_lvalue_warning (COMPOUND_EXPR); ! return build (COMPOUND_EXPR, TREE_TYPE (op1), ! TREE_OPERAND (datum, 0), op1); } case COND_EXPR: - pedantic_lvalue_warning (COND_EXPR); return build_conditional_expr (TREE_OPERAND (datum, 0), --- 1325,1334 ---- case COMPOUND_EXPR: { ! tree value = build_component_ref (TREE_OPERAND (datum, 1), component, ! basetype_path, protect); ! return build (COMPOUND_EXPR, TREE_TYPE (value), ! TREE_OPERAND (datum, 0), value); } case COND_EXPR: return build_conditional_expr (TREE_OPERAND (datum, 0), *************** *** 1387,1391 **** basetype_path = TYPE_BINFO (basetype); field = lookup_field (basetype_path, component, ! protect && ! VFIELD_NAME_P (component)); if (field == error_mark_node) return error_mark_node; --- 1406,1410 ---- basetype_path = TYPE_BINFO (basetype); field = lookup_field (basetype_path, component, ! protect && ! VFIELD_NAME_P (component), 0); if (field == error_mark_node) return error_mark_node; *************** *** 1473,1477 **** assert (datum != error_mark_node); } ! ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field); if (TREE_READONLY (datum) || TREE_READONLY (field)) --- 1492,1496 ---- assert (datum != error_mark_node); } ! ref = build (COMPONENT_REF, TREE_TYPE (field), break_out_cleanups (datum), field); if (TREE_READONLY (datum) || TREE_READONLY (field)) *************** *** 1619,1623 **** while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); ! if (TREE_CODE (foo) == VAR_DECL && TREE_REGDECL (foo)) pedwarn ("ANSI C forbids subscripting non-lvalue array"); } --- 1638,1642 ---- while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); ! if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) pedwarn ("ANSI C forbids subscripting non-lvalue array"); } *************** *** 1871,1876 **** && DECL_CONTEXT (function) == NULL_TREE) { ! error ("cannot call `main' from within program"); ! return error_mark_node; } --- 1890,1894 ---- && DECL_CONTEXT (function) == NULL_TREE) { ! pedwarn ("ANSI C++ forbids calling `main' from within program"); } *************** *** 1879,1883 **** needs to be separately compiled). */ ! if (! TREE_INLINE (function)) { assemble_external (function); --- 1897,1901 ---- needs to be separately compiled). */ ! if (! DECL_INLINE (function)) { assemble_external (function); *************** *** 2056,2060 **** if (fndecl) { ! char buf[80]; sprintf (buf, "too many arguments to %s `%%s'", called_thing); error_with_decl (fndecl, buf); --- 2074,2078 ---- if (fndecl) { ! char *buf = (char *)alloca (40 + strlen (called_thing)); sprintf (buf, "too many arguments to %s `%%s'", called_thing); error_with_decl (fndecl, buf); *************** *** 2152,2155 **** --- 2170,2176 ---- val = require_complete_type (val); + if (val == error_mark_node) + continue; + maybe_raises |= TREE_RAISES (val); *************** *** 2199,2203 **** { if (pedantic) ! error_with_aggr_type (TREE_TYPE (val), "cannot pass objects of type `%s' through `...'"); else warning ("cannot pass objects of type `%s' through `...'", --- 2220,2225 ---- { if (pedantic) ! pedwarn ("ANSI C++ forbids passing objects of type `%s' through `...'", ! TYPE_NAME_STRING (TREE_TYPE (val))); else warning ("cannot pass objects of type `%s' through `...'", *************** *** 2448,2456 **** int common = 0; ! /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ ! if (TREE_CODE (op0) == NON_LVALUE_EXPR) ! op0 = TREE_OPERAND (op0, 0); ! if (TREE_CODE (op1) == NON_LVALUE_EXPR) ! op1 = TREE_OPERAND (op1, 0); /* If an error was already reported for one of the arguments, --- 2470,2476 ---- int common = 0; ! /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ ! STRIP_TYPE_NOPS (op0); ! STRIP_TYPE_NOPS (op1); /* If an error was already reported for one of the arguments, *************** *** 2568,2581 **** if (TREE_CODE (op1) == INTEGER_CST) { ! if (TREE_INT_CST_LOW (op1) > 0) ! short_shift = 1; ! else if (TREE_INT_CST_LOW (op1) < 0) warning ("shift count is negative"); ! if ((unsigned) TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0)) ! warning ("shift count exceeds width of value shifted"); } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ ! if (TREE_TYPE (op1) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ --- 2588,2606 ---- if (TREE_CODE (op1) == INTEGER_CST) { ! if (tree_int_cst_lt (op1, integer_zero_node)) warning ("shift count is negative"); ! else ! { ! if (TREE_INT_CST_LOW (op1) | TREE_INT_CST_HIGH (op1)) ! short_shift = 1; ! if (TREE_INT_CST_HIGH (op1) != 0 ! || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1) ! >= TYPE_PRECISION (type0))) ! warning ("shift count >= width of type"); ! } } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ ! if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ *************** *** 2588,2600 **** { result_type = type0; ! if (TREE_CODE (op1) == INTEGER_CST ! && TREE_INT_CST_LOW (op1) < 0) ! warning ("shift count is negative"); ! if (TREE_CODE (op1) == INTEGER_CST ! && (unsigned) TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0)) ! warning ("shift count exceeds width of value shifted"); /* Convert the shift-count to an integer, regardless of size of value being shifted. */ ! if (TREE_TYPE (op1) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ --- 2613,2628 ---- { result_type = type0; ! if (TREE_CODE (op1) == INTEGER_CST) ! { ! if (tree_int_cst_lt (op1, integer_zero_node)) ! warning ("shift count is negative"); ! else if (TREE_INT_CST_HIGH (op1) != 0 ! || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1) ! >= TYPE_PRECISION (type0))) ! warning ("shift count >= width of type"); ! } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ ! if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ *************** *** 2608,2620 **** { result_type = type0; ! if (TREE_CODE (op1) == INTEGER_CST ! && TREE_INT_CST_LOW (op1) < 0) ! warning ("shift count is negative"); ! if (TREE_CODE (op1) == INTEGER_CST ! && (unsigned) TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0)) ! warning ("shift count >= width of value shifted"); /* Convert the shift-count to an integer, regardless of size of value being shifted. */ ! if (TREE_TYPE (op1) != integer_type_node) op1 = convert (integer_type_node, op1); } --- 2636,2651 ---- { result_type = type0; ! if (TREE_CODE (op1) == INTEGER_CST) ! { ! if (tree_int_cst_lt (op1, integer_zero_node)) ! warning ("shift count is negative"); ! else if (TREE_INT_CST_HIGH (op1) != 0 ! || ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1) ! >= TYPE_PRECISION (type0))) ! warning ("shift count >= width of type"); ! } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ ! if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = convert (integer_type_node, op1); } *************** *** 2647,2658 **** return error_mark_node; } - if (integer_zerop (op0)) - op0 = null_pointer_node; - else - op0 = convert_pointer_to (base, op0); - if (integer_zerop (op1)) - op1 = null_pointer_node; else ! op1 = convert_pointer_to (base, op1); } else if (comp_target_types (type0, type1, 1)) --- 2678,2692 ---- return error_mark_node; } else ! { ! if (integer_zerop (op0)) ! op0 = null_pointer_node; ! else ! op0 = convert_pointer_to (base, op0); ! if (integer_zerop (op1)) ! op1 = null_pointer_node; ! else ! op1 = convert_pointer_to (base, op1); ! } } else if (comp_target_types (type0, type1, 1)) *************** *** 2679,2688 **** else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { ! error ("comparison between pointer and integer"); op1 = convert (TREE_TYPE (op0), op1); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { ! error ("comparison between pointer and integer"); op0 = convert (TREE_TYPE (op1), op0); } --- 2713,2722 ---- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { ! error ("ANSI C forbids comparison between pointer and integer"); op1 = convert (TREE_TYPE (op0), op1); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { ! error ("ANSI C forbids comparison between pointer and integer"); op0 = convert (TREE_TYPE (op1), op0); } *************** *** 2756,2760 **** op0 = null_pointer_node; if (pedantic) ! pedwarn ("ordered comparison of pointer with integer zero"); } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) --- 2790,2794 ---- op0 = null_pointer_node; if (pedantic) ! pedwarn ("ANSI C forbids ordered comparison of pointer with integer zero"); } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) *************** *** 2762,2766 **** result_type = integer_type_node; if (pedantic) ! error ("comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); --- 2796,2800 ---- result_type = integer_type_node; if (pedantic) ! pedwarn ("ANSI C forbids comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); *************** *** 2771,2775 **** result_type = integer_type_node; if (pedantic) ! error ("comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); --- 2805,2809 ---- result_type = integer_type_node; if (pedantic) ! pedwarn ("ANSI C forbids comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); *************** *** 2948,2952 **** { tree primop; ! long constant, mask; int unsignedp; unsigned bits; --- 2982,2986 ---- { tree primop; ! HOST_WIDE_INT constant, mask; int unsignedp; unsigned bits; *************** *** 2969,2973 **** && bits < HOST_BITS_PER_LONG && unsignedp) { ! mask = (~0L) << bits; if ((mask & constant) != mask) warning ("comparison of promoted ~unsigned with constant"); --- 3003,3007 ---- && bits < HOST_BITS_PER_LONG && unsignedp) { ! mask = (~ (HOST_WIDE_INT) 0) << bits; if ((mask & constant) != mask) warning ("comparison of promoted ~unsigned with constant"); *************** *** 3044,3048 **** { if (pedantic || warn_pointer_arith) ! pedwarn ("pointer of type `void *' used in arithmetic"); size_exp = integer_one_node; } --- 3078,3082 ---- { if (pedantic || warn_pointer_arith) ! pedwarn ("ANSI C forbids using pointer of type `void *' in arithmetic"); size_exp = integer_one_node; } *************** *** 3050,3060 **** { if (pedantic || warn_pointer_arith) ! pedwarn ("pointer to a function used in arithmetic"); size_exp = integer_one_node; } else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE) { ! if (pedantic) ! pedwarn ("pointer to a method used in arithmetic"); size_exp = integer_one_node; } --- 3084,3094 ---- { if (pedantic || warn_pointer_arith) ! pedwarn ("ANSI C forbids using pointer to a function in arithmetic"); size_exp = integer_one_node; } else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE) { ! if (pedantic || warn_pointer_arith) ! pedwarn ("ANSI C++ forbids using pointer to a method in arithmetic"); size_exp = integer_one_node; } *************** *** 3062,3066 **** { if (pedantic) ! pedwarn ("pointer to a member used in arithmetic"); size_exp = integer_one_node; } --- 3096,3100 ---- { if (pedantic) ! pedwarn ("ANSI C++ forbids using pointer to a member in arithmetic"); size_exp = integer_one_node; } *************** *** 3120,3130 **** { if (TREE_CODE (target_type) == VOID_TYPE) ! pedwarn ("pointer of type `void *' used in subtraction"); if (TREE_CODE (target_type) == FUNCTION_TYPE) ! pedwarn ("pointer to a function used in subtraction"); if (TREE_CODE (target_type) == METHOD_TYPE) ! pedwarn ("pointer to a method used in subtraction"); if (TREE_CODE (target_type) == OFFSET_TYPE) ! pedwarn ("pointer to a member used in subtraction"); } --- 3154,3164 ---- { if (TREE_CODE (target_type) == VOID_TYPE) ! pedwarn ("ANSI C forbids using pointer of type `void *' in subtraction"); if (TREE_CODE (target_type) == FUNCTION_TYPE) ! pedwarn ("ANSI C forbids using pointer to a function in subtraction"); if (TREE_CODE (target_type) == METHOD_TYPE) ! pedwarn ("ANSI C++ forbids using pointer to a method in subtraction"); if (TREE_CODE (target_type) == OFFSET_TYPE) ! pedwarn ("ANSI C++ forbids using pointer to a member in subtraction"); } *************** *** 3407,3411 **** || TREE_CODE (argtype) == VOID_TYPE || TREE_CODE (argtype) == OFFSET_TYPE)) ! pedwarn ("wrong type argument to %s", ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) --- 3441,3445 ---- || TREE_CODE (argtype) == VOID_TYPE || TREE_CODE (argtype) == OFFSET_TYPE)) ! pedwarn ("ANSI C forbids %sing this type of pointer value", ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) *************** *** 3579,3583 **** case FIX_CEIL_EXPR: if (pedantic) ! pedwarn ("ANSI C forbids the address of a cast expression"); return convert (build_pointer_type (TREE_TYPE (arg)), build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0)); --- 3613,3617 ---- case FIX_CEIL_EXPR: if (pedantic) ! pedwarn ("ANSI C forbids taking the address of a cast expression"); return convert (build_pointer_type (TREE_TYPE (arg)), build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0)); *************** *** 3625,3629 **** /* Address of a static or external variable or function counts as a constant */ ! TREE_CONSTANT (addr) = staticp (arg); return addr; } --- 3659,3664 ---- /* Address of a static or external variable or function counts as a constant */ ! if (staticp (arg)) ! TREE_CONSTANT (addr) = 1; return addr; } *************** *** 3913,3920 **** /* Caller should not be trying to mark initialized constant fields addressable. */ ! assert (DECL_LANG_SPECIFIC (x) == 0 || DECL_IN_AGGR_P (x) == 0 || TREE_STATIC (x) || TREE_EXTERNAL (x)); case CONST_DECL: ! if (TREE_REGDECL (x)) { if (TREE_PUBLIC (x)) --- 3948,3955 ---- /* Caller should not be trying to mark initialized constant fields addressable. */ ! assert (DECL_LANG_SPECIFIC (x) == 0 || DECL_IN_AGGR_P (x) == 0 || TREE_STATIC (x) || DECL_EXTERNAL (x)); case CONST_DECL: ! if (DECL_REGISTER (x)) { if (TREE_PUBLIC (x)) *************** *** 3941,3949 **** The second may be non-zero in the case of a template function. */ x = DECL_MAIN_VARIANT (x); ! if ((TREE_INLINE (x) || DECL_PENDING_INLINE_INFO (x)) && (DECL_CONTEXT (x) == NULL_TREE ! || TREE_CODE (DECL_CONTEXT (x)) != RECORD_TYPE || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x)))) ! mark_inline_for_output (x); TREE_ADDRESSABLE (x) = 1; TREE_USED (x) = 1; --- 3976,3988 ---- The second may be non-zero in the case of a template function. */ x = DECL_MAIN_VARIANT (x); ! if ((DECL_INLINE (x) || DECL_PENDING_INLINE_INFO (x)) && (DECL_CONTEXT (x) == NULL_TREE ! || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't' || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x)))) ! { ! mark_inline_for_output (x); ! if (x == current_function_decl) ! DECL_EXTERNAL (x) = 0; ! } TREE_ADDRESSABLE (x) = 1; TREE_USED (x) = 1; *************** *** 4055,4063 **** op2 = decl_constant_value (op2); if (type1 != type2) ! { ! int constp = TYPE_READONLY (type1) || TYPE_READONLY (type2); ! int volatilep = TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2); ! type1 = build_type_variant (type1, constp, volatilep); ! } /* ??? This is a kludge to deal with the fact that we don't sort out integers and enums properly, yet. */ --- 4094,4101 ---- op2 = decl_constant_value (op2); if (type1 != type2) ! type1 = build_type_variant ! (type1, ! TREE_READONLY (op1) || TREE_READONLY (op2), ! TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); /* ??? This is a kludge to deal with the fact that we don't sort out integers and enums properly, yet. */ *************** *** 4102,4112 **** if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) { ! if (type1 != type2) ! { ! int constp = TYPE_READONLY (type1) || TYPE_READONLY (type2); ! int volatilep = TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2); ! type1 = build_type_variant (type1, constp, volatilep); ! } ! result_type = type1; } else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE) --- 4140,4150 ---- if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)) { ! if (type1 == type2) ! result_type = type1; ! else ! result_type = build_type_variant ! (type1, ! TREE_READONLY (op1) || TREE_READONLY (op2), ! TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); } else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE) *************** *** 4308,4312 **** { register tree rest; - register tree tmp; if (TREE_READONLY_DECL_P (TREE_VALUE (list))) --- 4346,4349 ---- *************** *** 4348,4352 **** if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - type = TYPE_MAIN_VARIANT (type); /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. --- 4385,4388 ---- *************** *** 4363,4373 **** if (TREE_CODE (type) == ARRAY_TYPE) { ! error ("cast specifies array type"); ! return error_mark_node; } ! if (type == TREE_TYPE (value)) { ! if (pedantic) { if (TREE_CODE (type) == RECORD_TYPE --- 4399,4440 ---- if (TREE_CODE (type) == ARRAY_TYPE) { ! /* Allow casting from T1* to T2[] because Cfront allows it. ! NIHCL uses it. It is not valid ANSI C however, and hence, not ! valid ANSI C++. */ ! if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) ! { ! if (pedantic) ! pedwarn ("ANSI C forbids casting to an array type"); ! type = build_pointer_type (TREE_TYPE (type)); ! } ! else ! { ! error ("ANSI C forbids casting to an array type"); ! return error_mark_node; ! } } ! /* When converting into a reference type, just convert into a pointer ! to the new type and deference it. While this is not exactly what ARM 5.4 ! calls for, it is pretty close for now. (int &)ri ---> *(int*)&ri */ ! if (TREE_CODE (type) == REFERENCE_TYPE) { ! value = build_unary_op (ADDR_EXPR, value, 0); ! if (value != error_mark_node) ! value = convert (build_pointer_type (TREE_TYPE (type)), value); ! if (value != error_mark_node) ! value = build_indirect_ref (value, "reference conversion"); ! return value; ! } ! ! if (TREE_TYPE (value) ! && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (value))) ! { ! if (TREE_READONLY (value) != TYPE_READONLY (type)) ! { ! value = copy_node (value); ! TREE_READONLY (value) = TYPE_READONLY (type); ! } ! else if (pedantic) { if (TREE_CODE (type) == RECORD_TYPE *************** *** 4397,4400 **** --- 4464,4469 ---- return error_mark_node; } + #if 0 + /* The below case probably does not happen any more. */ else if (TREE_CODE (type) == REFERENCE_TYPE && TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) *************** *** 4408,4411 **** --- 4477,4482 ---- return build1 (NOP_EXPR, type, value); } + + #endif else { *************** *** 4566,4570 **** if (modifycode == INIT_EXPR && TYPE_HAS_INIT_REF (lhstype)) { ! result = build_method_call (lhs, TYPE_IDENTIFIER (lhstype), build_tree_list (NULL_TREE, rhs), basetype_path, LOOKUP_NORMAL); --- 4637,4641 ---- if (modifycode == INIT_EXPR && TYPE_HAS_INIT_REF (lhstype)) { ! result = build_method_call (lhs, constructor_name (lhstype), build_tree_list (NULL_TREE, rhs), basetype_path, LOOKUP_NORMAL); *************** *** 4644,4649 **** while (vbases) { ! tree elt_lhs_addr = build_unary_op (ADDR_EXPR, elt_lhs); ! tree elt_rhs_addr = build_unary_op (ADDR_EXPR, elt_rhs); elt_lhs_addr = convert_pointer_to (vbases, elt_lhs_addr); --- 4715,4720 ---- while (vbases) { ! tree elt_lhs_addr = build_unary_op (ADDR_EXPR, elt_lhs, 0); ! tree elt_rhs_addr = build_unary_op (ADDR_EXPR, elt_rhs, 0); elt_lhs_addr = convert_pointer_to (vbases, elt_lhs_addr); *************** *** 4822,4826 **** { /* This case must convert to some sort of lvalue that ! can participate in a op= operation. */ tree lhs_tmp = lhs; tree rhs_tmp = rhs; --- 4893,4897 ---- { /* This case must convert to some sort of lvalue that ! can participate in an op= operation. */ tree lhs_tmp = lhs; tree rhs_tmp = rhs; *************** *** 4886,4900 **** } else ! { ! tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (lhs, 0), 0); ! tree member = build_unary_op (ADDR_EXPR, TREE_OPERAND (lhs, 1), 0); - if (TREE_CODE (base) == ERROR_MARK - || TREE_CODE (member) == ERROR_MARK) - return error_mark_node; - lhs = build_indirect_ref (build (PLUS_EXPR, build_pointer_type (TREE_TYPE (lhs)), - base, member)); - } - /* Now we have handled acceptable kinds of LHS that are not truly lvalues. Reject anything strange now. */ --- 4957,4962 ---- } else ! lhs = resolve_offset_ref (lhs); /* Now we have handled acceptable kinds of LHS that are not truly lvalues. Reject anything strange now. */ *************** *** 5000,5004 **** { tree vbases = CLASSTYPE_VBASECLASSES (lhstype); ! tree lhs_addr = build_unary_op (ADDR_EXPR, lhs); tree rhs_addr; --- 5062,5066 ---- { tree vbases = CLASSTYPE_VBASECLASSES (lhstype); ! tree lhs_addr = build_unary_op (ADDR_EXPR, lhs, 0); tree rhs_addr; *************** *** 5018,5022 **** newrhs = save_expr (break_out_cleanups (newrhs)); ! rhs_addr = build_unary_op (ADDR_EXPR, newrhs); result = NULL_TREE; --- 5080,5084 ---- newrhs = save_expr (break_out_cleanups (newrhs)); ! rhs_addr = build_unary_op (ADDR_EXPR, newrhs, 0); result = NULL_TREE; *************** *** 5046,5050 **** /* It is now illegal to assign unions which contain members that have non-default assignment operators. */ ! if (pedantic && TREE_CODE (lhstype) == UNION_TYPE) { if (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype)) --- 5108,5112 ---- /* It is now illegal to assign unions which contain members that have non-default assignment operators. */ ! if (! flag_traditional && TREE_CODE (lhstype) == UNION_TYPE) { if (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype)) *************** *** 5078,5082 **** can't easily know the latter, just do it always. */ - extern struct rtx_def *get_insns (), *const0_rtx; result = make_node (RTL_EXPR); --- 5140,5143 ---- *************** *** 5151,5163 **** cond = build_compound_expr (tree_cons (NULL_TREE, lhs, build_tree_list (NULL_TREE, cond))); ! /* cannot have to identical lhs on this one tree (result) as preexpand calls will rip them out and fill in RTL for them, but when the rtl is generated, the calls will only be in the first side of the condition, not on both, or before the conditional jump! (mrs) */ lhs1 = break_out_calls (lhs); ! result = build (COND_EXPR, TREE_TYPE (newrhs), ! cond, ! build_modify_expr (lhs, modifycode, TREE_OPERAND (newrhs, 1)), ! build_modify_expr (lhs1, modifycode, TREE_OPERAND (newrhs, 2))); } else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR) --- 5212,5237 ---- cond = build_compound_expr (tree_cons (NULL_TREE, lhs, build_tree_list (NULL_TREE, cond))); ! /* Cannot have two identical lhs on this one tree (result) as preexpand calls will rip them out and fill in RTL for them, but when the rtl is generated, the calls will only be in the first side of the condition, not on both, or before the conditional jump! (mrs) */ lhs1 = break_out_calls (lhs); ! ! if (lhs == lhs1) ! /* If there's no change, the COND_EXPR behaves like any other rhs. */ ! result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, ! lhstype, lhs, newrhs); ! else ! { ! tree result_type = TREE_TYPE (newrhs); ! /* We have to convert each arm to the proper type because the ! types may have been munged by constant folding. */ ! result = build (COND_EXPR, result_type, ! cond, ! build_modify_expr (lhs, modifycode, ! convert (result_type, TREE_OPERAND (newrhs, 1))), ! build_modify_expr (lhs1, modifycode, ! convert (result_type, TREE_OPERAND (newrhs, 2)))); ! } } else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR) *************** *** 5383,5393 **** || comp_target_types (type, rhstype, 1)) { ! if (pedantic && TYPE_MAIN_VARIANT (ttl) != void_type_node ! && TYPE_MAIN_VARIANT (ttr) == void_type_node) ! { ! error ("invalid conversion from `void *' in %s", errtype); ! return error_mark_node; ! } ! if (pedantic && ((TYPE_MAIN_VARIANT (ttl) == void_type_node && (TREE_CODE (ttr) == FUNCTION_TYPE --- 5457,5465 ---- || comp_target_types (type, rhstype, 1)) { ! if (TYPE_MAIN_VARIANT (ttl) != void_type_node ! && TYPE_MAIN_VARIANT (ttr) == void_type_node ! && rhs != null_pointer_node) ! pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s", errtype); ! else if (pedantic && ((TYPE_MAIN_VARIANT (ttl) == void_type_node && (TREE_CODE (ttr) == FUNCTION_TYPE *************** *** 5399,5403 **** warn_for_assignment ("%s between function pointer and `void *'", "function pointer and `void *' incompatible; argument %d of `%s'", ! errtype, fndecl, parmnum, 0); /* Const and volatile mean something different for function types, so the usual warnings are not appropriate. */ --- 5471,5475 ---- warn_for_assignment ("%s between function pointer and `void *'", "function pointer and `void *' incompatible; argument %d of `%s'", ! errtype, fndecl, parmnum, flag_pedantic_errors); /* Const and volatile mean something different for function types, so the usual warnings are not appropriate. */ *************** *** 5415,5423 **** warn_for_assignment ("%s of non-`const *' pointer from `const *'", "pointer to const given for argument %d of `%s'", ! errtype, fndecl, parmnum, pedantic); if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) warn_for_assignment ("%s of non-`volatile *' pointer from `volatile *'", "pointer to volatile given for argument %d of `%s'", ! errtype, fndecl, parmnum, pedantic); } } --- 5487,5495 ---- warn_for_assignment ("%s of non-`const *' pointer from `const *'", "pointer to const given for argument %d of `%s'", ! errtype, fndecl, parmnum, flag_pedantic_errors); if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) warn_for_assignment ("%s of non-`volatile *' pointer from `volatile *'", "pointer to volatile given for argument %d of `%s'", ! errtype, fndecl, parmnum, flag_pedantic_errors); } } *************** *** 5481,5489 **** warn_for_assignment ("%s of unsigned pointer from signed pointer", "passing signed pointer to unsigned pointer argument %d of `%s'", ! errtype, fndecl, parmnum, pedantic); else if (unsigned_parity < 0) warn_for_assignment ("%s of signed pointer from unsigned pointer", "passing unsigned pointer to signed pointer argument %d of `%s'", ! errtype, fndecl, parmnum, pedantic); /* C++ is not so friendly about converting function and --- 5553,5561 ---- warn_for_assignment ("%s of unsigned pointer from signed pointer", "passing signed pointer to unsigned pointer argument %d of `%s'", ! errtype, fndecl, parmnum, flag_pedantic_errors); else if (unsigned_parity < 0) warn_for_assignment ("%s of signed pointer from unsigned pointer", "passing unsigned pointer to signed pointer argument %d of `%s'", ! errtype, fndecl, parmnum, flag_pedantic_errors); /* C++ is not so friendly about converting function and *************** *** 5542,5546 **** warn_for_assignment ("%s of pointer from integer lacks a cast", "passing integer to pointer argument %d of `%s' lacks a cast", ! errtype, fndecl, parmnum, pedantic); return convert (type, rhs); } --- 5614,5618 ---- warn_for_assignment ("%s of pointer from integer lacks a cast", "passing integer to pointer argument %d of `%s' lacks a cast", ! errtype, fndecl, parmnum, flag_pedantic_errors); return convert (type, rhs); } *************** *** 5551,5555 **** warn_for_assignment ("%s of integer from pointer lacks a cast", "passing pointer to integer argument %d of `%s' lacks a cast", ! errtype, fndecl, parmnum, pedantic); return convert (type, rhs); } --- 5623,5627 ---- warn_for_assignment ("%s of integer from pointer lacks a cast", "passing pointer to integer argument %d of `%s' lacks a cast", ! errtype, fndecl, parmnum, flag_pedantic_errors); return convert (type, rhs); } *************** *** 5633,5637 **** copied in the latter, and aggregates are assigned in the former (operator=) while initialized in the ! latter (X(X&)). */ tree convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) --- 5705,5712 ---- copied in the latter, and aggregates are assigned in the former (operator=) while initialized in the ! latter (X(X&)). ! ! If using constructor make sure no conversion operator exists, if one does ! exist, an ambiguity exists. */ tree convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) *************** *** 5652,5655 **** --- 5727,5733 ---- rhs = TREE_OPERAND (rhs, 0); + if (TREE_VALUE (rhs) == error_mark_node) + return error_mark_node; + if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE) { *************** *** 5735,5739 **** if (TYPE_HAS_INIT_REF (type)) { ! tree init = build_method_call (exp, TYPE_IDENTIFIER (type), build_tree_list (NULL_TREE, rhs), NULL_TREE, LOOKUP_NORMAL); --- 5813,5817 ---- if (TYPE_HAS_INIT_REF (type)) { ! tree init = build_method_call (exp, constructor_name (type), build_tree_list (NULL_TREE, rhs), NULL_TREE, LOOKUP_NORMAL); *************** *** 5787,5791 **** #endif - converted: if (type == TREE_TYPE (rhs)) { --- 5865,5868 ---- *************** *** 5817,5821 **** register tree tail; ! /* Record the contents of OUTPUTS before it is modifed. */ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) o[i] = TREE_VALUE (tail); --- 5894,5898 ---- register tree tail; ! /* Record the contents of OUTPUTS before it is modified. */ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) o[i] = TREE_VALUE (tail); *************** *** 5835,5840 **** for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) { - extern struct rtx_def *const0_rtx; - if (o[i] != TREE_VALUE (tail)) { --- 5912,5915 ---- *************** *** 5876,5880 **** { extern struct nesting *cond_stack, *loop_stack, *case_stack; - extern struct rtx_def *original_result_rtx; extern tree dtor_label, ctor_label; tree result = DECL_RESULT (current_function_decl); --- 5951,5954 ---- *************** *** 5929,5934 **** { current_function_returns_null = 1; ! if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) ! warning ("`return' with a value, in function returning void"); expand_return (retval); } --- 6003,6008 ---- { current_function_returns_null = 1; ! if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) ! pedwarn ("ANSI C++ forbids `return' with a value, in function returning void"); expand_return (retval); } *************** *** 5979,5983 **** warning_with_decl (whats_returned, "reference to local variable `%s' returned"); } ! /* Now deal with possible C++ hair: (1) Compute the return value. --- 6053,6065 ---- warning_with_decl (whats_returned, "reference to local variable `%s' returned"); } ! else if (TREE_CODE (retval) == ADDR_EXPR) ! { ! tree whats_returned = TREE_OPERAND (retval, 0); ! if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned)) ! && !TREE_STATIC (whats_returned)) ! warning_with_decl (whats_returned, ! "address of local variable `%s' returned"); ! } ! /* Now deal with possible C++ hair: (1) Compute the return value. *************** *** 6067,6071 **** use_variable (DECL_RTL (result)); ! if (ctor_label) expand_goto (ctor_label); else --- 6149,6153 ---- use_variable (DECL_RTL (result)); ! if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) expand_goto (ctor_label); else *************** *** 6086,6090 **** result = make_tree (TREE_TYPE (result), original_result_rtx); } ! else if (ctor_label) { /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */ --- 6168,6172 ---- result = make_tree (TREE_TYPE (result), original_result_rtx); } ! else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) { /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */ *************** *** 6131,6134 **** --- 6213,6221 ---- else exp = default_conversion (exp); + if (exp == NULL_TREE) + { + error ("switch quantity not an integer"); + exp = error_mark_node; + } type = TREE_TYPE (exp); code = TREE_CODE (type); diff -rc2N gcc-2.2.2/cp-xref.c gcc-2.3.1/cp-xref.c *** gcc-2.2.2/cp-xref.c Thu Jun 11 00:31:23 1992 --- gcc-2.3.1/cp-xref.c Wed Aug 26 20:21:50 1992 *************** *** 27,40 **** #include - #ifdef USG - #include - #include - #define rindex strrchr - #else - #include - #endif char *getpwd (); /* The character(s) used to join a directory specification (obtained with getwd or equivalent) with a non-absolute file name. */ --- 27,36 ---- #include char *getpwd (); + extern char *index (); + extern char *rindex (); + /* The character(s) used to join a directory specification (obtained with getwd or equivalent) with a non-absolute file name. */ *************** *** 368,377 **** if (fndecl == NULL && TREE_STATIC(decl) && TREE_READONLY(decl) && DECL_INITIAL(decl) != 0 ! && !TREE_PUBLIC(decl) && !TREE_EXTERNAL(decl) && DECL_MODE(decl) != BLKmode) cls = "CONST"; ! else if (TREE_EXTERNAL(decl)) cls = "EXTERN"; else if (TREE_PUBLIC(decl)) cls = "EXTDEF"; else if (TREE_STATIC(decl)) cls = "STATIC"; ! else if (TREE_REGDECL(decl)) cls = "REGISTER"; else cls = "AUTO"; } --- 364,373 ---- if (fndecl == NULL && TREE_STATIC(decl) && TREE_READONLY(decl) && DECL_INITIAL(decl) != 0 ! && !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl) && DECL_MODE(decl) != BLKmode) cls = "CONST"; ! else if (DECL_EXTERNAL(decl)) cls = "EXTERN"; else if (TREE_PUBLIC(decl)) cls = "EXTDEF"; else if (TREE_STATIC(decl)) cls = "STATIC"; ! else if (DECL_REGISTER(decl)) cls = "REGISTER"; else cls = "AUTO"; } *************** *** 381,385 **** else if (TREE_CODE (decl) == FUNCTION_DECL) { ! if (TREE_EXTERNAL (decl)) cls = "EXTERN"; else if (TREE_PUBLIC (decl)) cls = "EFUNCTION"; else cls = "SFUNCTION"; --- 377,381 ---- else if (TREE_CODE (decl) == FUNCTION_DECL) { ! if (DECL_EXTERNAL (decl)) cls = "EXTERN"; else if (TREE_PUBLIC (decl)) cls = "EFUNCTION"; else cls = "SFUNCTION"; *************** *** 424,428 **** name = IDENTIFIER_POINTER (DECL_NAME (decl)); ! type_as_string (buf, TREE_TYPE (decl)); simplify_type (buf); --- 420,424 ---- name = IDENTIFIER_POINTER (DECL_NAME (decl)); ! strcpy (buf, type_as_string (TREE_TYPE (decl))); simplify_type (buf); *************** *** 636,640 **** filename(xf), fld->decl.linenum, d, bufa, prot, (TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1), ! (TREE_INLINE (fld) ? 1 : 0), (DECL_FRIEND_P(fld) ? 1 : 0), (DECL_VINDEX(fld) ? 1 : 0), --- 632,636 ---- filename(xf), fld->decl.linenum, d, bufa, prot, (TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1), ! (DECL_INLINE (fld) ? 1 : 0), (DECL_FRIEND_P(fld) ? 1 : 0), (DECL_VINDEX(fld) ? 1 : 0), diff -rc2N gcc-2.2.2/cpp.aux gcc-2.3.1/cpp.aux *** gcc-2.2.2/cpp.aux Mon Jun 8 18:59:09 1992 --- gcc-2.3.1/cpp.aux Fri Oct 30 02:14:23 1992 *************** *** 5,9 **** 'xrdef {Commands-pg}{3} 'xrdef {Commands-snt}{Section'tie1.2} ! 'xrdef {Header Files-pg}{3} 'xrdef {Header Files-snt}{Section'tie1.3} 'xrdef {Header Uses-pg}{4} --- 5,9 ---- 'xrdef {Commands-pg}{3} 'xrdef {Commands-snt}{Section'tie1.2} ! 'xrdef {Header Files-pg}{4} 'xrdef {Header Files-snt}{Section'tie1.3} 'xrdef {Header Uses-pg}{4} *************** *** 11,84 **** 'xrdef {Include Syntax-pg}{4} 'xrdef {Include Syntax-snt}{Section'tie1.3.2} ! 'xrdef {Include Operation-pg}{5} 'xrdef {Include Operation-snt}{Section'tie1.3.3} ! 'xrdef {Once-Only-pg}{6} 'xrdef {Once-Only-snt}{Section'tie1.3.4} ! 'xrdef {Inheritance-pg}{7} 'xrdef {Inheritance-snt}{Section'tie1.4} ! 'xrdef {Macros-pg}{8} 'xrdef {Macros-snt}{Section'tie1.5} 'xrdef {Simple Macros-pg}{9} 'xrdef {Simple Macros-snt}{Section'tie1.5.1} ! 'xrdef {Argument Macros-pg}{10} 'xrdef {Argument Macros-snt}{Section'tie1.5.2} ! 'xrdef {Predefined-pg}{13} 'xrdef {Predefined-snt}{Section'tie1.5.3} ! 'xrdef {Standard Predefined-pg}{13} 'xrdef {Standard Predefined-snt}{Section'tie1.5.3.1} ! 'xrdef {Nonstandard Predefined-pg}{15} 'xrdef {Nonstandard Predefined-snt}{Section'tie1.5.3.2} ! 'xrdef {Stringification-pg}{16} 'xrdef {Stringification-snt}{Section'tie1.5.4} ! 'xrdef {Concatenation-pg}{18} 'xrdef {Concatenation-snt}{Section'tie1.5.5} ! 'xrdef {Undefining-pg}{19} 'xrdef {Undefining-snt}{Section'tie1.5.6} ! 'xrdef {Redefining-pg}{20} 'xrdef {Redefining-snt}{Section'tie1.5.7} ! 'xrdef {Macro Pitfalls-pg}{21} 'xrdef {Macro Pitfalls-snt}{Section'tie1.5.8} ! 'xrdef {Misnesting-pg}{21} 'xrdef {Misnesting-snt}{Section'tie1.5.8.1} ! 'xrdef {Macro Parentheses-pg}{21} 'xrdef {Macro Parentheses-snt}{Section'tie1.5.8.2} ! 'xrdef {Swallow Semicolon-pg}{23} 'xrdef {Swallow Semicolon-snt}{Section'tie1.5.8.3} ! 'xrdef {Side Effects-pg}{24} 'xrdef {Side Effects-snt}{Section'tie1.5.8.4} ! 'xrdef {Self-Reference-pg}{25} 'xrdef {Self-Reference-snt}{Section'tie1.5.8.5} ! 'xrdef {Argument Prescan-pg}{26} 'xrdef {Argument Prescan-snt}{Section'tie1.5.8.6} ! 'xrdef {Cascaded Macros-pg}{29} 'xrdef {Cascaded Macros-snt}{Section'tie1.5.8.7} ! 'xrdef {Conditionals-pg}{29} 'xrdef {Conditionals-snt}{Section'tie1.6} ! 'xrdef {Conditional Uses-pg}{30} 'xrdef {Conditional Uses-snt}{Section'tie1.6.1} ! 'xrdef {Conditional Syntax-pg}{30} 'xrdef {Conditional Syntax-snt}{Section'tie1.6.2} ! 'xrdef {#if Command-pg}{30} 'xrdef {#if Command-snt}{Section'tie1.6.2.1} ! 'xrdef {#else Command-pg}{31} 'xrdef {#else Command-snt}{Section'tie1.6.2.2} ! 'xrdef {#elif Command-pg}{32} 'xrdef {#elif Command-snt}{Section'tie1.6.2.3} ! 'xrdef {Deleted Code-pg}{33} 'xrdef {Deleted Code-snt}{Section'tie1.6.3} ! 'xrdef {Conditionals-Macros-pg}{33} 'xrdef {Conditionals-Macros-snt}{Section'tie1.6.4} ! 'xrdef {#error Command-pg}{34} ! 'xrdef {#error Command-snt}{Section'tie1.6.5} ! 'xrdef {Combining Sources-pg}{35} 'xrdef {Combining Sources-snt}{Section'tie1.7} ! 'xrdef {Other Commands-pg}{36} 'xrdef {Other Commands-snt}{Section'tie1.8} ! 'xrdef {Output-pg}{37} 'xrdef {Output-snt}{Section'tie1.9} ! 'xrdef {Invocation-pg}{37} 'xrdef {Invocation-snt}{Section'tie1.10} ! 'xrdef {Concept Index-pg}{43} 'xrdef {Concept Index-snt}{} ! 'xrdef {Index-pg}{i} 'xrdef {Index-snt}{} --- 11,88 ---- 'xrdef {Include Syntax-pg}{4} 'xrdef {Include Syntax-snt}{Section'tie1.3.2} ! 'xrdef {Include Operation-pg}{6} 'xrdef {Include Operation-snt}{Section'tie1.3.3} ! 'xrdef {Once-Only-pg}{7} 'xrdef {Once-Only-snt}{Section'tie1.3.4} ! 'xrdef {Inheritance-pg}{8} 'xrdef {Inheritance-snt}{Section'tie1.4} ! 'xrdef {Macros-pg}{9} 'xrdef {Macros-snt}{Section'tie1.5} 'xrdef {Simple Macros-pg}{9} 'xrdef {Simple Macros-snt}{Section'tie1.5.1} ! 'xrdef {Argument Macros-pg}{11} 'xrdef {Argument Macros-snt}{Section'tie1.5.2} ! 'xrdef {Predefined-pg}{14} 'xrdef {Predefined-snt}{Section'tie1.5.3} ! 'xrdef {Standard Predefined-pg}{14} 'xrdef {Standard Predefined-snt}{Section'tie1.5.3.1} ! 'xrdef {Nonstandard Predefined-pg}{16} 'xrdef {Nonstandard Predefined-snt}{Section'tie1.5.3.2} ! 'xrdef {Stringification-pg}{17} 'xrdef {Stringification-snt}{Section'tie1.5.4} ! 'xrdef {Concatenation-pg}{19} 'xrdef {Concatenation-snt}{Section'tie1.5.5} ! 'xrdef {Undefining-pg}{20} 'xrdef {Undefining-snt}{Section'tie1.5.6} ! 'xrdef {Redefining-pg}{21} 'xrdef {Redefining-snt}{Section'tie1.5.7} ! 'xrdef {Macro Pitfalls-pg}{22} 'xrdef {Macro Pitfalls-snt}{Section'tie1.5.8} ! 'xrdef {Misnesting-pg}{22} 'xrdef {Misnesting-snt}{Section'tie1.5.8.1} ! 'xrdef {Macro Parentheses-pg}{23} 'xrdef {Macro Parentheses-snt}{Section'tie1.5.8.2} ! 'xrdef {Swallow Semicolon-pg}{24} 'xrdef {Swallow Semicolon-snt}{Section'tie1.5.8.3} ! 'xrdef {Side Effects-pg}{25} 'xrdef {Side Effects-snt}{Section'tie1.5.8.4} ! 'xrdef {Self-Reference-pg}{27} 'xrdef {Self-Reference-snt}{Section'tie1.5.8.5} ! 'xrdef {Argument Prescan-pg}{28} 'xrdef {Argument Prescan-snt}{Section'tie1.5.8.6} ! 'xrdef {Cascaded Macros-pg}{31} 'xrdef {Cascaded Macros-snt}{Section'tie1.5.8.7} ! 'xrdef {Newlines in Args-pg}{32} ! 'xrdef {Newlines in Args-snt}{Section'tie1.5.9} ! 'xrdef {Conditionals-pg}{32} 'xrdef {Conditionals-snt}{Section'tie1.6} ! 'xrdef {Conditional Uses-pg}{33} 'xrdef {Conditional Uses-snt}{Section'tie1.6.1} ! 'xrdef {Conditional Syntax-pg}{33} 'xrdef {Conditional Syntax-snt}{Section'tie1.6.2} ! 'xrdef {#if Command-pg}{33} 'xrdef {#if Command-snt}{Section'tie1.6.2.1} ! 'xrdef {#else Command-pg}{34} 'xrdef {#else Command-snt}{Section'tie1.6.2.2} ! 'xrdef {#elif Command-pg}{35} 'xrdef {#elif Command-snt}{Section'tie1.6.2.3} ! 'xrdef {Deleted Code-pg}{36} 'xrdef {Deleted Code-snt}{Section'tie1.6.3} ! 'xrdef {Conditionals-Macros-pg}{36} 'xrdef {Conditionals-Macros-snt}{Section'tie1.6.4} ! 'xrdef {Assertions-pg}{38} ! 'xrdef {Assertions-snt}{Section'tie1.6.5} ! 'xrdef {#error Command-pg}{40} ! 'xrdef {#error Command-snt}{Section'tie1.6.6} ! 'xrdef {Combining Sources-pg}{40} 'xrdef {Combining Sources-snt}{Section'tie1.7} ! 'xrdef {Other Commands-pg}{42} 'xrdef {Other Commands-snt}{Section'tie1.8} ! 'xrdef {Output-pg}{42} 'xrdef {Output-snt}{Section'tie1.9} ! 'xrdef {Invocation-pg}{43} 'xrdef {Invocation-snt}{Section'tie1.10} ! 'xrdef {Concept Index-pg}{49} 'xrdef {Concept Index-snt}{} ! 'xrdef {Index-pg}{51} 'xrdef {Index-snt}{} diff -rc2N gcc-2.2.2/cpp.cps gcc-2.3.1/cpp.cps *** gcc-2.2.2/cpp.cps Mon Jun 8 18:58:08 1992 --- gcc-2.3.1/cpp.cps Fri Oct 30 02:13:47 1992 *************** *** 1,33 **** \initial {C} ! \entry {cascaded macros}{29} \entry {commands}{3} ! \entry {concatenation}{18} ! \entry {conditionals}{29} \initial {H} ! \entry {header file}{3} \initial {I} ! \entry {inheritance}{7} \initial {L} ! \entry {line control}{35} \initial {M} ! \entry {macro body uses macro}{29} \initial {N} ! \entry {null command}{36} \initial {O} ! \entry {options}{38} ! \entry {output format}{37} ! \entry {overriding a header file}{7} \initial {P} ! \entry {predefined macros}{13} \entry {preprocessor commands}{3} \initial {R} ! \entry {redefining macros}{20} ! \entry {repeated inclusion}{6} \initial {S} ! \entry {self-reference}{25} ! \entry {semicolons (after macro calls)}{23} ! \entry {side effects (in macro arguments)}{24} ! \entry {stringification}{16} \initial {U} ! \entry {undefining macros}{19} ! \entry {unsafe macros}{24} --- 1,41 ---- + \initial {A} + \entry {assertions}{38} + \entry {assertions, undoing}{39} \initial {C} ! \entry {cascaded macros}{31} \entry {commands}{3} ! \entry {concatenation}{19} ! \entry {conditionals}{32} \initial {H} ! \entry {header file}{4} \initial {I} ! \entry {inheritance}{8} \initial {L} ! \entry {line control}{40} \initial {M} ! \entry {macro body uses macro}{31} \initial {N} ! \entry {null command}{42} \initial {O} ! \entry {options}{43} ! \entry {output format}{42} ! \entry {overriding a header file}{8} \initial {P} ! \entry {predefined macros}{14} ! \entry {predicates}{38} \entry {preprocessor commands}{3} \initial {R} ! \entry {redefining macros}{21} ! \entry {repeated inclusion}{7} ! \entry {retracting assertions}{39} \initial {S} ! \entry {self-reference}{27} ! \entry {semicolons (after macro calls)}{24} ! \entry {side effects (in macro arguments)}{25} ! \entry {stringification}{17} ! \initial {T} ! \entry {testing predicates}{38} \initial {U} ! \entry {unassert}{39} ! \entry {undefining macros}{20} ! \entry {unsafe macros}{25} diff -rc2N gcc-2.2.2/cpp.fns gcc-2.3.1/cpp.fns *** gcc-2.2.2/cpp.fns Mon Jun 8 18:58:09 1992 --- gcc-2.3.1/cpp.fns Fri Oct 30 02:13:47 1992 *************** *** 1,66 **** \initial {#} ! \entry {\code {#elif}}{32} ! \entry {\code {#else}}{31} ! \entry {\code {#error}}{34} ! \entry {\code {#ident}}{36} ! \entry {\code {#if}}{30} ! \entry {\code {#ifdef}}{34} ! \entry {\code {#ifndef}}{34} \entry {\code {#include}}{4} \entry {\code {#include{\_}next}}{8} ! \entry {\code {#line}}{35} ! \entry {\code {#pragma}}{36} \entry {\code {#pragma once}}{7} ! \entry {\code {#warning}}{35} \initial {-} ! \entry {\code {-C}}{38} ! \entry {\code {-D}}{39} ! \entry {\code {-dD}}{40} ! \entry {\code {-dM}}{39} ! \entry {\code {-H}}{40} ! \entry {\code {-I}}{39} ! \entry {\code {-imacros}}{40} ! \entry {\code {-include}}{40} ! \entry {\code {-M}}{40} ! \entry {\code {-MD}}{40} ! \entry {\code {-MM}}{40} ! \entry {\code {-MMD}}{40} ! \entry {\code {-P}}{38} ! \entry {\code {-pedantic}}{38} ! \entry {\code {-pedantic-errors}}{38} ! \entry {\code {-trigraphs}}{38} ! \entry {\code {-U}}{39} ! \entry {\code {-undef}}{39} ! \entry {\code {-Wall}}{38} ! \entry {\code {-Wcomment}}{38} ! \entry {\code {-Wtraditional}}{38} \initial {{\_}} ! \entry {\code {{\_}{\_}BASE{\_}FILE{\_}{\_}}}{14} ! \entry {\code {{\_}{\_}DATE{\_}{\_}}}{14} ! \entry {\code {{\_}{\_}FILE{\_}{\_}}}{13} ! \entry {\code {{\_}{\_}INCLUDE{\_}LEVEL{\_}}}{14} ! \entry {\code {{\_}{\_}LINE{\_}{\_}}}{13} ! \entry {\code {{\_}{\_}STDC{\_}{\_}}}{14} ! \entry {\code {{\_}{\_}TIME{\_}{\_}}}{14} ! \entry {\code {{\_}AM29000}}{15} ! \entry {\code {{\_}AM29K}}{15} \initial {B} ! \entry {\code {BSD}}{15} \initial {D} ! \entry {\code {defined}}{33} \initial {M} ! \entry {\code {M68020}}{15} ! \entry {\code {m68k}}{15} ! \entry {\code {mc68000}}{15} \initial {N} ! \entry {\code {ns32000}}{15} \initial {P} ! \entry {\code {pyr}}{16} \initial {S} ! \entry {\code {sequent}}{16} ! \entry {\code {sun}}{16} \entry {\code {system header files}}{4} \initial {U} ! \entry {\code {unix}}{15} \initial {V} ! \entry {\code {vax}}{15} --- 1,69 ---- \initial {#} ! \entry {\code {#assert}}{39} ! \entry {\code {#elif}}{35} ! \entry {\code {#else}}{34} ! \entry {\code {#error}}{40} ! \entry {\code {#ident}}{42} ! \entry {\code {#if}}{33} ! \entry {\code {#ifdef}}{37} ! \entry {\code {#ifndef}}{37} \entry {\code {#include}}{4} \entry {\code {#include{\_}next}}{8} ! \entry {\code {#line}}{40} ! \entry {\code {#pragma}}{42} \entry {\code {#pragma once}}{7} ! \entry {\code {#unassert}}{39} ! \entry {\code {#warning}}{40} \initial {-} ! \entry {\code {-A}}{45} ! \entry {\code {-C}}{43} ! \entry {\code {-D}}{45} ! \entry {\code {-dD}}{46} ! \entry {\code {-dM}}{45} ! \entry {\code {-H}}{46} ! \entry {\code {-I}}{44} ! \entry {\code {-imacros}}{46} ! \entry {\code {-include}}{46} ! \entry {\code {-M}}{46} ! \entry {\code {-MD}}{46} ! \entry {\code {-MM}}{46} ! \entry {\code {-MMD}}{46} ! \entry {\code {-P}}{43} ! \entry {\code {-pedantic}}{44} ! \entry {\code {-pedantic-errors}}{44} ! \entry {\code {-traditional}}{43} ! \entry {\code {-trigraphs}}{44} ! \entry {\code {-U}}{45} ! \entry {\code {-Wall}}{44} ! \entry {\code {-Wcomment}}{44} ! \entry {\code {-Wtraditional}}{44} \initial {{\_}} ! \entry {\code {{\_}{\_}BASE{\_}FILE{\_}{\_}}}{15} ! \entry {\code {{\_}{\_}DATE{\_}{\_}}}{15} ! \entry {\code {{\_}{\_}FILE{\_}{\_}}}{14} ! \entry {\code {{\_}{\_}INCLUDE{\_}LEVEL{\_}}}{15} ! \entry {\code {{\_}{\_}LINE{\_}{\_}}}{14} ! \entry {\code {{\_}{\_}STDC{\_}{\_}}}{15} ! \entry {\code {{\_}{\_}TIME{\_}{\_}}}{15} ! \entry {\code {{\_}AM29000}}{16} ! \entry {\code {{\_}AM29K}}{16} \initial {B} ! \entry {\code {BSD}}{16} \initial {D} ! \entry {\code {defined}}{36} \initial {M} ! \entry {\code {M68020}}{16} ! \entry {\code {m68k}}{16} ! \entry {\code {mc68000}}{16} \initial {N} ! \entry {\code {ns32000}}{16} \initial {P} ! \entry {\code {pyr}}{17} \initial {S} ! \entry {\code {sequent}}{17} ! \entry {\code {sun}}{17} \entry {\code {system header files}}{4} \initial {U} ! \entry {\code {unix}}{16} \initial {V} ! \entry {\code {vax}}{16} diff -rc2N gcc-2.2.2/cpp.texi gcc-2.3.1/cpp.texi *** gcc-2.2.2/cpp.texi Mon Jun 8 18:48:59 1992 --- gcc-2.3.1/cpp.texi Sat Oct 17 21:41:26 1992 *************** *** 20,24 **** This file documents the GNU C Preprocessor. ! Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 20,24 ---- This file documents the GNU C Preprocessor. ! Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of *************** *** 44,51 **** @titlepage @c @finalout ! @title{The C Preprocessor} ! @subtitle{Last revised July 1990} ! @subtitle{for GCC version 2} ! @author{Richard M. Stallman} @page @vskip 2pc --- 44,51 ---- @titlepage @c @finalout ! @title The C Preprocessor ! @subtitle Last revised July 1992 ! @subtitle for GCC version 2 ! @author Richard M. Stallman @page @vskip 2pc *************** *** 54,58 **** @vskip 0pt plus 1filll ! Copyright @copyright{} 1987, 1989, 1991 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of --- 54,58 ---- @vskip 0pt plus 1filll ! Copyright @copyright{} 1987, 1989, 1991, 1992 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of *************** *** 709,712 **** --- 709,723 ---- (Line breaks shown here for clarity would not actually be generated.) + If a macro @code{foo} takes one argument, and you want to supply an + empty argument, you must write at least some whitespace between the + parentheses, like this: @samp{foo ( )}. Just @samp{foo ()} is providing + no arguments, which is an error if @code{foo} expects an argument. But + @samp{foo0 ()} is the correct way to call a macro defined to take zero + arguments, like this: + + @example + #define foo0() @dots{} + @end example + If you use the macro name followed by something other than an open-parenthesis (after ignoring any spaces, tabs and comments that *************** *** 738,742 **** must follow the macro name immediately with no space in between. If there is a space after the macro name, the macro is defined as taking no ! arguments, and all the rest of the lineis taken to be the expansion. The reason for this is that it is often useful to define a macro that takes no arguments and whose definition begins with an identifier in parentheses. --- 749,753 ---- must follow the macro name immediately with no space in between. If there is a space after the macro name, the macro is defined as taking no ! arguments, and all the rest of the line is taken to be the expansion. The reason for this is that it is often useful to define a macro that takes no arguments and whose definition begins with an identifier in parentheses. *************** *** 1043,1047 **** how an equivalent result can be obtained in ANSI Standard C using the feature that adjacent string constants are concatenated as one string ! constant. The preprocessor stringifies @samp{EXP}'s actual argument into a separate string constant, resulting in text like --- 1054,1058 ---- how an equivalent result can be obtained in ANSI Standard C using the feature that adjacent string constants are concatenated as one string ! constant. The preprocessor stringifies the actual value of @samp{EXP} into a separate string constant, resulting in text like *************** *** 1247,1250 **** --- 1258,1262 ---- before they are substituted. * Cascaded Macros:: Macros whose definitions use other macros. + * Newlines in Args:: Sometimes line numbers get confused. @end menu *************** *** 1296,1302 **** @noindent ! whose purpose is to divide, rounding up. (One use for this ! operation is to compute how many @samp{int}'s are needed to hold ! a certain number of @samp{char}'s.) Then suppose it is used as follows: @example --- 1308,1314 ---- @noindent ! whose purpose is to divide, rounding up. (One use for this operation is ! to compute how many @samp{int} objects are needed to hold a certain ! number of @samp{char} objects.) Then suppose it is used as follows: @example *************** *** 1520,1527 **** The special rule for self-reference applies also to @dfn{indirect} self-reference. This is the case where a macro @var{x} expands to use a ! macro @samp{y}, and @samp{y}'s expansion refers to the macro @samp{x}. The ! resulting reference to @samp{x} comes indirectly from the expansion of ! @samp{x}, so it is a self-reference and is not further expanded. Thus, ! after @example --- 1532,1539 ---- The special rule for self-reference applies also to @dfn{indirect} self-reference. This is the case where a macro @var{x} expands to use a ! macro @samp{y}, and the expansion of @samp{y} refers to the macro ! @samp{x}. The resulting reference to @samp{x} comes indirectly from the ! expansion of @samp{x}, so it is a self-reference and is not further ! expanded. Thus, after @example *************** *** 1691,1695 **** already done by @samp{xstr}. ! @node Cascaded Macros,, Argument Prescan, Macro Pitfalls @subsubsection Cascaded Use of Macros --- 1703,1707 ---- already done by @samp{xstr}. ! @node Cascaded Macros, Newlines in Args, Argument Prescan, Macro Pitfalls @subsubsection Cascaded Use of Macros *************** *** 1727,1730 **** --- 1739,1775 ---- Now @samp{TABLESIZE} expands (in two stages) to @samp{37}. + @node Newlines in Args,, Cascaded Macros, Macro Pitfalls + @subsection Newlines in Macro Arguments + + Traditional macro processing carries forward all newlines in macro + arguments into the expansion of the macro. This means that, if some of + the arguments are substituted more than once, or not at all, or out of + order, newlines can be duplicated, lost, or moved around within the + expansion. If the expansion consists of multiple statements, then the + effect is to distort the line numbers of some of these statements. The + result can can be incorrect line numbers, in error messages or + displayed in a debugger. + + The GNU C preprocessor operating in ANSI C mode adjusts appropriately + for multiple use of an argument---the first use expands all the + newlines, and subsequent uses of the same argument produce no newlines. + But even in this mode, it can produce incorrect line numbering if + arguments are used out of order, or not used at all. + + Here is an example illustrating this problem: + + @example + #define ignore_second_arg(a,b,c) a; c + + ignore_second_arg (foo (), + ignored (), + syntax error); + @end example + + @noindent + The syntax error triggered by the tokens @samp{syntax error} results + in an error message citing line four, even though the statement text + comes from line five. + @node Conditionals, Combining Sources, Macros, Top @section Conditionals *************** *** 1750,1757 **** * Deletion: Deleted Code. Making code into a comment. * Macros: Conditionals-Macros. Why conditionals are used with macros. * Errors: #error Command. Detecting inconsistent compilation parameters. @end menu ! @node Conditional Uses, Conditional Syntax, Conditionals, Conditionals @subsection Why Conditionals are Used --- 1795,1803 ---- * Deletion: Deleted Code. Making code into a comment. * Macros: Conditionals-Macros. Why conditionals are used with macros. + * Assertions:: How and why to use assertions. * Errors: #error Command. Detecting inconsistent compilation parameters. @end menu ! @node Conditional Uses @subsection Why Conditionals are Used *************** *** 1785,1789 **** not need to use preprocessor conditionals. ! @node Conditional Syntax, Deleted Code, Conditional Uses, Conditionals @subsection Syntax of Conditionals --- 1831,1835 ---- not need to use preprocessor conditionals. ! @node Conditional Syntax @subsection Syntax of Conditionals *************** *** 1800,1804 **** @end menu ! @node #if Command, #else Command, Conditional Syntax, Conditional Syntax @subsubsection The @samp{#if} Command --- 1846,1850 ---- @end menu ! @node #if Command @subsubsection The @samp{#if} Command *************** *** 1856,1863 **** preprocessor commands. Then the commands inside the conditional are obeyed only if that branch of the conditional succeeds. The text can ! also contain other conditional groups. However, the @samp{#if}'s and ! @samp{#endif}'s must balance. ! @node #else Command, #elif Command, #if Command, Conditional Syntax @subsubsection The @samp{#else} Command --- 1902,1909 ---- preprocessor commands. Then the commands inside the conditional are obeyed only if that branch of the conditional succeeds. The text can ! also contain other conditional groups. However, the @samp{#if} and ! @samp{#endif} commands must balance. ! @node #else Command @subsubsection The @samp{#else} Command *************** *** 1880,1884 **** conditional fails, the @var{text-if-false} is considered included. ! @node #elif Command,, #else Command, Conditional Syntax @subsubsection The @samp{#elif} Command --- 1926,1930 ---- conditional fails, the @var{text-if-false} is considered included. ! @node #elif Command @subsubsection The @samp{#elif} Command *************** *** 1918,1930 **** The text following the @samp{#elif} is processed only if the original ! @samp{#if}-condition failed and the @samp{#elif} condition succeeds. More ! than one @samp{#elif} can go in the same @samp{#if}-@samp{#endif} group. ! Then the text after each @samp{#elif} is processed only if the @samp{#elif} ! condition succeeds after the original @samp{#if} and any previous ! @samp{#elif}'s within it have failed. @samp{#else} is equivalent to ! @samp{#elif 1}, and @samp{#else} is allowed after any number of ! @samp{#elif}'s, but @samp{#elif} may not follow @samp{#else}. ! @node Deleted Code, Conditionals-Macros, Conditional Syntax, Conditionals @subsection Keeping Deleted Code for Future Reference --- 1964,1977 ---- The text following the @samp{#elif} is processed only if the original ! @samp{#if}-condition failed and the @samp{#elif} condition succeeds. ! More than one @samp{#elif} can go in the same @samp{#if}-@samp{#endif} ! group. Then the text after each @samp{#elif} is processed only if the ! @samp{#elif} condition succeeds after the original @samp{#if} and any ! previous @samp{#elif} commands within it have failed. @samp{#else} is ! equivalent to @samp{#elif 1}, and @samp{#else} is allowed after any ! number of @samp{#elif} commands, but @samp{#elif} may not follow ! @samp{#else}. ! @node Deleted Code @subsection Keeping Deleted Code for Future Reference *************** *** 1936,1948 **** they must be entire conditionals (balanced @samp{#if} and @samp{#endif}). ! @node Conditionals-Macros, #error Command, Deleted Code, Conditionals @subsection Conditionals and Macros ! Conditionals are rarely useful except in connection with macros. A ! @samp{#if} command whose expression uses no macros is equivalent to ! @samp{#if 1} or @samp{#if 0}; you might as well determine which one, by ! computing the value of the expression yourself, and then simplify the ! program. But when the expression uses macros, its value can vary from ! compilation to compilation. For example, here is a conditional that tests the expression --- 1983,1995 ---- they must be entire conditionals (balanced @samp{#if} and @samp{#endif}). ! @node Conditionals-Macros @subsection Conditionals and Macros ! Conditionals are useful in connection with macros or assertions, because ! those are the only ways that an expression's value can vary from one ! compilaton to another. A @samp{#if} command whose expression uses no ! macros or assertions is equivalent to @samp{#if 1} or @samp{#if 0}; you ! might as well determine which one, by computing the value of the ! expression yourself, and then simplify the program. For example, here is a conditional that tests the expression *************** *** 1955,1966 **** @end example @findex defined ! The special operator @samp{defined} may be used in @samp{#if} expressions ! to test whether a certain name is defined as a macro. Either @samp{defined ! @var{name}} or @samp{defined (@var{name})} is an expression whose value is ! 1 if @var{name} is defined as macro at the current point in the program, ! and 0 otherwise. For the @samp{defined} operator it makes no difference ! what the definition of the macro is; all that matters is whether there is a ! definition. Thus, for example,@refill @example --- 2002,2018 ---- @end example + (Programmers often wish they could test the size of a variable or data + type in @samp{#if}, but this does not work. The preprocessor does not + understand @code{sizeof}, or typedef names, or even the type keywords + such as @code{int}.) + @findex defined ! The special operator @samp{defined} is used in @samp{#if} expressions to ! test whether a certain name is defined as a macro. Either @samp{defined ! @var{name}} or @samp{defined (@var{name})} is an expression whose value ! is 1 if @var{name} is defined as macro at the current point in the ! program, and 0 otherwise. For the @samp{defined} operator it makes no ! difference what the definition of the macro is; all that matters is ! whether there is a definition. Thus, for example,@refill @example *************** *** 1970,1977 **** @noindent would include the following code if either of the names @samp{vax} and ! @samp{ns16000} is defined as a macro. If a macro is defined and later undefined with @samp{#undef}, ! subsequent use of the @samp{defined} operator will return 0, because the name is no longer defined. If the macro is defined again with another @samp{#define}, @samp{defined} will recommence returning 1. --- 2022,2034 ---- @noindent would include the following code if either of the names @samp{vax} and ! @samp{ns16000} is defined as a macro. You can test the same condition ! using assertions (@pxref{Assertions}), like this: ! ! @example ! #if #cpu (vax) || #cpu (ns16000) ! @end example If a macro is defined and later undefined with @samp{#undef}, ! subsequent use of the @samp{defined} operator returns 0, because the name is no longer defined. If the macro is defined again with another @samp{#define}, @samp{defined} will recommence returning 1. *************** *** 1980,1984 **** @findex #ifndef Conditionals that test just the definedness of one name are very common, so ! there are two special short conditional commands for this case. They are @table @code --- 2037,2041 ---- @findex #ifndef Conditionals that test just the definedness of one name are very common, so ! there are two special short conditional commands for this case. @table @code *************** *** 2022,2026 **** @end itemize ! @node #error Command,, Conditionals-Macros, Conditionals @subsection The @samp{#error} and @samp{#warning} Commands --- 2079,2198 ---- @end itemize ! @ifinfo ! Assertions are usually predefined, but can be defined with preprocessor ! commands or command-line options. ! @end ifinfo ! ! @node Assertions ! @subsection Assertions ! ! @cindex assertions ! @dfn{Assertions} are a more systematic alternative to macros in writing ! conditionals to test what sort of computer or system the compiled ! program will run on. Assertions are usually predefined, but you can ! define them with preprocessor commands or command-line options. ! ! @cindex predicates ! The macros traditionally used to describe the type of target are not ! classified in any way according to which question they answer; they may ! indicate a hardware architecture, a particular hardware model, an ! operating system, a particular version of an operating system, or ! specific configuration options. These are jumbled together in a single ! namespace. In contrast, each assertion consists of a named question and ! an answer. The question is usually called the @dfn{predicate}. ! An assertion looks like this: ! ! @example ! #@var{predicate} (@var{answer}) ! @end example ! ! @noindent ! You must use a properly formed identifier for @var{predicate}. The ! value of @var{answer} can be any sequence of words; all characters are ! significant except for leading and trailing whitespace, and differences ! in internal whitespace sequences are ignored. Thus, @samp{x + y} is ! different from @samp{x+y} but equivalent to @samp{x + y}. @samp{)} is ! not allowed in an answer. ! ! @cindex testing predicates ! Here is a conditional to test whether the answer @var{answer} is asserted ! for the predicate @var{predicate}: ! ! @example ! #if #@var{predicate} (@var{answer}) ! @end example ! ! @noindent ! There may be more than one answer asserted for a given predicate. If ! you omit the answer, you can test whether @emph{any} answer is asserted ! for @var{predicate}: ! ! @example ! #if #@var{predicate} ! @end example ! ! Most of the time, the assertions you test will be predefined assertions. ! GNU C provides three predefined predicates: @code{system}, @code{cpu}, ! and @code{machine}. @code{system} is for assertions about the type of ! software, @code{cpu} describes the type of computer architecture, and ! @code{machine} gives more information about the computer. For example, ! on a GNU system, the following assertions would be true: ! ! @example ! #system (gnu) ! #system (mach) ! #system (mach 3) ! #system (mach 3.@var{subversion}) ! #system (hurd) ! #system (hurd @var{version}) ! @end example ! ! @noindent ! and perhaps others. On a Unix system, you would find @code{#system ! (unix)} and either @code{#system (unix bsd)} or @code{#system (unix ! sysv)}, with possible version numbers following. The alternatives with ! more or less version information let you ask more or less detailed ! questions about the type of system software. ! ! @strong{Portability note:} Many Unix C compilers provide only one answer ! for the @code{system} assertion: @code{#system (unix)}, if they support ! assertions at all. This is less than useful. ! ! An assertion with a multi-word answer is completely different from several ! assertions with individual single-word answers. For example, the presence ! of @code{system (mach 3.0)} does not mean that @code{system (3.0)} is true. ! It also does not directly imply @code{system (mach)}, but in GNU C, that ! last will normally be asserted as well. ! ! @findex #assert ! You can create assertions within a C program using @samp{#assert}, like ! this: ! ! @example ! #assert @var{predicate} (@var{answer}) ! @end example ! ! @noindent ! (Note the absence of a @samp{#} before @var{predicate}.) ! ! @cindex unassert ! @cindex assertions, undoing ! @cindex retracting assertions ! @findex #unassert ! Each time you do this, you assert a new true answer for @var{predicate}. ! Asserting one answer does not invalidate previously asserted answers; ! they all remain true. The only way to remove an assertion is with ! @samp{#unassert}. @samp{#unassert} has the same syntax as ! @samp{#assert}. You can also remove all assertions about ! @var{predicate} like this: ! ! @example ! #unassert @var{predicate} ! @end example ! ! You can also add or cancel assertions using command options ! when you run @code{gcc} or @code{cpp}. @xref{Invocation}. ! ! @node #error Command @subsection The @samp{#error} and @samp{#warning} Commands *************** *** 2119,2122 **** --- 2291,2299 ---- Predefined}. + The output of the preprocessor (which is the input for the rest of the + compiler) contains commands that look much like @samp{#line} commands. + They start with just @samp{#} instead of @samp{#line}, but this is + followed by a line number and file name as in @samp{#line}. @xref{Output}. + @node Other Commands, Output, Combining Sources, Top @section Miscellaneous Preprocessor Commands *************** *** 2144,2148 **** other systems. It is followed by a line of text. On some systems, the text is copied into a special place in the object file; on most systems, ! the text is ignored and this directive has no effect. Typically @samp{#ident} is only used in header files supplied with those systems where it is meaningful. --- 2321,2325 ---- other systems. It is followed by a line of text. On some systems, the text is copied into a special place in the object file; on most systems, ! the text is ignored and this command has no effect. Typically @samp{#ident} is only used in header files supplied with those systems where it is meaningful. *************** *** 2161,2165 **** @example ! # @var{linenum} @var{filename} @var{flag} @end example --- 2338,2342 ---- @example ! # @var{linenum} @var{filename} @var{flags} @end example *************** *** 2169,2176 **** following line originated in file @var{filename} at line @var{linenum}. ! The third field, @var{flag}, may be a number, or may be absent. It is ! @samp{1} for the beginning of a new source file, and @samp{2} for return ! to an old source file at the end of an included file. It is absent ! otherwise. @node Invocation, Concept Index, Output, Top --- 2346,2362 ---- following line originated in file @var{filename} at line @var{linenum}. ! After the file name comes zero or more flags, which are @samp{1}, ! @samp{2} or @samp{3}. If there are multiple flags, spaces separate ! them. Here is what the flags mean: ! ! @table @samp ! @item 1 ! This indicates the start of a new file. ! @item 2 ! This indicates returning to a file (after having included another file). ! @item 3 ! This indicates that the following text comes from a system header file, ! so certain warnings should be suppressed. ! @end table @node Invocation, Concept Index, Output, Top *************** *** 2212,2215 **** --- 2398,2448 ---- output before the expansion of the macro call. + @item -traditional + @findex -traditional + Try to imitate the behavior of old-fashioned C, as opposed to ANSI C. + + @itemize @bullet + @item + Traditional macro expansion pays no attention to singlequote or + doublequote characters; macro argument symbols are replaced by the + argument values even when they appear within apparent string or + character constants. + + @item + Traditionally, it is permissable for a macro expansion to end in the + middle of a string or character constant. The constant continues into + the text surrounding the macro call. + + @item + However, traditionally the end of the line terminates a string or + character constant, with no error. + + @item + In traditional C, a comment is equivalent to no text at all. (In ANSI + C, a comment counts as whitespace.) + + @item + Traditional C does not have the concept of a ``preprocessing number''. + It considers @samp{1.0e+4} to be three tokens: @samp{1.0e}, @samp{+}, + and @samp{4}. + + @item + A macro is not suppressed within its own definition, in traditional C. + Thus, any macro that is used recursively inevitably causes an error. + + @item + The character @samp{#} has no special meaning within a macro definition + in traditional C. + + @item + In traditional C, the text at the end of a macro expansion can run + together with the text after the macro call, to produce a single token. + (This is impossible in ANSI C.) + + @item + Traditionally, @samp{\} inside a macro argument suppresses the syntactic + significance of the following character. + @end itemize + @item -trigraphs @findex -trigraphs *************** *** 2275,2279 **** If additional directories are specified with @samp{-I} options after the @samp{-I-}, these directories are searched for all @samp{#include} ! directives. In addition, the @samp{-I-} option inhibits the use of the current --- 2508,2512 ---- If additional directories are specified with @samp{-I} options after the @samp{-I-}, these directories are searched for all @samp{#include} ! commands. In addition, the @samp{-I-} option inhibits the use of the current *************** *** 2313,2319 **** is not predefined. ! @item -undef ! @findex -undef ! Do not predefine any nonstandard macros. @item -dM --- 2546,2557 ---- is not predefined. ! @item -A @var{predicate}(@var{answer}) ! @findex -A ! Make an assertion with the predicate @var{predicate} and answer ! @var{answer}. @xref{Assertions}. ! ! @noindent ! You can use @samp{-A-} to disable all predefined assertions; it also ! undefines all predefined macros that identify the type of target system. @item -dM *************** *** 2398,2402 **** handle C++ comment syntax, and includes extra default include directories for C++, and @samp{-lang-objc} enables the Objective C ! @samp{#import} directive. @samp{-lang-c} explicitly turns off both of these extensions, and @samp{-lang-objc++} enables both. --- 2636,2640 ---- handle C++ comment syntax, and includes extra default include directories for C++, and @samp{-lang-objc} enables the Objective C ! @samp{#import} command. @samp{-lang-c} explicitly turns off both of these extensions, and @samp{-lang-objc++} enables both. diff -rc2N gcc-2.2.2/cross-make gcc-2.3.1/cross-make *** gcc-2.2.2/cross-make Thu Mar 5 18:31:47 1992 --- gcc-2.3.1/cross-make Tue Oct 6 16:37:15 1992 *************** *** 1,5 **** ! # Don't build or use libgcc1. ! LIBGCC1 = # Specify tools and options for manipulating libraries for the target machine. AR = $(AR_FOR_TARGET) --- 1,9 ---- ! # This variable gets added to GCC_CFLAGS. ! CROSS_GCC_CFLAGS = -B$(tooldir)/bin/ + # Expect user to provide libgcc1.a, + # and give up immediately if the user has not done so. + LIBGCC1 = libgcc1.cross + # Specify tools and options for manipulating libraries for the target machine. AR = $(AR_FOR_TARGET) *************** *** 14,17 **** --- 18,24 ---- CROSS_TOOLS = install-cross-tools + # Dir to search for system headers. Normally /usr/include. + SYSTEM_HEADER_DIR = $(libsubdir)/sys-include + # Cause installation using install-cross. INSTALL_TARGET = install-cross *************** *** 19,20 **** --- 26,30 ---- # Don't try to compile the things we can't compile. ALL = all.cross + + # Don't install assert.h in /usr/local/include. + assertdir = $(tooldir)/include diff -rc2N gcc-2.2.2/cse.c gcc-2.3.1/cse.c *** gcc-2.2.2/cse.c Thu Jun 4 18:27:23 1992 --- gcc-2.3.1/cse.c Sun Oct 18 15:55:20 1992 *************** *** 327,331 **** We use them to see whether a reg is used outside a given basic block. */ ! static short *uid_cuid; /* Get the cuid of an insn. */ --- 327,331 ---- We use them to see whether a reg is used outside a given basic block. */ ! static int *uid_cuid; /* Get the cuid of an insn. */ *************** *** 864,868 **** if (GET_CODE (XEXP (x, 0)) == REG && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))) ! if (insert_regs (XEXP (x, 0), 0, 0)) { rehash_using_reg (XEXP (x, 0)); --- 864,868 ---- if (GET_CODE (XEXP (x, 0)) == REG && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))) ! if (insert_regs (XEXP (x, 0), NULL_PTR, 0)) { rehash_using_reg (XEXP (x, 0)); *************** *** 872,876 **** if (GET_CODE (XEXP (x, 1)) == REG && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 1)))) ! if (insert_regs (XEXP (x, 1), 0, 0)) { rehash_using_reg (XEXP (x, 1)); --- 872,876 ---- if (GET_CODE (XEXP (x, 1)) == REG && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 1)))) ! if (insert_regs (XEXP (x, 1), NULL_PTR, 0)) { rehash_using_reg (XEXP (x, 1)); *************** *** 930,933 **** --- 930,947 ---- } } + + /* If X is a SUBREG, we will likely be inserting the inner register in the + table. If that register doesn't have an assigned quantity number at + this point but does later, the insertion that we will be doing now will + not be accessible because its hash code will have changed. So assign + a quantity number now. */ + + else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG + && ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x)))) + { + insert_regs (SUBREG_REG (x), NULL_PTR, 0); + mention_regs (SUBREG_REG (x)); + return 1; + } else return mention_regs (x); *************** *** 1284,1288 **** subelt = lookup (subexp, subhash, mode); if (subelt == 0) ! subelt = insert (subexp, 0, subhash, mode); /* Initialize SUBELT's circular chain if it has none. */ if (subelt->related_value == 0) --- 1298,1302 ---- subelt = lookup (subexp, subhash, mode); if (subelt == 0) ! subelt = insert (subexp, NULL_PTR, subhash, mode); /* Initialize SUBELT's circular chain if it has none. */ if (subelt->related_value == 0) *************** *** 1374,1378 **** register struct table_elt *p; register rtx base; ! register int start, end; /* If X is a register, dependencies on its contents --- 1388,1392 ---- register struct table_elt *p; register rtx base; ! register HOST_WIDE_INT start, end; /* If X is a register, dependencies on its contents *************** *** 1514,1518 **** next = p->next_same_hash; if (GET_CODE (p->exp) != REG ! && refers_to_regno_p (regno, regno + 1, p->exp, 0)) remove_from_table (p, i); } --- 1528,1532 ---- next = p->next_same_hash; if (GET_CODE (p->exp) != REG ! && refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR)) remove_from_table (p, i); } *************** *** 1662,1666 **** register struct table_elt *relt = 0; register struct table_elt *p, *q; ! int offset; /* First, is there anything related known? --- 1676,1680 ---- register struct table_elt *relt = 0; register struct table_elt *p, *q; ! HOST_WIDE_INT offset; /* First, is there anything related known? *************** *** 1804,1813 **** case LABEL_REF: /* Use `and' to ensure a positive number. */ ! return (hash + ((int) LABEL_REF << 7) ! + ((int) XEXP (x, 0) & ((1 << HASHBITS) - 1))); case SYMBOL_REF: ! return (hash + ((int) SYMBOL_REF << 7) ! + ((int) XEXP (x, 0) & ((1 << HASHBITS) - 1))); case MEM: --- 1818,1827 ---- case LABEL_REF: /* Use `and' to ensure a positive number. */ ! return (hash + ((HOST_WIDE_INT) LABEL_REF << 7) ! + ((HOST_WIDE_INT) XEXP (x, 0) & ((1 << HASHBITS) - 1))); case SYMBOL_REF: ! return (hash + ((HOST_WIDE_INT) SYMBOL_REF << 7) ! + ((HOST_WIDE_INT) XEXP (x, 0) & ((1 << HASHBITS) - 1))); case MEM: *************** *** 1939,1943 **** int equal_values; { ! register int i; register enum rtx_code code; register char *fmt; --- 1953,1957 ---- int equal_values; { ! register int i, j; register enum rtx_code code; register char *fmt; *************** *** 1985,1989 **** case CONST_INT: ! return XINT (x, 0) == XINT (y, 0); case LABEL_REF: --- 1999,2003 ---- case CONST_INT: ! return INTVAL (x) == INTVAL (y); case LABEL_REF: *************** *** 2039,2050 **** for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { ! if (fmt[i] == 'e') { if (! exp_equiv_p (XEXP (x, i), XEXP (y, i), validate, equal_values)) return 0; ! } ! else if (fmt[i] == 'E') ! { ! int j; if (XVECLEN (x, i) != XVECLEN (y, i)) return 0; --- 2053,2064 ---- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { ! switch (fmt[i]) { + case 'e': if (! exp_equiv_p (XEXP (x, i), XEXP (y, i), validate, equal_values)) return 0; ! break; ! ! case 'E': if (XVECLEN (x, i) != XVECLEN (y, i)) return 0; *************** *** 2053,2070 **** validate, equal_values)) return 0; ! } ! else if (fmt[i] == 's') ! { if (strcmp (XSTR (x, i), XSTR (y, i))) return 0; ! } ! else if (fmt[i] == 'i') ! { if (XINT (x, i) != XINT (y, i)) return 0; } ! else if (fmt[i] != '0') ! abort (); ! } return 1; } --- 2067,2095 ---- validate, equal_values)) return 0; ! break; ! ! case 's': if (strcmp (XSTR (x, i), XSTR (y, i))) return 0; ! break; ! ! case 'i': if (XINT (x, i) != XINT (y, i)) return 0; + break; + + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + + case '0': + break; + + default: + abort (); } ! } ! return 1; } *************** *** 2139,2145 **** refers_to_mem_p (x, base, start, end) rtx x, base; ! int start, end; { ! register int i; register enum rtx_code code; register char *fmt; --- 2164,2170 ---- refers_to_mem_p (x, base, start, end) rtx x, base; ! HOST_WIDE_INT start, end; { ! register HOST_WIDE_INT i; register enum rtx_code code; register char *fmt; *************** *** 2208,2212 **** && GET_CODE (XEXP (base, 1)) == CONST_INT) { ! int tem = INTVAL (XEXP (base, 1)); start += tem; end += tem; --- 2233,2237 ---- && GET_CODE (XEXP (base, 1)) == CONST_INT) { ! HOST_WIDE_INT tem = INTVAL (XEXP (base, 1)); start += tem; end += tem; *************** *** 2223,2227 **** && GET_CODE (XEXP (base, 1)) == CONST_INT) { ! int tem = INTVAL (XEXP (base, 1)); start += tem; end += tem; --- 2248,2252 ---- && GET_CODE (XEXP (base, 1)) == CONST_INT) { ! HOST_WIDE_INT tem = INTVAL (XEXP (base, 1)); start += tem; end += tem; *************** *** 2362,2370 **** /* If replacing pseudo with hard reg or vice versa, ensure the insn remains valid. Likewise if the insn has MATCH_DUPs. */ ! if (new && GET_CODE (new) == REG && GET_CODE (XEXP (x, i)) == REG && (((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (XEXP (x, i)) < FIRST_PSEUDO_REGISTER)) ! || (insn != 0 && insn_n_dups[recog_memoized (insn)] > 0))) ! validate_change (insn, &XEXP (x, i), new, 0); else XEXP (x, i) = new; --- 2387,2396 ---- /* If replacing pseudo with hard reg or vice versa, ensure the insn remains valid. Likewise if the insn has MATCH_DUPs. */ ! if (insn != 0 && new != 0 ! && GET_CODE (new) == REG && GET_CODE (XEXP (x, i)) == REG && (((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (XEXP (x, i)) < FIRST_PSEUDO_REGISTER)) ! || insn_n_dups[recog_memoized (insn)] > 0)) ! validate_change (insn, &XEXP (x, i), new, 1); else XEXP (x, i) = new; *************** *** 2438,2443 **** addr = *loc; ! /* If this address is not in the hash table, we can't do any better. ! Also, ignore if volatile. */ do_not_record = 0; hash_code = HASH (addr, Pmode); --- 2464,2470 ---- addr = *loc; ! /* If this address is not in the hash table, we can't look for equivalences ! of the whole address. Also, ignore if volatile. */ ! do_not_record = 0; hash_code = HASH (addr, Pmode); *************** *** 2452,2505 **** elt = lookup (addr, hash_code, Pmode); - if (elt == 0) - return; - #ifndef ADDRESS_COST ! our_cost = elt->cost; ! ! /* Find the lowest cost below ours that works. */ ! for (elt = elt->first_same_value; elt; elt = elt->next_same_value) ! if (elt->cost < our_cost ! && (GET_CODE (elt->exp) == REG || exp_equiv_p (elt->exp, elt->exp, 1, 0)) ! && validate_change (insn, loc, canon_reg (copy_rtx (elt->exp), 0), 0)) ! return; #else ! /* We need to find the best (under the criteria documented above) entry in ! the class that is valid. We use the `flag' field to indicate choices ! that were invalid and iterate until we can't find a better one that ! hasn't already been tried. */ ! for (p = elt->first_same_value; p; p = p->next_same_value) ! p->flag = 0; ! while (found_better) { ! int best_addr_cost = ADDRESS_COST (*loc); ! int best_rtx_cost = (elt->cost + 1) >> 1; ! struct table_elt *best_elt = elt; ! found_better = 0; for (p = elt->first_same_value; p; p = p->next_same_value) ! if (! p->flag ! && (GET_CODE (p->exp) == REG || exp_equiv_p (p->exp, p->exp, 1, 0)) ! && (ADDRESS_COST (p->exp) < best_addr_cost ! || (ADDRESS_COST (p->exp) == best_addr_cost ! && (p->cost + 1) >> 1 > best_rtx_cost))) ! { ! found_better = 1; ! best_addr_cost = ADDRESS_COST (p->exp); ! best_rtx_cost = (p->cost + 1) >> 1; ! best_elt = p; ! } ! if (found_better) { ! if (validate_change (insn, loc, ! canon_reg (copy_rtx (best_elt->exp), 0), 0)) ! return; ! else ! best_elt->flag = 1; } } --- 2479,2616 ---- elt = lookup (addr, hash_code, Pmode); #ifndef ADDRESS_COST ! if (elt) ! { ! our_cost = elt->cost; + /* Find the lowest cost below ours that works. */ + for (elt = elt->first_same_value; elt; elt = elt->next_same_value) + if (elt->cost < our_cost + && (GET_CODE (elt->exp) == REG + || exp_equiv_p (elt->exp, elt->exp, 1, 0)) + && validate_change (insn, loc, + canon_reg (copy_rtx (elt->exp), NULL_RTX), 0)) + return; + } #else ! if (elt) ! { ! /* We need to find the best (under the criteria documented above) entry ! in the class that is valid. We use the `flag' field to indicate ! choices that were invalid and iterate until we can't find a better ! one that hasn't already been tried. */ ! ! for (p = elt->first_same_value; p; p = p->next_same_value) ! p->flag = 0; ! ! while (found_better) ! { ! int best_addr_cost = ADDRESS_COST (*loc); ! int best_rtx_cost = (elt->cost + 1) >> 1; ! struct table_elt *best_elt = elt; ! ! found_better = 0; ! for (p = elt->first_same_value; p; p = p->next_same_value) ! if (! p->flag ! && (GET_CODE (p->exp) == REG ! || exp_equiv_p (p->exp, p->exp, 1, 0)) ! && (ADDRESS_COST (p->exp) < best_addr_cost ! || (ADDRESS_COST (p->exp) == best_addr_cost ! && (p->cost + 1) >> 1 > best_rtx_cost))) ! { ! found_better = 1; ! best_addr_cost = ADDRESS_COST (p->exp); ! best_rtx_cost = (p->cost + 1) >> 1; ! best_elt = p; ! } ! ! if (found_better) ! { ! if (validate_change (insn, loc, ! canon_reg (copy_rtx (best_elt->exp), ! NULL_RTX), 0)) ! return; ! else ! best_elt->flag = 1; ! } ! } ! } ! /* If the address is a binary operation with the first operand a register ! and the second a constant, do the same as above, but looking for ! equivalences of the register. Then try to simplify before checking for ! the best address to use. This catches a few cases: First is when we ! have REG+const and the register is another REG+const. We can often merge ! the constants and eliminate one insn and one register. It may also be ! that a machine has a cheap REG+REG+const. Finally, this improves the ! code on the Alpha for unaligned byte stores. */ ! if (flag_expensive_optimizations ! && (GET_RTX_CLASS (GET_CODE (*loc)) == '2' ! || GET_RTX_CLASS (GET_CODE (*loc)) == 'c') ! && GET_CODE (XEXP (*loc, 0)) == REG ! && GET_CODE (XEXP (*loc, 1)) == CONST_INT) { ! rtx c = XEXP (*loc, 1); ! ! do_not_record = 0; ! hash_code = HASH (XEXP (*loc, 0), Pmode); ! do_not_record = save_do_not_record; ! hash_arg_in_memory = save_hash_arg_in_memory; ! hash_arg_in_struct = save_hash_arg_in_struct; ! ! elt = lookup (XEXP (*loc, 0), hash_code, Pmode); ! if (elt == 0) ! return; ! /* We need to find the best (under the criteria documented above) entry ! in the class that is valid. We use the `flag' field to indicate ! choices that were invalid and iterate until we can't find a better ! one that hasn't already been tried. */ ! for (p = elt->first_same_value; p; p = p->next_same_value) ! p->flag = 0; ! while (found_better) { ! int best_addr_cost = ADDRESS_COST (*loc); ! int best_rtx_cost = (COST (*loc) + 1) >> 1; ! struct table_elt *best_elt = elt; ! rtx best_rtx = *loc; ! ! found_better = 0; ! for (p = elt->first_same_value; p; p = p->next_same_value) ! if (! p->flag ! && (GET_CODE (p->exp) == REG ! || exp_equiv_p (p->exp, p->exp, 1, 0))) ! { ! rtx new = simplify_binary_operation (GET_CODE (*loc), Pmode, ! p->exp, c); ! ! if (new == 0) ! new = gen_rtx (GET_CODE (*loc), Pmode, p->exp, c); ! ! if ((ADDRESS_COST (new) < best_addr_cost ! || (ADDRESS_COST (new) == best_addr_cost ! && (COST (new) + 1) >> 1 > best_rtx_cost))) ! { ! found_better = 1; ! best_addr_cost = ADDRESS_COST (new); ! best_rtx_cost = (COST (new) + 1) >> 1; ! best_elt = p; ! best_rtx = new; ! } ! } ! ! if (found_better) ! { ! if (validate_change (insn, loc, ! canon_reg (copy_rtx (best_rtx), ! NULL_RTX), 0)) ! return; ! else ! best_elt->flag = 1; ! } } } *************** *** 2520,2526 **** static enum rtx_code ! find_comparison_args (code, parg1, parg2) enum rtx_code code; rtx *parg1, *parg2; { rtx arg1, arg2; --- 2631,2638 ---- static enum rtx_code ! find_comparison_args (code, parg1, parg2, pmode1, pmode2) enum rtx_code code; rtx *parg1, *parg2; + enum machine_mode *pmode1, *pmode2; { rtx arg1, arg2; *************** *** 2530,2534 **** /* If ARG2 is const0_rtx, see what ARG1 is equivalent to. */ ! while (arg2 == const0_rtx) { /* Set non-zero when we find something of interest. */ --- 2642,2646 ---- /* If ARG2 is const0_rtx, see what ARG1 is equivalent to. */ ! while (arg2 == CONST0_RTX (GET_MODE (arg1))) { /* Set non-zero when we find something of interest. */ *************** *** 2550,2556 **** else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<') { ! if (code == NE || (code == LT && STORE_FLAG_VALUE == -1)) x = arg1; ! else if (code == EQ || (code == GE && STORE_FLAG_VALUE == -1)) x = arg1, reverse_code = 1; } --- 2662,2682 ---- else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<') { ! if (code == NE ! || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT ! && code == LT && STORE_FLAG_VALUE == -1) ! #ifdef FLOAT_STORE_FLAG_VALUE ! || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT ! && FLOAT_STORE_FLAG_VALUE < 0) ! #endif ! ) x = arg1; ! else if (code == EQ ! || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT ! && code == GE && STORE_FLAG_VALUE == -1) ! #ifdef FLOAT_STORE_FLAG_VALUE ! || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT ! && FLOAT_STORE_FLAG_VALUE < 0) ! #endif ! ) x = arg1, reverse_code = 1; } *************** *** 2587,2594 **** || ((code == NE || (code == LT ! && inner_mode != VOIDmode ! && GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_INT && (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (inner_mode) - 1))))) && GET_RTX_CLASS (GET_CODE (p->exp)) == '<')) { --- 2713,2728 ---- || ((code == NE || (code == LT ! && GET_MODE_CLASS (inner_mode) == MODE_INT ! && (GET_MODE_BITSIZE (inner_mode) ! <= HOST_BITS_PER_WIDE_INT) && (STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (inner_mode) - 1)))) ! #ifdef FLOAT_STORE_FLAG_VALUE ! || (code == LT ! && GET_MODE_CLASS (inner_mode) == MODE_FLOAT ! && FLOAT_STORE_FLAG_VALUE < 0) ! #endif ! ) && GET_RTX_CLASS (GET_CODE (p->exp)) == '<')) { *************** *** 2598,2605 **** else if ((code == EQ || (code == GE ! && inner_mode != VOIDmode ! && GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_INT && (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (inner_mode) - 1))))) && GET_RTX_CLASS (GET_CODE (p->exp)) == '<') { --- 2732,2747 ---- else if ((code == EQ || (code == GE ! && GET_MODE_CLASS (inner_mode) == MODE_INT ! && (GET_MODE_BITSIZE (inner_mode) ! <= HOST_BITS_PER_WIDE_INT) && (STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (inner_mode) - 1)))) ! #ifdef FLOAT_STORE_FLAG_VALUE ! || (code == GE ! && GET_MODE_CLASS (inner_mode) == MODE_FLOAT ! && FLOAT_STORE_FLAG_VALUE < 0) ! #endif ! ) && GET_RTX_CLASS (GET_CODE (p->exp)) == '<') { *************** *** 2631,2635 **** } ! /* Return our results. */ *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0); --- 2773,2779 ---- } ! /* Return our results. Return the modes from before fold_rtx ! because fold_rtx might produce const_int, and then it's too late. */ ! *pmode1 = GET_MODE (arg1), *pmode2 = GET_MODE (arg2); *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0); *************** *** 2689,2695 **** { d = (double) (~ CONST_DOUBLE_HIGH (op)); ! d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) ! * (double) (1 << (HOST_BITS_PER_INT / 2))); ! d += (double) (unsigned) (~ CONST_DOUBLE_LOW (op)); d = (- d - 1.0); } --- 2833,2839 ---- { d = (double) (~ CONST_DOUBLE_HIGH (op)); ! d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) ! * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); ! d += (double) (unsigned HOST_WIDE_INT) (~ CONST_DOUBLE_LOW (op)); d = (- d - 1.0); } *************** *** 2697,2703 **** { d = (double) CONST_DOUBLE_HIGH (op); ! d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) ! * (double) (1 << (HOST_BITS_PER_INT / 2))); ! d += (double) (unsigned) CONST_DOUBLE_LOW (op); } #endif /* REAL_ARITHMETIC */ --- 2841,2847 ---- { d = (double) CONST_DOUBLE_HIGH (op); ! d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) ! * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); ! d += (double) (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op); } #endif /* REAL_ARITHMETIC */ *************** *** 2714,2720 **** #else d = (double) CONST_DOUBLE_HIGH (op); ! d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) ! * (double) (1 << (HOST_BITS_PER_INT / 2))); ! d += (double) (unsigned) CONST_DOUBLE_LOW (op); #endif /* REAL_ARITHMETIC */ return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); --- 2858,2864 ---- #else d = (double) CONST_DOUBLE_HIGH (op); ! d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) ! * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); ! d += (double) (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op); #endif /* REAL_ARITHMETIC */ return CONST_DOUBLE_FROM_REAL_VALUE (d, mode); *************** *** 2722,2730 **** #endif ! else if (GET_CODE (op) == CONST_INT ! && width <= HOST_BITS_PER_INT && width > 0) { ! register int arg0 = INTVAL (op); ! register int val; switch (code) --- 2866,2874 ---- #endif ! if (GET_CODE (op) == CONST_INT ! && width <= HOST_BITS_PER_WIDE_INT && width > 0) { ! register HOST_WIDE_INT arg0 = INTVAL (op); ! register HOST_WIDE_INT val; switch (code) *************** *** 2756,2763 **** if (op_mode == VOIDmode) op_mode = mode; ! if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_INT) ! val = arg0; ! else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_INT) ! val = arg0 & ~((-1) << GET_MODE_BITSIZE (op_mode)); else return 0; --- 2900,2914 ---- if (op_mode == VOIDmode) op_mode = mode; ! if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT) ! { ! /* If we were really extending the mode, ! we would have to distinguish between zero-extension ! and sign-extension. */ ! if (width != GET_MODE_BITSIZE (op_mode)) ! abort (); ! val = arg0; ! } ! else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) ! val = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode)); else return 0; *************** *** 2767,2777 **** if (op_mode == VOIDmode) op_mode = mode; ! if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_INT) ! val = arg0; ! else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_INT) ! { ! val = arg0 & ~((-1) << GET_MODE_BITSIZE (op_mode)); ! if (val & (1 << (GET_MODE_BITSIZE (op_mode) - 1))) ! val -= 1 << GET_MODE_BITSIZE (op_mode); } else --- 2918,2937 ---- if (op_mode == VOIDmode) op_mode = mode; ! if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT) ! { ! /* If we were really extending the mode, ! we would have to distinguish between zero-extension ! and sign-extension. */ ! if (width != GET_MODE_BITSIZE (op_mode)) ! abort (); ! val = arg0; ! } ! else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT) ! { ! val ! = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode)); ! if (val ! & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (op_mode) - 1))) ! val -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode); } else *************** *** 2790,2798 **** So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_INT ! && ((val & ((-1) << (width - 1))) != ((-1) << (width - 1)))) val &= (1 << width) - 1; ! return gen_rtx (CONST_INT, VOIDmode, val); } --- 2950,2959 ---- So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_WIDE_INT ! && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) val &= (1 << width) - 1; ! return GEN_INT (val); } *************** *** 2802,2806 **** && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)) { ! int l1, h1, lv, hv; if (GET_CODE (op) == CONST_DOUBLE) --- 2963,2967 ---- && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)) { ! HOST_WIDE_INT l1, h1, lv, hv; if (GET_CODE (op) == CONST_DOUBLE) *************** *** 2830,2834 **** hv = 0; if (l1 == 0) ! lv = HOST_BITS_PER_INT + exact_log2 (h1 & (-h1)) + 1; else lv = exact_log2 (l1 & (-l1)) + 1; --- 2991,2995 ---- hv = 0; if (l1 == 0) ! lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & (-h1)) + 1; else lv = exact_log2 (l1 & (-l1)) + 1; *************** *** 2836,2845 **** case TRUNCATE: ! if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT) ! return gen_rtx (CONST_INT, VOIDmode, l1 & GET_MODE_MASK (mode)); else return 0; break; case SQRT: return 0; --- 2997,3031 ---- case TRUNCATE: ! if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) ! return GEN_INT (l1 & GET_MODE_MASK (mode)); else return 0; break; + case ZERO_EXTEND: + if (op_mode == VOIDmode + || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT) + return 0; + + hv = 0; + lv = l1 & GET_MODE_MASK (op_mode); + break; + + case SIGN_EXTEND: + if (op_mode == VOIDmode + || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT) + return 0; + else + { + lv = l1 & GET_MODE_MASK (op_mode); + if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT + && (lv & ((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (op_mode) - 1))) != 0) + lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode); + + hv = (lv < 0) ? ~ (HOST_WIDE_INT) 0 : 0; + } + break; + case SQRT: return 0; *************** *** 2882,2886 **** case FLOAT_TRUNCATE: ! d = (double) REAL_VALUE_TRUNCATE (mode, d); break; --- 3068,3072 ---- case FLOAT_TRUNCATE: ! d = (double) real_value_truncate (mode, d); break; *************** *** 2905,2918 **** x = immed_real_const_1 (d, mode); ! set_float_handler (0); return x; } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE_CLASS (mode) == MODE_INT ! && width <= HOST_BITS_PER_INT && width > 0) { REAL_VALUE_TYPE d; jmp_buf handler; rtx x; ! int val; if (setjmp (handler)) --- 3091,3104 ---- x = immed_real_const_1 (d, mode); ! set_float_handler (NULL_PTR); return x; } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE_CLASS (mode) == MODE_INT ! && width <= HOST_BITS_PER_WIDE_INT && width > 0) { REAL_VALUE_TYPE d; jmp_buf handler; rtx x; ! HOST_WIDE_INT val; if (setjmp (handler)) *************** *** 2937,2941 **** } ! set_float_handler (0); /* Clear the bits that don't belong in our mode, --- 3123,3127 ---- } ! set_float_handler (NULL_PTR); /* Clear the bits that don't belong in our mode, *************** *** 2943,2951 **** So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_INT ! && ((val & ((-1) << (width - 1))) != ((-1) << (width - 1)))) ! val &= (1 << width) - 1; ! return gen_rtx (CONST_INT, VOIDmode, val); } #endif --- 3129,3138 ---- So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_WIDE_INT ! && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) ! val &= ((HOST_WIDE_INT) 1 << width) - 1; ! return GEN_INT (val); } #endif *************** *** 2995,3000 **** rtx op0, op1; { ! register int arg0, arg1, arg0s, arg1s; ! int val; int width = GET_MODE_BITSIZE (mode); --- 3182,3187 ---- rtx op0, op1; { ! register HOST_WIDE_INT arg0, arg1, arg0s, arg1s; ! HOST_WIDE_INT val; int width = GET_MODE_BITSIZE (mode); *************** *** 3022,3027 **** REAL_VALUE_FROM_CONST_DOUBLE (f0, op0); REAL_VALUE_FROM_CONST_DOUBLE (f1, op1); ! f0 = REAL_VALUE_TRUNCATE (mode, f0); ! f1 = REAL_VALUE_TRUNCATE (mode, f1); #ifdef REAL_ARITHMETIC --- 3209,3214 ---- REAL_VALUE_FROM_CONST_DOUBLE (f0, op0); REAL_VALUE_FROM_CONST_DOUBLE (f1, op1); ! f0 = real_value_truncate (mode, f0); ! f1 = real_value_truncate (mode, f1); #ifdef REAL_ARITHMETIC *************** *** 3042,3046 **** #ifndef REAL_INFINITY if (f1 == 0) ! abort (); #endif value = f0 / f1; --- 3229,3233 ---- #ifndef REAL_INFINITY if (f1 == 0) ! return 0; #endif value = f0 / f1; *************** *** 3057,3062 **** #endif ! set_float_handler (0); ! value = REAL_VALUE_TRUNCATE (mode, value); return immed_real_const_1 (value, mode); } --- 3244,3249 ---- #endif ! set_float_handler (NULL_PTR); ! value = real_value_truncate (mode, value); return immed_real_const_1 (value, mode); } *************** *** 3067,3071 **** && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT)) { ! int l1, l2, h1, h2, lv, hv; l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0); --- 3254,3258 ---- && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT)) { ! HOST_WIDE_INT l1, l2, h1, h2, lv, hv; l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0); *************** *** 3111,3115 **** case SMIN: ! if (h1 < h2 || (h1 == h2 && (unsigned) l1 < (unsigned) l2)) lv = l1, hv = h1; else --- 3298,3305 ---- case SMIN: ! if (h1 < h2 ! || (h1 == h2 ! && ((unsigned HOST_WIDE_INT) l1 ! < (unsigned HOST_WIDE_INT) l2))) lv = l1, hv = h1; else *************** *** 3118,3122 **** case SMAX: ! if (h1 > h2 || (h1 == h2 && (unsigned) l1 > (unsigned) l2)) lv = l1, hv = h1; else --- 3308,3315 ---- case SMAX: ! if (h1 > h2 ! || (h1 == h2 ! && ((unsigned HOST_WIDE_INT) l1 ! > (unsigned HOST_WIDE_INT) l2))) lv = l1, hv = h1; else *************** *** 3125,3130 **** case UMIN: ! if ((unsigned) h1 < (unsigned) h2 ! || (h1 == h2 && (unsigned) l1 < (unsigned) l2)) lv = l1, hv = h1; else --- 3318,3325 ---- case UMIN: ! if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2 ! || (h1 == h2 ! && ((unsigned HOST_WIDE_INT) l1 ! < (unsigned HOST_WIDE_INT) l2))) lv = l1, hv = h1; else *************** *** 3133,3138 **** case UMAX: ! if ((unsigned) h1 > (unsigned) h2 ! || (h1 == h2 && (unsigned) l1 > (unsigned) l2)) lv = l1, hv = h1; else --- 3328,3335 ---- case UMAX: ! if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2 ! || (h1 == h2 ! && ((unsigned HOST_WIDE_INT) l1 ! > (unsigned HOST_WIDE_INT) l2))) lv = l1, hv = h1; else *************** *** 3171,3175 **** if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT ! || width > HOST_BITS_PER_INT || width == 0) { /* Even if we can't compute a constant result, --- 3368,3372 ---- if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT ! || width > HOST_BITS_PER_WIDE_INT || width == 0) { /* Even if we can't compute a constant result, *************** *** 3245,3248 **** --- 3442,3450 ---- return plus_constant (op1, INTVAL (op0)); else + break; + #if 0 /* No good, because this can produce the sum of two relocatable + symbols, in an assembler instruction. Most UNIX assemblers can't + handle that. */ + else return gen_rtx (CONST, mode, gen_rtx (PLUS, mode, *************** *** 3251,3254 **** --- 3453,3457 ---- GET_CODE (op1) == CONST ? XEXP (op1, 0) : op1)); + #endif } else if (GET_CODE (op1) == CONST_INT *************** *** 3467,3472 **** if (GET_CODE (op1) == CONST_INT && (val = exact_log2 (INTVAL (op1))) >= 0) ! return gen_rtx (ASHIFT, mode, op0, ! gen_rtx (CONST_INT, VOIDmode, val)); if (GET_CODE (op1) == CONST_DOUBLE --- 3670,3674 ---- if (GET_CODE (op1) == CONST_INT && (val = exact_log2 (INTVAL (op1))) >= 0) ! return gen_rtx (ASHIFT, mode, op0, GEN_INT (val)); if (GET_CODE (op1) == CONST_DOUBLE *************** *** 3532,3537 **** if (GET_CODE (op1) == CONST_INT && (arg1 = exact_log2 (INTVAL (op1))) > 0) ! return gen_rtx (LSHIFTRT, mode, op0, ! gen_rtx (CONST_INT, VOIDmode, arg1)); /* ... fall through ... */ --- 3734,3738 ---- if (GET_CODE (op1) == CONST_INT && (arg1 = exact_log2 (INTVAL (op1))) > 0) ! return gen_rtx (LSHIFTRT, mode, op0, GEN_INT (arg1)); /* ... fall through ... */ *************** *** 3540,3546 **** if (op1 == CONST1_RTX (mode)) return op0; ! else if (op0 == CONST0_RTX (mode) ! && ! side_effects_p (op1)) return op0; #if 0 /* Turned off till an expert says this is a safe thing to do. */ #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) --- 3741,3752 ---- if (op1 == CONST1_RTX (mode)) return op0; ! ! /* In IEEE floating point, 0/x is not always 0. */ ! if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT ! || GET_MODE_CLASS (mode) == MODE_INT) ! && op0 == CONST0_RTX (mode) ! && ! side_effects_p (op1)) return op0; + #if 0 /* Turned off till an expert says this is a safe thing to do. */ #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) *************** *** 3571,3576 **** if (GET_CODE (op1) == CONST_INT && exact_log2 (INTVAL (op1)) > 0) ! return gen_rtx (AND, mode, op0, ! gen_rtx (CONST_INT, VOIDmode, INTVAL (op1) - 1)); /* ... fall through ... */ --- 3777,3781 ---- if (GET_CODE (op1) == CONST_INT && exact_log2 (INTVAL (op1)) > 0) ! return gen_rtx (AND, mode, op0, GEN_INT (INTVAL (op1) - 1)); /* ... fall through ... */ *************** *** 3585,3589 **** case ROTATE: /* Rotating ~0 always results in ~0. */ ! if (GET_CODE (op0) == CONST_INT && width <= HOST_BITS_PER_INT && INTVAL (op0) == GET_MODE_MASK (mode) && ! side_effects_p (op1)) --- 3790,3794 ---- case ROTATE: /* Rotating ~0 always results in ~0. */ ! if (GET_CODE (op0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT && INTVAL (op0) == GET_MODE_MASK (mode) && ! side_effects_p (op1)) *************** *** 3603,3608 **** case SMIN: ! if (width <= HOST_BITS_PER_INT && GET_CODE (op1) == CONST_INT ! && INTVAL (op1) == 1 << (width -1) && ! side_effects_p (op0)) return op1; --- 3808,3813 ---- case SMIN: ! if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT ! && INTVAL (op1) == (HOST_WIDE_INT) 1 << (width -1) && ! side_effects_p (op0)) return op1; *************** *** 3612,3616 **** case SMAX: ! if (width <= HOST_BITS_PER_INT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == GET_MODE_MASK (mode) >> 1 && ! side_effects_p (op0)) --- 3817,3821 ---- case SMAX: ! if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == GET_MODE_MASK (mode) >> 1 && ! side_effects_p (op0)) *************** *** 3647,3662 **** arg1 = INTVAL (op1); ! if (width < HOST_BITS_PER_INT) { ! arg0 &= (1 << width) - 1; ! arg1 &= (1 << width) - 1; arg0s = arg0; ! if (arg0s & (1 << (width - 1))) ! arg0s |= ((-1) << width); arg1s = arg1; ! if (arg1s & (1 << (width - 1))) ! arg1s |= ((-1) << width); } else --- 3852,3867 ---- arg1 = INTVAL (op1); ! if (width < HOST_BITS_PER_WIDE_INT) { ! arg0 &= ((HOST_WIDE_INT) 1 << width) - 1; ! arg1 &= ((HOST_WIDE_INT) 1 << width) - 1; arg0s = arg0; ! if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1))) ! arg0s |= ((HOST_WIDE_INT) (-1) << width); arg1s = arg1; ! if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1))) ! arg1s |= ((HOST_WIDE_INT) (-1) << width); } else *************** *** 3697,3701 **** if (arg1 == 0) return 0; ! val = (unsigned) arg0 / arg1; break; --- 3902,3906 ---- if (arg1 == 0) return 0; ! val = (unsigned HOST_WIDE_INT) arg0 / arg1; break; *************** *** 3703,3707 **** if (arg1 == 0) return 0; ! val = (unsigned) arg0 % arg1; break; --- 3908,3912 ---- if (arg1 == 0) return 0; ! val = (unsigned HOST_WIDE_INT) arg0 % arg1; break; *************** *** 3731,3735 **** return 0; ! val = ((unsigned) arg0) >> arg1; break; --- 3936,3940 ---- return 0; ! val = ((unsigned HOST_WIDE_INT) arg0) >> arg1; break; *************** *** 3746,3750 **** return 0; ! val = ((unsigned) arg0) << arg1; break; --- 3951,3955 ---- return 0; ! val = ((unsigned HOST_WIDE_INT) arg0) << arg1; break; *************** *** 3761,3764 **** --- 3966,3975 ---- val = arg0s >> arg1; + + /* Bootstrap compiler may not have sign extended the right shift. + Manually extend the sign to insure bootstrap cc matches gcc. */ + if (arg0s < 0 && arg1 > 0) + val |= ((HOST_WIDE_INT) -1) << (HOST_BITS_PER_WIDE_INT - arg1); + break; *************** *** 3768,3773 **** arg1 %= width; ! val = ((((unsigned) arg0) << (width - arg1)) ! | (((unsigned) arg0) >> arg1)); break; --- 3979,3984 ---- arg1 %= width; ! val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1)) ! | (((unsigned HOST_WIDE_INT) arg0) >> arg1)); break; *************** *** 3777,3782 **** arg1 %= width; ! val = ((((unsigned) arg0) << arg1) ! | (((unsigned) arg0) >> (width - arg1))); break; --- 3988,3993 ---- arg1 %= width; ! val = ((((unsigned HOST_WIDE_INT) arg0) << arg1) ! | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1))); break; *************** *** 3790,3794 **** case UMIN: ! val = (unsigned int)arg0 <= (unsigned int)arg1 ? arg0 : arg1; break; --- 4001,4006 ---- case UMIN: ! val = ((unsigned HOST_WIDE_INT) arg0 ! <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); break; *************** *** 3798,3802 **** case UMAX: ! val = (unsigned int)arg0 > (unsigned int)arg1 ? arg0 : arg1; break; --- 4010,4015 ---- case UMAX: ! val = ((unsigned HOST_WIDE_INT) arg0 ! > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1); break; *************** *** 3808,3816 **** bit are all one. So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_INT ! && ((val & ((-1) << (width - 1))) != ((-1) << (width - 1)))) ! val &= (1 << width) - 1; ! ! return gen_rtx (CONST_INT, VOIDmode, val); } --- 4021,4030 ---- bit are all one. So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_WIDE_INT ! && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) ! val &= ((HOST_WIDE_INT) 1 << width) - 1; ! ! return GEN_INT (val); } *************** *** 3824,3829 **** rtx op0, op1; { ! register int arg0, arg1, arg0s, arg1s; ! int val; int width = GET_MODE_BITSIZE (mode); --- 4038,4043 ---- rtx op0, op1; { ! register HOST_WIDE_INT arg0, arg1, arg0s, arg1s; ! HOST_WIDE_INT val; int width = GET_MODE_BITSIZE (mode); *************** *** 3833,3837 **** if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT ! || width > HOST_BITS_PER_INT || width == 0) { /* Even if we can't compute a constant result, --- 4047,4051 ---- if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT ! || width > HOST_BITS_PER_WIDE_INT || width == 0) { /* Even if we can't compute a constant result, *************** *** 3850,3854 **** { REAL_VALUE_TYPE d0, d1; - int value; jmp_buf handler; int op0lt, op1lt, equal; --- 4064,4067 ---- *************** *** 3863,3867 **** op0lt = REAL_VALUES_LESS (d0, d1); op1lt = REAL_VALUES_LESS (d1, d0); ! set_float_handler (0); switch (code) --- 4076,4080 ---- op0lt = REAL_VALUES_LESS (d0, d1); op1lt = REAL_VALUES_LESS (d1, d0); ! set_float_handler (NULL_PTR); switch (code) *************** *** 3950,3965 **** arg1 = INTVAL (op1); ! if (width < HOST_BITS_PER_INT) { ! arg0 &= (1 << width) - 1; ! arg1 &= (1 << width) - 1; arg0s = arg0; ! if (arg0s & (1 << (width - 1))) ! arg0s |= ((-1) << width); arg1s = arg1; ! if (arg1s & (1 << (width - 1))) ! arg1s |= ((-1) << width); } else --- 4163,4178 ---- arg1 = INTVAL (op1); ! if (width < HOST_BITS_PER_WIDE_INT) { ! arg0 &= ((HOST_WIDE_INT) 1 << width) - 1; ! arg1 &= ((HOST_WIDE_INT) 1 << width) - 1; arg0s = arg0; ! if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1))) ! arg0s |= ((HOST_WIDE_INT) (-1) << width); arg1s = arg1; ! if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1))) ! arg1s |= ((HOST_WIDE_INT) (-1) << width); } else *************** *** 3998,4014 **** case LEU: ! val = ((unsigned) arg0) <= ((unsigned) arg1) ? STORE_FLAG_VALUE : 0; break; case LTU: ! val = ((unsigned) arg0) < ((unsigned) arg1) ? STORE_FLAG_VALUE : 0; break; case GEU: ! val = ((unsigned) arg0) >= ((unsigned) arg1) ? STORE_FLAG_VALUE : 0; break; case GTU: ! val = ((unsigned) arg0) > ((unsigned) arg1) ? STORE_FLAG_VALUE : 0; break; --- 4211,4231 ---- case LEU: ! val = (((unsigned HOST_WIDE_INT) arg0) ! <= ((unsigned HOST_WIDE_INT) arg1) ? STORE_FLAG_VALUE : 0); break; case LTU: ! val = (((unsigned HOST_WIDE_INT) arg0) ! < ((unsigned HOST_WIDE_INT) arg1) ? STORE_FLAG_VALUE : 0); break; case GEU: ! val = (((unsigned HOST_WIDE_INT) arg0) ! >= ((unsigned HOST_WIDE_INT) arg1) ? STORE_FLAG_VALUE : 0); break; case GTU: ! val = (((unsigned HOST_WIDE_INT) arg0) ! > ((unsigned HOST_WIDE_INT) arg1) ? STORE_FLAG_VALUE : 0); break; *************** *** 4020,4028 **** bit are all one. So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_INT ! && ((val & ((-1) << (width - 1))) != ((-1) << (width - 1)))) ! val &= (1 << width) - 1; ! return gen_rtx (CONST_INT, VOIDmode, val); } --- 4237,4246 ---- bit are all one. So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_WIDE_INT ! && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) ! val &= ((HOST_WIDE_INT) 1 << width) - 1; ! return GEN_INT (val); } *************** *** 4041,4045 **** /* VOIDmode means "infinite" precision. */ if (width == 0) ! width = HOST_BITS_PER_INT; switch (code) --- 4259,4263 ---- /* VOIDmode means "infinite" precision. */ if (width == 0) ! width = HOST_BITS_PER_WIDE_INT; switch (code) *************** *** 4051,4058 **** && GET_CODE (op2) == CONST_INT && INTVAL (op1) + INTVAL (op2) <= GET_MODE_BITSIZE (op0_mode) ! && width <= HOST_BITS_PER_INT) { /* Extracting a bit-field from a constant */ ! int val = INTVAL (op0); #if BITS_BIG_ENDIAN --- 4269,4276 ---- && GET_CODE (op2) == CONST_INT && INTVAL (op1) + INTVAL (op2) <= GET_MODE_BITSIZE (op0_mode) ! && width <= HOST_BITS_PER_WIDE_INT) { /* Extracting a bit-field from a constant */ ! HOST_WIDE_INT val = INTVAL (op0); #if BITS_BIG_ENDIAN *************** *** 4061,4071 **** val >>= INTVAL (op2); #endif ! if (HOST_BITS_PER_INT != INTVAL (op1)) { /* First zero-extend. */ ! val &= (1 << INTVAL (op1)) - 1; /* If desired, propagate sign bit. */ ! if (code == SIGN_EXTRACT && (val & (1 << (INTVAL (op1) - 1)))) ! val |= ~ ((1 << INTVAL (op1)) - 1); } --- 4279,4290 ---- val >>= INTVAL (op2); #endif ! if (HOST_BITS_PER_WIDE_INT != INTVAL (op1)) { /* First zero-extend. */ ! val &= ((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1; /* If desired, propagate sign bit. */ ! if (code == SIGN_EXTRACT ! && (val & ((HOST_WIDE_INT) 1 << (INTVAL (op1) - 1)))) ! val |= ~ (((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1); } *************** *** 4074,4082 **** So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_INT ! && ((val & ((-1) << (width - 1))) != ((-1) << (width - 1)))) ! val &= (1 << width) - 1; ! return gen_rtx (CONST_INT, VOIDmode, val); } break; --- 4293,4302 ---- So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ ! if (width < HOST_BITS_PER_WIDE_INT ! && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) ! val &= ((HOST_WIDE_INT) 1 << width) - 1; ! return GEN_INT (val); } break; *************** *** 4115,4119 **** register enum machine_mode mode; register char *fmt; ! register int i, val; rtx new = 0; int copied = 0; --- 4335,4339 ---- register enum machine_mode mode; register char *fmt; ! register int i; rtx new = 0; int copied = 0; *************** *** 4176,4190 **** case SUBREG: ! /* If this is a single word of a multi-word value, see if we previously ! assigned a value to that word. */ ! if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD ! && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD ! && (new = lookup_as_function (x, CONST_INT)) != 0) return new; ! /* If this is a paradoxical SUBREG, we can't do anything with ! it because we have no idea what value the extra bits would have. */ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) ! return x; /* Fold SUBREG_REG. If it changed, see if we can simplify the SUBREG. --- 4396,4430 ---- case SUBREG: ! /* See if we previously assigned a constant value to this SUBREG. */ ! if ((new = lookup_as_function (x, CONST_INT)) != 0 ! || (new = lookup_as_function (x, CONST_DOUBLE)) != 0) return new; ! /* If this is a paradoxical SUBREG, we have no idea what value the ! extra bits would have. However, if the operand is equivalent ! to a SUBREG whose operand is the same as our mode, and all the ! modes are within a word, we can just use the inner operand ! because these SUBREGs just say how to treat the register. */ ! if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) ! { ! enum machine_mode imode = GET_MODE (SUBREG_REG (x)); ! struct table_elt *elt; ! ! if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD ! && GET_MODE_SIZE (imode) <= UNITS_PER_WORD ! && (elt = lookup (SUBREG_REG (x), HASH (SUBREG_REG (x), imode), ! imode)) != 0) ! { ! for (elt = elt->first_same_value; ! elt; elt = elt->next_same_value) ! if (GET_CODE (elt->exp) == SUBREG ! && GET_MODE (SUBREG_REG (elt->exp)) == mode ! && exp_equiv_p (elt->exp, elt->exp, 1, 0)) ! return copy_rtx (SUBREG_REG (elt->exp)); ! } ! ! return x; ! } /* Fold SUBREG_REG. If it changed, see if we can simplify the SUBREG. *************** *** 4213,4217 **** /* If this is a narrowing SUBREG and our operand is a REG, see if ! we can find an equivalence for REG that is a arithmetic operation in a wider mode where both operands are paradoxical SUBREGs from objects of our result mode. In that case, we couldn't report --- 4453,4457 ---- /* If this is a narrowing SUBREG and our operand is a REG, see if ! we can find an equivalence for REG that is an arithmetic operation in a wider mode where both operands are paradoxical SUBREGs from objects of our result mode. In that case, we couldn't report *************** *** 4220,4227 **** by folding that operation is the narrow mode. This allows us to fold arithmetic in narrow modes when the machine only supports ! word-sized arithmetic. */ if (GET_CODE (folded_arg0) == REG ! && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0))) { struct table_elt *elt; --- 4460,4473 ---- by folding that operation is the narrow mode. This allows us to fold arithmetic in narrow modes when the machine only supports ! word-sized arithmetic. ! ! Also look for a case where we have a SUBREG whose operand is the ! same as our result. If both modes are smaller than a word, we ! are simply interpreting a register in different modes and we ! can use the inner value. */ if (GET_CODE (folded_arg0) == REG ! && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0)) ! && subreg_lowpart_p (x)) { struct table_elt *elt; *************** *** 4238,4241 **** --- 4484,4489 ---- for (; elt; elt = elt->next_same_value) { + enum rtx_code eltcode = GET_CODE (elt->exp); + /* Just check for unary and binary operations. */ if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1' *************** *** 4248,4252 **** if (GET_CODE (op0) != REG && ! CONSTANT_P (op0)) ! op0 = fold_rtx (op0, 0); op0 = equiv_constant (op0); --- 4496,4500 ---- if (GET_CODE (op0) != REG && ! CONSTANT_P (op0)) ! op0 = fold_rtx (op0, NULL_RTX); op0 = equiv_constant (op0); *************** *** 4257,4260 **** --- 4505,4512 ---- else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2' || GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c') + && eltcode != DIV && eltcode != MOD + && eltcode != UDIV && eltcode != UMOD + && eltcode != ASHIFTRT && eltcode != LSHIFTRT + && eltcode != ROTATE && eltcode != ROTATERT && ((GET_CODE (XEXP (elt->exp, 0)) == SUBREG && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) *************** *** 4270,4274 **** if (op0 && GET_CODE (op0) != REG && ! CONSTANT_P (op0)) ! op0 = fold_rtx (op0, 0); if (op0) --- 4522,4526 ---- if (op0 && GET_CODE (op0) != REG && ! CONSTANT_P (op0)) ! op0 = fold_rtx (op0, NULL_RTX); if (op0) *************** *** 4276,4280 **** if (op1 && GET_CODE (op1) != REG && ! CONSTANT_P (op1)) ! op1 = fold_rtx (op1, 0); if (op1) --- 4528,4532 ---- if (op1 && GET_CODE (op1) != REG && ! CONSTANT_P (op1)) ! op1 = fold_rtx (op1, NULL_RTX); if (op1) *************** *** 4286,4289 **** --- 4538,4548 ---- } + else if (GET_CODE (elt->exp) == SUBREG + && GET_MODE (SUBREG_REG (elt->exp)) == mode + && (GET_MODE_SIZE (GET_MODE (folded_arg0)) + <= UNITS_PER_WORD) + && exp_equiv_p (elt->exp, elt->exp, 1, 0)) + new = copy_rtx (SUBREG_REG (elt->exp)); + if (new) return new; *************** *** 4301,4305 **** return fold_rtx (copy_rtx (XEXP (new, 0)), insn); break; ! case MEM: /* If we are not actually processing an insn, don't try to find the --- 4560,4564 ---- return fold_rtx (copy_rtx (XEXP (new, 0)), insn); break; ! case MEM: /* If we are not actually processing an insn, don't try to find the *************** *** 4312,4318 **** /* Even if we don't fold in the insn itself, we can safely do so here, in hopes of getting a constant. */ ! rtx addr = fold_rtx (XEXP (x, 0), 0); rtx base = 0; ! int offset = 0; if (GET_CODE (addr) == REG --- 4571,4577 ---- /* Even if we don't fold in the insn itself, we can safely do so here, in hopes of getting a constant. */ ! rtx addr = fold_rtx (XEXP (x, 0), NULL_RTX); rtx base = 0; ! HOST_WIDE_INT offset = 0; if (GET_CODE (addr) == REG *************** *** 4599,4620 **** { struct table_elt *p0, *p1; ! code = find_comparison_args (code, &folded_arg0, &folded_arg1); const_arg0 = equiv_constant (folded_arg0); const_arg1 = equiv_constant (folded_arg1); ! /* Get a mode from the values actually being compared, or from the ! old value of MODE_ARG0 if both are constants. If the resulting ! mode is VOIDmode or a MODE_CC mode, we don't know what kinds ! of things are being compared, so we can't do anything with this ! comparison. */ ! ! if (GET_MODE (folded_arg0) != VOIDmode ! && GET_MODE_CLASS (GET_MODE (folded_arg0)) != MODE_CC) ! mode_arg0 = GET_MODE (folded_arg0); ! ! else if (GET_MODE (folded_arg1) != VOIDmode ! && GET_MODE_CLASS (GET_MODE (folded_arg1)) != MODE_CC) ! mode_arg0 = GET_MODE (folded_arg1); if (mode_arg0 == VOIDmode || GET_MODE_CLASS (mode_arg0) == MODE_CC) --- 4858,4880 ---- { struct table_elt *p0, *p1; + rtx true = const_true_rtx, false = const0_rtx; + enum machine_mode mode_arg1; + + #ifdef FLOAT_STORE_FLAG_VALUE + if (GET_MODE_CLASS (mode) == MODE_FLOAT) + { + true = immed_real_const_1 (FLOAT_STORE_FLAG_VALUE, mode); + false = CONST0_RTX (mode); + } + #endif ! code = find_comparison_args (code, &folded_arg0, &folded_arg1, ! &mode_arg0, &mode_arg1); const_arg0 = equiv_constant (folded_arg0); const_arg1 = equiv_constant (folded_arg1); ! /* If the mode is VOIDmode or a MODE_CC mode, we don't know ! what kinds of things are being compared, so we can't do ! anything with this comparison. */ if (mode_arg0 == VOIDmode || GET_MODE_CLASS (mode_arg0) == MODE_CC) *************** *** 4637,4643 **** { if (code == EQ) ! return const0_rtx; else if (code == NE) ! return const_true_rtx; } --- 4897,4903 ---- { if (code == EQ) ! return false; else if (code == NE) ! return true; } *************** *** 4662,4666 **** return ((code == EQ || code == LE || code == GE || code == LEU || code == GEU) ! ? const_true_rtx : const0_rtx); /* If FOLDED_ARG0 is a register, see if the comparison we are --- 4922,4926 ---- return ((code == EQ || code == LE || code == GE || code == LEU || code == GEU) ! ? true : false); /* If FOLDED_ARG0 is a register, see if the comparison we are *************** *** 4685,4689 **** return (comparison_dominates_p (qty_comparison_code[qty], code) ! ? const_true_rtx : const0_rtx); } } --- 4945,4949 ---- return (comparison_dominates_p (qty_comparison_code[qty], code) ! ? true : false); } } *************** *** 4705,4724 **** { int sign_bitnum = GET_MODE_BITSIZE (mode_arg0) - 1; ! int has_sign = (HOST_BITS_PER_INT >= sign_bitnum ! && (INTVAL (inner_const) & (1 << sign_bitnum))); switch (code) { case EQ: ! return const0_rtx; case NE: ! return const_true_rtx; case LT: case LE: if (has_sign) ! return const_true_rtx; break; case GT: case GE: if (has_sign) ! return const0_rtx; break; } --- 4965,4994 ---- { int sign_bitnum = GET_MODE_BITSIZE (mode_arg0) - 1; ! int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum ! && (INTVAL (inner_const) ! & ((HOST_WIDE_INT) 1 << sign_bitnum))); ! rtx true = const_true_rtx, false = const0_rtx; + #ifdef FLOAT_STORE_FLAG_VALUE + if (GET_MODE_CLASS (mode) == MODE_FLOAT) + { + true = immed_real_const_1 (FLOAT_STORE_FLAG_VALUE, mode); + false = CONST0_RTX (mode); + } + #endif + switch (code) { case EQ: ! return false; case NE: ! return true; case LT: case LE: if (has_sign) ! return true; break; case GT: case GE: if (has_sign) ! return false; break; } *************** *** 4729,4732 **** --- 4999,5007 ---- const_arg0 ? const_arg0 : folded_arg0, const_arg1 ? const_arg1 : folded_arg1); + #ifdef FLOAT_STORE_FLAG_VALUE + if (new != 0 && GET_MODE_CLASS (mode) == MODE_FLOAT) + new = ((new == const0_rtx) ? CONST0_RTX (mode) + : immed_real_const_1 (FLOAT_STORE_FLAG_VALUE, mode)); + #endif break; *************** *** 4748,4755 **** return XEXP (y, 0); } /* ... fall through ... */ ! case MINUS: case SMIN: case SMAX: case UMIN: case UMAX: case IOR: case AND: case XOR: --- 5023,5041 ---- return XEXP (y, 0); } + goto from_plus; + case MINUS: + /* If we have (MINUS Y C), see if Y is known to be (PLUS Z C2). + If so, produce (PLUS Z C2-C). */ + if (const_arg1 != 0 && GET_CODE (const_arg1) == CONST_INT) + { + rtx y = lookup_as_function (XEXP (x, 0), PLUS); + if (y && GET_CODE (XEXP (y, 1)) == CONST_INT) + return fold_rtx (plus_constant (y, -INTVAL (const_arg1))); + } + /* ... fall through ... */ ! from_plus: case SMIN: case SMAX: case UMIN: case UMAX: case IOR: case AND: case XOR: *************** *** 4889,4893 **** struct table_elt *elt; ! x = fold_rtx (x, 0); if (CONSTANT_P (x)) return x; --- 5175,5179 ---- struct table_elt *elt; ! x = fold_rtx (x, NULL_RTX); if (CONSTANT_P (x)) return x; *************** *** 4969,4973 **** int cond_known_true; rtx op0, op1; ! enum machine_mode mode; int reversed_nonequality = 0; enum rtx_code code; --- 5255,5259 ---- int cond_known_true; rtx op0, op1; ! enum machine_mode mode, mode0, mode1; int reversed_nonequality = 0; enum rtx_code code; *************** *** 4990,4994 **** op1 = fold_rtx (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1), insn); ! code = find_comparison_args (code, &op0, &op1); if (! cond_known_true) { --- 5276,5280 ---- op1 = fold_rtx (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1), insn); ! code = find_comparison_args (code, &op0, &op1, &mode0, &mode1); if (! cond_known_true) { *************** *** 4998,5003 **** /* The mode is the mode of the non-constant. */ ! mode = GET_MODE (op0); ! if (mode == VOIDmode) mode = GET_MODE (op1); record_jump_cond (code, mode, op0, op1, reversed_nonequality); --- 5284,5290 ---- /* The mode is the mode of the non-constant. */ ! mode = mode0; ! if (mode1 != VOIDmode) ! mode = mode1; record_jump_cond (code, mode, op0, op1, reversed_nonequality); *************** *** 5101,5106 **** /* If we aren't setting two things equal all we can do is save this ! comparison. */ ! if (code != EQ) { /* If we reversed a floating-point comparison, if OP0 is not a --- 5388,5397 ---- /* If we aren't setting two things equal all we can do is save this ! comparison. Similarly if this is floating-point. In the latter ! case, OP1 might be zero and both -0.0 and 0.0 are equal to it. ! If we record the equality, we might inadvertently delete code ! whose intent was to change -0 to +0. */ ! ! if (code != EQ || GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) { /* If we reversed a floating-point comparison, if OP0 is not a *************** *** 5119,5123 **** if (op0_elt == 0) { ! if (insert_regs (op0, 0, 0)) { rehash_using_reg (op0); --- 5410,5414 ---- if (op0_elt == 0) { ! if (insert_regs (op0, NULL_PTR, 0)) { rehash_using_reg (op0); *************** *** 5125,5129 **** } ! op0_elt = insert (op0, 0, op0_hash_code, mode); op0_elt->in_memory = op0_in_memory; op0_elt->in_struct = op0_in_struct; --- 5416,5420 ---- } ! op0_elt = insert (op0, NULL_PTR, op0_hash_code, mode); op0_elt->in_memory = op0_in_memory; op0_elt->in_struct = op0_in_struct; *************** *** 5136,5140 **** if (op1_elt == 0) { ! if (insert_regs (op1, 0, 0)) { rehash_using_reg (op1); --- 5427,5431 ---- if (op1_elt == 0) { ! if (insert_regs (op1, NULL_PTR, 0)) { rehash_using_reg (op1); *************** *** 5142,5146 **** } ! op1_elt = insert (op1, 0, op1_hash_code, mode); op1_elt->in_memory = op1_in_memory; op1_elt->in_struct = op1_in_struct; --- 5433,5437 ---- } ! op1_elt = insert (op1, NULL_PTR, op1_hash_code, mode); op1_elt->in_memory = op1_in_memory; op1_elt->in_struct = op1_in_struct; *************** *** 5299,5302 **** --- 5590,5594 ---- { canon_reg (SET_SRC (x), insn); + apply_change_group (); fold_rtx (SET_SRC (x), insn); invalidate (SET_DEST (x)); *************** *** 5340,5343 **** --- 5632,5636 ---- { canon_reg (SET_SRC (y), insn); + apply_change_group (); fold_rtx (SET_SRC (y), insn); invalidate (SET_DEST (y)); *************** *** 5357,5361 **** if (GET_CODE (XEXP (y, 0)) == MEM) { ! canon_reg (XEXP (y, 0), 0); note_mem_written (XEXP (y, 0), &writes_memory); } --- 5650,5654 ---- if (GET_CODE (XEXP (y, 0)) == MEM) { ! canon_reg (XEXP (y, 0), NULL_RTX); note_mem_written (XEXP (y, 0), &writes_memory); } *************** *** 5364,5371 **** && ! (GET_CODE (XEXP (y, 0)) == REG && REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER)) ! canon_reg (y, 0); else if (GET_CODE (y) == CALL) { canon_reg (y, insn); fold_rtx (y, insn); } --- 5657,5665 ---- && ! (GET_CODE (XEXP (y, 0)) == REG && REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER)) ! canon_reg (y, NULL_RTX); else if (GET_CODE (y) == CALL) { canon_reg (y, insn); + apply_change_group (); fold_rtx (y, insn); } *************** *** 5376,5380 **** if (GET_CODE (XEXP (x, 0)) == MEM) { ! canon_reg (XEXP (x, 0), 0); note_mem_written (XEXP (x, 0), &writes_memory); } --- 5670,5674 ---- if (GET_CODE (XEXP (x, 0)) == MEM) { ! canon_reg (XEXP (x, 0), NULL_RTX); note_mem_written (XEXP (x, 0), &writes_memory); } *************** *** 5385,5392 **** && ! (GET_CODE (XEXP (x, 0)) == REG && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)) ! canon_reg (XEXP (x, 0), 0); else if (GET_CODE (x) == CALL) { canon_reg (x, insn); fold_rtx (x, insn); } --- 5679,5687 ---- && ! (GET_CODE (XEXP (x, 0)) == REG && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)) ! canon_reg (XEXP (x, 0), NULL_RTX); else if (GET_CODE (x) == CALL) { canon_reg (x, insn); + apply_change_group (); fold_rtx (x, insn); } *************** *** 5395,5402 **** { /* Store the equivalent value in SRC_EQV, if different. */ ! rtx tem = find_reg_note (insn, REG_EQUAL, 0); if (tem && ! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))) ! src_eqv = canon_reg (XEXP (tem, 0), 0); } --- 5690,5697 ---- { /* Store the equivalent value in SRC_EQV, if different. */ ! rtx tem = find_reg_note (insn, REG_EQUAL, NULL_RTX); if (tem && ! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))) ! src_eqv = canon_reg (XEXP (tem, 0), NULL_RTX); } *************** *** 5407,5424 **** both operands at the same time. Otherwise, we would fail to find an equivalent substitution in the loop calling validate_change below. - (We also speed up that loop when a canonicalization was done since - recog_memoized need not be called for just a canonicalization unless - a pseudo register is being replaced by a hard reg of vice versa.) We used to suppress canonicalization of DEST if it appears in SRC, ! but we don't do this any more. ! ! ??? The way this code is written now, if we have a MATCH_DUP between ! two operands that are pseudos and we would want to canonicalize them ! to a hard register, we won't do that. The only time this would happen ! is if the hard reg was a fixed register, and this should be rare. ! ! ??? This won't work if there is a MATCH_DUP between an input and an ! output, but these never worked and must be declared invalid. */ for (i = 0; i < n_sets; i++) --- 5702,5708 ---- both operands at the same time. Otherwise, we would fail to find an equivalent substitution in the loop calling validate_change below. We used to suppress canonicalization of DEST if it appears in SRC, ! but we don't do this any more. */ for (i = 0; i < n_sets; i++) *************** *** 5428,5435 **** rtx new = canon_reg (src, insn); ! if (GET_CODE (new) == REG && GET_CODE (src) == REG ! && ((REGNO (new) < FIRST_PSEUDO_REGISTER) ! != (REGNO (src) < FIRST_PSEUDO_REGISTER))) ! validate_change (insn, &SET_SRC (sets[i].rtl), new, 0); else SET_SRC (sets[i].rtl) = new; --- 5712,5720 ---- rtx new = canon_reg (src, insn); ! if ((GET_CODE (new) == REG && GET_CODE (src) == REG ! && ((REGNO (new) < FIRST_PSEUDO_REGISTER) ! != (REGNO (src) < FIRST_PSEUDO_REGISTER))) ! || insn_n_dups[recog_memoized (insn)] > 0) ! validate_change (insn, &SET_SRC (sets[i].rtl), new, 1); else SET_SRC (sets[i].rtl) = new; *************** *** 5438,5444 **** { validate_change (insn, &XEXP (dest, 1), ! canon_reg (XEXP (dest, 1), insn), 0); validate_change (insn, &XEXP (dest, 2), ! canon_reg (XEXP (dest, 2), insn), 0); } --- 5723,5729 ---- { validate_change (insn, &XEXP (dest, 1), ! canon_reg (XEXP (dest, 1), insn), 1); validate_change (insn, &XEXP (dest, 2), ! canon_reg (XEXP (dest, 2), insn), 1); } *************** *** 5452,5455 **** --- 5737,5748 ---- } + /* Now that we have done all the replacements, we can apply the change + group and see if they all work. Note that this will cause some + canonicalizations that would have worked individually not to be applied + because some other canonicalization didn't work, but this should not + occur often. */ + + apply_change_group (); + /* Set sets[i].src_elt to the class each source belongs to. Detect assignments from or to volatile things *************** *** 5527,5534 **** if (GET_CODE (src) == CONST_INT && GET_CODE (width) == CONST_INT ! && INTVAL (width) < HOST_BITS_PER_INT ! && (INTVAL (src) & ((-1) << INTVAL (width)))) ! src_folded = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (src) & ((1 << INTVAL (width)) - 1)); } --- 5820,5828 ---- if (GET_CODE (src) == CONST_INT && GET_CODE (width) == CONST_INT ! && INTVAL (width) < HOST_BITS_PER_WIDE_INT ! && (INTVAL (src) & ((HOST_WIDE_INT) (-1) << INTVAL (width)))) ! src_folded ! = GEN_INT (INTVAL (src) & (((HOST_WIDE_INT) 1 ! << INTVAL (width)) - 1)); } *************** *** 5546,5549 **** --- 5840,5847 ---- sets[i].src_in_struct = hash_arg_in_struct; + #if 0 + /* It is no longer clear why we used to do this, but it doesn't + appear to still be needed. So let's try without it since this + code hurts cse'ing widened ops. */ /* If source is a perverse subreg (such as QI treated as an SI), treat it as volatile. It may do the work of an SI in one context *************** *** 5554,5557 **** --- 5852,5856 ---- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))) sets[i].src_volatile = 1; + #endif /* Locate all possible equivalent forms for SRC. Try to replace *************** *** 5667,5670 **** --- 5966,6000 ---- } + /* See if we have a CONST_INT that is already in a register in a + wider mode. */ + + if (src_const && src_related == 0 && GET_CODE (src_const) == CONST_INT + && GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_BITSIZE (mode) < BITS_PER_WORD) + { + enum machine_mode wider_mode; + + for (wider_mode = GET_MODE_WIDER_MODE (mode); + GET_MODE_BITSIZE (wider_mode) <= BITS_PER_WORD + && src_related == 0; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + struct table_elt *const_elt + = lookup (src_const, HASH (src_const, wider_mode), wider_mode); + + if (const_elt == 0) + continue; + + for (const_elt = const_elt->first_same_value; + const_elt; const_elt = const_elt->next_same_value) + if (GET_CODE (const_elt->exp) == REG) + { + src_related = gen_lowpart_if_possible (mode, + const_elt->exp); + break; + } + } + } + /* Another possibility is that we have an AND with a constant in a mode narrower than a word. If so, it might have been generated *************** *** 5678,5682 **** { enum machine_mode tmode; ! rtx new_and = gen_rtx (AND, VOIDmode, 0, XEXP (src, 1)); for (tmode = GET_MODE_WIDER_MODE (mode); --- 6008,6012 ---- { enum machine_mode tmode; ! rtx new_and = gen_rtx (AND, VOIDmode, NULL_RTX, XEXP (src, 1)); for (tmode = GET_MODE_WIDER_MODE (mode); *************** *** 5873,5876 **** --- 6203,6207 ---- { SET_SRC (sets[i].rtl) = canon_reg (SET_SRC (sets[i].rtl), insn); + apply_change_group (); break; } *************** *** 5948,5952 **** && GET_CODE (src_const) != REG) { ! rtx tem = find_reg_note (insn, REG_EQUAL, 0); /* Record the actual constant value in a REG_EQUAL note, making --- 6279,6283 ---- && GET_CODE (src_const) != REG) { ! rtx tem = find_reg_note (insn, REG_EQUAL, NULL_RTX); /* Record the actual constant value in a REG_EQUAL note, making *************** *** 5973,5977 **** { /* See if we previously had a REG_WAS_0 note. */ ! rtx note = find_reg_note (insn, REG_WAS_0, 0); rtx const_insn = qty_const_insn[reg_qty[REGNO (dest)]]; --- 6304,6308 ---- { /* See if we previously had a REG_WAS_0 note. */ ! rtx note = find_reg_note (insn, REG_WAS_0, NULL_RTX); rtx const_insn = qty_const_insn[reg_qty[REGNO (dest)]]; *************** *** 6033,6038 **** if (src_const != 0 && GET_CODE (src_const) == CONST_INT && GET_CODE (width) == CONST_INT ! && INTVAL (width) < HOST_BITS_PER_INT ! && ! (INTVAL (src_const) & ((-1) << INTVAL (width)))) /* Exception: if the value is constant, and it won't be truncated, record it. */ --- 6364,6370 ---- if (src_const != 0 && GET_CODE (src_const) == CONST_INT && GET_CODE (width) == CONST_INT ! && INTVAL (width) < HOST_BITS_PER_WIDE_INT ! && ! (INTVAL (src_const) ! & ((HOST_WIDE_INT) (-1) << INTVAL (width)))) /* Exception: if the value is constant, and it won't be truncated, record it. */ *************** *** 6234,6242 **** invalidate_from_clobbers (&writes_memory, x); ! /* Memory, and some registers, are invalidate by subroutine calls. */ if (GET_CODE (insn) == CALL_INSN) { static struct write_data everything = {0, 1, 1, 1}; ! invalidate_memory (&everything); invalidate_for_call (); } --- 6566,6579 ---- invalidate_from_clobbers (&writes_memory, x); ! ! /* Some registers are invalidated by subroutine calls. Memory is ! invalidated by non-constant calls. */ ! if (GET_CODE (insn) == CALL_INSN) { static struct write_data everything = {0, 1, 1, 1}; ! ! if (! CONST_CALL_P (insn)) ! invalidate_memory (&everything); invalidate_for_call (); } *************** *** 6324,6328 **** dest = SUBREG_REG (XEXP (dest, 0)); ! if (GET_CODE (dest) == REG) /* Registers must also be inserted into chains for quantities. */ if (insert_regs (dest, sets[i].src_elt, 1)) --- 6661,6665 ---- dest = SUBREG_REG (XEXP (dest, 0)); ! if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG) /* Registers must also be inserted into chains for quantities. */ if (insert_regs (dest, sets[i].src_elt, 1)) *************** *** 6437,6441 **** { rtx dest = SET_DEST (sets[0].rtl); ! rtx note = find_reg_note (prev, REG_EQUIV, 0); validate_change (prev, & SET_DEST (PATTERN (prev)), dest, 1); --- 6774,6778 ---- { rtx dest = SET_DEST (sets[0].rtl); ! rtx note = find_reg_note (prev, REG_EQUIV, NULL_RTX); validate_change (prev, & SET_DEST (PATTERN (prev)), dest, 1); *************** *** 6451,6459 **** /* If there was a REG_WAS_0 note on PREV, remove it. Move any REG_WAS_0 note on INSN to PREV. */ ! note = find_reg_note (prev, REG_WAS_0, 0); if (note) remove_note (prev, note); ! note = find_reg_note (insn, REG_WAS_0, 0); if (note) { --- 6788,6796 ---- /* If there was a REG_WAS_0 note on PREV, remove it. Move any REG_WAS_0 note on INSN to PREV. */ ! note = find_reg_note (prev, REG_WAS_0, NULL_RTX); if (note) remove_note (prev, note); ! note = find_reg_note (insn, REG_WAS_0, NULL_RTX); if (note) { *************** *** 6630,6636 **** case INSN_LIST: if (REG_NOTE_KIND (x) == REG_EQUAL) ! XEXP (x, 0) = cse_process_notes (XEXP (x, 0), 0); if (XEXP (x, 1)) ! XEXP (x, 1) = cse_process_notes (XEXP (x, 1), 0); return x; --- 6967,6973 ---- case INSN_LIST: if (REG_NOTE_KIND (x) == REG_EQUAL) ! XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX); if (XEXP (x, 1)) ! XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX); return x; *************** *** 6661,6665 **** /* Otherwise, canonicalize this register. */ ! return canon_reg (x, 0); } --- 6998,7002 ---- /* Otherwise, canonicalize this register. */ ! return canon_reg (x, NULL_RTX); } *************** *** 6667,6671 **** if (fmt[i] == 'e') validate_change (object, &XEXP (x, i), ! cse_process_notes (XEXP (x, i), object), 0); return x; --- 7004,7008 ---- if (fmt[i] == 'e') validate_change (object, &XEXP (x, i), ! cse_process_notes (XEXP (x, i), object), NULL_RTX); return x; *************** *** 6708,6712 **** /* If the last insn of the loop (the end test) was an NE comparison, we will interpret it as an EQ comparison, since we fell through ! the loop. Any equivalances resulting from that comparison are therefore not valid and must be invalidated. */ if (last_jump_equiv_class) --- 7045,7049 ---- /* If the last insn of the loop (the end test) was an NE comparison, we will interpret it as an EQ comparison, since we fell through ! the loop. Any equivalences resulting from that comparison are therefore not valid and must be invalidated. */ if (last_jump_equiv_class) *************** *** 6941,6945 **** /* Define maximum length of a branch path. */ ! #define PATHLENGTH 20 struct cse_basic_block_data { --- 7278,7282 ---- /* Define maximum length of a branch path. */ ! #define PATHLENGTH 10 struct cse_basic_block_data { *************** *** 7219,7224 **** i = get_max_uid (); ! uid_cuid = (short *) alloca ((i + 1) * sizeof (short)); ! bzero (uid_cuid, (i + 1) * sizeof (short)); /* Compute the mapping from uids to cuids. --- 7556,7561 ---- i = get_max_uid (); ! uid_cuid = (int *) alloca ((i + 1) * sizeof (int)); ! bzero (uid_cuid, (i + 1) * sizeof (int)); /* Compute the mapping from uids to cuids. *************** *** 7419,7423 **** if (REG_NOTES (insn)) ! REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn), 0); /* Track when we are inside in LIBCALL block. Inside such a block, --- 7756,7760 ---- if (REG_NOTES (insn)) ! REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn), NULL_RTX); /* Track when we are inside in LIBCALL block. Inside such a block, *************** *** 7427,7433 **** recorded. */ ! if (find_reg_note (insn, REG_LIBCALL, 0)) in_libcall_block = 1; ! else if (find_reg_note (insn, REG_RETVAL, 0)) in_libcall_block = 0; --- 7764,7770 ---- recorded. */ ! if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)) in_libcall_block = 1; ! else if (find_reg_note (insn, REG_RETVAL, NULL_RTX)) in_libcall_block = 0; *************** *** 7612,7616 **** { int *counts = (int *) alloca (nreg * sizeof (int)); ! rtx insn; rtx tem; int i; --- 7949,7953 ---- { int *counts = (int *) alloca (nreg * sizeof (int)); ! rtx insn, prev; rtx tem; int i; *************** *** 7625,7636 **** registers or copy a register to itself. As we delete an insn, remove usage counts for registers it uses. */ ! for (insn = prev_real_insn (get_last_insn ()); ! insn; insn = prev_real_insn (insn)) { int live_insn = 0; /* Don't delete any insns that are part of a libcall block. ! Flow or loop might get confused if we did that. */ ! if (find_reg_note (insn, REG_LIBCALL, 0)) in_libcall = 1; --- 7962,7975 ---- registers or copy a register to itself. As we delete an insn, remove usage counts for registers it uses. */ ! for (insn = prev_real_insn (get_last_insn ()); insn; insn = prev) { int live_insn = 0; + prev = prev_real_insn (insn); + /* Don't delete any insns that are part of a libcall block. ! Flow or loop might get confused if we did that. Remember ! that we are scanning backwards. */ ! if (find_reg_note (insn, REG_RETVAL, NULL_RTX)) in_libcall = 1; *************** *** 7694,7703 **** { count_reg_usage (insn, counts, -1); ! PUT_CODE (insn, NOTE); ! NOTE_SOURCE_FILE (insn) = 0; ! NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; } ! if (find_reg_note (insn, REG_RETVAL, 0)) in_libcall = 0; } --- 8033,8040 ---- { count_reg_usage (insn, counts, -1); ! delete_insn (insn); } ! if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)) in_libcall = 0; } diff -rc2N gcc-2.2.2/dbxout.c gcc-2.3.1/dbxout.c *** gcc-2.2.2/dbxout.c Wed Jun 10 16:05:23 1992 --- gcc-2.3.1/dbxout.c Fri Sep 25 01:58:30 1992 *************** *** 78,81 **** --- 78,83 ---- #include "insn-config.h" #include "reload.h" + #include "defaults.h" + #include "output.h" /* ASM_OUTPUT_SOURCE_LINE may refer to sdb functions. */ #ifndef errno *************** *** 397,401 **** #ifndef DBX_WORKING_DIRECTORY /* Only some versions of DBX want this, but GDB always does. */ ! if (use_gdb_dbx_extensions) #endif { --- 399,403 ---- #ifndef DBX_WORKING_DIRECTORY /* Only some versions of DBX want this, but GDB always does. */ ! if (use_gnu_debug_info_extensions) #endif { *************** *** 425,428 **** --- 427,437 ---- #endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */ + /* Possibly output something to inform GDB that this compilation was by + GCC. It's easier for GDB to parse it when after the N_SO's. This + is used in Solaris 2. */ + #ifdef ASM_IDENTIFY_GCC_AFTER_SOURCE + ASM_IDENTIFY_GCC_AFTER_SOURCE (asmfile); + #endif + lastfile = input_file_name; *************** *** 493,496 **** --- 502,523 ---- } + /* Output a line number symbol entry into output stream FILE, + for source file FILENAME and line number LINENO. */ + + void + dbxout_source_line (file, filename, lineno) + FILE *file; + char *filename; + int lineno; + { + dbxout_source_file (file, filename); + + #ifdef ASM_OUTPUT_SOURCE_LINE + ASM_OUTPUT_SOURCE_LINE (file, lineno); + #else + fprintf (file, "\t%s %d,0,%d\n", ASM_STABD_OP, N_SLINE, lineno); + #endif + } + /* At the end of compilation, finish writing the symbol table. Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is *************** *** 521,525 **** fprintf (asmfile, "\\\\"); #endif ! dbxout_finish_symbol (0); fprintf (asmfile, "%s \"", ASM_STABS_OP); current_sym_nchars = 0; --- 548,552 ---- fprintf (asmfile, "\\\\"); #endif ! dbxout_finish_symbol (NULL_TREE); fprintf (asmfile, "%s \"", ASM_STABS_OP); current_sym_nchars = 0; *************** *** 535,544 **** { tree tem; for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) { ! /* Output the name, type, position (in bits), size (in bits) ! of each field. */ if (DECL_NAME (tem) == NULL_TREE ! && TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE) dbxout_type_fields (TREE_TYPE (tem)); /* Omit here local type decls until we know how to support them. */ --- 562,573 ---- { tree tem; + /* Output the name, type, position (in bits), size (in bits) of each + field. */ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) { ! /* For nameless subunions and subrecords, treat their fields as ours. */ if (DECL_NAME (tem) == NULL_TREE ! && (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE ! || TREE_CODE (TREE_TYPE (tem)) == RECORD_TYPE)) dbxout_type_fields (TREE_TYPE (tem)); /* Omit here local type decls until we know how to support them. */ *************** *** 553,557 **** CONTIN; ! if (use_gdb_dbx_extensions && flag_minimal_debug && TREE_CODE (tem) == FIELD_DECL --- 582,586 ---- CONTIN; ! if (use_gnu_debug_info_extensions && flag_minimal_debug && TREE_CODE (tem) == FIELD_DECL *************** *** 573,577 **** CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem))); ! if (use_gdb_dbx_extensions && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem) || TREE_CODE (tem) != FIELD_DECL)) --- 602,606 ---- CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem))); ! if (use_gnu_debug_info_extensions && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem) || TREE_CODE (tem) != FIELD_DECL)) *************** *** 592,596 **** if (TREE_CODE (tem) == VAR_DECL) { ! if (TREE_STATIC (tem) && use_gdb_dbx_extensions) { char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)); --- 621,625 ---- if (TREE_CODE (tem) == VAR_DECL) { ! if (TREE_STATIC (tem) && use_gnu_debug_info_extensions) { char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)); *************** *** 677,680 **** --- 706,710 ---- register tree fndecl; register tree last; + char formatted_type_identifier_length[16]; register int type_identifier_length; *************** *** 689,693 **** { char *ptr = IDENTIFIER_POINTER (type_encoding); ! /* Avoid strchr or index since those names aren't universal. */ while (*ptr && *ptr != '<') ptr++; if (*ptr != 0) --- 719,723 ---- { char *ptr = IDENTIFIER_POINTER (type_encoding); ! /* This should use index. (mrs) */ while (*ptr && *ptr != '<') ptr++; if (*ptr != 0) *************** *** 705,713 **** type_identifier_length = IDENTIFIER_LENGTH (type_encoding); if (TREE_CODE (methods) == FUNCTION_DECL) fndecl = methods; else if (TREE_VEC_ELT (methods, 0) != NULL_TREE) fndecl = TREE_VEC_ELT (methods, 0); ! else fndecl = TREE_VEC_ELT (methods, 1); while (fndecl) --- 735,746 ---- type_identifier_length = IDENTIFIER_LENGTH (type_encoding); + sprintf(formatted_type_identifier_length, "%d", type_identifier_length); + if (TREE_CODE (methods) == FUNCTION_DECL) fndecl = methods; else if (TREE_VEC_ELT (methods, 0) != NULL_TREE) fndecl = TREE_VEC_ELT (methods, 0); ! else ! fndecl = TREE_VEC_ELT (methods, 1); while (fndecl) *************** *** 748,754 **** --- 781,791 ---- { char *method_name = debug_name + 2; + char *length_ptr = formatted_type_identifier_length; /* Get past const and volatile qualifiers. */ while (*method_name == 'C' || *method_name == 'V') method_name++; + /* Skip digits for length of type_encoding. */ + while (*method_name == *length_ptr && *length_ptr) + length_ptr++, method_name++; if (! strncmp (method_name, IDENTIFIER_POINTER (type_encoding), *************** *** 762,767 **** --- 799,808 ---- { char *ctor_name = debug_name + 2; + char *length_ptr = formatted_type_identifier_length; while (*ctor_name == 'C' || *ctor_name == 'V') ctor_name++; + /* Skip digits for length of type_encoding. */ + while (*ctor_name == *length_ptr && *length_ptr) + length_ptr++, ctor_name++; if (!strncmp (IDENTIFIER_POINTER (type_encoding), ctor_name, type_identifier_length)) *************** *** 951,954 **** --- 992,1033 ---- break; + case CHAR_TYPE: + /* Output the type `char' as a subrange of itself. + That is what pcc seems to do. */ + fprintf (asmfile, "r%d;0;%d;", TYPE_SYMTAB_ADDRESS (char_type_node), + TREE_UNSIGNED (type) ? 255 : 127); + CHARS (9); + break; + + case BOOLEAN_TYPE: /* Define as enumeral type (False, True) */ + fprintf (asmfile, "eFalse:0,True:1,;"); + CHARS (17); + break; + + case FILE_TYPE: + putc ('d', asmfile); + CHARS (1); + dbxout_type (TREE_TYPE (type), 0); + break; + + case COMPLEX_TYPE: + /* Differs from the REAL_TYPE by its new data type number */ + + if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) + { + fprintf (asmfile, "r%d;%d;0;", + TYPE_SYMTAB_ADDRESS (type), + TREE_INT_CST_LOW (size_in_bytes (TREE_TYPE (type)))); + CHARS (15); /* The number is propably incorrect here */ + } else + abort (); /* What to do with CSImode complex? */ + break; + + case SET_TYPE: + putc ('S', asmfile); + CHARS (1); + dbxout_type (TREE_TYPE (type), 0); + break; + case ARRAY_TYPE: /* Output "a" followed by a range type definition *************** *** 1014,1018 **** TREE_INT_CST_LOW (tem)); ! if (use_gdb_dbx_extensions) { if (n_baseclasses) --- 1093,1097 ---- TREE_INT_CST_LOW (tem)); ! if (use_gnu_debug_info_extensions) { if (n_baseclasses) *************** *** 1026,1030 **** { tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i); ! if (use_gdb_dbx_extensions) { have_used_extensions = 1; --- 1105,1109 ---- { tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i); ! if (use_gnu_debug_info_extensions) { have_used_extensions = 1; *************** *** 1060,1064 **** /* Write out the field declarations. */ dbxout_type_fields (type); ! if (use_gdb_dbx_extensions && TYPE_METHODS (type) != NULL_TREE) { have_used_extensions = 1; --- 1139,1143 ---- /* Write out the field declarations. */ dbxout_type_fields (type); ! if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE) { have_used_extensions = 1; *************** *** 1067,1071 **** putc (';', asmfile); ! if (use_gdb_dbx_extensions && TREE_CODE (type) == RECORD_TYPE /* Avoid the ~ if we don't really need it--it confuses dbx. */ && TYPE_VFIELD (type)) --- 1146,1150 ---- putc (';', asmfile); ! if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE /* Avoid the ~ if we don't really need it--it confuses dbx. */ && TYPE_VFIELD (type)) *************** *** 1128,1132 **** case METHOD_TYPE: ! if (use_gdb_dbx_extensions) { have_used_extensions = 1; --- 1207,1211 ---- case METHOD_TYPE: ! if (use_gnu_debug_info_extensions) { have_used_extensions = 1; *************** *** 1144,1148 **** else { ! /* When outputing destructors, we need to write the argument types out longhand. */ dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0); --- 1223,1227 ---- else { ! /* When outputting destructors, we need to write the argument types out longhand. */ dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0); *************** *** 1163,1167 **** case OFFSET_TYPE: ! if (use_gdb_dbx_extensions) { have_used_extensions = 1; --- 1242,1246 ---- case OFFSET_TYPE: ! if (use_gnu_debug_info_extensions) { have_used_extensions = 1; *************** *** 1182,1188 **** case REFERENCE_TYPE: ! if (use_gdb_dbx_extensions) have_used_extensions = 1; ! putc (use_gdb_dbx_extensions ? '&' : '*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); --- 1261,1267 ---- case REFERENCE_TYPE: ! if (use_gnu_debug_info_extensions) have_used_extensions = 1; ! putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); *************** *** 1207,1213 **** tree c; { ! unsigned int high = TREE_INT_CST_HIGH (c); ! unsigned int low = TREE_INT_CST_LOW (c); ! int excess = (3 - (HOST_BITS_PER_INT % 3)); fprintf (asmfile, "0"); --- 1286,1292 ---- tree c; { ! unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c); ! unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c); ! int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3)); fprintf (asmfile, "0"); *************** *** 1215,1230 **** if (excess == 3) { ! print_octal (high, HOST_BITS_PER_INT / 3); ! print_octal (low, HOST_BITS_PER_INT / 3); } else { ! unsigned int beg = high >> excess; ! unsigned int middle ! = ((high & ((1 << excess) - 1)) << (3 - excess) ! | (low >> (HOST_BITS_PER_INT / 3 * 3))); ! unsigned int end = low & ((1 << (HOST_BITS_PER_INT / 3 * 3)) - 1); fprintf (asmfile, "%o%01o", beg, middle); ! print_octal (end, HOST_BITS_PER_INT / 3); } } --- 1294,1310 ---- if (excess == 3) { ! print_octal (high, HOST_BITS_PER_WIDE_INT / 3); ! print_octal (low, HOST_BITS_PER_WIDE_INT / 3); } else { ! unsigned HOST_WIDE_INT beg = high >> excess; ! unsigned HOST_WIDE_INT middle ! = ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess) ! | (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3))); ! unsigned HOST_WIDE_INT end ! = low & (((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 3 * 3)) - 1); fprintf (asmfile, "%o%01o", beg, middle); ! print_octal (end, HOST_BITS_PER_WIDE_INT / 3); } } *************** *** 1232,1236 **** static void print_octal (value, digits) ! unsigned int value; int digits; { --- 1312,1316 ---- static void print_octal (value, digits) ! unsigned HOST_WIDE_INT value; int digits; { *************** *** 1310,1314 **** if (DECL_RTL (decl) == 0) return; ! if (TREE_EXTERNAL (decl)) break; /* Don't mention a nested function under its parent. */ --- 1390,1394 ---- if (DECL_RTL (decl) == 0) return; ! if (DECL_EXTERNAL (decl)) break; /* Don't mention a nested function under its parent. */ *************** *** 1366,1369 **** --- 1446,1450 ---- { int tag_needed = 1; + int did_output = 0; if (DECL_NAME (decl)) *************** *** 1375,1386 **** where the TYPE_NAME is a TYPE_DECL which gives both a typedef name and a tag. */ ! /* dbx requires the tag first and the typedef second. ! ??? there is a bug here. It generates spurious tags ! for C code. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) && TYPE_NAME (type) == decl ! && !(use_gdb_dbx_extensions && have_used_extensions) ! && !TREE_ASM_WRITTEN (TYPE_NAME (type))) { tree name = TYPE_NAME (type); --- 1456,1468 ---- where the TYPE_NAME is a TYPE_DECL which gives both a typedef name and a tag. */ ! /* dbx requires the tag first and the typedef second. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) && TYPE_NAME (type) == decl ! && !(use_gnu_debug_info_extensions && have_used_extensions) ! && !TREE_ASM_WRITTEN (TYPE_NAME (type)) ! /* Distinguish the implicit typedefs of C++ ! from explicit ones that might be found in C. */ ! && DECL_SOURCE_LINE (decl) == 0) { tree name = TYPE_NAME (type); *************** *** 1396,1400 **** IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); ! dbxout_finish_symbol (0); } --- 1478,1482 ---- IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); ! dbxout_finish_symbol (NULL_TREE); } *************** *** 1403,1416 **** IDENTIFIER_POINTER (DECL_NAME (decl))); - /* #ifndef DBX_NO_EXTRA_TAGS rms: I think this is no longer needed. */ - /* This section makes absolutely no sense to me. Why would a tag - ever be needed at this point? The result of this is that any - structure typedef with the tag omitted is treated as if the - tag was given to be the same as the typedef name. Probably - no harm in it, unless the programmer used the same name for - the tag of a *different* structure. At any rate, Alliant's - debugger would want the tag output before the typedef, so - this code still loses. -- hyc */ - /* Short cut way to output a tag also. */ if ((TREE_CODE (type) == RECORD_TYPE --- 1485,1488 ---- *************** *** 1418,1422 **** && TYPE_NAME (type) == decl) { ! if (use_gdb_dbx_extensions && have_used_extensions) { putc ('T', asmfile); --- 1490,1494 ---- && TYPE_NAME (type) == decl) { ! if (use_gnu_debug_info_extensions && have_used_extensions) { putc ('T', asmfile); *************** *** 1428,1432 **** #endif } - /* #endif */ putc ('t', asmfile); --- 1500,1503 ---- *************** *** 1435,1438 **** --- 1506,1510 ---- dbxout_type (type, 1, 0); dbxout_finish_symbol (decl); + did_output = 1; } *************** *** 1457,1461 **** IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); ! dbxout_finish_symbol (0); } --- 1529,1549 ---- IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); ! dbxout_finish_symbol (NULL_TREE); ! did_output = 1; ! } ! ! /* If an enum type has no name, it cannot be referred to, ! but we must output it anyway, since the enumeration constants ! can be referred to. */ ! if (!did_output && TREE_CODE (type) == ENUMERAL_TYPE) ! { ! current_sym_code = DBX_TYPE_DECL_STABS_CODE; ! current_sym_value = 0; ! current_sym_addr = 0; ! current_sym_nchars = 2; ! ! fprintf (asmfile, "%s \":T", ASM_STABS_OP); ! dbxout_type (type, 1, 0); ! dbxout_finish_symbol (NULL_TREE); } *************** *** 1477,1481 **** /* Don't mention a variable that is external. Let the file that defines it describe it. */ ! if (TREE_EXTERNAL (decl)) break; --- 1565,1569 ---- /* Don't mention a variable that is external. Let the file that defines it describe it. */ ! if (DECL_EXTERNAL (decl)) break; *************** *** 1495,1499 **** || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) { ! int ival = TREE_INT_CST_LOW (DECL_INITIAL (decl)); #ifdef DBX_OUTPUT_CONSTANT_SYMBOL DBX_OUTPUT_CONSTANT_SYMBOL (asmfile, name, ival); --- 1583,1587 ---- || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) { ! HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl)); #ifdef DBX_OUTPUT_CONSTANT_SYMBOL DBX_OUTPUT_CONSTANT_SYMBOL (asmfile, name, ival); *************** *** 1513,1517 **** } ! DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl)); #ifdef LEAF_REG_REMAP if (leaf_function) --- 1601,1605 ---- } ! DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, 0); #ifdef LEAF_REG_REMAP if (leaf_function) *************** *** 1529,1535 **** regno = REGNO (DECL_RTL (decl)); if (regno >= FIRST_PSEUDO_REGISTER) ! regno = reg_renumber[REGNO (DECL_RTL (decl))]; ! if (regno < 0) ! break; } else if (GET_CODE (DECL_RTL (decl)) == SUBREG) --- 1617,1621 ---- regno = REGNO (DECL_RTL (decl)); if (regno >= FIRST_PSEUDO_REGISTER) ! return; } else if (GET_CODE (DECL_RTL (decl)) == SUBREG) *************** *** 1546,1553 **** regno = REGNO (value); if (regno >= FIRST_PSEUDO_REGISTER) ! regno = reg_renumber[REGNO (value)]; ! if (regno >= 0) ! regno += offset; } } --- 1632,1639 ---- regno = REGNO (value); if (regno >= FIRST_PSEUDO_REGISTER) ! return; ! regno += offset; } + alter_subreg (DECL_RTL (decl)); } *************** *** 1601,1617 **** current_sym_value = DBX_REGISTER_NUMBER (regno); } - else if (GET_CODE (DECL_RTL (decl)) == SUBREG) - { - rtx value = DECL_RTL (decl); - int offset = 0; - while (GET_CODE (value) == SUBREG) - { - offset += SUBREG_WORD (value); - value = SUBREG_REG (value); - } - letter = 'r'; - current_sym_code = N_RSYM; - current_sym_value = DBX_REGISTER_NUMBER (REGNO (value) + offset); - } else if (GET_CODE (DECL_RTL (decl)) == MEM && (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM --- 1687,1690 ---- *************** *** 1788,1793 **** so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) ! = eliminate_regs (DECL_INCOMING_RTL (parms), 0, 0); ! DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, 0); #ifdef LEAF_REG_REMAP if (leaf_function) --- 1861,1866 ---- so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) ! = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX); ! DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX); #ifdef LEAF_REG_REMAP if (leaf_function) *************** *** 1907,1913 **** } else if (GET_CODE (DECL_RTL (parms)) == MEM ! && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG ! && rtx_equal_p (XEXP (DECL_RTL (parms), 0), ! DECL_INCOMING_RTL (parms))) { /* Parm was passed via invisible reference. --- 1980,1986 ---- } else if (GET_CODE (DECL_RTL (parms)) == MEM ! && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG) ! /* && rtx_equal_p (XEXP (DECL_RTL (parms), 0), ! DECL_INCOMING_RTL (parms))) */ { /* Parm was passed via invisible reference. *************** *** 2071,2074 **** --- 2144,2181 ---- dbxout_finish_symbol (parms); } + #if 0 + else if (GET_CODE (DECL_RTL (parms)) == MEM + && GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG) + { + /* Parm was passed via invisible reference. + That is, its address was passed in a register. + Output it as if it lived in that register. + The debugger will know from the type + that it was actually passed by invisible reference. */ + + current_sym_code = N_RSYM; + + /* DECL_RTL looks like (MEM (REG...). Get the register number. */ + current_sym_value = REGNO (XEXP (DECL_RTL (parms), 0)); + current_sym_addr = 0; + + FORCE_TEXT; + if (DECL_NAME (parms)) + { + current_sym_nchars = 2 + strlen (IDENTIFIER_POINTER (DECL_NAME (parms))); + + fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP, + IDENTIFIER_POINTER (DECL_NAME (parms))); + } + else + { + current_sym_nchars = 8; + fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP); + } + + dbxout_type (TREE_TYPE (parms), 0, 0); + dbxout_finish_symbol (parms); + } + #endif } } *************** *** 2179,2182 **** --- 2286,2293 ---- fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_LBRAC); assemble_name (asmfile, buf); + #if DBX_BLOCKS_FUNCTION_RELATIVE + fputc ('-', asmfile); + assemble_name (asmfile, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl))); + #endif fprintf (asmfile, "\n"); #endif *************** *** 2196,2200 **** /* Output the subblocks. */ ! dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, 0); /* Refer to the marker for the end of the block. */ --- 2307,2311 ---- /* Output the subblocks. */ ! dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE); /* Refer to the marker for the end of the block. */ *************** *** 2208,2211 **** --- 2319,2326 ---- fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_RBRAC); assemble_name (asmfile, buf); + #if DBX_BLOCKS_FUNCTION_RELATIVE + fputc ('-', asmfile); + assemble_name (asmfile, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl))); + #endif fprintf (asmfile, "\n"); #endif diff -rc2N gcc-2.2.2/defaults.h gcc-2.3.1/defaults.h *** gcc-2.2.2/defaults.h Thu May 28 15:28:29 1992 --- gcc-2.3.1/defaults.h Sat Aug 1 22:45:31 1992 *************** *** 23,26 **** --- 23,72 ---- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Store in OUTPUT a string (made with alloca) containing + an assembler-name for a local static variable or function named NAME. + LABELNO is an integer which is different for each call. */ + + #ifndef ASM_FORMAT_PRIVATE_NAME + #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ + do { \ + int len = strlen (NAME); \ + char *temp = (char *) alloca (len + 3); \ + temp[0] = 'L'; \ + strcpy (&temp[1], (NAME)); \ + temp[len + 1] = '.'; \ + temp[len + 2] = 0; \ + (OUTPUT) = (char *) alloca (strlen (NAME) + 11); \ + ASM_GENERATE_INTERNAL_LABEL (OUTPUT, temp, LABELNO); \ + } while (0) + #endif + + #ifndef ASM_STABD_OP + #define ASM_STABD_OP ".stabd" + #endif + + /* This is how to output an element of a case-vector that is absolute. + Some targets don't use this, but we have to define it anyway. */ + + #ifndef ASM_OUTPUT_ADDR_VEC_ELT + #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + do { fprintf (FILE, "\t%s\t", ASM_LONG); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, "L", (VALUE)); \ + fputc ('\n', FILE); \ + } while (0) + #endif + + /* This is how to output an element of a case-vector that is relative. + Some targets don't use this, but we have to define it anyway. */ + + #ifndef ASM_OUTPUT_ADDR_DIFF_ELT + #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + do { fprintf (FILE, "\t%s\t", ASM_SHORT); \ + ASM_GENERATE_INTERNAL_LABEL (FILE, "L", (VALUE)); \ + fputc ('-', FILE); \ + ASM_GENERATE_INTERNAL_LABEL (FILE, "L", (REL)); \ + fputc ('\n', FILE); \ + } while (0) + #endif + /* choose a reasonable default for ASM_OUTPUT_ASCII. */ diff -rc2N gcc-2.2.2/dostage2 gcc-2.3.1/dostage2 *** gcc-2.2.2/dostage2 Sun Dec 15 03:58:51 1991 --- gcc-2.3.1/dostage2 Mon Jun 29 00:59:24 1992 *************** *** 1,2 **** #!/bin/sh ! make -k LANGUAGES=c $1 CC=stage1/gcc XCFLAGS=-Bstage1/ CFLAGS="-g $2" >log2 2>&1 --- 1,2 ---- #!/bin/sh ! make -k LANGUAGES=c $1 CC=stage1/xgcc XCFLAGS=-Bstage1/ CFLAGS="-g $2" >log2 2>&1 diff -rc2N gcc-2.2.2/dostage3 gcc-2.3.1/dostage3 *** gcc-2.2.2/dostage3 Tue Dec 24 17:29:41 1991 --- gcc-2.3.1/dostage3 Fri Sep 18 19:59:45 1992 *************** *** 1,3 **** #!/bin/sh ! make -k $1 CC=stage2/gcc XCFLAGS=-Bstage2/ CFLAGS="-g $2" >log3 2>&1 --- 1,3 ---- #!/bin/sh ! make -k LANGUAGES=c $1 CC=stage2/xgcc XCFLAGS=-Bstage2/ CFLAGS="-g $2" >log3 2>&1 diff -rc2N gcc-2.2.2/dwarf.h gcc-2.3.1/dwarf.h *** gcc-2.2.2/dwarf.h Mon Apr 27 16:49:33 1992 --- gcc-2.3.1/dwarf.h Wed Oct 7 16:23:38 1992 *************** *** 78,82 **** #define TAG_lo_user 0x8000 /* implementation-defined range start */ #define TAG_hi_user 0xffff /* implementation-defined range end */ ! #define TAG_source_file TAG_compile_unit /* for backward compatability */ /* Form names and codes. */ --- 78,82 ---- #define TAG_lo_user 0x8000 /* implementation-defined range start */ #define TAG_hi_user 0xffff /* implementation-defined range end */ ! #define TAG_source_file TAG_compile_unit /* for backward compatibility */ /* Form names and codes. */ *************** *** 149,153 **** AT_pure_virtual = (0x0290|FORM_STRING), AT_return_addr = (0x02a0|FORM_BLOCK2), ! AT_specification = (0x02b0|FORM_REF), AT_start_scope = (0x02c0|FORM_DATA4), AT_stride_size = (0x02e0|FORM_DATA4), --- 149,153 ---- AT_pure_virtual = (0x0290|FORM_STRING), AT_return_addr = (0x02a0|FORM_BLOCK2), ! AT_abstract_origin = (0x02b0|FORM_REF), AT_start_scope = (0x02c0|FORM_DATA4), AT_stride_size = (0x02e0|FORM_DATA4), *************** *** 163,167 **** AT_src_info = (0x8010|FORM_DATA4), AT_mac_info = (0x8020|FORM_DATA4), ! AT_src_coords = (0x8030|FORM_DATA4) }; --- 163,169 ---- AT_src_info = (0x8010|FORM_DATA4), AT_mac_info = (0x8020|FORM_DATA4), ! AT_src_coords = (0x8030|FORM_DATA4), ! AT_body_begin = (0x8040|FORM_ADDR), ! AT_body_end = (0x8050|FORM_ADDR) }; diff -rc2N gcc-2.2.2/dwarfout.c gcc-2.3.1/dwarfout.c *** gcc-2.2.2/dwarfout.c Sun May 31 01:08:49 1992 --- gcc-2.3.1/dwarfout.c Thu Oct 29 05:47:27 1992 *************** *** 29,32 **** --- 29,33 ---- #include "flags.h" #include "rtl.h" + #include "hard-reg-set.h" #include "insn-config.h" #include "reload.h" *************** *** 39,43 **** /* #define NDEBUG 1 */ ! #include #if defined(DWARF_TIMESTAMPS) --- 40,44 ---- /* #define NDEBUG 1 */ ! #include "assert.h" #if defined(DWARF_TIMESTAMPS) *************** *** 54,66 **** #endif /* defined(DWARF_TIMESTAMPS) */ - #if defined(USG) || defined(POSIX) - #include - #else - #include - #define strrchr rindex - #endif - extern char *getpwd (); /* IMPORTANT NOTE: Please see the file README.DWARF for important details regarding the GNU implementation of Dwarf. */ --- 55,63 ---- #endif /* defined(DWARF_TIMESTAMPS) */ extern char *getpwd (); + extern char *index (); + extern char *rindex (); + /* IMPORTANT NOTE: Please see the file README.DWARF for important details regarding the GNU implementation of Dwarf. */ *************** *** 85,94 **** #endif ! /* Define a macro which, when given a pointer to some BLOCK node, returns ! a pointer to the FUNCTION_DECL node from which the given BLOCK node ! was instantiated (as an inline expansion). This macro needs to be ! defined properly in tree.h, however for the moment, we just fake it. */ ! ! #define BLOCK_INLINE_FUNCTION(block) 0 /* Define a macro which returns non-zero for any tagged type which is --- 82,90 ---- #endif ! /* How to print out a register name. */ ! #ifndef PRINT_REG ! #define PRINT_REG(RTX, CODE, FILE) \ ! fprintf ((FILE), "%s", reg_names[REGNO (RTX)]) ! #endif /* Define a macro which returns non-zero for any tagged type which is *************** *** 289,292 **** --- 285,295 ---- static unsigned current_funcdef_number = 1; + /* A pointer to the ..._DECL node which we have most recently been working + on. We keep this around just in case something about it looks screwy + and we want to tell the user what the source coordinates for the actual + declaration are. */ + + static tree dwarf_last_decl; + /* Forward declarations for functions defined in this file. */ *************** *** 530,533 **** --- 533,542 ---- #define SL_END_LABEL_FMT ".L_sl%u_e" #endif + #ifndef BODY_BEGIN_LABEL_FMT + #define BODY_BEGIN_LABEL_FMT ".L_b%u" + #endif + #ifndef BODY_END_LABEL_FMT + #define BODY_END_LABEL_FMT ".L_b%u_e" + #endif #ifndef FUNC_END_LABEL_FMT #define FUNC_END_LABEL_FMT ".L_f%u_e" *************** *** 536,539 **** --- 545,551 ---- #define TYPE_NAME_FMT ".L_T%u" #endif + #ifndef DECL_NAME_FMT + #define DECL_NAME_FMT ".L_E%u" + #endif #ifndef LINE_CODE_LABEL_FMT #define LINE_CODE_LABEL_FMT ".L_LC%u" *************** *** 751,754 **** --- 763,777 ---- } + /* Return non-zero if the given type node represents a tagged type. */ + + inline int + is_tagged_type (type) + register tree type; + { + register enum tree_code code = TREE_CODE (type); + + return (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE); + } + static char * dwarf_tag_name (tag) *************** *** 797,801 **** case TAG_class_template: return "TAG_class_template"; ! default: return ""; } } --- 820,824 ---- case TAG_class_template: return "TAG_class_template"; ! default: return "TAG_"; } } *************** *** 857,861 **** case AT_pure_virtual: return "AT_pure_virtual"; case AT_return_addr: return "AT_return_addr"; ! case AT_specification: return "AT_specification"; case AT_start_scope: return "AT_start_scope"; case AT_stride_size: return "AT_stride_size"; --- 880,884 ---- case AT_pure_virtual: return "AT_pure_virtual"; case AT_return_addr: return "AT_return_addr"; ! case AT_abstract_origin: return "AT_abstract_origin"; case AT_start_scope: return "AT_start_scope"; case AT_stride_size: return "AT_stride_size"; *************** *** 872,877 **** case AT_mac_info: return "AT_mac_info"; case AT_src_coords: return "AT_src_coords"; ! default: return ""; } } --- 895,902 ---- case AT_mac_info: return "AT_mac_info"; case AT_src_coords: return "AT_src_coords"; + case AT_body_begin: return "AT_body_begin"; + case AT_body_end: return "AT_body_end"; ! default: return "AT_"; } } *************** *** 890,894 **** case OP_DEREF4: return "OP_DEREF4"; case OP_ADD: return "OP_ADD"; ! default: return ""; } } --- 915,919 ---- case OP_DEREF4: return "OP_DEREF4"; case OP_ADD: return "OP_ADD"; ! default: return "OP_"; } } *************** *** 904,908 **** case MOD_const: return "MOD_const"; case MOD_volatile: return "MOD_volatile"; ! default: return ""; } } --- 929,933 ---- case MOD_const: return "MOD_const"; case MOD_volatile: return "MOD_volatile"; ! default: return "MOD_"; } } *************** *** 923,927 **** case FMT_UT_X_X: return "FMT_UT_X_X"; case FMT_ET: return "FMT_ET"; ! default: return ""; } } --- 948,952 ---- case FMT_UT_X_X: return "FMT_UT_X_X"; case FMT_ET: return "FMT_ET"; ! default: return "FMT_"; } } *************** *** 979,988 **** case FT_real128: return "FT_real128"; ! default: return ""; } } /**************** utility functions for attribute functions ******************/ /* Given a pointer to a tree node for some type, return a Dwarf fundamental type code for the given type. --- 1004,1158 ---- case FT_real128: return "FT_real128"; ! default: return "FT_"; ! } ! } ! ! /* Determine the "ultimate origin" of a decl. The decl may be an ! inlined instance of an inlined instance of a decl which is local ! to an inline function, so we have to trace all of the way back ! through the origin chain to find out what sort of node actually ! served as the original seed for the given block. */ ! ! static tree ! decl_ultimate_origin (decl) ! register tree decl; ! { ! register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl); ! ! if (immediate_origin == NULL) ! return NULL; ! else ! { ! register tree ret_val; ! register tree lookahead = immediate_origin; ! ! do ! { ! ret_val = lookahead; ! lookahead = DECL_ABSTRACT_ORIGIN (ret_val); ! } ! while (lookahead != NULL && lookahead != ret_val); ! return ret_val; ! } ! } ! ! /* Determine the "ultimate origin" of a block. The block may be an ! inlined instance of an inlined instance of a block which is local ! to an inline function, so we have to trace all of the way back ! through the origin chain to find out what sort of node actually ! served as the original seed for the given block. */ ! ! static tree ! block_ultimate_origin (block) ! register tree block; ! { ! register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); ! ! if (immediate_origin == NULL) ! return NULL; ! else ! { ! register tree ret_val; ! register tree lookahead = immediate_origin; ! ! do ! { ! ret_val = lookahead; ! lookahead = (TREE_CODE (ret_val) == BLOCK) ! ? BLOCK_ABSTRACT_ORIGIN (ret_val) ! : NULL; ! } ! while (lookahead != NULL && lookahead != ret_val); ! return ret_val; ! } ! } ! ! static void ! output_unsigned_leb128 (value) ! register unsigned long value; ! { ! register unsigned long orig_value = value; ! ! do ! { ! register unsigned byte = (value & 0x7f); ! ! value >>= 7; ! if (value != 0) /* more bytes to follow */ ! byte |= 0x80; ! fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte); ! if (flag_verbose_asm && value == 0) ! fprintf (asm_out_file, "\t%s ULEB128 number - value = %u", ! ASM_COMMENT_START, orig_value); ! fputc ('\n', asm_out_file); ! } ! while (value != 0); ! } ! ! static void ! output_signed_leb128 (value) ! register long value; ! { ! register long orig_value = value; ! register int negative = (value < 0); ! register int more; ! ! do ! { ! register unsigned byte = (value & 0x7f); ! ! value >>= 7; ! if (negative) ! value |= 0xfe000000; /* manually sign extend */ ! if (((value == 0) && ((byte & 0x40) == 0)) ! || ((value == -1) && ((byte & 0x40) == 1))) ! more = 0; ! else ! { ! byte |= 0x80; ! more = 1; ! } ! fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte); ! if (flag_verbose_asm && more == 0) ! fprintf (asm_out_file, "\t%s SLEB128 number - value = %d", ! ASM_COMMENT_START, orig_value); ! fputc ('\n', asm_out_file); } + while (more); } /**************** utility functions for attribute functions ******************/ + /* Given a pointer to a BLOCK node return non-zero if (and only if) the + node in question represents the outermost pair of curly braces (i.e. + the "body block") of a function or method. + + For any BLOCK node representing a "body block" of a function or method, + the BLOCK_SUPERCONTEXT of the node will point to another BLOCK node + which represents the outermost (function) scope for the function or + method (i.e. the one which includes the formal parameters). The + BLOCK_SUPERCONTEXT of *that* node in turn will point to the relevant + FUNCTION_DECL node. + */ + + inline int + is_body_block (stmt) + register tree stmt; + { + if (TREE_CODE (stmt) == BLOCK) + { + register tree parent = BLOCK_SUPERCONTEXT (stmt); + + if (TREE_CODE (parent) == BLOCK) + { + register tree grandparent = BLOCK_SUPERCONTEXT (parent); + + if (TREE_CODE (grandparent) == FUNCTION_DECL) + return 1; + } + } + return 0; + } + /* Given a pointer to a tree node for some type, return a Dwarf fundamental type code for the given type. *************** *** 993,1004 **** The current Dwarf draft specification calls for Dwarf fundamental types to accurately reflect the fact that a given type was either a "plain" ! integral type or an explicitly "signed" integral type. Unfortuantely, we can't always do this, because GCC may already have thrown away the information about the precise way in which the type was originally specified, as in: ! typedef signed int field_type; ! struct s { field_type f; }; Since we may be stuck here without enought information to do exactly --- 1163,1174 ---- The current Dwarf draft specification calls for Dwarf fundamental types to accurately reflect the fact that a given type was either a "plain" ! integral type or an explicitly "signed" integral type. Unfortunately, we can't always do this, because GCC may already have thrown away the information about the precise way in which the type was originally specified, as in: ! typedef signed int my_type; ! struct s { my_type f; }; Since we may be stuck here without enought information to do exactly *************** *** 1227,1233 **** } /* Given a pointer to some ..._TYPE tree node, generate an assembly language ! equate directive which will associate an easily remembered symbolic name ! with the current DIE. The name used is an artificial label generated from the TYPE_UID number --- 1397,1434 ---- } + /* Given a pointer to some ..._DECL tree node, generate an assembly language + equate directive which will associate a symbolic name with the current DIE. + + The name used is an artificial label generated from the DECL_UID number + associated with the given decl node. The name it gets equated to is the + symbolic label that we (previously) output at the start of the DIE that + we are currently generating. + + Calling this function while generating some "decl related" form of DIE + makes it possible to later refer to the DIE which represents the given + decl simply by re-generating the symbolic name from the ..._DECL node's + UID number. */ + + static void + equate_decl_number_to_die_number (decl) + register tree decl; + { + /* In the case where we are generating a DIE for some ..._DECL node + which represents either some inline function declaration or some + entity declared within an inline function declaration/definition, + setup a symbolic name for the current DIE so that we have a name + for this DIE that we can easily refer to later on within + AT_abstract_origin attributes. */ + + char decl_label[MAX_ARTIFICIAL_LABEL_BYTES]; + char die_label[MAX_ARTIFICIAL_LABEL_BYTES]; + + sprintf (decl_label, DECL_NAME_FMT, DECL_UID (decl)); + sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum); + ASM_OUTPUT_DEF (asm_out_file, decl_label, die_label); + } + /* Given a pointer to some ..._TYPE tree node, generate an assembly language ! equate directive which will associate a symbolic name with the current DIE. The name used is an artificial label generated from the TYPE_UID number *************** *** 1260,1263 **** --- 1461,1486 ---- } + static void + output_reg_number (rtl) + register rtx rtl; + { + register unsigned regno = REGNO (rtl); + + if (regno >= FIRST_PSEUDO_REGISTER) + { + warning_with_decl (dwarf_last_decl, "internal regno botch: regno = %d\n", + regno); + regno = 0; + } + fprintf (asm_out_file, "\t%s\t0x%x", + UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno)); + if (flag_verbose_asm) + { + fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START); + PRINT_REG (rtl, 0, asm_out_file); + } + fputc ('\n', asm_out_file); + } + /* The following routine is a nice and simple transducer. It converts the RTL for a variable or parameter (resident in memory) into an equivalent *************** *** 1296,1308 **** /* Whenever a register number forms a part of the description of the method for calculating the (dynamic) address of a memory ! resident object, Dwarf rules require the register number to be referred to as a "base register". This distinction is not based in any way upon what category of register the hardware believes the given register belongs to. This is strictly ! Dwarf terminology we're dealing with here. */ ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_BASEREG); ! ASM_OUTPUT_DWARF_DATA4 (asm_out_file, ! DBX_REGISTER_NUMBER (REGNO (rtl))); break; --- 1519,1541 ---- /* Whenever a register number forms a part of the description of the method for calculating the (dynamic) address of a memory ! resident object, DWARF rules require the register number to be referred to as a "base register". This distinction is not based in any way upon what category of register the hardware believes the given register belongs to. This is strictly ! DWARF terminology we're dealing with here. + Note that in cases where the location of a memory-resident data + object could be expressed as: + + OP_ADD (OP_BASEREG (basereg), OP_CONST (0)) + + the actual DWARF location descriptor that we generate may just + be OP_BASEREG (basereg). This may look deceptively like the + object in question was allocated to a register (rather than + in memory) so DWARF consumers need to be aware of the subtle + distinction between OP_REG and OP_BASEREG. */ + ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_BASEREG); ! output_reg_number (rtl); break; *************** *** 1359,1364 **** case REG: ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_REG); ! ASM_OUTPUT_DWARF_DATA4 (asm_out_file, ! DBX_REGISTER_NUMBER (REGNO (rtl))); break; --- 1592,1596 ---- case REG: ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_REG); ! output_reg_number (rtl); break; *************** *** 1449,1453 **** if (! optimize) output_loc_descriptor ! (eliminate_regs (SAVE_EXPR_RTL (bound), 0, 0)); ASM_OUTPUT_LABEL (asm_out_file, end_label); --- 1681,1685 ---- if (! optimize) output_loc_descriptor ! (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX)); ASM_OUTPUT_LABEL (asm_out_file, end_label); *************** *** 1478,1481 **** --- 1710,1895 ---- } + /* Given an unsigned value, round it up to the lowest multiple of `boundary' + which is not less than the value itself. */ + + inline unsigned + ceiling (value, boundary) + register unsigned value; + register unsigned boundary; + { + return (((value + boundary - 1) / boundary) * boundary); + } + + /* Given a pointer to what is assumed to be a FIELD_DECL node, return a + pointer to the declared type for the relevant field variable, or return + `integer_type_node' if the given node turns out to be an ERROR_MARK node. */ + + inline tree + field_type (decl) + register tree decl; + { + register tree type; + + if (TREE_CODE (decl) == ERROR_MARK) + return integer_type_node; + + type = DECL_BIT_FIELD_TYPE (decl); + if (type == NULL) + type = TREE_TYPE (decl); + return type; + } + + /* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE + node, return the alignment in bits for the type, or else return + BITS_PER_WORD if the node actually turns out to be an ERROR_MARK node. */ + + inline unsigned + simple_type_align_in_bits (type) + register tree type; + { + return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD; + } + + /* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE + node, return the size in bits for the type if it is a constant, or + else return the alignment for the type if the type's size is not + constant, or else return BITS_PER_WORD if the type actually turns out + to be an ERROR_MARK node. */ + + inline unsigned + simple_type_size_in_bits (type) + register tree type; + { + if (TREE_CODE (type) == ERROR_MARK) + return BITS_PER_WORD; + else + { + register tree type_size_tree = TYPE_SIZE (type); + + if (TREE_CODE (type_size_tree) != INTEGER_CST) + return TYPE_ALIGN (type); + + return (unsigned) TREE_INT_CST_LOW (type_size_tree); + } + } + + /* Given a pointer to what is assumed to be a FIELD_DECL node, compute and + return the byte offset of the lowest addressed byte of the "containing + object" for the given FIELD_DECL, or return 0 if we are unable to deter- + mine what that offset is, either because the argument turns out to be a + pointer to an ERROR_MARK node, or because the offset is actually variable. + (We can't handle the latter case just yet.) */ + + static unsigned + field_byte_offset (decl) + register tree decl; + { + register unsigned type_align_in_bytes; + register unsigned type_align_in_bits; + register unsigned type_size_in_bits; + register unsigned object_offset_in_align_units; + register unsigned object_offset_in_bits; + register unsigned object_offset_in_bytes; + register tree type; + register tree bitpos_tree; + register tree field_size_tree; + register unsigned bitpos_int; + register unsigned deepest_bitpos; + register unsigned field_size_in_bits; + + if (TREE_CODE (decl) == ERROR_MARK) + return 0; + + if (TREE_CODE (decl) != FIELD_DECL) + abort (); + + type = field_type (decl); + + bitpos_tree = DECL_FIELD_BITPOS (decl); + field_size_tree = DECL_SIZE (decl); + + /* We cannot yet cope with fields whose positions or sizes are variable, + so for now, when we see such things, we simply return 0. Someday, + we may be able to handle such cases, but it will be damn difficult. */ + + if (TREE_CODE (bitpos_tree) != INTEGER_CST) + return 0; + bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree); + + if (TREE_CODE (field_size_tree) != INTEGER_CST) + return 0; + field_size_in_bits = (unsigned) TREE_INT_CST_LOW (field_size_tree); + + type_size_in_bits = simple_type_size_in_bits (type); + + type_align_in_bits = simple_type_align_in_bits (type); + type_align_in_bytes = type_align_in_bits / BITS_PER_UNIT; + + /* Note that the GCC front-end doesn't make any attempt to keep track + of the starting bit offset (relative to the start of the containing + structure type) of the hypothetical "containing object" for a bit- + field. Thus, when computing the byte offset value for the start of + the "containing object" of a bit-field, we must deduce this infor- + mation on our own. + + This can be rather tricky to do in some cases. For example, handling + the following structure type definition when compiling for an i386/i486 + target (which only aligns long long's to 32-bit boundaries) can be very + tricky: + + struct S { + int field1; + long long field2:31; + }; + + Fortunately, there is a simple rule-of-thumb which can be used in such + cases. When compiling for an i386/i486, GCC will allocate 8 bytes for + the structure shown above. It decides to do this based upon one simple + rule for bit-field allocation. Quite simply, GCC allocates each "con- + taining object" for each bit-field at the first (i.e. lowest addressed) + legitimate alignment boundary (based upon the required minimum alignment + for the declared type of the field) which it can possibly use, subject + to the condition that there is still enough available space remaining + in the containing object (when allocated at the selected point) to + fully accomodate all of the bits of the bit-field itself. + + This simple rule makes it obvious why GCC allocates 8 bytes for each + object of the structure type shown above. When looking for a place to + allocate the "containing object" for `field2', the compiler simply tries + to allocate a 64-bit "containing object" at each successive 32-bit + boundary (starting at zero) until it finds a place to allocate that 64- + bit field such that at least 31 contiguous (and previously unallocated) + bits remain within that selected 64 bit field. (As it turns out, for + the example above, the compiler finds that it is OK to allocate the + "containing object" 64-bit field at bit-offset zero within the + structure type.) + + Here we attempt to work backwards from the limited set of facts we're + given, and we try to deduce from those facts, where GCC must have + believed that the containing object started (within the structure type). + + The value we deduce is then used (by the callers of this routine) to + generate AT_location and AT_bit_offset attributes for fields (both + bit-fields and, in the case of AT_location, regular fields as well). + */ + + /* Figure out the bit-distance from the start of the structure to the + "deepest" bit of the bit-field. */ + deepest_bitpos = bitpos_int + field_size_in_bits; + + /* This is the tricky part. Use some fancy footwork to deduce where the + lowest addressed bit of the containing object must be. */ + object_offset_in_bits + = ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits; + + /* Compute the offset of the containing object in "alignment units". */ + object_offset_in_align_units = object_offset_in_bits / type_align_in_bits; + + /* Compute the offset of the containing object in bytes. */ + object_offset_in_bytes = object_offset_in_align_units * type_align_in_bytes; + + return object_offset_in_bytes; + } + /****************************** attributes *********************************/ *************** *** 1517,1528 **** for a variable or parameter which has been optimized out of existence, don't do that. Instead we output a zero-length location descriptor ! value as part of the location attribute. Note that we cannot simply ! suppress the entire location attribute, because the absence of a ! location attribute in certain kinds of DIEs is used to indicate some- ! thing entirely different... i.e. that the DIE represents an object ! declaration, but not a definition. So sayeth the PLSIG. */ ! if (! is_pseudo_reg (rtl)) ! output_loc_descriptor (eliminate_regs (rtl, 0, 0)); ASM_OUTPUT_LABEL (asm_out_file, end_label); --- 1931,1956 ---- for a variable or parameter which has been optimized out of existence, don't do that. Instead we output a zero-length location descriptor ! value as part of the location attribute. ! ! A variable which has been optimized out of existance will have a ! DECL_RTL value which denotes a pseudo-reg. ! ! Currently, in some rare cases, variables can have DECL_RTL values ! which look like (MEM (REG pseudo-reg#)). These cases are due to ! bugs elsewhere in the compiler. We treat such cases ! as if the variable(s) in question had been optimized out of existance. ! ! Note that in all cases where we wish to express the fact that a ! variable has been optimized out of existance, we do not simply ! suppress the generation of the entire location attribute because ! the absence of a location attribute in certain kinds of DIEs is ! used to indicate something else entirely... i.e. that the DIE ! represents an object declaration, but not a definition. So sayeth ! the PLSIG. ! */ ! if (! is_pseudo_reg (rtl) ! && (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0)))) ! output_loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX)); ASM_OUTPUT_LABEL (asm_out_file, end_label); *************** *** 1530,1534 **** /* Output the specialized form of location attribute used for data members ! of struct types. In the special case of a FIELD_DECL node which represents a bit-field, --- 1958,1962 ---- /* Output the specialized form of location attribute used for data members ! of struct and union types. In the special case of a FIELD_DECL node which represents a bit-field, *************** *** 1536,1585 **** distance in bytes from the lowest-addressed byte of the containing struct or union type to the lowest-addressed byte of the "containing ! object" for the bit-field. For any given bit-field, the "containing object" is a hypothetical object (of some integral or enum type) within which the given bit-field lives. The type of this hypothetical "containing object" is always the ! same as the declared type of the individual bit-field itself. Note that it is the size (in bytes) of the hypothetical "containing object" which will be given in the AT_byte_size attribute for this ! bit-field. (See the `byte_size_attribute' function below.) */ - static void data_member_location_attribute (decl) register tree decl; { char begin_label[MAX_ARTIFICIAL_LABEL_BYTES]; char end_label[MAX_ARTIFICIAL_LABEL_BYTES]; - register unsigned type_align_in_bytes; - register unsigned type_align_in_bits; - register unsigned offset_in_align_units; - register unsigned offset_in_bytes; - register tree type; - register tree bitpos_tree = DECL_FIELD_BITPOS (decl); - register unsigned bitpos_int; - - if (TREE_CODE (decl) == ERROR_MARK) - return; - - if (TREE_CODE (decl) != FIELD_DECL) - abort (); - - /* The bit position given by DECL_FIELD_BITPOS could be non-constant - in the case where one or more variable sized members preceeded this - member in the containing struct type. We could probably correctly - handle this case someday, by it's too complicated to deal with at - the moment (and probably too rare to worry about), so just punt on - the whole AT_location attribute for now. Eventually, we'll have - to analyze the expression given as the DECL_FIELD_BITPOS and turn - it into a member-style AT_location descriptor, but that'll be - tough to do. -- rfg */ - - if (TREE_CODE (bitpos_tree) != INTEGER_CST) - return; - bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree); ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location); --- 1964,1989 ---- distance in bytes from the lowest-addressed byte of the containing struct or union type to the lowest-addressed byte of the "containing ! object" for the bit-field. (See the `field_byte_offset' function above.) For any given bit-field, the "containing object" is a hypothetical object (of some integral or enum type) within which the given bit-field lives. The type of this hypothetical "containing object" is always the ! same as the declared type of the individual bit-field itself (for GCC ! anyway... the DWARF spec doesn't actually mandate this). Note that it is the size (in bytes) of the hypothetical "containing object" which will be given in the AT_byte_size attribute for this ! bit-field. (See the `byte_size_attribute' function below.) It is ! also used when calculating the value of the AT_bit_offset attribute. ! (See the `bit_offset_attribute' function below.) */ static void data_member_location_attribute (decl) register tree decl; { + register unsigned object_offset_in_bytes = field_byte_offset (decl); char begin_label[MAX_ARTIFICIAL_LABEL_BYTES]; char end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location); *************** *** 1589,1691 **** ASM_OUTPUT_LABEL (asm_out_file, begin_label); ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST); ! ! type = DECL_BIT_FIELD_TYPE (decl); ! if (type == NULL) ! type = TREE_TYPE (decl); ! ! type_align_in_bits = TYPE_ALIGN (type); ! type_align_in_bytes = type_align_in_bits / BITS_PER_UNIT; ! ! /* WARNING! Note that the GCC front-end doesn't make any attempt to ! keep track of the starting bit offset (relative to the start of ! the containing structure type) of the hypothetical "containing ! object" for a bit-field. (See the comments at the start of this ! function.) Thus, when computing the byte offset value for a ! bit-field, all we can do is to divide the starting bit offset of ! the bit-field by the alignment of the hypothetical "containing ! object" (which we can easily find) and then multiply by the number ! of bytes of that alignment. ! ! This solution only yields an unambiguously correct result when ! the size of the bit-field is strictly larger than the size of the ! declared type minus the alignment of the declared type. When this ! condition is not satisfied, it means that there is at least an ! "alignment unit's" worth of other slop which co-resides within the ! hypothetical "containing object" with the bit field, and this other ! slop could be either to the left of the bit-field or to the right ! of the bit-field. (We have no way of knowing which.) ! ! It also means that we cannot unambiguously tell exactly where the ! hypothetical "containing object" begins within the containing struct ! type. We only know the precise position of the bit-field which is ! contained therein, and that the hypothetical containing object must ! be aligned as required for its type. But when there is at least an ! alignment unit's worth of slop co-resident in the containing object ! with the actual bit-field, the actual start of the containing object ! is ambiguous and thus, we cannot unambiguously determine the "correct" ! byte offset to put into the AT_location attribute for the bit-field ! itself. ! ! This whole thing is a non-issue for the majority of targets, because ! (for most GCC targets) the alignment of each supported integral type ! is the same as the size of that type, and thus (size - alignment) for ! the declared type of any bit-field yields zero, and the size (in bits) ! of any bit-field must be bigger than zero, so there is never any ! ambiguity about the starting positions of the containing objects of ! bit-fields for most GCC targets. ! ! An exception arises however for some machines (e.g. i386) which have ! BIGGEST_ALIGNMENT set to something less than the size of type `long ! long' (i.e. 64) and when we are confronted with something like: ! ! struct S { ! int field1; ! long long field2:31; ! }; ! ! Here it is ambiguous (going by DWARF rules anyway) whether the con- ! taining `long long' object for `field2' should be said to occupy the ! first and second (32-bit) words of the containing struct type, or ! whether it should be said to occupy the second and third words of ! the struct type. ! ! Currently, GCC allocates 8 bytes (for an i386 target) for each object ! of the above type. This is probably a bug however, and GCC should ! probably be allocating 12 bytes for each such structure (for the i386 ! target). ! ! Assuming this bug gets fixed, one would have a strong case for saying ! that the containing `long long' object for `field2' occupies the second ! and third words of the above structure type, and that `field2' itself ! occupies the first 31 bits of that containing object. However consider: ! ! struct S { ! int field1; ! long long field2:31; ! long long field3:2; ! long long field4:31; ! }; ! ! Even if the current "member allocation" bug in GCC is fixed, this ex- ! ample would still illustrate a case in which the starting point of the ! containing `long long' object for `field4' would be ambiguous, even ! though we know the exact starting bit offset (within the structure) of ! the `field4' bit-field itself. ! ! We essentially just ignore this whole issue here and always act as if ! most of the slop which co-resides in a containing object along with a ! bit-field appears in that containing object *AFTER* the bit field. ! Thus, for the above example, we say that the containing object for ! `field4' occupies the third and fourth words of the structure type, ! even though objects of the type only occupy three words. As long ! as the debugger understands that the compiler uses this disambiguation ! rule, the debugger should easily be able to do the Right Thing in all ! cases. ! */ ! ! offset_in_align_units = bitpos_int / type_align_in_bits; ! offset_in_bytes = offset_in_align_units * type_align_in_bytes; ! ! ASM_OUTPUT_DWARF_DATA4 (asm_out_file, offset_in_bytes); ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADD); ASM_OUTPUT_LABEL (asm_out_file, end_label); --- 1993,1997 ---- ASM_OUTPUT_LABEL (asm_out_file, begin_label); ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST); ! ASM_OUTPUT_DWARF_DATA4 (asm_out_file, object_offset_in_bytes); ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADD); ASM_OUTPUT_LABEL (asm_out_file, end_label); *************** *** 1734,1739 **** ASM_OUTPUT_DWARF_DATA8 (asm_out_file, ! (unsigned) CONST_DOUBLE_HIGH (rtl), ! (unsigned) CONST_DOUBLE_LOW (rtl)); break; --- 2040,2045 ---- ASM_OUTPUT_DWARF_DATA8 (asm_out_file, ! (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (rtl), ! (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (rtl)); break; *************** *** 1763,1766 **** --- 2069,2075 ---- FORM_BLOCK4 and a length of zero. */ break; + + default: + abort (); /* No other kinds of rtx should be possible here. */ } *************** *** 1795,1799 **** formal parameters to reflect either the place where the parameters get passed (if they are passed on the stack and in memory) or else the ! (preserved) registers which the paramaters get copied to during the function prologue. --- 2104,2108 ---- formal parameters to reflect either the place where the parameters get passed (if they are passed on the stack and in memory) or else the ! (preserved) registers which the parameters get copied to during the function prologue. *************** *** 1951,1954 **** --- 2260,2264 ---- } + #ifdef USE_ORDERING_ATTRIBUTE inline void ordering_attribute (ordering) *************** *** 1958,1961 **** --- 2268,2272 ---- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, ordering); } + #endif /* defined(USE_ORDERING_ATTRIBUTE) */ /* Note that the block of subscript information for an array type also *************** *** 2085,2094 **** case FIELD_DECL: /* For a data member of a struct or union, the AT_byte_size is ! always given as the number of bytes normally allocated for an object of the *declared* type of the member itself. This is true even for bit-fields. */ ! size = int_size_in_bytes (DECL_BIT_FIELD_TYPE (tree_node) ! ? DECL_BIT_FIELD_TYPE (tree_node) ! : TREE_TYPE (tree_node)); break; --- 2396,2404 ---- case FIELD_DECL: /* For a data member of a struct or union, the AT_byte_size is ! generally given as the number of bytes normally allocated for an object of the *declared* type of the member itself. This is true even for bit-fields. */ ! size = simple_type_size_in_bits (field_type (tree_node)) ! / BITS_PER_UNIT; break; *************** *** 2115,2118 **** --- 2425,2432 ---- same as the declared type of the individual bit-field itself. + The determination of the exact location of the "containing object" for + a bit-field is rather complicated. It's handled by the `field_byte_offset' + function (above). + Note that it is the size (in bytes) of the hypothetical "containing object" which will be given in the AT_byte_size attribute for this *************** *** 2124,2143 **** register tree decl; { register tree type = DECL_BIT_FIELD_TYPE (decl); - register unsigned dwarf_bit_offset; register tree bitpos_tree = DECL_FIELD_BITPOS (decl); register unsigned bitpos_int; assert (TREE_CODE (decl) == FIELD_DECL); /* Must be a field. */ assert (type); /* Must be a bit field. */ ! /* The bit position given by DECL_FIELD_BITPOS could be non-constant ! in the case where one or more variable sized members preceeded this ! member in the containing struct type. We could probably correctly ! handle this case someday, by it's too complicated to deal with at ! the moment, so just punt on the whole AT_bit_offset attribute for ! now. Eventually, we'll have to analyze the (variable) expression ! given as the DECL_FIELD_BITPOS and see if we can factor out just ! the (constant) bit offset part of that expression. -- rfg */ if (TREE_CODE (bitpos_tree) != INTEGER_CST) --- 2438,2455 ---- register tree decl; { + register unsigned object_offset_in_bytes = field_byte_offset (decl); register tree type = DECL_BIT_FIELD_TYPE (decl); register tree bitpos_tree = DECL_FIELD_BITPOS (decl); register unsigned bitpos_int; + register unsigned highest_order_object_bit_offset; + register unsigned highest_order_field_bit_offset; + register unsigned bit_offset; assert (TREE_CODE (decl) == FIELD_DECL); /* Must be a field. */ assert (type); /* Must be a bit field. */ ! /* We can't yet handle bit-fields whose offsets are variable, so if we ! encounter such things, just return without generating any attribute ! whatsoever. */ if (TREE_CODE (bitpos_tree) != INTEGER_CST) *************** *** 2145,2172 **** bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree); ! /* For a detailed description of how the AT_bit_offset attribute value ! is calculated, see the comments in `data_member_location_attribute' ! above. */ ! ! #if (BYTES_BIG_ENDIAN == 1) ! dwarf_bit_offset = bitpos_int % TYPE_ALIGN (type); ! #else ! { ! register unsigned high_order_bitpos ! = bitpos_int + (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl)); ! register tree type_size_tree = TYPE_SIZE (type); ! register unsigned type_size_in_bits; ! ! if (TREE_CODE (type_size_tree) != INTEGER_CST) ! abort (); ! type_size_in_bits = (unsigned) TREE_INT_CST_LOW (type_size_tree); ! ! dwarf_bit_offset = type_size_in_bits ! - (high_order_bitpos % TYPE_ALIGN (type)); ! } ! #endif ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_offset); ! ASM_OUTPUT_DWARF_DATA2 (asm_out_file, dwarf_bit_offset); } --- 2457,2485 ---- bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree); ! /* Note that the bit offset is always the distance (in bits) from the ! highest-order bit of the "containing object" to the highest-order ! bit of the bit-field itself. Since the "high-order end" of any ! object or field is different on big-endian and little-endian machines, ! the computation below must take account of these differences. */ ! ! highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT; ! highest_order_field_bit_offset = bitpos_int; ! ! #if (BYTES_BIG_ENDIAN == 0) ! highest_order_field_bit_offset ! += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl)); ! ! highest_order_object_bit_offset += simple_type_size_in_bits (type); ! #endif /* (BYTES_BIG_ENDIAN == 0) */ ! ! bit_offset = ! #if (BYTES_BIG_ENDIAN == 0) ! highest_order_object_bit_offset - highest_order_field_bit_offset; ! #else /* (BYTES_BIG_ENDIAN != 0) */ ! highest_order_field_bit_offset - highest_order_object_bit_offset; ! #endif /* (BYTES_BIG_ENDIAN != 0) */ ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_offset); ! ASM_OUTPUT_DWARF_DATA2 (asm_out_file, bit_offset); } *************** *** 2248,2251 **** --- 2561,2584 ---- } + /* Generate an AT_body_begin attribute for a subroutine DIE. */ + + inline void + body_begin_attribute (asm_begin_label) + register char *asm_begin_label; + { + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_begin); + ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_begin_label); + } + + /* Generate an AT_body_end attribute for a subroutine DIE. */ + + inline void + body_end_attribute (asm_end_label) + register char *asm_end_label; + { + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_end); + ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_end_label); + } + /* Generate an AT_language attribute given a LANG value. These attributes are used only within TAG_compile_unit DIEs. */ *************** *** 2267,2273 **** /* Generate this attribute only for members in C++. */ ! if (context != NULL ! && (TREE_CODE (context) == RECORD_TYPE ! || TREE_CODE (context) == UNION_TYPE)) { ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_member); --- 2600,2604 ---- /* Generate this attribute only for members in C++. */ ! if (context != NULL && is_tagged_type (context)) { ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_member); *************** *** 2352,2356 **** register tree decl; { ! if (TREE_INLINE (decl)) { ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_inline); --- 2683,2687 ---- register tree decl; { ! if (DECL_INLINE (decl)) { ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_inline); *************** *** 2371,2374 **** --- 2702,2730 ---- inline void + abstract_origin_attribute (origin) + register tree origin; + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_abstract_origin); + switch (TREE_CODE_CLASS (TREE_CODE (origin))) + { + case 'd': + sprintf (label, DECL_NAME_FMT, DECL_UID (origin)); + break; + + case 't': + sprintf (label, TYPE_NAME_FMT, TYPE_UID (origin)); + break; + + default: + abort (); /* Should never happen. */ + + } + ASM_OUTPUT_DWARF_REF (asm_out_file, label); + } + + #ifdef DWARF_DECL_COORDINATES + inline void src_coords_attribute (src_fileno, src_lineno) register unsigned src_fileno; *************** *** 2379,2382 **** --- 2735,2755 ---- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, src_lineno); } + #endif /* defined(DWARF_DECL_COORDINATES) */ + + inline void + pure_or_virtual_attribute (func_decl) + register tree func_decl; + { + if (DECL_VIRTUAL_P (func_decl)) + { + #if 0 /* DECL_ABSTRACT_VIRTUAL_P is C++-specific. */ + if (DECL_ABSTRACT_VIRTUAL_P (func_decl)) + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual); + else + #endif + ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual); + ASM_OUTPUT_DWARF_STRING (asm_out_file, ""); + } + } /************************* end of attributes *****************************/ *************** *** 2387,2391 **** given decl, but only if it actually has a name. */ ! inline void name_and_src_coords_attributes (decl) register tree decl; --- 2760,2764 ---- given decl, but only if it actually has a name. */ ! static void name_and_src_coords_attributes (decl) register tree decl; *************** *** 2416,2420 **** src_coords_attribute (file_index, DECL_SOURCE_LINE (decl)); } ! #endif } } --- 2789,2793 ---- src_coords_attribute (file_index, DECL_SOURCE_LINE (decl)); } ! #endif /* defined(DWARF_DECL_COORDINATES) */ } } *************** *** 2564,2570 **** want to waste space in the .debug section now do we?) */ ! #if 0 ordering_attribute (ORD_row_major); ! #endif subscript_data_attribute (type); --- 2937,2943 ---- want to waste space in the .debug section now do we?) */ ! #ifdef USE_ORDERING_ATTRIBUTE ordering_attribute (ORD_row_major); ! #endif /* defined(USE_ORDERING_ATTRIBUTE) */ subscript_data_attribute (type); *************** *** 2591,2606 **** { register tree decl = arg; ! register tree type = TREE_TYPE (decl); ! register tree return_type = TREE_TYPE (type); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_entry_point); sibling_attribute (); dienum_push (); ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (return_type, 0, 0); } #endif /* Output a DIE to represent an enumeration type. Note that these DIEs include all of the information about the enumeration values also. --- 2964,3029 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_entry_point); sibling_attribute (); dienum_push (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! { ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (TREE_TYPE (TREE_TYPE (decl)), 0, 0); ! } ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); ! else ! low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); } #endif + /* Output a DIE to represent an inlined instance of an enumeration type. */ + + static void + output_inlined_enumeration_type_die (arg) + register void *arg; + { + register tree type = arg; + + ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_enumeration_type); + sibling_attribute (); + assert (TREE_ASM_WRITTEN (type)); + abstract_origin_attribute (type); + } + + /* Output a DIE to represent an inlined instance of a structure type. */ + + static void + output_inlined_structure_type_die (arg) + register void *arg; + { + register tree type = arg; + + ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_structure_type); + sibling_attribute (); + assert (TREE_ASM_WRITTEN (type)); + abstract_origin_attribute (type); + } + + /* Output a DIE to represent an inlined instance of a union type. */ + + static void + output_inlined_union_type_die (arg) + register void *arg; + { + register tree type = arg; + + ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_union_type); + sibling_attribute (); + assert (TREE_ASM_WRITTEN (type)); + abstract_origin_attribute (type); + } + /* Output a DIE to represent an enumeration type. Note that these DIEs include all of the information about the enumeration values also. *************** *** 2635,2643 **** Note that this routine is a bit unusual because its argument may be ! either a PARM_DECL node or else some sort of a ..._TYPE node. If it's ! the formar then this function is being called to output a real live ! formal parameter declaration. If it's the latter, then this function ! is only being called to output a TAG_formal_parameter DIE to stand as ! a placeholder for some formal argument type of some subprogram type. */ static void --- 3058,3068 ---- Note that this routine is a bit unusual because its argument may be ! a ..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which ! represents an inlining of some PARM_DECL) or else some sort of a ! ..._TYPE node. If it's the former then this function is being called ! to output a DIE to represent a formal parameter object (or some inlining ! thereof). If it's the latter, then this function is only being called ! to output a TAG_formal_parameter DIE to stand as a placeholder for some ! formal argument type of some subprogram type. */ static void *************** *** 2645,2669 **** register void *arg; { ! register tree decl = arg; ! register tree type; ! ! if (TREE_CODE (decl) == PARM_DECL) ! type = TREE_TYPE (decl); ! else ! { ! type = decl; /* we were called with a type, not a decl */ ! decl = NULL; ! } ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_formal_parameter); sibling_attribute (); ! if (decl) { ! name_and_src_coords_attributes (decl); ! type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); ! location_or_const_value_attribute (decl); } - else - type_attribute (type, 0, 0); } --- 3070,3106 ---- register void *arg; { ! register tree node = arg; ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_formal_parameter); sibling_attribute (); ! ! switch (TREE_CODE_CLASS (TREE_CODE (node))) { ! case 'd': /* We were called with some kind of a ..._DECL node. */ ! { ! register tree origin = decl_ultimate_origin (node); ! ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! { ! name_and_src_coords_attributes (node); ! type_attribute (TREE_TYPE (node), ! TREE_READONLY (node), TREE_THIS_VOLATILE (node)); ! } ! if (DECL_ABSTRACT (node)) ! equate_decl_number_to_die_number (node); ! else ! location_or_const_value_attribute (node); ! } ! break; ! ! case 't': /* We were called with some kind of a ..._TYPE node. */ ! type_attribute (node, 0, 0); ! break; ! ! default: ! abort (); /* Should never happen. */ } } *************** *** 2676,2697 **** { register tree decl = arg; ! register tree type = TREE_TYPE (decl); ! register tree return_type = TREE_TYPE (type); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_subroutine); sibling_attribute (); dienum_push (); ! name_and_src_coords_attributes (decl); ! inline_attribute (decl); ! prototyped_attribute (type); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (return_type, 0, 0); ! if (!TREE_EXTERNAL (decl)) { ! char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ! low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); ! sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number); ! high_pc_attribute (func_end_label); } } --- 3113,3150 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_subroutine); sibling_attribute (); dienum_push (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! { ! register tree type = TREE_TYPE (decl); ! ! name_and_src_coords_attributes (decl); ! inline_attribute (decl); ! prototyped_attribute (type); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (TREE_TYPE (type), 0, 0); ! pure_or_virtual_attribute (decl); ! } ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); ! else { ! if (! DECL_EXTERNAL (decl)) ! { ! char label[MAX_ARTIFICIAL_LABEL_BYTES]; ! low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); ! sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number); ! high_pc_attribute (label); ! sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number); ! body_begin_attribute (label); ! sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number); ! body_end_attribute (label); ! } } } *************** *** 2705,2772 **** { register tree decl = arg; ! register tree type = TREE_TYPE (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_variable); sibling_attribute (); ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); ! if (!TREE_EXTERNAL (decl)) ! location_or_const_value_attribute (decl); ! } ! ! #if 0 ! /* TAG_inline_subroutine has been retired by the UI/PLSIG. We're ! now supposed to use either TAG_subroutine or TAG_global_subroutine ! (depending on whether or not the function in question has internal ! or external linkage) and we're supposed to just put in an AT_inline ! attribute. */ ! static void ! output_inline_subroutine_die (arg) ! register void *arg; ! { ! register tree decl = arg; ! register tree type = TREE_TYPE (decl); ! register tree return_type = TREE_TYPE (type); ! ! ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inline_subroutine); ! sibling_attribute (); ! dienum_push (); ! name_and_src_coords_attributes (decl); ! prototyped_attribute (type); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (return_type, 0, 0); ! ! /* Note: For each inline function which gets an out-of-line body ! generated for it, we want to generate AT_low_pc and AT_high_pc ! attributes here for the function's out-of-line body. ! ! Unfortunately, the decision as to whether or not to generate an ! out-of-line body for any given inline function may not be made ! until we reach the end of the containing scope for the given ! inline function (because only then will it be known if the ! function was ever even called). ! ! For this reason, the output of DIEs representing file-scope inline ! functions gets delayed until a special post-pass which happens only ! after we have reached the end of the compilation unit. Because of ! this mechanism, we can always be sure (by the time we reach here) ! that TREE_ASM_WRITTEN(decl) will correctly indicate whether or not ! there was an out-of-line body generated for this inline function. ! */ ! ! if (!TREE_EXTERNAL (decl)) { ! if (TREE_ASM_WRITTEN (decl)) ! { ! char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ! ! low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); ! sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number); ! high_pc_attribute (func_end_label); ! } } } - #endif static void --- 3158,3182 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_variable); sibling_attribute (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else { ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (TREE_TYPE (decl), ! TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); ! } ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); ! else ! { ! if (!DECL_EXTERNAL (decl)) ! location_or_const_value_attribute (decl); } } static void *************** *** 2775,2805 **** { register tree decl = arg; ! register rtx insn = DECL_RTL (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_label); sibling_attribute (); ! name_and_src_coords_attributes (decl); ! ! /* When optimization is enabled (with -O) the code in jump.c and in flow.c ! may cause insns representing one of more of the user's own labels to ! be deleted. This happens whenever it is determined that a given label ! is unreachable. ! ! In such cases, we here generate an abbreviated form of a label DIE. ! This abbreviated version does *not* have a low_pc attribute. This ! should signify to the debugger that the label has been optimized away. ! ! Note that a CODE_LABEL can get deleted either by begin converted into ! a NOTE_INSN_DELETED note, or by simply having its INSN_DELETED_P flag ! set to true. We handle both cases here. ! */ ! ! if (GET_CODE (insn) == CODE_LABEL && ! INSN_DELETED_P (insn)) { ! char label[MAX_ARTIFICIAL_LABEL_BYTES]; ! sprintf (label, INSN_LABEL_FMT, current_funcdef_number, ! (unsigned) INSN_UID (insn)); ! low_pc_attribute (label); } } --- 3185,3219 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_label); sibling_attribute (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! name_and_src_coords_attributes (decl); ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); ! else { ! register rtx insn = DECL_RTL (decl); ! if (GET_CODE (insn) == CODE_LABEL) ! { ! char label[MAX_ARTIFICIAL_LABEL_BYTES]; ! ! /* When optimization is enabled (via -O) some parts of the compiler ! (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which ! represent source-level labels which were explicitly declared by ! the user. This really shouldn't be happening though, so catch ! it if it ever does happen. */ ! ! if (INSN_DELETED_P (insn)) ! abort (); /* Should never happen. */ ! ! sprintf (label, INSN_LABEL_FMT, current_funcdef_number, ! (unsigned) INSN_UID (insn)); ! low_pc_attribute (label); ! } } } *************** *** 2810,2823 **** { register tree stmt = arg; - char begin_label[MAX_ARTIFICIAL_LABEL_BYTES]; - char end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_lexical_block); sibling_attribute (); dienum_push (); ! sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number); ! low_pc_attribute (begin_label); ! sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number); ! high_pc_attribute (end_label); } --- 3224,3241 ---- { register tree stmt = arg; ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_lexical_block); sibling_attribute (); dienum_push (); ! if (! BLOCK_ABSTRACT (stmt)) ! { ! char begin_label[MAX_ARTIFICIAL_LABEL_BYTES]; ! char end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ! ! sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number); ! low_pc_attribute (begin_label); ! sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number); ! high_pc_attribute (end_label); ! } } *************** *** 2827,2840 **** { register tree stmt = arg; - char begin_label[MAX_ARTIFICIAL_LABEL_BYTES]; - char end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inlined_subroutine); sibling_attribute (); dienum_push (); ! sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number); ! low_pc_attribute (begin_label); ! sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number); ! high_pc_attribute (end_label); } --- 3245,3263 ---- { register tree stmt = arg; ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inlined_subroutine); sibling_attribute (); dienum_push (); ! abstract_origin_attribute (block_ultimate_origin (stmt)); ! if (! BLOCK_ABSTRACT (stmt)) ! { ! char begin_label[MAX_ARTIFICIAL_LABEL_BYTES]; ! char end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ! ! sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number); ! low_pc_attribute (begin_label); ! sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number); ! high_pc_attribute (end_label); ! } } *************** *** 2847,2858 **** { register tree decl = arg; ! register tree type = TREE_TYPE (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_local_variable); sibling_attribute (); ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); ! location_or_const_value_attribute (decl); } --- 3270,3290 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_local_variable); sibling_attribute (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! { ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (TREE_TYPE (decl), ! TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); ! } ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); ! else ! location_or_const_value_attribute (decl); } *************** *** 2879,2889 **** #if 0 ! /* Don't generate either pointer_type DIEs or reference_type DIEs. According ! to the 4-4-90 Dwarf draft spec (just after requirement #47): ! ! These two type entries are not currently generated by any compiler. ! Since the only way to name a pointer (or reference) type is C or C++ ! is via a "typedef", an entry with the "typedef" tag is generated ! instead. We keep this code here just in case these types of DIEs may be needed --- 3311,3316 ---- #if 0 ! /* Don't generate either pointer_type DIEs or reference_type DIEs. Use ! modified types instead. We keep this code here just in case these types of DIEs may be needed *************** *** 2918,2921 **** --- 3345,3349 ---- #endif + static void output_ptr_to_mbr_type_die (arg) register void *arg; *************** *** 2988,2993 **** /* Fudge the string length attribute for now. */ ! string_length_attribute ( ! TYPE_MAX_VALUE (TYPE_DOMAIN (type))); } --- 3416,3420 ---- /* Fudge the string length attribute for now. */ ! string_length_attribute (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); } *************** *** 3025,3049 **** { register tree decl = arg; ! register tree type = TREE_TYPE (decl); ! register tree return_type = TREE_TYPE (type); ! char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_subroutine); sibling_attribute (); dienum_push (); ! name_and_src_coords_attributes (decl); ! inline_attribute (decl); ! prototyped_attribute (type); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (return_type, 0, 0); ! ! /* Avoid getting screwed up in cases where a function was declared static ! but where no definition was ever given for it. */ ! if (TREE_ASM_WRITTEN (decl)) { ! low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); ! sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number); ! high_pc_attribute (func_end_label); } } --- 3452,3492 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_subroutine); sibling_attribute (); dienum_push (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! { ! register tree type = TREE_TYPE (decl); ! name_and_src_coords_attributes (decl); ! inline_attribute (decl); ! prototyped_attribute (type); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (TREE_TYPE (type), 0, 0); ! pure_or_virtual_attribute (decl); ! } ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); ! else { ! /* Avoid getting screwed up in cases where a function was declared ! static but where no definition was ever given for it. */ ! ! if (TREE_ASM_WRITTEN (decl)) ! { ! char label[MAX_ARTIFICIAL_LABEL_BYTES]; ! ! low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); ! sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number); ! high_pc_attribute (label); ! sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number); ! body_begin_attribute (label); ! sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number); ! body_end_attribute (label); ! } } } *************** *** 3070,3080 **** { register tree decl = arg; ! register tree type = TREE_TYPE (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_typedef); sibling_attribute (); ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (type, TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); } --- 3513,3531 ---- { register tree decl = arg; ! register tree origin = decl_ultimate_origin (decl); ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_typedef); sibling_attribute (); ! if (origin != NULL) ! abstract_origin_attribute (origin); ! else ! { ! name_and_src_coords_attributes (decl); ! member_attribute (DECL_CONTEXT (decl)); ! type_attribute (TREE_TYPE (decl), ! TREE_READONLY (decl), TREE_THIS_VOLATILE (decl)); ! } ! if (DECL_ABSTRACT (decl)) ! equate_decl_number_to_die_number (decl); } *************** *** 3217,3221 **** { register tree link; ! register tree formal_type; register tree first_parm_type = TYPE_ARG_TYPES (function_or_method_type); --- 3668,3672 ---- { register tree link; ! register tree formal_type = NULL; register tree first_parm_type = TYPE_ARG_TYPES (function_or_method_type); *************** *** 3291,3309 **** /* Return non-zero if it is legitimate to output DIEs to represent a given type while we are generating the list of child DIEs for some ! DIE associated with a given scope. ! ! This function returns non-zero if *either* of the following two conditions ! is satisfied: ! ! o the type actually belongs to the given scope (as evidenced ! by its TYPE_CONTEXT value), or ! ! o the type is anonymous, and the `scope' in question is *not* ! a RECORD_TYPE or UNION_TYPE. ! In theory, we should be able to generate DIEs for anonymous types ! *anywhere* (since the scope of an anonymous type is irrelevant) ! however svr4 SDB doesn't want to see other type DIEs within the ! lists of child DIEs for a TAG_structure_type or TAG_union_type DIE. Note that TYPE_CONTEXT(type) may be NULL (to indicate global scope) --- 3742,3749 ---- /* Return non-zero if it is legitimate to output DIEs to represent a given type while we are generating the list of child DIEs for some ! DIE (e.g. a function or lexical block DIE) associated with a given scope. ! See the comments within the function for a description of when it is ! considered legitimate to output DIEs for various kinds of types. Note that TYPE_CONTEXT(type) may be NULL (to indicate global scope) *************** *** 3327,3352 **** parameters, callers of this function supply `fake_containing_scope' as the `scope' parameter to this function. Given that fake_containing_scope ! is *not* the containing scope for *any* other type, the desired effect ! is achieved, i.e. output of DIEs representing types is temporarily ! suspended, and any type DIEs which would have been output otherwise ! are instead placed onto the pending_types_list. Later on, we can force ! these (temporarily pended) types to be output simply by calling `output_pending_types_for_scope' with an actual argument equal to the true scope of the types we temporarily pended. */ ! static int type_ok_for_scope (type, scope) register tree type; register tree scope; { ! return (TYPE_CONTEXT (type) == scope ! || (TYPE_NAME (type) == NULL ! && TREE_CODE (scope) != RECORD_TYPE ! && TREE_CODE (scope) != UNION_TYPE)); } /* Output any pending types (from the pending_types list) which we can output ! now (given the limitations of the scope that we are working on now). For each type output, remove the given type from the pending_types_list --- 3767,3802 ---- parameters, callers of this function supply `fake_containing_scope' as the `scope' parameter to this function. Given that fake_containing_scope ! is a tagged type which is *not* the containing scope for *any* other type, ! the desired effect is achieved, i.e. output of DIEs representing types ! is temporarily suspended, and any type DIEs which would have otherwise ! been output are instead placed onto the pending_types_list. Later on, ! we force these (temporarily pended) types to be output simply by calling `output_pending_types_for_scope' with an actual argument equal to the true scope of the types we temporarily pended. */ ! inline int type_ok_for_scope (type, scope) register tree type; register tree scope; { ! /* Tagged types (i.e. struct, union, and enum types) must always be ! output only in the scopes where they actually belong (or else the ! scoping of their own tag names and the scoping of their member ! names will be incorrect). Non-tagged-types on the other hand can ! generally be output anywhere, except that svr4 SDB really doesn't ! want to see them nested within struct or union types, so here we ! say it is always OK to immediately output any such a (non-tagged) ! type, so long as we are not within such a context. Note that the ! only kinds of non-tagged types which we will be dealing with here ! (for C and C++ anyway) will be array types and function types. */ ! ! return is_tagged_type (type) ! ? (TYPE_CONTEXT (type) == scope) ! : (scope == NULL_TREE || ! is_tagged_type (scope)); } /* Output any pending types (from the pending_types list) which we can output ! now (taking into account the scope that we are working on now). For each type output, remove the given type from the pending_types_list *************** *** 3429,3433 **** case REFERENCE_TYPE: /* For these types, all that is required is that we output a DIE ! (or a set of DIEs) to represent that "basis" type. */ output_type (TREE_TYPE (type), containing_scope); break; --- 3879,3883 ---- case REFERENCE_TYPE: /* For these types, all that is required is that we output a DIE ! (or a set of DIEs) to represent the "basis" type. */ output_type (TREE_TYPE (type), containing_scope); break; *************** *** 3546,3549 **** --- 3996,4002 ---- output_die (output_union_type_die, type); break; + + default: + abort (); /* Should never happen. */ } *************** *** 3605,3608 **** --- 4058,4067 ---- } + /* RECORD_TYPEs and UNION_TYPEs are themselves scopes (at least + in C++) so we must now output any nested pending types which + are local just to this RECORD_TYPE or UNION_TYPE. */ + + output_pending_types_for_scope (type); + end_sibling_chain (); /* Terminate member chain. */ } *************** *** 3627,3630 **** --- 4086,4127 ---- TREE_ASM_WRITTEN (type) = 1; } + + static void + output_tagged_type_instantiation (type) + register tree type; + { + if (type == 0 || type == error_mark_node) + return; + + /* We are going to output a DIE to represent the unqualified version of + of this type (i.e. without any const or volatile qualifiers) so make + sure that we have the main variant (i.e. the unqualified version) of + this type now. */ + + assert (type == TYPE_MAIN_VARIANT (type)); + + assert (TREE_ASM_WRITTEN (type)); + + switch (TREE_CODE (type)) + { + case ERROR_MARK: + break; + + case ENUMERAL_TYPE: + output_die (output_inlined_enumeration_type_die, type); + break; + + case RECORD_TYPE: + output_die (output_inlined_structure_type_die, type); + break; + + case UNION_TYPE: + output_die (output_inlined_union_type_die, type); + break; + + default: + abort (); /* Should never happen. */ + } + } /* Output a TAG_lexical_block DIE followed by DIEs to represent all of *************** *** 3635,3639 **** register tree stmt; { ! register int have_significant_locals = 0; /* Ignore blocks never really used to make RTL. */ --- 4132,4138 ---- register tree stmt; { ! register int must_output_die = 0; ! register tree origin; ! register enum tree_code origin_code; /* Ignore blocks never really used to make RTL. */ *************** *** 3642,3665 **** return; ! /* Determine if this block contains any "significant" local declarations ! which we need to output DIEs for. */ ! ! if (BLOCK_INLINE_FUNCTION (stmt)) ! /* The outer scopes for inlinings *must* always be represented. */ ! have_significant_locals = 1; else ! if (debug_info_level > DINFO_LEVEL_TERSE) ! have_significant_locals = (BLOCK_VARS (stmt) != NULL); ! else ! { ! register tree decl; ! for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) { ! have_significant_locals = 1; ! break; } ! } /* It would be a waste of space to generate a Dwarf TAG_lexical_block --- 4141,4196 ---- return; ! /* Determine the "ultimate origin" of this block. This block may be an ! inlined instance of an inlined instance of inline function, so we ! have to trace all of the way back through the origin chain to find ! out what sort of node actually served as the original seed for the ! creation of the current block. */ ! ! origin = block_ultimate_origin (stmt); ! origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK; ! ! /* Determine if we need to output any Dwarf DIEs at all to represent this ! block. */ ! ! if (origin_code == FUNCTION_DECL) ! /* The outer scopes for inlinings *must* always be represented. We ! generate TAG_inlined_subroutine DIEs for them. (See below.) */ ! must_output_die = 1; else ! { ! /* In the case where the current block represents an inlining of the ! "body block" of an inline function, we must *NOT* output any DIE ! for this block because we have already output a DIE to represent ! the whole inlined function scope and the "body block" of any ! function doesn't really represent a different scope according to ! ANSI C rules. So we check here to make sure that this block does ! not represent a "body block inlining" before trying to set the ! `must_output_die' flag. */ ! if (origin == NULL || ! is_body_block (origin)) ! { ! /* Determine if this block directly contains any "significant" ! local declarations which we will need to output DIEs for. */ ! ! if (debug_info_level > DINFO_LEVEL_TERSE) ! /* We are not in terse mode so *any* local declaration counts ! as being a "significant" one. */ ! must_output_die = (BLOCK_VARS (stmt) != NULL); ! else { ! register tree decl; ! ! /* We are in terse mode, so only local (nested) function ! definitions count as "significant" local declarations. */ ! ! for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl)) ! if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) ! { ! must_output_die = 1; ! break; ! } } ! } ! } /* It would be a waste of space to generate a Dwarf TAG_lexical_block *************** *** 3671,3679 **** inlined function instances and local (nested) function definitions. */ ! if (have_significant_locals) { ! output_die (BLOCK_INLINE_FUNCTION (stmt) ! ? output_inlined_subroutine_die ! : output_lexical_block_die, stmt); output_decls_for_scope (stmt); --- 4202,4210 ---- inlined function instances and local (nested) function definitions. */ ! if (must_output_die) { ! output_die ((origin_code == FUNCTION_DECL) ! ? output_inlined_subroutine_die ! : output_lexical_block_die, stmt); output_decls_for_scope (stmt); *************** *** 3696,3700 **** return; ! next_block_number++; /* Output the DIEs to represent all of the data objects, functions, --- 4227,4232 ---- return; ! if (! BLOCK_ABSTRACT (stmt)) ! next_block_number++; /* Output the DIEs to represent all of the data objects, functions, *************** *** 3731,3734 **** --- 4263,4272 ---- register tree containing_scope; { + /* Make a note of the decl node we are going to be working on. We may + need to give the user the source coordinates of where it appeared in + case we notice (later on) that something about it looks screwy. */ + + dwarf_last_decl = decl; + if (TREE_CODE (decl) == ERROR_MARK) return; *************** *** 3756,3760 **** mere external function declarations. */ ! if (TREE_EXTERNAL (decl)) #if (DWARF_VERSION > 1) if (debug_info_level <= DINFO_LEVEL_TERSE) --- 4294,4298 ---- mere external function declarations. */ ! if (DECL_EXTERNAL (decl)) #if (DWARF_VERSION > 1) if (debug_info_level <= DINFO_LEVEL_TERSE) *************** *** 3783,3787 **** /* Now output a DIE to represent the function itself. */ ! output_die (TREE_PUBLIC (decl) || TREE_EXTERNAL (decl) ? output_global_subroutine_die : output_local_subroutine_die, --- 4321,4325 ---- /* Now output a DIE to represent the function itself. */ ! output_die (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl) ? output_global_subroutine_die : output_local_subroutine_die, *************** *** 3803,3807 **** the *types* of its formal parameters. */ ! if (TREE_EXTERNAL (decl)) output_formal_types (TREE_TYPE (decl)); else --- 4341,4345 ---- the *types* of its formal parameters. */ ! if (DECL_EXTERNAL (decl)) output_formal_types (TREE_TYPE (decl)); else *************** *** 3809,3824 **** register tree arg_decls = DECL_ARGUMENTS (decl); - /* In the case where the FUNCTION_DECL represents a C++ non-static - member function, skip over the first thing on the DECL_ARGUMENTS - chain. It only represents the hidden `this pointer' parameter - and the debugger should know implicitly that non-static member - functions have such a thing, and should be able to figure out - exactly what the type of each `this pointer' is (from the - AT_member attribute of the parent TAG_subroutine DIE) without - being explicitly told. */ - - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) - arg_decls = TREE_CHAIN (arg_decls); - { register tree last_arg; --- 4347,4350 ---- *************** *** 3943,3959 **** { /* Note that here, `outer_scope' is a pointer to the outermost ! BLOCK node created to represent the body of a function. This outermost BLOCK actually represents the outermost binding contour for the function, i.e. the contour in which ! the function's formal parameters get declared. Just within ! this contour, there will be another (nested) BLOCK which ! represents the function's outermost block. We don't want ! to generate a lexical_block DIE to represent the outermost ! block of a function body, because that is not really an independent scope according to ANSI C rules. Rather, it is ! the same scope in which the parameters were declared and ! for Dwarf, we do not generate a TAG_lexical_block DIE for ! that scope. We must however see to it that the LABEL_DECLs ! associated with `outer_scope' get DIEs generated for them. */ { --- 4469,4491 ---- { /* Note that here, `outer_scope' is a pointer to the outermost ! BLOCK node created to represent a function. This outermost BLOCK actually represents the outermost binding contour for the function, i.e. the contour in which ! the function's formal parameters and labels get declared. ! ! Curiously, it appears that the front end doesn't actually ! put the PARM_DECL nodes for the current function onto the ! BLOCK_VARS list for this outer scope. (They are strung ! off of the DECL_ARGUMENTS list for the function instead.) ! The BLOCK_VARS list for the `outer_scope' does provide us ! with a list of the LABEL_DECL nodes for the function however, ! and we output DWARF info for those here. ! ! Just within the `outer_scope' there will be another BLOCK ! node representing the function's outermost pair of curly ! braces. We musn't generate a lexical_block DIE for this ! outermost pair of curly braces because that is not really an independent scope according to ANSI C rules. Rather, it is ! the same scope in which the parameters were declared. */ { *************** *** 3966,3969 **** --- 4498,4506 ---- } + /* Note here that `BLOCK_SUBBLOCKS (outer_scope)' points to a + list of BLOCK nodes which is always only one element long. + That one element represents the outermost pair of curley + braces for the function body. */ + output_decls_for_scope (BLOCK_SUBBLOCKS (outer_scope)); *************** *** 3996,3999 **** --- 4533,4550 ---- return; + /* In the special case of a null-named TYPE_DECL node (representing + the declaration of some type tag), if the given TYPE_DECL is + marked as having been instantiated from some other (original) + TYPE_DECL node (e.g. one which was generated within the original + definition of an inline function) we have to generate a special + (abbreviated) TAG_structure_type, TAG_union_type, or + TAG_enumeration-type DIE here. */ + + if (! DECL_NAME (decl) && DECL_ABSTRACT_ORIGIN (decl)) + { + output_tagged_type_instantiation (TREE_TYPE (decl)); + return; + } + output_type (TREE_TYPE (decl), containing_scope); *************** *** 4022,4026 **** #if (DWARF_VERSION <= 1) ! if (TREE_EXTERNAL (decl) && ! TREE_PUBLIC (decl)) break; #endif --- 4573,4577 ---- #if (DWARF_VERSION <= 1) ! if (DECL_EXTERNAL (decl) && ! TREE_PUBLIC (decl)) break; #endif *************** *** 4043,4047 **** for this data object definition. */ ! if (TREE_PUBLIC (decl)) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; --- 4594,4598 ---- for this data object definition. */ ! if (TREE_PUBLIC (decl) && ! DECL_ABSTRACT (decl)) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; *************** *** 4051,4059 **** } ! /* Now output the DIE to represent the data object itself. */ ! output_die (TREE_PUBLIC (decl) || TREE_EXTERNAL (decl) ! ? output_global_variable_die : output_local_variable_die, ! decl); break; --- 4602,4625 ---- } ! /* Now output the DIE to represent the data object itself. This gets ! complicated because of the possibility that the VAR_DECL really ! represents an inlined instance of a formal parameter for an inline ! function. */ ! { ! register void (*func) (); ! register tree origin = decl_ultimate_origin (decl); ! ! if (origin != NULL && TREE_CODE (origin) == PARM_DECL) ! func = output_formal_parameter_die; ! else ! { ! if (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)) ! func = output_global_variable_die; ! else ! func = output_local_variable_die; ! } ! output_die (func, decl); ! } break; *************** *** 4113,4117 **** these same functions should NOT be ignored however. */ ! if (TREE_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl)) return; --- 4679,4683 ---- these same functions should NOT be ignored however. */ ! if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl)) return; *************** *** 4126,4133 **** to be in scope at a given point. */ ! if (TREE_EXTERNAL (decl) && !TREE_USED (decl)) return; ! if (TREE_PUBLIC (decl) && ! TREE_EXTERNAL (decl)) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; --- 4692,4701 ---- to be in scope at a given point. */ ! if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) return; ! if (TREE_PUBLIC (decl) ! && ! DECL_EXTERNAL (decl) ! && ! DECL_ABSTRACT (decl)) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; *************** *** 4159,4168 **** to be in scope at a given point. */ ! if (TREE_EXTERNAL (decl) && !TREE_USED (decl)) return; if (TREE_PUBLIC (decl) ! && ! TREE_EXTERNAL (decl) ! && GET_CODE (DECL_RTL (decl)) == MEM) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; --- 4727,4737 ---- to be in scope at a given point. */ ! if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) return; if (TREE_PUBLIC (decl) ! && ! DECL_EXTERNAL (decl) ! && GET_CODE (DECL_RTL (decl)) == MEM ! && ! DECL_ABSTRACT (decl)) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; *************** *** 4206,4212 **** case TYPE_DECL: ! /* Don't generate any DIEs to represent the standard built-in types. */ ! if (DECL_SOURCE_LINE (decl) == 0) return; --- 4775,4790 ---- case TYPE_DECL: ! /* Don't bother trying to generate any DIEs to represent any of the ! normal built-in types for the language we are compiling, except ! in cases where the types in question are *not* DWARF fundamental ! types. We make an exception in the case of non-fundamental types ! for the sake of objective C (and perhaps C++) because the GNU ! front-ends for these languages may in fact create certain "built-in" ! types which are (for example) RECORD_TYPEs. In such cases, we ! really need to output these (non-fundamental) types because other ! DIEs may contain references to them. */ ! if (DECL_SOURCE_LINE (decl) == 0 ! && type_is_fundamental (TREE_TYPE (decl))) return; *************** *** 4231,4235 **** ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION); finalizing = set_finalizing; ! output_decl (decl, NULL); /* NOTE: The call above to `output_decl' may have caused one or more --- 4809,4813 ---- ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION); finalizing = set_finalizing; ! output_decl (decl, NULL_TREE); /* NOTE: The call above to `output_decl' may have caused one or more *************** *** 4244,4248 **** their TREE_ASM_WRITTEN flags. */ ! output_pending_types_for_scope (NULL); /* The above call should have totally emptied the pending_types_list. */ --- 4822,4826 ---- their TREE_ASM_WRITTEN flags. */ ! output_pending_types_for_scope (NULL_TREE); /* The above call should have totally emptied the pending_types_list. */ *************** *** 4302,4305 **** --- 4880,4910 ---- } + /* Output a marker (i.e. a label) for the point in the generated code where + the real body of the function begins (after parameters have been moved + to their home locations). */ + + void + dwarfout_begin_function () + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + text_section (); + sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number); + ASM_OUTPUT_LABEL (asm_out_file, label); + } + + /* Output a marker (i.e. a label) for the point in the generated code where + the real body of the function ends (just before the epilogue code). */ + + void + dwarfout_end_function () + { + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + text_section (); + sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number); + ASM_OUTPUT_LABEL (asm_out_file, label); + } + /* Output a marker (i.e. a label) for the absolute end of the generated code for a function definition. This gets called *after* the epilogue code *************** *** 4487,4491 **** { ! register char *tail = strrchr (filename, '/'); if (tail != NULL) --- 5092,5096 ---- { ! register char *tail = rindex (filename, '/'); if (tail != NULL) *************** *** 4638,4641 **** --- 5243,5247 ---- ASM_OUTPUT_POP_SECTION (asm_out_file); + #if 0 /* GNU C doesn't currently use .data1. */ /* Output a starting label for the .data1 section. */ *************** *** 4644,4647 **** --- 5250,5254 ---- ASM_OUTPUT_LABEL (asm_out_file, DATA1_BEGIN_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); + #endif /* Output a starting label for the .rodata section. */ *************** *** 4652,4655 **** --- 5259,5263 ---- ASM_OUTPUT_POP_SECTION (asm_out_file); + #if 0 /* GNU C doesn't currently use .rodata1. */ /* Output a starting label for the .rodata1 section. */ *************** *** 4658,4661 **** --- 5266,5270 ---- ASM_OUTPUT_LABEL (asm_out_file, RODATA1_BEGIN_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); + #endif /* Output a starting label for the .bss section. */ *************** *** 4815,4818 **** --- 5424,5428 ---- ASM_OUTPUT_POP_SECTION (asm_out_file); + #if 0 /* GNU C doesn't currently use .data1. */ /* Output a terminator label for the .data1 section. */ *************** *** 4821,4824 **** --- 5431,5435 ---- ASM_OUTPUT_LABEL (asm_out_file, DATA1_END_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); + #endif /* Output a terminator label for the .rodata section. */ *************** *** 4829,4832 **** --- 5440,5444 ---- ASM_OUTPUT_POP_SECTION (asm_out_file); + #if 0 /* GNU C doesn't currently use .rodata1. */ /* Output a terminator label for the .rodata1 section. */ *************** *** 4835,4838 **** --- 5447,5451 ---- ASM_OUTPUT_LABEL (asm_out_file, RODATA1_END_LABEL); ASM_OUTPUT_POP_SECTION (asm_out_file); + #endif /* Output a terminator label for the .bss section. */ *************** *** 4909,4915 **** --- 5522,5530 ---- ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA_END_LABEL, DATA_BEGIN_LABEL); + #if 0 /* GNU C doesn't currently use .data1. */ ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA1_BEGIN_LABEL); ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA1_END_LABEL, DATA1_BEGIN_LABEL); + #endif ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA_BEGIN_LABEL); *************** *** 4917,4923 **** --- 5532,5540 ---- RODATA_BEGIN_LABEL); + #if 0 /* GNU C doesn't currently use .rodata1. */ ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA1_BEGIN_LABEL); ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA1_END_LABEL, RODATA1_BEGIN_LABEL); + #endif ASM_OUTPUT_DWARF_ADDR (asm_out_file, BSS_BEGIN_LABEL); diff -rc2N gcc-2.2.2/emit-rtl.c gcc-2.3.1/emit-rtl.c *** gcc-2.2.2/emit-rtl.c Tue May 26 19:25:49 1992 --- gcc-2.3.1/emit-rtl.c Sat Oct 17 00:32:27 1992 *************** *** 35,39 **** #include "config.h" - #include #include "gvarargs.h" #include "rtl.h" --- 35,38 ---- *************** *** 44,47 **** --- 43,47 ---- #include "insn-config.h" #include "real.h" + #include /* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function. *************** *** 248,252 **** if (code == CONST_INT) { ! int arg = va_arg (p, int); if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT) --- 248,252 ---- if (code == CONST_INT) { ! HOST_WIDE_INT arg = va_arg (p, HOST_WIDE_INT); if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT) *************** *** 272,284 **** be using it as a normal register, for example as a spill register. In such cases, we might be accessing it in a mode that is not ! Pmode and therefore cannot use the pre-allocated rtx. */ ! if (frame_pointer_rtx && regno == FRAME_POINTER_REGNUM && mode == Pmode) return frame_pointer_rtx; #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM ! if (arg_pointer_rtx && regno == ARG_POINTER_REGNUM && mode == Pmode) return arg_pointer_rtx; #endif ! if (stack_pointer_rtx && regno == STACK_POINTER_REGNUM && mode == Pmode) return stack_pointer_rtx; else --- 272,290 ---- be using it as a normal register, for example as a spill register. In such cases, we might be accessing it in a mode that is not ! Pmode and therefore cannot use the pre-allocated rtx. ! Also don't do this when we are making new REGs in reload, ! since we don't want to get confused with the real pointers. */ ! ! if (frame_pointer_rtx && regno == FRAME_POINTER_REGNUM && mode == Pmode ! && ! reload_in_progress) return frame_pointer_rtx; #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM ! if (arg_pointer_rtx && regno == ARG_POINTER_REGNUM && mode == Pmode ! && ! reload_in_progress) return arg_pointer_rtx; #endif ! if (stack_pointer_rtx && regno == STACK_POINTER_REGNUM && mode == Pmode ! && ! reload_in_progress) return stack_pointer_rtx; else *************** *** 307,310 **** --- 313,320 ---- break; + case 'w': /* A wide integer? */ + XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT); + break; + case 's': /* A string? */ XSTR (rt_val, i) = va_arg (p, char *); *************** *** 487,491 **** if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) ! && GET_MODE_CLASS (mode) == MODE_INT) { /* If we are getting the low-order part of something that has been --- 497,502 ---- if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) ! && (GET_MODE_CLASS (mode) == MODE_INT ! || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)) { /* If we are getting the low-order part of something that has been *************** *** 520,524 **** /* integrate.c can't handle parts of a return value register. */ && (! REG_FUNCTION_VALUE_P (x) ! || ! rtx_equal_function_value_matters)) return gen_rtx (REG, mode, REGNO (x) + word); else --- 531,542 ---- /* integrate.c can't handle parts of a return value register. */ && (! REG_FUNCTION_VALUE_P (x) ! || ! rtx_equal_function_value_matters) ! /* We want to keep the stack, frame, and arg pointers ! special. */ ! && REGNO (x) != FRAME_POINTER_REGNUM ! #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM ! && REGNO (x) != ARG_POINTER_REGNUM ! #endif ! && REGNO (x) != STACK_POINTER_REGNUM) return gen_rtx (REG, mode, REGNO (x) + word); else *************** *** 528,532 **** /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits from the low-order part of the constant. */ ! else if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (x) == VOIDmode && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)) { --- 546,552 ---- /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits from the low-order part of the constant. */ ! else if ((GET_MODE_CLASS (mode) == MODE_INT ! || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) ! && GET_MODE (x) == VOIDmode && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)) { *************** *** 539,561 **** for this mode. */ ! if (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_INT) return x; ! else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_INT) return 0; ! else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_INT) return (GET_CODE (x) == CONST_INT ? x ! : gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (x))); else { /* MODE must be narrower than HOST_BITS_PER_INT. */ int width = GET_MODE_BITSIZE (mode); ! int val = (GET_CODE (x) == CONST_INT ? INTVAL (x) ! : CONST_DOUBLE_LOW (x)); ! if (((val & ((-1) << (width - 1))) != ((-1) << (width - 1)))) ! val &= (1 << width) - 1; return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x ! : gen_rtx (CONST_INT, VOIDmode, val)); } } --- 559,582 ---- for this mode. */ ! if (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT) return x; ! else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT) return 0; ! else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT) return (GET_CODE (x) == CONST_INT ? x ! : GEN_INT (CONST_DOUBLE_LOW (x))); else { /* MODE must be narrower than HOST_BITS_PER_INT. */ int width = GET_MODE_BITSIZE (mode); ! HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x) ! : CONST_DOUBLE_LOW (x)); ! if (((val & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) ! val &= ((HOST_WIDE_INT) 1 << width) - 1; return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x ! : GEN_INT (val)); } } *************** *** 568,579 **** else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_SIZE (mode) == UNITS_PER_WORD && GET_CODE (x) == CONST_INT ! && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_INT) { ! union {int i; float d; } u; u.i = INTVAL (x); --- 589,600 ---- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_SIZE (mode) == UNITS_PER_WORD && GET_CODE (x) == CONST_INT ! && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT) { ! union {HOST_WIDE_INT i; float d; } u; u.i = INTVAL (x); *************** *** 582,586 **** else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT --- 603,607 ---- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT *************** *** 588,598 **** && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) && GET_MODE (x) == VOIDmode ! && sizeof (double) * HOST_BITS_PER_CHAR == 2 * HOST_BITS_PER_INT) { ! union {int i[2]; double d; } u; ! int low, high; if (GET_CODE (x) == CONST_INT) ! low = INTVAL (x), high = low >> (HOST_BITS_PER_INT -1); else low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x); --- 609,620 ---- && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) && GET_MODE (x) == VOIDmode ! && (sizeof (double) * HOST_BITS_PER_CHAR ! == 2 * HOST_BITS_PER_WIDE_INT)) { ! union {HOST_WIDE_INT i[2]; double d; } u; ! HOST_WIDE_INT low, high; if (GET_CODE (x) == CONST_INT) ! low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1); else low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x); *************** *** 612,618 **** else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_INT == BITS_PER_WORD) || flag_pretend_float) ! && GET_MODE_CLASS (mode) == MODE_INT && GET_CODE (x) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT --- 634,641 ---- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) || flag_pretend_float) ! && (GET_MODE_CLASS (mode) == MODE_INT ! || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) && GET_CODE (x) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT *************** *** 626,632 **** else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_INT == BITS_PER_WORD) || flag_pretend_float) ! && GET_MODE_CLASS (mode) == MODE_INT && GET_CODE (x) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT --- 649,656 ---- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) || flag_pretend_float) ! && (GET_MODE_CLASS (mode) == MODE_INT ! || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) && GET_CODE (x) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT *************** *** 645,648 **** --- 669,700 ---- } + /* Return the real part (which has mode MODE) of a complex value X. + This always comes at the low address in memory. */ + + rtx + gen_realpart (mode, x) + enum machine_mode mode; + register rtx x; + { + if (WORDS_BIG_ENDIAN) + return gen_highpart (mode, x); + else + return gen_lowpart (mode, x); + } + + /* Return the imaginary part (which has mode MODE) of a complex value X. + This always comes at the high address in memory. */ + + rtx + gen_imagpart (mode, x) + enum machine_mode mode; + register rtx x; + { + if (WORDS_BIG_ENDIAN) + return gen_lowpart (mode, x); + else + return gen_highpart (mode, x); + } + /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the *************** *** 681,684 **** --- 733,807 ---- } + /* Like `gen_lowpart', but refer to the most significant part. + This is used to access the imaginary part of a complex number. */ + + rtx + gen_highpart (mode, x) + enum machine_mode mode; + register rtx x; + { + /* This case loses if X is a subreg. To catch bugs early, + complain if an invalid MODE is used even in other cases. */ + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD + && GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x))) + abort (); + if (GET_CODE (x) == CONST_DOUBLE + #if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined(REAL_IS_NOT_DOUBLE)) + && GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT + #endif + ) + return gen_rtx (CONST_INT, VOIDmode, + CONST_DOUBLE_HIGH (x) & GET_MODE_MASK (mode)); + else if (GET_CODE (x) == CONST_INT) + return const0_rtx; + else if (GET_CODE (x) == MEM) + { + register int offset = 0; + #if !WORDS_BIG_ENDIAN + offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) + - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); + #endif + #if !BYTES_BIG_ENDIAN + if (GET_MODE_SIZE (mode) < UNITS_PER_WORD) + offset -= (GET_MODE_SIZE (mode) + - MIN (UNITS_PER_WORD, + GET_MODE_SIZE (GET_MODE (x)))); + #endif + return change_address (x, mode, plus_constant (XEXP (x, 0), offset)); + } + else if (GET_CODE (x) == SUBREG) + { + /* The only time this should occur is when we are looking at a + multi-word item with a SUBREG whose mode is the same as that of the + item. It isn't clear what we would do if it wasn't. */ + if (SUBREG_WORD (x) != 0) + abort (); + return gen_highpart (mode, SUBREG_REG (x)); + } + else if (GET_CODE (x) == REG) + { + int word = 0; + + #if !WORDS_BIG_ENDIAN + if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) + word = ((GET_MODE_SIZE (GET_MODE (x)) + - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)) + / UNITS_PER_WORD); + #endif + if (REGNO (x) < FIRST_PSEUDO_REGISTER + /* We want to keep the stack, frame, and arg pointers special. */ + && REGNO (x) != FRAME_POINTER_REGNUM + #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM + && REGNO (x) != ARG_POINTER_REGNUM + #endif + && REGNO (x) != STACK_POINTER_REGNUM) + return gen_rtx (REG, mode, REGNO (x) + word); + else + return gen_rtx (SUBREG, mode, x, word); + } + else + abort (); + } + /* Return 1 iff X, assumed to be a SUBREG, refers to the least significant part of its containing reg. *************** *** 726,731 **** enum machine_mode mode; { ! int val; ! int size_ratio = HOST_BITS_PER_INT / BITS_PER_WORD; if (mode == VOIDmode) --- 849,854 ---- enum machine_mode mode; { ! HOST_WIDE_INT val; ! int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD; if (mode == VOIDmode) *************** *** 756,760 **** else if (REGNO (op) >= FIRST_PSEUDO_REGISTER || (REG_FUNCTION_VALUE_P (op) ! && rtx_equal_function_value_matters)) return gen_rtx (SUBREG, word_mode, op, i); else --- 879,890 ---- else if (REGNO (op) >= FIRST_PSEUDO_REGISTER || (REG_FUNCTION_VALUE_P (op) ! && rtx_equal_function_value_matters) ! /* We want to keep the stack, frame, and arg pointers ! special. */ ! || REGNO (op) == FRAME_POINTER_REGNUM ! #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM ! || REGNO (op) == ARG_POINTER_REGNUM ! #endif ! || REGNO (op) == STACK_POINTER_REGNUM) return gen_rtx (SUBREG, word_mode, op, i); else *************** *** 794,812 **** constants are easy. */ if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD && GET_CODE (op) == CONST_DOUBLE) ! return gen_rtx (CONST_INT, VOIDmode, ! i ^ (WORDS_BIG_ENDIAN != ! /* The constant is stored in the host's word-ordering, ! but we want to access it in the target's word-ordering. */ #ifdef HOST_WORDS_BIG_ENDIAN ! 1 #else ! 0 #endif ! ) ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op)); /* Single word float is a little harder, since single- and double-word --- 924,945 ---- constants are easy. */ if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD && GET_CODE (op) == CONST_DOUBLE) ! { ! /* The constant is stored in the host's word-ordering, ! but we want to access it in the target's word-ordering. Some ! compilers don't like a conditional inside macro args, so we have two ! copies of the return. */ #ifdef HOST_WORDS_BIG_ENDIAN ! return GEN_INT (i == WORDS_BIG_ENDIAN ! ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op)); #else ! return GEN_INT (i != WORDS_BIG_ENDIAN ! ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op)); #endif ! } /* Single word float is a little harder, since single- and double-word *************** *** 814,818 **** verified that we want the only defined word of the single-word value. */ if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT --- 947,951 ---- verified that we want the only defined word of the single-word value. */ if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT ! && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) || flag_pretend_float) && GET_MODE_CLASS (mode) == MODE_FLOAT *************** *** 821,830 **** { double d; ! union {float f; int i; } u; REAL_VALUE_FROM_CONST_DOUBLE (d, op); u.f = d; ! return gen_rtx (CONST_INT, VOIDmode, u.i); } --- 954,963 ---- { double d; ! union {float f; HOST_WIDE_INT i; } u; REAL_VALUE_FROM_CONST_DOUBLE (d, op); u.f = d; ! return GEN_INT (u.i); } *************** *** 855,863 **** /* If BITS_PER_WORD is smaller than an int, get the appropriate bits. */ ! if (BITS_PER_WORD < HOST_BITS_PER_INT) val = ((val >> ((i % size_ratio) * BITS_PER_WORD)) ! & ((1 << (BITS_PER_WORD % HOST_BITS_PER_INT)) - 1)); ! return gen_rtx (CONST_INT, VOIDmode, val); } --- 988,997 ---- /* If BITS_PER_WORD is smaller than an int, get the appropriate bits. */ ! if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT) val = ((val >> ((i % size_ratio) * BITS_PER_WORD)) ! & (((HOST_WIDE_INT) 1 ! << (BITS_PER_WORD % HOST_BITS_PER_WIDE_INT)) - 1)); ! return GEN_INT (val); } *************** *** 966,970 **** gen_label_rtx () { ! register rtx label = gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0, label_num++, 0); LABEL_NUSES (label) = 0; return label; --- 1100,1105 ---- gen_label_rtx () { ! register rtx label = gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0, ! label_num++, NULL_PTR); LABEL_NUSES (label) = 0; return label; *************** *** 992,996 **** { rtx header = gen_rtx (INLINE_HEADER, VOIDmode, ! cur_insn_uid++, NULL, first_insn, first_parm_insn, first_labelno, last_labelno, --- 1127,1131 ---- { rtx header = gen_rtx (INLINE_HEADER, VOIDmode, ! cur_insn_uid++, NULL_RTX, first_insn, first_parm_insn, first_labelno, last_labelno, *************** *** 1578,1582 **** rtx insn; { ! rtx note = find_reg_note (insn, REG_CC_USER, 0); if (note) --- 1713,1717 ---- rtx insn; { ! rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX); if (note) *************** *** 1601,1605 **** rtx insn; { ! rtx note = find_reg_note (insn, REG_CC_SETTER, 0); rtx link; --- 1736,1740 ---- rtx insn; { ! rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); rtx link; *************** *** 1689,1699 **** /* Make and return an INSN rtx, initializing all its slots. ! Store PATTERN in the pattern slots. ! PAT_FORMALS is an idea that never really went anywhere. */ rtx ! make_insn_raw (pattern, pat_formals) rtx pattern; - rtvec pat_formals; { register rtx insn; --- 1824,1832 ---- /* Make and return an INSN rtx, initializing all its slots. ! Store PATTERN in the pattern slots. */ rtx ! make_insn_raw (pattern) rtx pattern; { register rtx insn; *************** *** 1713,1723 **** static rtx ! make_jump_insn_raw (pattern, pat_formals) rtx pattern; - rtvec pat_formals; { register rtx insn; ! insn = rtx_alloc(JUMP_INSN); INSN_UID(insn) = cur_insn_uid++; --- 1846,1855 ---- static rtx ! make_jump_insn_raw (pattern) rtx pattern; { register rtx insn; ! insn = rtx_alloc (JUMP_INSN); INSN_UID(insn) = cur_insn_uid++; *************** *** 1904,1908 **** else { ! insn = make_insn_raw (pattern, 0); add_insn_after (insn, PREV_INSN (before)); } --- 2036,2040 ---- else { ! insn = make_insn_raw (pattern); add_insn_after (insn, PREV_INSN (before)); } *************** *** 1924,1928 **** else { ! insn = make_jump_insn_raw (pattern, 0); add_insn_after (insn, PREV_INSN (before)); } --- 2056,2060 ---- else { ! insn = make_jump_insn_raw (pattern, NULL_RTVEC); add_insn_after (insn, PREV_INSN (before)); } *************** *** 1998,2002 **** else { ! insn = make_insn_raw (pattern, 0); add_insn_after (insn, after); } --- 2130,2134 ---- else { ! insn = make_insn_raw (pattern); add_insn_after (insn, after); } *************** *** 2005,2008 **** --- 2137,2162 ---- } + /* Similar to emit_insn_after, except that line notes are to be inserted so + as to act as if this insn were at FROM. */ + + void + emit_insn_after_with_line_notes (pattern, after, from) + rtx pattern, after, from; + { + rtx from_line = find_line_note (from); + rtx after_line = find_line_note (after); + rtx insn = emit_insn_after (pattern, after); + + if (from_line) + emit_line_note_after (NOTE_SOURCE_FILE (from_line), + NOTE_LINE_NUMBER (from_line), + after); + + if (after_line) + emit_line_note_after (NOTE_SOURCE_FILE (after_line), + NOTE_LINE_NUMBER (after_line), + insn); + } + /* Make an insn of code JUMP_INSN with body PATTERN and output it after the insn AFTER. */ *************** *** 2018,2022 **** else { ! insn = make_jump_insn_raw (pattern, 0); add_insn_after (insn, after); } --- 2172,2176 ---- else { ! insn = make_jump_insn_raw (pattern, NULL_RTVEC); add_insn_after (insn, after); } *************** *** 2124,2128 **** else { ! insn = make_insn_raw (pattern, NULL); add_insn (insn); } --- 2278,2282 ---- else { ! insn = make_insn_raw (pattern); add_insn (insn); } *************** *** 2172,2175 **** --- 2326,2362 ---- } + /* Emit the insns in a chain starting with FIRST and place them in back of + the insn AFTER. Return the last insn emitted. */ + + rtx + emit_insns_after (first, after) + register rtx first; + register rtx after; + { + register rtx last; + register rtx after_after; + + if (!after) + abort (); + + if (!first) + return first; + + for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) + continue; + + after_after = NEXT_INSN (after); + + NEXT_INSN (after) = first; + PREV_INSN (first) = after; + NEXT_INSN (last) = after_after; + if (after_after) + PREV_INSN (after_after) = last; + + if (after == last_insn) + last_insn = last; + return last; + } + /* Make an insn of code JUMP_INSN with pattern PATTERN and add it to the end of the doubly-linked list. */ *************** *** 2183,2187 **** else { ! register rtx insn = make_jump_insn_raw (pattern, NULL); add_insn (insn); return insn; --- 2370,2374 ---- else { ! register rtx insn = make_jump_insn_raw (pattern, NULL_RTVEC); add_insn (insn); return insn; *************** *** 2200,2204 **** else { ! register rtx insn = make_insn_raw (pattern, NULL); add_insn (insn); PUT_CODE (insn, CALL_INSN); --- 2387,2391 ---- else { ! register rtx insn = make_insn_raw (pattern); add_insn (insn); PUT_CODE (insn, CALL_INSN); *************** *** 2671,2674 **** --- 2858,2872 ---- regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx; regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx; + + /* Indicate that the virtual registers and stack locations are + all pointers. */ + REGNO_POINTER_FLAG (STACK_POINTER_REGNUM) = 1; + REGNO_POINTER_FLAG (FRAME_POINTER_REGNUM) = 1; + REGNO_POINTER_FLAG (ARG_POINTER_REGNUM) = 1; + + REGNO_POINTER_FLAG (VIRTUAL_INCOMING_ARGS_REGNUM) = 1; + REGNO_POINTER_FLAG (VIRTUAL_STACK_VARS_REGNUM) = 1; + REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1; + REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1; } *************** *** 2702,2712 **** /* These four calls obtain some of the rtx expressions made above. */ ! const0_rtx = gen_rtx (CONST_INT, VOIDmode, 0); ! const1_rtx = gen_rtx (CONST_INT, VOIDmode, 1); ! const2_rtx = gen_rtx (CONST_INT, VOIDmode, 2); ! constm1_rtx = gen_rtx (CONST_INT, VOIDmode, -1); /* This will usually be one of the above constants, but may be a new rtx. */ ! const_true_rtx = gen_rtx (CONST_INT, VOIDmode, STORE_FLAG_VALUE); dconst0 = REAL_VALUE_ATOF ("0"); --- 2900,2910 ---- /* These four calls obtain some of the rtx expressions made above. */ ! const0_rtx = GEN_INT (0); ! const1_rtx = GEN_INT (1); ! const2_rtx = GEN_INT (2); ! constm1_rtx = GEN_INT (-1); /* This will usually be one of the above constants, but may be a new rtx. */ ! const_true_rtx = GEN_INT (STORE_FLAG_VALUE); dconst0 = REAL_VALUE_ATOF ("0"); *************** *** 2733,2742 **** } ! const_tiny_rtx[i][(int) VOIDmode] = gen_rtx (CONST_INT, VOIDmode, i); for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) ! const_tiny_rtx[i][(int) mode] = gen_rtx (CONST_INT, VOIDmode, i); } stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); --- 2931,2944 ---- } ! const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i); for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) ! const_tiny_rtx[i][(int) mode] = GEN_INT (i); } + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_CC); mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + const_tiny_rtx[0][(int) mode] = const0_rtx; stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); diff -rc2N gcc-2.2.2/enquire.c gcc-2.3.1/enquire.c *** gcc-2.2.2/enquire.c Fri Jun 5 02:18:51 1992 --- gcc-2.3.1/enquire.c Fri Jul 31 02:29:07 1992 *************** *** 901,905 **** /* Print a value of type TYPE with value VAL, assuming that sprintf can't handle this type properly (without truncation). ! We create an expession that uses type casting to create the value from a bit pattern. */ --- 901,905 ---- /* Print a value of type TYPE with value VAL, assuming that sprintf can't handle this type properly (without truncation). ! We create an expression that uses type casting to create the value from a bit pattern. */ diff -rc2N gcc-2.2.2/explow.c gcc-2.3.1/explow.c *** gcc-2.2.2/explow.c Fri May 29 16:14:01 1992 --- gcc-2.3.1/explow.c Sat Oct 3 02:07:10 1992 *************** *** 30,39 **** #include "insn-codes.h" ! /* Return an rtx for the sum of X and the integer C. */ rtx ! plus_constant (x, c) register rtx x; ! register int c; { register RTX_CODE code; --- 30,41 ---- #include "insn-codes.h" ! /* Return an rtx for the sum of X and the integer C. + This fucntion should be used via the `plus_constant' macro. */ + rtx ! plus_constant_wide (x, c) register rtx x; ! register HOST_WIDE_INT c; { register RTX_CODE code; *************** *** 52,64 **** { case CONST_INT: ! return gen_rtx (CONST_INT, VOIDmode, (INTVAL (x) + c)); case CONST_DOUBLE: { ! int l1 = CONST_DOUBLE_LOW (x); ! int h1 = CONST_DOUBLE_HIGH (x); ! int l2 = c; ! int h2 = c < 0 ? ~0 : 0; ! int lv, hv; add_double (l1, h1, l2, h2, &lv, &hv); --- 54,66 ---- { case CONST_INT: ! return GEN_INT (INTVAL (x) + c); case CONST_DOUBLE: { ! HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x); ! HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x); ! HOST_WIDE_INT l2 = c; ! HOST_WIDE_INT h2 = c < 0 ? ~0 : 0; ! HOST_WIDE_INT lv, hv; add_double (l1, h1, l2, h2, &lv, &hv); *************** *** 100,114 **** with C. For an integer constant term, we make a combined integer. For a constant term that is not an explicit integer, ! we cannot really combine, but group them together anyway. */ ! if (GET_CODE (XEXP (x, 0)) == CONST_INT) ! { ! c += INTVAL (XEXP (x, 0)); ! x = XEXP (x, 1); ! } ! else if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! { ! c += INTVAL (XEXP (x, 1)); ! x = XEXP (x, 0); ! } else if (CONSTANT_P (XEXP (x, 0))) return gen_rtx (PLUS, mode, --- 102,112 ---- with C. For an integer constant term, we make a combined integer. For a constant term that is not an explicit integer, ! we cannot really combine, but group them together anyway. ! ! Use a recursive call in case the remaining operand is something ! that we handle specially, such as a SYMBOL_REF. */ ! ! if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! return plus_constant (XEXP (x, 0), c + INTVAL (XEXP (x, 1))); else if (CONSTANT_P (XEXP (x, 0))) return gen_rtx (PLUS, mode, *************** *** 122,126 **** if (c != 0) ! x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c)); if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) --- 120,124 ---- if (c != 0) ! x = gen_rtx (PLUS, mode, x, GEN_INT (c)); if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) *************** *** 132,141 **** } ! /* This is the same a `plus_constant', except that it handles LO_SUM. */ rtx ! plus_constant_for_output (x, c) register rtx x; ! register int c; { register RTX_CODE code = GET_CODE (x); --- 130,141 ---- } ! /* This is the same as `plus_constant', except that it handles LO_SUM. ! ! This function should be used via the `plus_constant_for_output' macro. */ rtx ! plus_constant_for_output_wide (x, c) register rtx x; ! register HOST_WIDE_INT c; { register RTX_CODE code = GET_CODE (x); *************** *** 244,248 **** { return expand_expr (size_in_bytes (TREE_TYPE (exp)), ! 0, TYPE_MODE (sizetype), 0); } --- 244,248 ---- { return expand_expr (size_in_bytes (TREE_TYPE (exp)), ! NULL_RTX, TYPE_MODE (sizetype), 0); } *************** *** 382,394 **** if (constant_term == const0_rtx || ! memory_address_p (mode, y)) ! return force_operand (x, 0); y = gen_rtx (PLUS, GET_MODE (x), copy_to_reg (y), constant_term); if (! memory_address_p (mode, y)) ! return force_operand (x, 0); return y; } if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS) ! return force_operand (x, 0); /* If we have a register that's an invalid address, --- 382,394 ---- if (constant_term == const0_rtx || ! memory_address_p (mode, y)) ! return force_operand (x, NULL_RTX); y = gen_rtx (PLUS, GET_MODE (x), copy_to_reg (y), constant_term); if (! memory_address_p (mode, y)) ! return force_operand (x, NULL_RTX); return y; } if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS) ! return force_operand (x, NULL_RTX); /* If we have a register that's an invalid address, *************** *** 413,417 **** return force_reg (Pmode, x); else ! return force_operand (x, 0); } return x; --- 413,417 ---- return force_reg (Pmode, x); else ! return force_operand (x, NULL_RTX); } return x; *************** *** 555,559 **** if (CONSTANT_P (x)) { ! rtx note = find_reg_note (insn, REG_EQUAL, 0); if (note) --- 555,559 ---- if (CONSTANT_P (x)) { ! rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX); if (note) *************** *** 667,680 **** int new = (INTVAL (size) + align - 1) / align * align; if (INTVAL (size) != new) ! size = gen_rtx (CONST_INT, VOIDmode, new); } else { ! size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, ! gen_rtx (CONST_INT, VOIDmode, align), ! 0, 1); ! size = expand_mult (Pmode, size, ! gen_rtx (CONST_INT, VOIDmode, align), ! 0, 1); } #endif /* STACK_BOUNDARY */ --- 667,677 ---- int new = (INTVAL (size) + align - 1) / align * align; if (INTVAL (size) != new) ! size = GEN_INT (new); } else { ! size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size, GEN_INT (align), ! NULL_RTX, 1); ! size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1); } #endif /* STACK_BOUNDARY */ *************** *** 869,884 **** #ifdef MUST_ALIGN if (known_align % BIGGEST_ALIGNMENT != 0) { if (GET_CODE (size) == CONST_INT) ! size = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (size) ! + (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1))); else size = expand_binop (Pmode, add_optab, size, ! gen_rtx (CONST_INT, VOIDmode, ! BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1), ! 0, 1, OPTAB_LIB_WIDEN); } #endif --- 866,887 ---- #ifdef MUST_ALIGN + #if 0 /* It turns out we must always make extra space, if MUST_ALIGN + because we must always round the address up at the end, + because we don't know whether the dynamic offset + will mess up the desired alignment. */ + /* If we have to round the address up regardless of known_align, + make extra space regardless, also. */ if (known_align % BIGGEST_ALIGNMENT != 0) + #endif { if (GET_CODE (size) == CONST_INT) ! size = GEN_INT (INTVAL (size) ! + (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1)); else size = expand_binop (Pmode, add_optab, size, ! GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1), ! NULL_RTX, 1, OPTAB_LIB_WIDEN); } + #endif *************** *** 892,898 **** rtx dynamic_offset = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx, ! stack_pointer_rtx, 0, 1, OPTAB_LIB_WIDEN); size = expand_binop (Pmode, add_optab, size, dynamic_offset, ! 0, 1, OPTAB_LIB_WIDEN); } #endif /* SETJMP_VIA_SAVE_AREA */ --- 895,901 ---- rtx dynamic_offset = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx, ! stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN); size = expand_binop (Pmode, add_optab, size, dynamic_offset, ! NULL_RTX, 1, OPTAB_LIB_WIDEN); } #endif /* SETJMP_VIA_SAVE_AREA */ *************** *** 913,917 **** --- 916,924 ---- #ifdef STACK_BOUNDARY + /* If we added a variable amount to SIZE, + we can no longer assume it is aligned. */ + #if !defined (SETJMP_VIA_SAVE_AREA) && !defined (MUST_ALIGN) if (known_align % STACK_BOUNDARY != 0) + #endif size = round_push (size); #endif *************** *** 955,969 **** #ifdef MUST_ALIGN if (known_align % BIGGEST_ALIGNMENT != 0) { target = expand_divmod (0, CEIL_DIV_EXPR, Pmode, target, ! gen_rtx (CONST_INT, VOIDmode, ! BIGGEST_ALIGNMENT / BITS_PER_UNIT), ! 0, 1); target = expand_mult (Pmode, target, ! gen_rtx (CONST_INT, VOIDmode, ! BIGGEST_ALIGNMENT / BITS_PER_UNIT), ! 0, 1); } #endif --- 962,978 ---- #ifdef MUST_ALIGN + #if 0 /* Even if we know the stack pointer has enough alignment, + there's no way to tell whether virtual_stack_dynamic_rtx shares that + alignment, so we still need to round the address up. */ if (known_align % BIGGEST_ALIGNMENT != 0) + #endif { target = expand_divmod (0, CEIL_DIV_EXPR, Pmode, target, ! GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT), ! NULL_RTX, 1); target = expand_mult (Pmode, target, ! GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT), ! NULL_RTX, 1); } #endif diff -rc2N gcc-2.2.2/expmed.c gcc-2.3.1/expmed.c *** gcc-2.2.2/expmed.c Wed May 27 16:52:20 1992 --- gcc-2.3.1/expmed.c Mon Oct 5 02:35:14 1992 *************** *** 63,69 **** to see what insns exist. */ rtx reg = gen_rtx (REG, word_mode, FIRST_PSEUDO_REGISTER); ! rtx pow2 = gen_rtx (CONST_INT, VOIDmode, 32); rtx lea; ! int i, dummy; add_cost = rtx_cost (gen_rtx (PLUS, word_mode, reg, reg), SET); --- 63,70 ---- to see what insns exist. */ rtx reg = gen_rtx (REG, word_mode, FIRST_PSEUDO_REGISTER); ! rtx pow2 = GEN_INT (32); rtx lea; ! HOST_WIDE_INT i; ! int dummy; add_cost = rtx_cost (gen_rtx (PLUS, word_mode, reg, reg), SET); *************** *** 72,76 **** estimate of typical costs. 1 or 2 might have quirks. */ ! gen_rtx (CONST_INT, VOIDmode, 3)), SET); mult_cost = rtx_cost (gen_rtx (MULT, word_mode, reg, reg), SET); negate_cost = rtx_cost (gen_rtx (NEG, word_mode, reg), SET); --- 73,77 ---- estimate of typical costs. 1 or 2 might have quirks. */ ! GEN_INT (3)), SET); mult_cost = rtx_cost (gen_rtx (MULT, word_mode, reg, reg), SET); negate_cost = rtx_cost (gen_rtx (NEG, word_mode, reg), SET); *************** *** 78,85 **** /* 999999 is chosen to avoid any plausible faster special case. */ mult_is_very_cheap ! = (rtx_cost (gen_rtx (MULT, word_mode, reg, ! gen_rtx (CONST_INT, VOIDmode, 999999)), SET) ! < rtx_cost (gen_rtx (LSHIFT, word_mode, reg, ! gen_rtx (CONST_INT, VOIDmode, 7)), SET)); sdiv_pow2_cheap --- 79,84 ---- /* 999999 is chosen to avoid any plausible faster special case. */ mult_is_very_cheap ! = (rtx_cost (gen_rtx (MULT, word_mode, reg, GEN_INT (999999)), SET) ! < rtx_cost (gen_rtx (LSHIFT, word_mode, reg, GEN_INT (7)), SET)); sdiv_pow2_cheap *************** *** 93,98 **** lea = gen_rtx (SET, VOIDmode, reg, gen_rtx (PLUS, word_mode, ! gen_rtx (MULT, word_mode, reg, ! gen_rtx (CONST_INT, VOIDmode, i)), reg)); /* Using 0 as second argument is not quite right, --- 92,96 ---- lea = gen_rtx (SET, VOIDmode, reg, gen_rtx (PLUS, word_mode, ! gen_rtx (MULT, word_mode, reg, GEN_INT (i)), reg)); /* Using 0 as second argument is not quite right, *************** *** 119,135 **** if (GET_CODE (x) == CONST_INT) { ! int val = - INTVAL (x); ! if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT) { /* Sign extend the value from the bits that are significant. */ ! if (val & (1 << (GET_MODE_BITSIZE (mode) - 1))) ! val |= (-1) << GET_MODE_BITSIZE (mode); else ! val &= (1 << GET_MODE_BITSIZE (mode)) - 1; } ! return gen_rtx (CONST_INT, VOIDmode, val); } else ! return expand_unop (GET_MODE (x), neg_optab, x, 0, 0); } --- 117,133 ---- if (GET_CODE (x) == CONST_INT) { ! HOST_WIDE_INT val = - INTVAL (x); ! if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT) { /* Sign extend the value from the bits that are significant. */ ! if (val & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))) ! val |= (HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (mode); else ! val &= ((HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (mode)) - 1; } ! return GEN_INT (val); } else ! return expand_unop (GET_MODE (x), neg_optab, x, NULL_RTX, 0); } *************** *** 426,433 **** value1 = force_reg (maxmode, value1); ! pat = gen_insv (xop0, ! gen_rtx (CONST_INT, VOIDmode, bitsize), ! gen_rtx (CONST_INT, VOIDmode, xbitpos), ! value1); if (pat) emit_insn (pat); --- 424,428 ---- value1 = force_reg (maxmode, value1); ! pat = gen_insv (xop0, GEN_INT (bitsize), GEN_INT (xbitpos), value1); if (pat) emit_insn (pat); *************** *** 547,559 **** if (GET_CODE (value) == CONST_INT) { ! register int v = INTVAL (value); ! if (bitsize < HOST_BITS_PER_INT) ! v &= (1 << bitsize) - 1; if (v == 0) all_zero = 1; ! else if ((bitsize < HOST_BITS_PER_INT && v == (1 << bitsize) - 1) ! || (bitsize == HOST_BITS_PER_INT && v == -1)) all_one = 1; --- 542,555 ---- if (GET_CODE (value) == CONST_INT) { ! register HOST_WIDE_INT v = INTVAL (value); ! if (bitsize < HOST_BITS_PER_WIDE_INT) ! v &= ((HOST_WIDE_INT) 1 << bitsize) - 1; if (v == 0) all_zero = 1; ! else if ((bitsize < HOST_BITS_PER_WIDE_INT ! && v == ((HOST_WIDE_INT) 1 << bitsize) - 1) ! || (bitsize == HOST_BITS_PER_WIDE_INT && v == -1)) all_one = 1; *************** *** 588,595 **** value = expand_binop (mode, and_optab, value, mask_rtx (mode, 0, bitsize, 0), ! 0, 1, OPTAB_LIB_WIDEN); if (bitpos > 0) value = expand_shift (LSHIFT_EXPR, mode, value, ! build_int_2 (bitpos, 0), 0, 1); } --- 584,591 ---- value = expand_binop (mode, and_optab, value, mask_rtx (mode, 0, bitsize, 0), ! NULL_RTX, 1, OPTAB_LIB_WIDEN); if (bitpos > 0) value = expand_shift (LSHIFT_EXPR, mode, value, ! build_int_2 (bitpos, 0), NULL_RTX, 1); } *************** *** 656,671 **** if (GET_CODE (value) == CONST_INT) { ! part1 = gen_rtx (CONST_INT, VOIDmode, ! (unsigned) (INTVAL (value)) >> bitsize_2); ! part2 = gen_rtx (CONST_INT, VOIDmode, ! (unsigned) (INTVAL (value)) & ((1 << bitsize_2) - 1)); } else { part1 = extract_fixed_bit_field (word_mode, value, 0, bitsize_1, ! BITS_PER_WORD - bitsize, 0, 1, BITS_PER_WORD); part2 = extract_fixed_bit_field (word_mode, value, 0, bitsize_2, ! BITS_PER_WORD - bitsize_2, 0, 1, BITS_PER_WORD); } --- 652,666 ---- if (GET_CODE (value) == CONST_INT) { ! part1 = GEN_INT ((unsigned HOST_WIDE_INT) (INTVAL (value)) >> bitsize_2); ! part2 = GEN_INT ((unsigned HOST_WIDE_INT) (INTVAL (value)) ! & (((HOST_WIDE_INT) 1 << bitsize_2) - 1)); } else { part1 = extract_fixed_bit_field (word_mode, value, 0, bitsize_1, ! BITS_PER_WORD - bitsize, NULL_RTX, 1, BITS_PER_WORD); part2 = extract_fixed_bit_field (word_mode, value, 0, bitsize_2, ! BITS_PER_WORD - bitsize_2, NULL_RTX, 1, BITS_PER_WORD); } *************** *** 674,688 **** if (GET_CODE (value) == CONST_INT) { ! part1 = gen_rtx (CONST_INT, VOIDmode, ! (unsigned) (INTVAL (value)) & ((1 << bitsize_1) - 1)); ! part2 = gen_rtx (CONST_INT, VOIDmode, ! (unsigned) (INTVAL (value)) >> bitsize_1); } else { part1 = extract_fixed_bit_field (word_mode, value, 0, bitsize_1, 0, ! 0, 1, BITS_PER_WORD); part2 = extract_fixed_bit_field (word_mode, value, 0, bitsize_2, ! bitsize_1, 0, 1, BITS_PER_WORD); } #endif --- 669,682 ---- if (GET_CODE (value) == CONST_INT) { ! part1 = GEN_INT ((unsigned HOST_WIDE_INT) (INTVAL (value)) ! & (((HOST_WIDE_INT) 1 << bitsize_1) - 1)); ! part2 = GEN_INT ((unsigned HOST_WIDE_INT) (INTVAL (value)) >> bitsize_1); } else { part1 = extract_fixed_bit_field (word_mode, value, 0, bitsize_1, 0, ! NULL_RTX, 1, BITS_PER_WORD); part2 = extract_fixed_bit_field (word_mode, value, 0, bitsize_2, ! bitsize_1, NULL_RTX, 1, BITS_PER_WORD); } #endif *************** *** 770,774 **** if (tmode == VOIDmode) tmode = mode; - while (GET_CODE (op0) == SUBREG) { --- 764,767 ---- *************** *** 990,995 **** xtarget = gen_reg_rtx (maxmode); ! bitsize_rtx = gen_rtx (CONST_INT, VOIDmode, bitsize); ! bitpos_rtx = gen_rtx (CONST_INT, VOIDmode, xbitpos); pat = gen_extzv (protect_from_queue (xtarget, 1), --- 983,988 ---- xtarget = gen_reg_rtx (maxmode); ! bitsize_rtx = GEN_INT (bitsize); ! bitpos_rtx = GEN_INT (xbitpos); pat = gen_extzv (protect_from_queue (xtarget, 1), *************** *** 1122,1127 **** xtarget = gen_reg_rtx (maxmode); ! bitsize_rtx = gen_rtx (CONST_INT, VOIDmode, bitsize); ! bitpos_rtx = gen_rtx (CONST_INT, VOIDmode, xbitpos); pat = gen_extv (protect_from_queue (xtarget, 1), --- 1115,1120 ---- xtarget = gen_reg_rtx (maxmode); ! bitsize_rtx = GEN_INT (bitsize); ! bitpos_rtx = GEN_INT (xbitpos); pat = gen_extv (protect_from_queue (xtarget, 1), *************** *** 1328,1348 **** int bitpos, bitsize, complement; { ! int masklow, maskhigh; ! if (bitpos < HOST_BITS_PER_INT) ! masklow = -1 << bitpos; else masklow = 0; ! if (bitpos + bitsize < HOST_BITS_PER_INT) ! masklow &= (unsigned) -1 >> (HOST_BITS_PER_INT - bitpos - bitsize); ! if (bitpos <= HOST_BITS_PER_INT) maskhigh = -1; else ! maskhigh = -1 << (bitpos - HOST_BITS_PER_INT); ! if (bitpos + bitsize > HOST_BITS_PER_INT) ! maskhigh &= (unsigned) -1 >> (2 * HOST_BITS_PER_INT - bitpos - bitsize); else maskhigh = 0; --- 1321,1343 ---- int bitpos, bitsize, complement; { ! HOST_WIDE_INT masklow, maskhigh; ! if (bitpos < HOST_BITS_PER_WIDE_INT) ! masklow = (HOST_WIDE_INT) -1 << bitpos; else masklow = 0; ! if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT) ! masklow &= ((unsigned HOST_WIDE_INT) -1 ! >> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize)); ! if (bitpos <= HOST_BITS_PER_WIDE_INT) maskhigh = -1; else ! maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT); ! if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT) ! maskhigh &= ((unsigned HOST_WIDE_INT) -1 ! >> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize)); else maskhigh = 0; *************** *** 1366,1384 **** int bitpos, bitsize; { ! unsigned v = INTVAL (value); ! int low, high; ! if (bitsize < HOST_BITS_PER_INT) ! v &= ~(-1 << bitsize); ! if (bitpos < HOST_BITS_PER_INT) { low = v << bitpos; ! high = (bitpos > 0 ? (v >> (HOST_BITS_PER_INT - bitpos)) : 0); } else { low = 0; ! high = v << (bitpos - HOST_BITS_PER_INT); } --- 1361,1379 ---- int bitpos, bitsize; { ! unsigned HOST_WIDE_INT v = INTVAL (value); ! HOST_WIDE_INT low, high; ! if (bitsize < HOST_BITS_PER_WIDE_INT) ! v &= ~((HOST_WIDE_INT) -1 << bitsize); ! if (bitpos < HOST_BITS_PER_WIDE_INT) { low = v << bitpos; ! high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0); } else { low = 0; ! high = v << (bitpos - HOST_BITS_PER_WIDE_INT); } *************** *** 1418,1422 **** part1 = extract_fixed_bit_field (word_mode, word, GET_CODE (op0) == MEM ? offset : 0, ! bitsize_1, bitpos % unit, 0, 1, align); /* Offset op0 by 1 word to get to the following one. */ --- 1413,1418 ---- part1 = extract_fixed_bit_field (word_mode, word, GET_CODE (op0) == MEM ? offset : 0, ! bitsize_1, bitpos % unit, NULL_RTX, ! 1, align); /* Offset op0 by 1 word to get to the following one. */ *************** *** 1434,1438 **** ? CEIL (offset + 1, UNITS_PER_WORD) * UNITS_PER_WORD : 0), ! bitsize_2, 0, 0, 1, align); /* Shift the more significant part up to fit above the other part. */ --- 1430,1434 ---- ? CEIL (offset + 1, UNITS_PER_WORD) * UNITS_PER_WORD : 0), ! bitsize_2, 0, NULL_RTX, 1, align); /* Shift the more significant part up to fit above the other part. */ *************** *** 1447,1451 **** /* Combine the two parts with bitwise or. This works because we extracted both parts as unsigned bit fields. */ ! result = expand_binop (word_mode, ior_optab, part1, part2, 0, 1, OPTAB_LIB_WIDEN); --- 1443,1447 ---- /* Combine the two parts with bitwise or. This works because we extracted both parts as unsigned bit fields. */ ! result = expand_binop (word_mode, ior_optab, part1, part2, NULL_RTX, 1, OPTAB_LIB_WIDEN); *************** *** 1455,1461 **** /* Signed bit field: sign-extend with two arithmetic shifts. */ result = expand_shift (LSHIFT_EXPR, word_mode, result, ! build_int_2 (BITS_PER_WORD - bitsize, 0), 0, 0); return expand_shift (RSHIFT_EXPR, word_mode, result, ! build_int_2 (BITS_PER_WORD - bitsize, 0), 0, 0); } --- 1451,1458 ---- /* Signed bit field: sign-extend with two arithmetic shifts. */ result = expand_shift (LSHIFT_EXPR, word_mode, result, ! build_int_2 (BITS_PER_WORD - bitsize, 0), ! NULL_RTX, 0); return expand_shift (RSHIFT_EXPR, word_mode, result, ! build_int_2 (BITS_PER_WORD - bitsize, 0), NULL_RTX, 0); } *************** *** 1511,1515 **** on all machines. */ ! op1 = expand_expr (amount, 0, VOIDmode, 0); if (op1 == const0_rtx) --- 1508,1512 ---- on all machines. */ ! op1 = expand_expr (amount, NULL_RTX, VOIDmode, 0); if (op1 == const0_rtx) *************** *** 1584,1589 **** && GET_MODE_SIZE (mode) < GET_MODE_SIZE (output_mode))) { ! /* Note convert_to_mode does protect_from_queue. */ ! rtx shifted1 = convert_to_mode (output_mode, shifted, 1); enum machine_mode length_mode = insn_operand_mode[(int) CODE_FOR_extzv][2]; --- 1581,1587 ---- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (output_mode))) { ! rtx shifted1 = convert_to_mode (output_mode, ! protect_from_queue (shifted, 0), ! 1); enum machine_mode length_mode = insn_operand_mode[(int) CODE_FOR_extzv][2]; *************** *** 1613,1616 **** --- 1611,1615 ---- target1 = gen_reg_rtx (output_mode); + xop1 = protect_from_queue (xop1, 0); xop1 = convert_to_mode (pos_mode, xop1, TREE_UNSIGNED (TREE_TYPE (amount))); *************** *** 1625,1640 **** wordsize minus # bits to shift by. */ if (GET_CODE (xop1) == CONST_INT) ! width = gen_rtx (CONST_INT, VOIDmode, ! (GET_MODE_BITSIZE (mode) - INTVAL (op1))); else { /* Now get the width in the proper mode. */ width = convert_to_mode (length_mode, op1, TREE_UNSIGNED (TREE_TYPE (amount))); width = expand_binop (length_mode, sub_optab, ! gen_rtx (CONST_INT, VOIDmode, ! GET_MODE_BITSIZE (mode)), ! width, 0, 0, OPTAB_LIB_WIDEN); } --- 1624,1638 ---- wordsize minus # bits to shift by. */ if (GET_CODE (xop1) == CONST_INT) ! width = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (op1)); else { /* Now get the width in the proper mode. */ + op1 = protect_from_queue (op1, 0); width = convert_to_mode (length_mode, op1, TREE_UNSIGNED (TREE_TYPE (amount))); width = expand_binop (length_mode, sub_optab, ! GEN_INT (GET_MODE_BITSIZE (mode)), ! width, NULL_RTX, 0, OPTAB_LIB_WIDEN); } *************** *** 1701,1711 **** static struct algorithm synth_mult (t, add_cost, shift_cost, max_cost) ! unsigned int t; int add_cost, shift_cost; int max_cost; { int m, n; ! struct algorithm *best_alg = (struct algorithm *)alloca (sizeof (struct algorithm)); ! struct algorithm *alg_in = (struct algorithm *)alloca (sizeof (struct algorithm)); unsigned int cost; --- 1699,1711 ---- static struct algorithm synth_mult (t, add_cost, shift_cost, max_cost) ! unsigned HOST_WIDE_INT t; int add_cost, shift_cost; int max_cost; { int m, n; ! struct algorithm *best_alg ! = (struct algorithm *)alloca (sizeof (struct algorithm)); ! struct algorithm *alg_in ! = (struct algorithm *)alloca (sizeof (struct algorithm)); unsigned int cost; *************** *** 1757,1767 **** for (m = floor_log2 (t) - 1; m >= 2; m--) { ! int m_exp_2 = 1 << m; ! int d; d = m_exp_2 + 1; if (t % d == 0) { ! int q = t / d; cost = add_cost + shift_cost * 2; --- 1757,1767 ---- for (m = floor_log2 (t) - 1; m >= 2; m--) { ! HOST_WIDE_INT m_exp_2 = (HOST_WIDE_INT) 1 << m; ! HOST_WIDE_INT d; d = m_exp_2 + 1; if (t % d == 0) { ! HOST_WIDE_INT q = t / d; cost = add_cost + shift_cost * 2; *************** *** 1792,1796 **** if (t % d == 0) { ! int q = t / d; cost = add_cost + shift_cost * 2; --- 1792,1796 ---- if (t % d == 0) { ! HOST_WIDE_INT q = t / d; cost = add_cost + shift_cost * 2; *************** *** 1822,1827 **** { ! int q; ! int w; q = t & -t; /* get out lsb */ --- 1822,1827 ---- { ! HOST_WIDE_INT q; ! HOST_WIDE_INT w; q = t & -t; /* get out lsb */ *************** *** 1862,1867 **** { ! int q; ! int w; q = t & -t; /* get out lsb */ --- 1862,1867 ---- { ! HOST_WIDE_INT q; ! HOST_WIDE_INT w; q = t & -t; /* get out lsb */ *************** *** 1959,1963 **** if ((CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) >= 0) || (CONST_DOUBLE_HIGH (op1) == -1 && CONST_DOUBLE_LOW (op1) < 0)) ! const_op1 = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); } --- 1959,1963 ---- if ((CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) >= 0) || (CONST_DOUBLE_HIGH (op1) == -1 && CONST_DOUBLE_LOW (op1) < 0)) ! const_op1 = GEN_INT (CONST_DOUBLE_LOW (op1)); } *************** *** 1971,1975 **** struct algorithm neg_alg; int negate = 0; ! int absval = INTVAL (op1); rtx last; --- 1971,1975 ---- struct algorithm neg_alg; int negate = 0; ! HOST_WIDE_INT absval = INTVAL (op1); rtx last; *************** *** 1983,1987 **** alg = synth_mult (absval, add_cost, shift_cost, mult_cost); neg_alg = synth_mult (- absval, add_cost, shift_cost, ! mult_cost - negate_cost); if (neg_alg.cost >= 0 && neg_alg.cost + negate_cost < alg.cost) --- 1983,1988 ---- alg = synth_mult (absval, add_cost, shift_cost, mult_cost); neg_alg = synth_mult (- absval, add_cost, shift_cost, ! (alg.cost >= 0 ? alg.cost : mult_cost) ! - negate_cost); if (neg_alg.cost >= 0 && neg_alg.cost + negate_cost < alg.cost) *************** *** 2016,2021 **** abort (); accum = expand_shift (LSHIFT_EXPR, mode, op0, ! build_int_2 (log, 0), ! 0, 0); } --- 2017,2021 ---- abort (); accum = expand_shift (LSHIFT_EXPR, mode, op0, ! build_int_2 (log, 0), NULL_RTX, 0); } *************** *** 2036,2040 **** { tem = expand_shift (LSHIFT_EXPR, mode, op0, ! build_int_2 (log, 0), 0, 0); accum = force_operand (gen_rtx (PLUS, mode, accum, tem), accum); --- 2036,2040 ---- { tem = expand_shift (LSHIFT_EXPR, mode, op0, ! build_int_2 (log, 0), NULL_RTX, 0); accum = force_operand (gen_rtx (PLUS, mode, accum, tem), accum); *************** *** 2055,2059 **** { tem = expand_shift (LSHIFT_EXPR, mode, op0, ! build_int_2 (log, 0), 0, 0); accum = force_operand (gen_rtx (MINUS, mode, accum, tem), accum); --- 2055,2059 ---- { tem = expand_shift (LSHIFT_EXPR, mode, op0, ! build_int_2 (log, 0), NULL_RTX, 0); accum = force_operand (gen_rtx (MINUS, mode, accum, tem), accum); *************** *** 2074,2082 **** factors_seen = 1; tem = expand_shift (LSHIFT_EXPR, mode, accum, ! build_int_2 (log, 0), 0, 0); log = floor_log2 (alg.coeff[opno + 1]); accum = expand_shift (LSHIFT_EXPR, mode, accum, ! build_int_2 (log, 0), 0, 0); opno++; if (alg.op[opno] == alg_add) --- 2074,2082 ---- factors_seen = 1; tem = expand_shift (LSHIFT_EXPR, mode, accum, ! build_int_2 (log, 0), NULL_RTX, 0); log = floor_log2 (alg.coeff[opno + 1]); accum = expand_shift (LSHIFT_EXPR, mode, accum, ! build_int_2 (log, 0), NULL_RTX, 0); opno++; if (alg.op[opno] == alg_add) *************** *** 2106,2112 **** = gen_rtx (EXPR_LIST, REG_EQUAL, gen_rtx (MULT, mode, op0, ! negate ? gen_rtx (CONST_INT, ! VOIDmode, absval) ! : op1), REG_NOTES (last)); } --- 2106,2110 ---- = gen_rtx (EXPR_LIST, REG_EQUAL, gen_rtx (MULT, mode, op0, ! negate ? GEN_INT (absval) : op1), REG_NOTES (last)); } *************** *** 2155,2158 **** --- 2153,2157 ---- enum machine_mode compute_mode; int log = -1; + int size; int can_clobber_op0; int mod_insn_no_good = 0; *************** *** 2160,2163 **** --- 2159,2168 ---- optab optab1, optab2; + /* We shouldn't be called with op1 == const1_rtx, but some of the + code below will malfunction if we are, so check here and handle + the special case if so. */ + if (op1 == const1_rtx) + return rem_flag ? const0_rtx : op0; + /* Don't use the function value register as a target since we have to read it as well as write it, *************** *** 2245,2248 **** --- 2250,2255 ---- compute_mode = mode; + size = GET_MODE_BITSIZE (compute_mode); + /* Now convert to the best mode to use. Show we made a copy of OP0 and hence we can clobber it (we cannot use a SUBREG to widen *************** *** 2277,2281 **** if (log >= 0 && ! unsignedp) { - rtx label = gen_label_rtx (); if (! can_clobber_op0) { --- 2284,2287 ---- *************** *** 2286,2293 **** op0 = force_reg (compute_mode, op0); } ! emit_cmp_insn (adjusted_op0, const0_rtx, GE, 0, compute_mode, 0, 0); ! emit_jump_insn (gen_bge (label)); ! expand_inc (adjusted_op0, plus_constant (op1, -1)); ! emit_label (label); mod_insn_no_good = 1; } --- 2292,2320 ---- op0 = force_reg (compute_mode, op0); } ! /* Here we need to add OP1-1 if OP0 is negative, 0 otherwise. ! This can be computed without jumps by arithmetically shifting ! OP0 right LOG-1 places and then shifting right logically ! SIZE-LOG bits. The resulting value is unconditionally added ! to OP0. */ ! if (log == 1 || BRANCH_COST >= 3) ! { ! rtx temp = gen_reg_rtx (compute_mode); ! temp = copy_to_suggested_reg (adjusted_op0, temp, compute_mode); ! temp = expand_shift (RSHIFT_EXPR, compute_mode, temp, ! build_int_2 (log - 1, 0), NULL_RTX, 0); ! temp = expand_shift (RSHIFT_EXPR, compute_mode, temp, ! build_int_2 (size - log, 0), ! temp, 1); ! expand_inc (adjusted_op0, temp); ! } ! else ! { ! rtx label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, GE, ! NULL_RTX, compute_mode, 0, 0); ! emit_jump_insn (gen_bge (label)); ! expand_inc (adjusted_op0, plus_constant (op1, -1)); ! emit_label (label); ! } mod_insn_no_good = 1; } *************** *** 2307,2311 **** op0 = force_reg (compute_mode, op0); } ! emit_cmp_insn (adjusted_op0, const0_rtx, GE, 0, compute_mode, 0, 0); emit_jump_insn (gen_bge (label)); expand_dec (adjusted_op0, op1); --- 2334,2339 ---- op0 = force_reg (compute_mode, op0); } ! emit_cmp_insn (adjusted_op0, const0_rtx, GE, ! NULL_RTX, compute_mode, 0, 0); emit_jump_insn (gen_bge (label)); expand_dec (adjusted_op0, op1); *************** *** 2332,2336 **** { label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, LE, 0, compute_mode, 0, 0); emit_jump_insn (gen_ble (label)); } --- 2360,2365 ---- { label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, LE, ! NULL_RTX, compute_mode, 0, 0); emit_jump_insn (gen_ble (label)); } *************** *** 2344,2348 **** adjusted_op0 = expand_binop (compute_mode, add_optab, adjusted_op0, plus_constant (op1, -1), ! 0, 0, OPTAB_LIB_WIDEN); } mod_insn_no_good = 1; --- 2373,2377 ---- adjusted_op0 = expand_binop (compute_mode, add_optab, adjusted_op0, plus_constant (op1, -1), ! NULL_RTX, 0, OPTAB_LIB_WIDEN); } mod_insn_no_good = 1; *************** *** 2362,2373 **** { op1 = expand_shift (RSHIFT_EXPR, compute_mode, op1, ! integer_one_node, 0, 0); if (! unsignedp) { ! rtx label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, GE, 0, compute_mode, 0, 0); ! emit_jump_insn (gen_bge (label)); ! expand_unop (compute_mode, neg_optab, op1, op1, 0); ! emit_label (label); } expand_inc (adjusted_op0, op1); --- 2391,2419 ---- { op1 = expand_shift (RSHIFT_EXPR, compute_mode, op1, ! integer_one_node, NULL_RTX, 0); if (! unsignedp) { ! if (BRANCH_COST >= 2) ! { ! /* Negate OP1 if OP0 < 0. Do this by computing a temporary ! that has all bits equal to the sign bit and exclusive ! or-ing it with OP1. */ ! rtx temp = gen_reg_rtx (compute_mode); ! temp = copy_to_suggested_reg (adjusted_op0, temp, compute_mode); ! temp = expand_shift (RSHIFT_EXPR, compute_mode, temp, ! build_int_2 (size - 1, 0), ! NULL_RTX, 0); ! op1 = expand_binop (compute_mode, xor_optab, op1, temp, op1, ! unsignedp, OPTAB_LIB_WIDEN); ! } ! else ! { ! rtx label = gen_label_rtx (); ! emit_cmp_insn (adjusted_op0, const0_rtx, GE, NULL_RTX, ! compute_mode, 0, 0); ! emit_jump_insn (gen_bge (label)); ! expand_unop (compute_mode, neg_optab, op1, op1, 0); ! emit_label (label); ! } } expand_inc (adjusted_op0, op1); *************** *** 2375,2379 **** else { ! op1 = gen_rtx (CONST_INT, VOIDmode, (1 << log) / 2); expand_inc (adjusted_op0, op1); } --- 2421,2425 ---- else { ! op1 = GEN_INT (((HOST_WIDE_INT) 1 << log) / 2); expand_inc (adjusted_op0, op1); } *************** *** 2387,2392 **** if (log >= 0) result = expand_binop (compute_mode, and_optab, adjusted_op0, ! gen_rtx (CONST_INT, VOIDmode, ! (1 << log) - 1), target, 1, OPTAB_LIB_WIDEN); else --- 2433,2437 ---- if (log >= 0) result = expand_binop (compute_mode, and_optab, adjusted_op0, ! GEN_INT (((HOST_WIDE_INT) 1 << log) - 1), target, 1, OPTAB_LIB_WIDEN); else *************** *** 2404,2408 **** ? udivmod_optab : sdivmod_optab, adjusted_op0, op1, ! 0, result, unsignedp)) result = 0; } --- 2449,2453 ---- ? udivmod_optab : sdivmod_optab, adjusted_op0, op1, ! NULL_RTX, result, unsignedp)) result = 0; } *************** *** 2422,2431 **** don't use a divide subroutine. */ result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! adjusted_op0, op1, 0, unsignedp, OPTAB_WIDEN); else { /* Try a quotient insn, but not a library call. */ result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! adjusted_op0, op1, rem_flag ? 0 : target, unsignedp, OPTAB_WIDEN); if (result == 0) --- 2467,2478 ---- don't use a divide subroutine. */ result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! adjusted_op0, op1, NULL_RTX, unsignedp, ! OPTAB_WIDEN); else { /* Try a quotient insn, but not a library call. */ result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! adjusted_op0, op1, ! rem_flag ? NULL_RTX : target, unsignedp, OPTAB_WIDEN); if (result == 0) *************** *** 2436,2440 **** if (! expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab, adjusted_op0, op1, ! result, 0, unsignedp)) result = 0; } --- 2483,2487 ---- if (! expand_twoval_binop (unsignedp ? udivmod_optab : sdivmod_optab, adjusted_op0, op1, ! result, NULL_RTX, unsignedp)) result = 0; } *************** *** 2443,2447 **** if (result == 0) result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! adjusted_op0, op1, rem_flag ? 0 : target, unsignedp, OPTAB_LIB_WIDEN); } --- 2490,2495 ---- if (result == 0) result = sign_expand_binop (compute_mode, udiv_optab, sdiv_optab, ! adjusted_op0, op1, ! rem_flag ? NULL_RTX : target, unsignedp, OPTAB_LIB_WIDEN); } *************** *** 2612,2616 **** tem = expand_binop (mode, and_optab, op0, op1, target, 0, OPTAB_LIB_WIDEN); else if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT) ! tem = gen_rtx (CONST_INT, VOIDmode, INTVAL (op0) & INTVAL (op1)); else abort (); --- 2660,2664 ---- tem = expand_binop (mode, and_optab, op0, op1, target, 0, OPTAB_LIB_WIDEN); else if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT) ! tem = GEN_INT (INTVAL (op0) & INTVAL (op1)); else abort (); *************** *** 2698,2703 **** && GET_MODE_CLASS (mode) == MODE_INT && (normalizep || STORE_FLAG_VALUE == 1 ! || (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! && STORE_FLAG_VALUE == 1 << (GET_MODE_BITSIZE (mode) - 1)))) { rtx subtarget = target; --- 2746,2752 ---- && GET_MODE_CLASS (mode) == MODE_INT && (normalizep || STORE_FLAG_VALUE == 1 ! || (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT ! && (STORE_FLAG_VALUE ! == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))))) { rtx subtarget = target; *************** *** 2708,2711 **** --- 2757,2761 ---- if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode)) { + op0 = protect_from_queue (op0, 0); op0 = convert_to_mode (target_mode, op0, 0); mode = target_mode; *************** *** 2743,2747 **** last = get_last_insn (); ! comparison = compare_from_rtx (op0, op1, code, unsignedp, mode, 0, 0); if (GET_CODE (comparison) == CONST_INT) return (comparison == const0_rtx ? const0_rtx --- 2793,2798 ---- last = get_last_insn (); ! comparison ! = compare_from_rtx (op0, op1, code, unsignedp, mode, NULL_RTX, 0); if (GET_CODE (comparison) == CONST_INT) return (comparison == const0_rtx ? const0_rtx *************** *** 2774,2780 **** convert_move (target, subtarget, (GET_MODE_BITSIZE (compare_mode) ! <= HOST_BITS_PER_INT) && 0 == (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (compare_mode) -1)))); op0 = target; compare_mode = target_mode; --- 2825,2832 ---- convert_move (target, subtarget, (GET_MODE_BITSIZE (compare_mode) ! <= HOST_BITS_PER_WIDE_INT) && 0 == (STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (compare_mode) -1)))); op0 = target; compare_mode = target_mode; *************** *** 2783,2786 **** --- 2835,2844 ---- op0 = subtarget; + /* If we want to keep subexpressions around, don't reuse our + last target. */ + + if (preserve_subexpressions_p ()) + subtarget = 0; + /* Now normalize to the proper value in COMPARE_MODE. Sometimes we don't have to do anything. */ *************** *** 2793,2799 **** makes it hard to use a value of just the sign bit due to ANSI integer constant typing rules. */ ! else if (GET_MODE_BITSIZE (compare_mode) <= HOST_BITS_PER_INT && (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (compare_mode) - 1)))) op0 = expand_shift (RSHIFT_EXPR, compare_mode, op0, size_int (GET_MODE_BITSIZE (compare_mode) - 1), --- 2851,2858 ---- makes it hard to use a value of just the sign bit due to ANSI integer constant typing rules. */ ! else if (GET_MODE_BITSIZE (compare_mode) <= HOST_BITS_PER_WIDE_INT && (STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (compare_mode) - 1)))) op0 = expand_shift (RSHIFT_EXPR, compare_mode, op0, size_int (GET_MODE_BITSIZE (compare_mode) - 1), *************** *** 2869,2874 **** normalizep = STORE_FLAG_VALUE; ! else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT ! && STORE_FLAG_VALUE == 1 << (GET_MODE_BITSIZE (mode) - 1)) ; else --- 2928,2934 ---- normalizep = STORE_FLAG_VALUE; ! else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT ! && (STORE_FLAG_VALUE ! == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))) ; else *************** *** 2932,2935 **** --- 2992,2996 ---- { mode = word_mode; + op0 = protect_from_queue (op0, 0); tem = convert_to_mode (mode, op0, 1); } diff -rc2N gcc-2.2.2/expr.c gcc-2.3.1/expr.c *** gcc-2.2.2/expr.c Wed Jun 3 15:42:57 1992 --- gcc-2.3.1/expr.c Sun Oct 25 14:47:00 1992 *************** *** 103,111 **** static void do_jump_by_parts_greater (); /* MOVE_RATIO is the number of move instructions that is better than a block move. */ #ifndef MOVE_RATIO ! #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) #define MOVE_RATIO 2 #else --- 103,118 ---- static void do_jump_by_parts_greater (); + /* Record for each mode whether we can move a register directly to or + from an object of that mode in memory. If we can't, we won't try + to use that mode directly when accessing a field of that mode. */ + + static char direct_load[NUM_MACHINE_MODES]; + static char direct_store[NUM_MACHINE_MODES]; + /* MOVE_RATIO is the number of move instructions that is better than a block move. */ #ifndef MOVE_RATIO ! #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti) #define MOVE_RATIO 2 #else *************** *** 116,119 **** --- 123,129 ---- #endif + /* This array records the insn_code of insns to perform block moves. */ + static enum insn_code movstr_optab[NUM_MACHINE_MODES]; + /* SLOW_UNALIGNED_ACCESS is non-zero if unaligned accesses are very slow. */ *************** *** 122,125 **** --- 132,210 ---- #endif + /* This is run once per compilation to set up which modes can be used + directly in memory and to initialize the block move optab. */ + + void + init_expr_once () + { + rtx insn, pat; + enum machine_mode mode; + rtx mem = gen_rtx (MEM, VOIDmode, stack_pointer_rtx); + + start_sequence (); + insn = emit_insn (gen_rtx (SET, 0, 0)); + pat = PATTERN (insn); + + for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES; + mode = (enum machine_mode) ((int) mode + 1)) + { + int regno; + rtx reg; + int num_clobbers; + + direct_load[(int) mode] = direct_store[(int) mode] = 0; + PUT_MODE (mem, mode); + + /* See if there is some register that can be used in this mode and + directly loaded or stored from memory. */ + + if (mode != VOIDmode && mode != BLKmode) + for (regno = 0; regno < FIRST_PSEUDO_REGISTER + && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0); + regno++) + { + if (! HARD_REGNO_MODE_OK (regno, mode)) + continue; + + reg = gen_rtx (REG, mode, regno); + + SET_SRC (pat) = mem; + SET_DEST (pat) = reg; + if (recog (pat, insn, &num_clobbers) >= 0) + direct_load[(int) mode] = 1; + + SET_SRC (pat) = reg; + SET_DEST (pat) = mem; + if (recog (pat, insn, &num_clobbers) >= 0) + direct_store[(int) mode] = 1; + } + + movstr_optab[(int) mode] = CODE_FOR_nothing; + } + + end_sequence (); + + #ifdef HAVE_movstrqi + if (HAVE_movstrqi) + movstr_optab[(int) QImode] = CODE_FOR_movstrqi; + #endif + #ifdef HAVE_movstrhi + if (HAVE_movstrhi) + movstr_optab[(int) HImode] = CODE_FOR_movstrhi; + #endif + #ifdef HAVE_movstrsi + if (HAVE_movstrsi) + movstr_optab[(int) SImode] = CODE_FOR_movstrsi; + #endif + #ifdef HAVE_movstrdi + if (HAVE_movstrdi) + movstr_optab[(int) DImode] = CODE_FOR_movstrdi; + #endif + #ifdef HAVE_movstrti + if (HAVE_movstrti) + movstr_optab[(int) TImode] = CODE_FOR_movstrti; + #endif + } + /* This is run at the start of compiling a function. */ *************** *** 190,194 **** { pending_chain = gen_rtx (QUEUED, GET_MODE (var), ! var, 0, 0, body, pending_chain); return pending_chain; } --- 275,279 ---- { pending_chain = gen_rtx (QUEUED, GET_MODE (var), ! var, NULL_RTX, NULL_RTX, body, pending_chain); return pending_chain; } *************** *** 340,343 **** --- 425,441 ---- abort (); + /* If FROM is a SUBREG that indicates that we have already done at least + the required extension, strip it. We don't handle such SUBREGs as + TO here. */ + + if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from) + && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from))) + >= GET_MODE_SIZE (to_mode)) + && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp) + from = gen_lowpart (to_mode, from), from_mode = to_mode; + + if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to)) + abort (); + if (to_mode == from_mode || (from_mode == VOIDmode && CONSTANT_P (from))) *************** *** 356,359 **** --- 454,464 ---- } #endif + #ifdef HAVE_extendsfxf2 + if (HAVE_extendsfxf2 && from_mode == SFmode && to_mode == XFmode) + { + emit_unop_insn (CODE_FOR_extendsfxf2, to, from, UNKNOWN); + return; + } + #endif #ifdef HAVE_extendsftf2 if (HAVE_extendsftf2 && from_mode == SFmode && to_mode == TFmode) *************** *** 363,366 **** --- 468,478 ---- } #endif + #ifdef HAVE_extenddfxf2 + if (HAVE_extenddfxf2 && from_mode == DFmode && to_mode == XFmode) + { + emit_unop_insn (CODE_FOR_extenddfxf2, to, from, UNKNOWN); + return; + } + #endif #ifdef HAVE_extenddftf2 if (HAVE_extenddftf2 && from_mode == DFmode && to_mode == TFmode) *************** *** 377,380 **** --- 489,499 ---- } #endif + #ifdef HAVE_truncxfsf2 + if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode) + { + emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN); + return; + } + #endif #ifdef HAVE_trunctfsf2 if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode) *************** *** 384,387 **** --- 503,513 ---- } #endif + #ifdef HAVE_truncxfdf2 + if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode) + { + emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN); + return; + } + #endif #ifdef HAVE_trunctfdf2 if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode) *************** *** 392,402 **** #endif ! if (from_mode == SFmode && to_mode == DFmode) ! libcall = extendsfdf2_libfunc; ! else if (from_mode == DFmode && to_mode == SFmode) ! libcall = truncdfsf2_libfunc; ! else ! /* This conversion is not implemented yet. There aren't any TFmode ! library calls. */ abort (); --- 518,587 ---- #endif ! libcall = (rtx) 0; ! switch (from_mode) ! { ! case SFmode: ! switch (to_mode) ! { ! case DFmode: ! libcall = extendsfdf2_libfunc; ! break; ! ! case XFmode: ! libcall = extendsfxf2_libfunc; ! break; ! ! case TFmode: ! libcall = extendsftf2_libfunc; ! break; ! } ! break; ! ! case DFmode: ! switch (to_mode) ! { ! case SFmode: ! libcall = truncdfsf2_libfunc; ! break; ! ! case XFmode: ! libcall = extenddfxf2_libfunc; ! break; ! ! case TFmode: ! libcall = extenddftf2_libfunc; ! break; ! } ! break; ! ! case XFmode: ! switch (to_mode) ! { ! case SFmode: ! libcall = truncxfsf2_libfunc; ! break; ! ! case DFmode: ! libcall = truncxfdf2_libfunc; ! break; ! } ! break; ! ! case TFmode: ! switch (to_mode) ! { ! case SFmode: ! libcall = trunctfsf2_libfunc; ! break; ! ! case DFmode: ! libcall = trunctfdf2_libfunc; ! break; ! } ! break; ! } ! ! if (libcall == (rtx) 0) ! /* This conversion is not implemented yet. */ abort (); *************** *** 424,427 **** --- 609,618 ---- != CODE_FOR_nothing) { + /* If FROM is a SUBREG, put it into a register. Do this + so that we always generate the same set of insns for + better cse'ing; if an intermediate assignment occurred, + we won't be doing the operation directly on the SUBREG. */ + if (optimize > 0 && GET_CODE (from) == SUBREG) + from = force_reg (from_mode, from); emit_unop_insn (code, to, from, equiv_code); return; *************** *** 462,466 **** && STORE_FLAG_VALUE == -1) { ! emit_cmp_insn (lowfrom, const0_rtx, NE, 0, lowpart_mode, 0, 0); fill_value = gen_reg_rtx (word_mode); emit_insn (gen_slt (fill_value)); --- 653,658 ---- && STORE_FLAG_VALUE == -1) { ! emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX, ! lowpart_mode, 0, 0); fill_value = gen_reg_rtx (word_mode); emit_insn (gen_slt (fill_value)); *************** *** 472,476 **** = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom, size_int (GET_MODE_BITSIZE (lowpart_mode) - 1), ! 0, 0); fill_value = convert_to_mode (word_mode, fill_value, 1); } --- 664,668 ---- = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom, size_int (GET_MODE_BITSIZE (lowpart_mode) - 1), ! NULL_RTX, 0); fill_value = convert_to_mode (word_mode, fill_value, 1); } *************** *** 493,497 **** end_sequence (); ! emit_no_conflict_block (insns, to, from, 0, gen_rtx (equiv_code, to_mode, from)); return; --- 685,689 ---- end_sequence (); ! emit_no_conflict_block (insns, to, from, NULL_RTX, gen_rtx (equiv_code, to_mode, from)); return; *************** *** 549,552 **** --- 741,745 ---- && ((GET_CODE (from) == MEM && ! MEM_VOLATILE_P (from) + && direct_load[(int) to_mode] && ! mode_dependent_address_p (XEXP (from, 0))) || GET_CODE (from) == REG *************** *** 564,567 **** --- 757,766 ---- != CODE_FOR_nothing) { + /* If FROM is a SUBREG, put it into a register. Do this + so that we always generate the same set of insns for + better cse'ing; if an intermediate assignment occurred, + we won't be doing the operation directly on the SUBREG. */ + if (optimize > 0 && GET_CODE (from) == SUBREG) + from = force_reg (from_mode, from); emit_unop_insn (code, to, from, equiv_code); return; *************** *** 688,693 **** UNSIGNEDP is nonzero if X is an unsigned value. This can be done by referring to a part of X in place ! or by copying to a new temporary with conversion. */ rtx convert_to_mode (mode, x, unsignedp) --- 887,895 ---- UNSIGNEDP is nonzero if X is an unsigned value. This can be done by referring to a part of X in place ! or by copying to a new temporary with conversion. + This function *must not* call protect_from_queue + except when putting X into an insn (in which case convert_move does it). */ + rtx convert_to_mode (mode, x, unsignedp) *************** *** 697,702 **** { register rtx temp; ! x = protect_from_queue (x, 0); if (mode == GET_MODE (x)) --- 899,910 ---- { register rtx temp; + + /* If FROM is a SUBREG that indicates that we have already done at least + the required extension, strip it. */ ! if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x) ! && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode) ! && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp) ! x = gen_lowpart (mode, x); if (mode == GET_MODE (x)) *************** *** 704,708 **** /* There is one case that we must handle specially: If we are converting ! a CONST_INT into a mode whose size is twice HOST_BITS_PER_INT and we are to interpret the constant as unsigned, gen_lowpart will do the wrong if the constant appears negative. What we want to do is --- 912,916 ---- /* There is one case that we must handle specially: If we are converting ! a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and we are to interpret the constant as unsigned, gen_lowpart will do the wrong if the constant appears negative. What we want to do is *************** *** 710,716 **** if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT ! && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_INT && GET_CODE (x) == CONST_INT && INTVAL (x) < 0) ! return immed_double_const (INTVAL (x), 0, mode); /* We can do this with a gen_lowpart if both desired and current modes --- 918,924 ---- if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT ! && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT && GET_CODE (x) == CONST_INT && INTVAL (x) < 0) ! return immed_double_const (INTVAL (x), (HOST_WIDE_INT) 0, mode); /* We can do this with a gen_lowpart if both desired and current modes *************** *** 725,728 **** --- 933,937 ---- || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x)) && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)) + && direct_load[(int) mode] || GET_CODE (x) == REG))))) return gen_lowpart (mode, x); *************** *** 933,941 **** #ifdef HAVE_PRE_DECREMENT if (data->explicit_inc_to < 0) ! emit_insn (gen_add2_insn (data->to_addr, ! gen_rtx (CONST_INT, VOIDmode, -size))); if (data->explicit_inc_from < 0) ! emit_insn (gen_add2_insn (data->from_addr, ! gen_rtx (CONST_INT, VOIDmode, -size))); #endif --- 1142,1148 ---- #ifdef HAVE_PRE_DECREMENT if (data->explicit_inc_to < 0) ! emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); if (data->explicit_inc_from < 0) ! emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size))); #endif *************** *** 943,951 **** #ifdef HAVE_POST_INCREMENT if (data->explicit_inc_to > 0) ! emit_insn (gen_add2_insn (data->to_addr, ! gen_rtx (CONST_INT, VOIDmode, size))); if (data->explicit_inc_from > 0) ! emit_insn (gen_add2_insn (data->from_addr, ! gen_rtx (CONST_INT, VOIDmode, size))); #endif --- 1150,1156 ---- #ifdef HAVE_POST_INCREMENT if (data->explicit_inc_to > 0) ! emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size))); if (data->explicit_inc_from > 0) ! emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size))); #endif *************** *** 980,983 **** --- 1185,1189 ---- x = protect_from_queue (x, 1); y = protect_from_queue (y, 0); + size = protect_from_queue (size, 0); if (GET_CODE (x) != MEM) *************** *** 989,994 **** if (GET_CODE (size) == CONST_INT ! && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align) ! < MOVE_RATIO)) move_by_pieces (x, y, INTVAL (size), align); else --- 1195,1199 ---- if (GET_CODE (size) == CONST_INT ! && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO)) move_by_pieces (x, y, INTVAL (size), align); else *************** *** 997,1065 **** including more than one in the machine description unless the more limited one has some advantage. */ ! #ifdef HAVE_movstrqi ! if (HAVE_movstrqi ! && GET_CODE (size) == CONST_INT ! && ((unsigned) INTVAL (size) ! < (1 << (GET_MODE_BITSIZE (QImode) - 1)))) ! { ! rtx insn = gen_movstrqi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align)); ! if (insn) ! { ! emit_insn (insn); ! return; ! } ! } ! #endif ! #ifdef HAVE_movstrhi ! if (HAVE_movstrhi ! && GET_CODE (size) == CONST_INT ! && ((unsigned) INTVAL (size) ! < (1 << (GET_MODE_BITSIZE (HImode) - 1)))) ! { ! rtx insn = gen_movstrhi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align)); ! if (insn) ! { ! emit_insn (insn); ! return; ! } ! } ! #endif ! #ifdef HAVE_movstrsi ! if (HAVE_movstrsi) ! { ! rtx insn = gen_movstrsi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align)); ! if (insn) ! { ! emit_insn (insn); ! return; ! } ! } ! #endif ! #ifdef HAVE_movstrdi ! if (HAVE_movstrdi) { ! rtx insn = gen_movstrdi (x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align)); ! if (insn) { ! emit_insn (insn); ! return; } } - #endif #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcpy_libfunc, 1, VOIDmode, 3, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, ! size, Pmode); #else ! emit_library_call (bcopy_libfunc, 1, VOIDmode, 3, XEXP (y, 0), Pmode, XEXP (x, 0), Pmode, ! size, Pmode); #endif } --- 1202,1258 ---- including more than one in the machine description unless the more limited one has some advantage. */ ! ! rtx opalign = GEN_INT (align); ! enum machine_mode mode; ! ! for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; ! mode = GET_MODE_WIDER_MODE (mode)) { ! enum insn_code code = movstr_optab[(int) mode]; ! ! if (code != CODE_FOR_nothing ! /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT ! here because if SIZE is less than the mode mask, as it is ! returned by the macro, it will definately be less than the ! actual mode mask. */ ! && (unsigned) INTVAL (size) <= GET_MODE_MASK (mode) ! && (insn_operand_predicate[(int) code][0] == 0 ! || (*insn_operand_predicate[(int) code][0]) (x, BLKmode)) ! && (insn_operand_predicate[(int) code][1] == 0 ! || (*insn_operand_predicate[(int) code][1]) (y, BLKmode)) ! && (insn_operand_predicate[(int) code][3] == 0 ! || (*insn_operand_predicate[(int) code][3]) (opalign, ! VOIDmode))) { ! rtx op2; ! rtx last = get_last_insn (); ! rtx pat; ! ! op2 = convert_to_mode (mode, size, 1); ! if (insn_operand_predicate[(int) code][2] != 0 ! && ! (*insn_operand_predicate[(int) code][2]) (op2, mode)) ! op2 = copy_to_mode_reg (mode, op2); ! ! pat = GEN_FCN ((int) code) (x, y, op2, opalign); ! if (pat) ! { ! emit_insn (pat); ! return; ! } ! else ! delete_insns_since (last); } } #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcpy_libfunc, 0, VOIDmode, 3, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, ! convert_to_mode (Pmode, size, 1), Pmode); #else ! emit_library_call (bcopy_libfunc, 0, VOIDmode, 3, XEXP (y, 0), Pmode, XEXP (x, 0), Pmode, ! convert_to_mode (Pmode, size, 1), Pmode); #endif } *************** *** 1086,1090 **** last = get_last_insn (); pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x, ! gen_rtx (CONST_INT, VOIDmode, nregs)); if (pat) { --- 1279,1283 ---- last = get_last_insn (); pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x, ! GEN_INT (nregs)); if (pat) { *************** *** 1117,1121 **** last = get_last_insn (); pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno), ! gen_rtx (CONST_INT, VOIDmode, nregs)); if (pat) { --- 1310,1314 ---- last = get_last_insn (); pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno), ! GEN_INT (nregs)); if (pat) { *************** *** 1150,1153 **** --- 1343,1371 ---- emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, word_mode, regno + i))); } + + /* Mark the instructions since PREV as a libcall block. + Add REG_LIBCALL to PREV and add a REG_RETVAL to the most recent insn. */ + + static rtx + group_insns (prev) + rtx prev; + { + rtx insn_first; + rtx insn_last; + + /* Find the instructions to mark */ + if (prev) + insn_first = NEXT_INSN (prev); + else + insn_first = get_insns (); + + insn_last = get_last_insn (); + + REG_NOTES (insn_last) = gen_rtx (INSN_LIST, REG_RETVAL, insn_first, + REG_NOTES (insn_last)); + + REG_NOTES (insn_first) = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last, + REG_NOTES (insn_first)); + } /* Write zeros through the storage of OBJECT. *************** *** 1162,1174 **** { #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memset_libfunc, 1, VOIDmode, 3, XEXP (object, 0), Pmode, const0_rtx, Pmode, ! gen_rtx (CONST_INT, VOIDmode, size), Pmode); #else ! emit_library_call (bzero_libfunc, 1, VOIDmode, 2, XEXP (object, 0), Pmode, ! gen_rtx (CONST_INT, VOIDmode, size), Pmode); #endif } --- 1380,1392 ---- { #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memset_libfunc, 0, VOIDmode, 3, XEXP (object, 0), Pmode, const0_rtx, Pmode, ! GEN_INT (size), Pmode); #else ! emit_library_call (bzero_libfunc, 0, VOIDmode, 2, XEXP (object, 0), Pmode, ! GEN_INT (size), Pmode); #endif } *************** *** 1189,1192 **** --- 1407,1412 ---- { enum machine_mode mode = GET_MODE (x); + enum machine_mode submode; + enum mode_class class = GET_MODE_CLASS (mode); int i; *************** *** 1218,1231 **** abort (); if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) return emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y)); /* This will handle any multi-word mode that lacks a move_insn pattern. However, you will get better code if you define such patterns, even if they must turn into multiple assembler instructions. */ ! else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD) { rtx last_insn = 0; for (i = 0; --- 1438,1489 ---- abort (); + if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) + submode = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, + (class == MODE_COMPLEX_INT + ? MODE_INT : MODE_FLOAT), + 0); + if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) return emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y)); + /* Expand complex moves by moving real part and imag part, if posible. */ + else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) + && submode != BLKmode + && (mov_optab->handlers[(int) submode].insn_code + != CODE_FOR_nothing)) + { + /* Don't split destination if it is a stack push. */ + int stack = push_operand (x, GET_MODE (x)); + rtx prev = get_last_insn (); + + /* Tell flow that the whole of the destination is being set. */ + if (GET_CODE (x) == REG) + emit_insn (gen_rtx (CLOBBER, VOIDmode, x)); + + /* If this is a stack, push the highpart first, so it + will be in the argument order. + + In that case, change_address is used only to convert + the mode, not to change the address. */ + emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) + ((stack ? change_address (x, submode, (rtx) 0) + : gen_highpart (submode, x)), + gen_highpart (submode, y))); + emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) + ((stack ? change_address (x, submode, (rtx) 0) + : gen_lowpart (submode, x)), + gen_lowpart (submode, y))); + + group_insns (prev); + } + /* This will handle any multi-word mode that lacks a move_insn pattern. However, you will get better code if you define such patterns, even if they must turn into multiple assembler instructions. */ ! else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) { rtx last_insn = 0; + rtx prev_insn = get_last_insn (); for (i = 0; *************** *** 1252,1255 **** --- 1510,1516 ---- last_insn = emit_move_insn (xpart, ypart); } + /* Mark these insns as a libcall block. */ + group_insns (prev_insn); + return last_insn; } *************** *** 1283,1289 **** rtx temp = copy_to_mode_reg (Pmode, size); if (extra != 0) ! temp = expand_binop (Pmode, add_optab, ! temp, ! gen_rtx (CONST_INT, VOIDmode, extra), temp, 0, OPTAB_LIB_WIDEN); anti_adjust_stack (temp); --- 1544,1548 ---- rtx temp = copy_to_mode_reg (Pmode, size); if (extra != 0) ! temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra), temp, 0, OPTAB_LIB_WIDEN); anti_adjust_stack (temp); *************** *** 1309,1313 **** } ! static rtx gen_push_operand () { --- 1568,1572 ---- } ! rtx gen_push_operand () { *************** *** 1427,1431 **** if (extra && args_addr == 0 && where_pad != none && where_pad != stack_direction) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner, --- 1686,1690 ---- if (extra && args_addr == 0 && where_pad != none && where_pad != stack_direction) ! anti_adjust_stack (GEN_INT (extra)); move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner, *************** *** 1442,1450 **** { if (GET_CODE (size) == CONST_INT) ! size = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - used); else size = expand_binop (GET_MODE (size), sub_optab, size, ! gen_rtx (CONST_INT, VOIDmode, used), ! 0, 0, OPTAB_LIB_WIDEN); } --- 1701,1709 ---- { if (GET_CODE (size) == CONST_INT) ! size = GEN_INT (INTVAL (size) - used); else size = expand_binop (GET_MODE (size), sub_optab, size, ! GEN_INT (used), NULL_RTX, 0, ! OPTAB_LIB_WIDEN); } *************** *** 1486,1491 **** { emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); goto ret; } --- 1745,1749 ---- { emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, GEN_INT (align))); goto ret; } *************** *** 1498,1503 **** { emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); goto ret; } --- 1756,1760 ---- { emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, GEN_INT (align))); goto ret; } *************** *** 1507,1512 **** { emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); goto ret; } --- 1764,1768 ---- { emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, GEN_INT (align))); goto ret; } *************** *** 1516,1521 **** { emit_insn (gen_movstrdi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, ! gen_rtx (CONST_INT, VOIDmode, align))); goto ret; } --- 1772,1776 ---- { emit_insn (gen_movstrdi (gen_rtx (MEM, BLKmode, temp), ! xinner, size, GEN_INT (align))); goto ret; } *************** *** 1536,1544 **** NO_DEFER_POP; #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcpy_libfunc, 1, VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode, size, Pmode); #else ! emit_library_call (bcopy_libfunc, 1, VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode, size, Pmode); --- 1791,1799 ---- NO_DEFER_POP; #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcpy_libfunc, 0, VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode, size, Pmode); #else ! emit_library_call (bcopy_libfunc, 0, VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode, size, Pmode); *************** *** 1565,1569 **** if (extra && args_addr == 0 && where_pad != none && where_pad != stack_direction) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); /* If we make space by pushing it, we might as well push --- 1820,1824 ---- if (extra && args_addr == 0 && where_pad != none && where_pad != stack_direction) ! anti_adjust_stack (GEN_INT (extra)); /* If we make space by pushing it, we might as well push *************** *** 1606,1612 **** if (i >= not_stack + offset) emit_push_insn (operand_subword_force (x, i, mode), ! word_mode, 0, 0, align, 0, 0, 0, args_addr, ! gen_rtx (CONST_INT, VOIDmode, ! args_offset + ((i - not_stack + skip) * UNITS_PER_WORD))); } --- 1861,1867 ---- if (i >= not_stack + offset) emit_push_insn (operand_subword_force (x, i, mode), ! word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX, ! 0, args_addr, ! GEN_INT (args_offset + ((i - not_stack + skip) * UNITS_PER_WORD))); } *************** *** 1620,1624 **** if (extra && args_addr == 0 && where_pad != none && where_pad != stack_direction) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); #ifdef PUSH_ROUNDING --- 1875,1879 ---- if (extra && args_addr == 0 && where_pad != none && where_pad != stack_direction) ! anti_adjust_stack (GEN_INT (extra)); #ifdef PUSH_ROUNDING *************** *** 1646,1650 **** if (extra && args_addr == 0 && where_pad == stack_direction) ! anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra)); } --- 1901,1905 ---- if (extra && args_addr == 0 && where_pad == stack_direction) ! anti_adjust_stack (GEN_INT (extra)); } *************** *** 1658,1662 **** NO_QUEUE will be true if and only if the library call is a `const' call which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent ! to the variable is_const in expand_call. */ void --- 1913,1926 ---- NO_QUEUE will be true if and only if the library call is a `const' call which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent ! to the variable is_const in expand_call. ! ! NO_QUEUE must be true for const calls, because if it isn't, then ! any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes, ! and will be lost if the libcall sequence is optimized away. ! ! NO_QUEUE must be false for non-const calls, because if it isn't, the ! call insn will have its CONST_CALL_P bit set, and it will be incorrectly ! optimized. For instance, the instruction scheduler may incorrectly ! move memory references across the non-const call. */ void *************** *** 1717,1727 **** #ifdef LIBGCC_NEEDS_DOUBLE if (LIBGCC_NEEDS_DOUBLE && mode == SFmode) ! val = convert_to_mode (DFmode, val), mode = DFmode; #endif /* Make sure it is a reasonable operand for a move or push insn. */ if (GET_CODE (val) != REG && GET_CODE (val) != MEM && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val))) ! val = force_operand (val, 0); argvec[count].value = val; --- 1981,1994 ---- #ifdef LIBGCC_NEEDS_DOUBLE if (LIBGCC_NEEDS_DOUBLE && mode == SFmode) ! val = convert_to_mode (DFmode, val, 0), mode = DFmode; #endif + /* There's no need to call protect_from_queue, because + either emit_move_insn or emit_push_insn will do that. */ + /* Make sure it is a reasonable operand for a move or push insn. */ if (GET_CODE (val) != REG && GET_CODE (val) != MEM && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val))) ! val = force_operand (val, NULL_RTX); argvec[count].value = val; *************** *** 1729,1749 **** #ifdef FUNCTION_ARG_PASS_BY_REFERENCE ! if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, (tree)0, 1)) abort (); #endif ! argvec[count].reg = FUNCTION_ARG (args_so_far, mode, (tree)0, 1); if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) abort (); #ifdef FUNCTION_ARG_PARTIAL_NREGS argvec[count].partial ! = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, (tree)0, 1); #else argvec[count].partial = 0; #endif ! locate_and_pad_parm (mode, 0, argvec[count].reg && argvec[count].partial == 0, ! 0, &args_size, &argvec[count].offset, &argvec[count].size); --- 1996,2016 ---- #ifdef FUNCTION_ARG_PASS_BY_REFERENCE ! if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1)) abort (); #endif ! argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) abort (); #ifdef FUNCTION_ARG_PARTIAL_NREGS argvec[count].partial ! = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1); #else argvec[count].partial = 0; #endif ! locate_and_pad_parm (mode, NULL_TREE, argvec[count].reg && argvec[count].partial == 0, ! NULL_TREE, &args_size, &argvec[count].offset, &argvec[count].size); *************** *** 1801,1806 **** #ifndef PUSH_ROUNDING ! argblock = push_block (gen_rtx (CONST_INT, VOIDmode, args_size.constant), ! 0, 0); #endif --- 2068,2072 ---- #ifndef PUSH_ROUNDING ! argblock = push_block (GEN_INT (args_size.constant), 0, 0); #endif *************** *** 1823,1829 **** if (! (reg != 0 && partial == 0)) ! emit_push_insn (val, mode, 0, 0, 0, partial, reg, 0, argblock, ! gen_rtx (CONST_INT, VOIDmode, ! argvec[count].offset.constant)); NO_DEFER_POP; } --- 2089,2094 ---- if (! (reg != 0 && partial == 0)) ! emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, ! argblock, GEN_INT (argvec[count].offset.constant)); NO_DEFER_POP; } *************** *** 1862,1866 **** end_sequence (); ! fun = prepare_call_address (fun, 0, &use_insns); /* Don't allow popping to be deferred, since then --- 2127,2131 ---- end_sequence (); ! fun = prepare_call_address (fun, NULL_TREE, &use_insns); /* Don't allow popping to be deferred, since then *************** *** 1873,1877 **** emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size.constant, 0, FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), ! outmode != VOIDmode ? hard_libcall_value (outmode) : 0, old_inhibit_defer_pop + 1, use_insns, no_queue); --- 2138,2142 ---- emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size.constant, 0, FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), ! outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX, old_inhibit_defer_pop + 1, use_insns, no_queue); *************** *** 1904,1908 **** if (TREE_CODE (to) == ERROR_MARK) ! return expand_expr (from, 0, VOIDmode, 0); /* Assignment of a structure component needs special treatment --- 2169,2173 ---- if (TREE_CODE (to) == ERROR_MARK) ! return expand_expr (from, NULL_RTX, VOIDmode, 0); /* Assignment of a structure component needs special treatment *************** *** 1932,1939 **** tem = stabilize_reference (tem); ! to_rtx = expand_expr (tem, 0, VOIDmode, 0); if (offset != 0) { ! rtx offset_rtx = expand_expr (offset, 0, VOIDmode, 0); if (GET_CODE (to_rtx) != MEM) --- 2197,2204 ---- tem = stabilize_reference (tem); ! to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0); if (offset != 0) { ! rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); if (GET_CODE (to_rtx) != MEM) *************** *** 1974,1978 **** if (to_rtx == 0) ! to_rtx = expand_expr (to, 0, VOIDmode, 0); /* In case we are returning the contents of an object which overlaps --- 2239,2243 ---- if (to_rtx == 0) ! to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0); /* In case we are returning the contents of an object which overlaps *************** *** 1983,1996 **** && !current_function_returns_pcc_struct) { ! rtx from_rtx = expand_expr (from, 0, VOIDmode, 0); rtx size = expr_size (from); #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcpy_libfunc, 1, VOIDmode, 3, XEXP (to_rtx, 0), Pmode, XEXP (from_rtx, 0), Pmode, size, Pmode); #else ! emit_library_call (bcopy_libfunc, 1, VOIDmode, 3, XEXP (from_rtx, 0), Pmode, XEXP (to_rtx, 0), Pmode, --- 2248,2261 ---- && !current_function_returns_pcc_struct) { ! rtx from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0); rtx size = expr_size (from); #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcpy_libfunc, 0, VOIDmode, 3, XEXP (to_rtx, 0), Pmode, XEXP (from_rtx, 0), Pmode, size, Pmode); #else ! emit_library_call (bcopy_libfunc, 0, VOIDmode, 3, XEXP (from_rtx, 0), Pmode, XEXP (to_rtx, 0), Pmode, *************** *** 2070,2074 **** We know expand_expr will not use the target in that case. */ { ! temp = expand_expr (exp, cse_not_expected ? 0 : target, GET_MODE (target), 0); if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) --- 2335,2339 ---- We know expand_expr will not use the target in that case. */ { ! temp = expand_expr (exp, cse_not_expected ? NULL_RTX : target, GET_MODE (target), 0); if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode) *************** *** 2090,2096 **** } else ! temp = expand_expr (exp, 0, GET_MODE (target), 0); dont_return_target = 1; } else { --- 2355,2372 ---- } else ! temp = expand_expr (exp, NULL_RTX, GET_MODE (target), 0); dont_return_target = 1; } + else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target)) + /* If this is an scalar in a register that is stored in a wider mode + than the declared mode, compute the result into its declared mode + and then convert to the wider mode. Our value is the computed + expression. */ + { + temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); + convert_move (SUBREG_REG (target), temp, + SUBREG_PROMOTED_UNSIGNED_P (target)); + return temp; + } else { *************** *** 2150,2154 **** convert (sizetype, build_int_2 (TREE_STRING_LENGTH (exp), 0)))); ! rtx copy_size_rtx = expand_expr (copy_size, 0, VOIDmode, 0); rtx label = 0; --- 2426,2431 ---- convert (sizetype, build_int_2 (TREE_STRING_LENGTH (exp), 0)))); ! rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX, ! VOIDmode, 0); rtx label = 0; *************** *** 2172,2181 **** temp = force_reg (Pmode, XEXP (target, 0)); temp = expand_binop (size_mode, add_optab, temp, ! copy_size_rtx, 0, 0, OPTAB_LIB_WIDEN); size = expand_binop (size_mode, sub_optab, size, ! copy_size_rtx, 0, 0, OPTAB_LIB_WIDEN); ! emit_cmp_insn (size, const0_rtx, LT, 0, GET_MODE (size), 0, 0); label = gen_label_rtx (); --- 2449,2460 ---- temp = force_reg (Pmode, XEXP (target, 0)); temp = expand_binop (size_mode, add_optab, temp, ! copy_size_rtx, NULL_RTX, 0, ! OPTAB_LIB_WIDEN); size = expand_binop (size_mode, sub_optab, size, ! copy_size_rtx, NULL_RTX, 0, ! OPTAB_LIB_WIDEN); ! emit_cmp_insn (size, const0_rtx, LT, NULL_RTX, GET_MODE (size), 0, 0); label = gen_label_rtx (); *************** *** 2186,2193 **** { #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memset_libfunc, 1, VOIDmode, 3, temp, Pmode, const0_rtx, Pmode, size, Pmode); #else ! emit_library_call (bzero_libfunc, 1, VOIDmode, 2, temp, Pmode, size, Pmode); #endif --- 2465,2472 ---- { #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memset_libfunc, 0, VOIDmode, 3, temp, Pmode, const0_rtx, Pmode, size, Pmode); #else ! emit_library_call (bzero_libfunc, 0, VOIDmode, 2, temp, Pmode, size, Pmode); #endif *************** *** 2266,2269 **** --- 2545,2554 ---- int unsignedp; + /* Just ignore missing fields. + We cleared the whole structure, above, + if any fields are missing. */ + if (field == 0) + continue; + bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)); unsignedp = TREE_UNSIGNED (field); *************** *** 2291,2296 **** register int i; tree domain = TYPE_DOMAIN (type); ! int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); ! int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); tree elttype = TREE_TYPE (type); --- 2576,2581 ---- register int i; tree domain = TYPE_DOMAIN (type); ! HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)); ! HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)); tree elttype = TREE_TYPE (type); *************** *** 2364,2371 **** int total_size; { ! int width_mask = 0; ! if (bitsize < HOST_BITS_PER_INT) ! width_mask = (1 << bitsize) - 1; /* If we are storing into an unaligned field of an aligned union that is --- 2649,2656 ---- int total_size; { ! HOST_WIDE_INT width_mask = 0; ! if (bitsize < HOST_BITS_PER_WIDE_INT) ! width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1; /* If we are storing into an unaligned field of an aligned union that is *************** *** 2404,2411 **** Use bit-field techniques or SUBREG to store in it. */ ! if (mode == VOIDmode || GET_CODE (target) == REG || GET_CODE (target) == SUBREG) { ! rtx temp = expand_expr (exp, 0, VOIDmode, 0); /* Store the value in the bitfield. */ store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size); --- 2689,2698 ---- Use bit-field techniques or SUBREG to store in it. */ ! if (mode == VOIDmode ! || (mode != BLKmode && ! direct_store[(int) mode]) ! || GET_CODE (target) == REG || GET_CODE (target) == SUBREG) { ! rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); /* Store the value in the bitfield. */ store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size); *************** *** 2416,2423 **** if (width_mask != 0 && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))) ! return expand_and (temp, ! gen_rtx (CONST_INT, VOIDmode, width_mask), 0); return extract_bit_field (target, bitsize, bitpos, unsignedp, ! 0, value_mode, 0, align, total_size); } return const0_rtx; --- 2703,2722 ---- if (width_mask != 0 && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))) ! { ! tree count; ! enum machine_mode tmode; ! ! if (unsignedp) ! return expand_and (temp, GEN_INT (width_mask), NULL_RTX); ! tmode = GET_MODE (temp); ! if (tmode == VOIDmode) ! tmode = value_mode; ! count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0); ! temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0); ! return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0); ! } return extract_bit_field (target, bitsize, bitpos, unsignedp, ! NULL_RTX, value_mode, 0, align, ! total_size); } return const0_rtx; *************** *** 2521,2524 **** --- 2820,2826 ---- while (1) { + if (TREE_CODE (exp) == INDIRECT_REF && flag_volatile) + *pvolatilep = 1; + if (TREE_CODE (exp) == COMPONENT_REF || TREE_CODE (exp) == BIT_FIELD_REF) { *************** *** 2610,2614 **** return an equivalent value that just refers to a register or memory. This is done by generating instructions to perform the arithmetic ! and returning a pseudo-register containing the value. */ rtx --- 2912,2918 ---- return an equivalent value that just refers to a register or memory. This is done by generating instructions to perform the arithmetic ! and returning a pseudo-register containing the value. ! ! The returned value may be a REG, SUBREG, MEM or constant. */ rtx *************** *** 2636,2640 **** tmp = force_operand (XEXP (value, 0), subtarget); return expand_mult (GET_MODE (value), tmp, ! force_operand (op2, 0), target, 0); } --- 2940,2944 ---- tmp = force_operand (XEXP (value, 0), subtarget); return expand_mult (GET_MODE (value), tmp, ! force_operand (op2, NULL_RTX), target, 0); } *************** *** 2674,2678 **** tmp = force_operand (XEXP (value, 0), subtarget); return expand_binop (GET_MODE (value), binoptab, tmp, ! force_operand (op2, 0), target, 0, OPTAB_LIB_WIDEN); /* We give UNSIGNEP = 0 to expand_binop --- 2978,2982 ---- tmp = force_operand (XEXP (value, 0), subtarget); return expand_binop (GET_MODE (value), binoptab, tmp, ! force_operand (op2, NULL_RTX), target, 0, OPTAB_LIB_WIDEN); /* We give UNSIGNEP = 0 to expand_binop *************** *** 2702,2712 **** tree part = TREE_VALUE (tail); tree part_type = TREE_TYPE (part); ! tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part, 0); rtx target = assign_stack_temp (TYPE_MODE (part_type), int_size_in_bytes (part_type), 0); if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0))) ! target = change_address (target, TYPE_MODE (part_type), 0); parts = tree_cons (to_be_saved, ! build (RTL_EXPR, part_type, 0, (tree) target), parts); store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0); --- 3006,3017 ---- tree part = TREE_VALUE (tail); tree part_type = TREE_TYPE (part); ! tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part); rtx target = assign_stack_temp (TYPE_MODE (part_type), int_size_in_bytes (part_type), 0); if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0))) ! target = change_address (target, TYPE_MODE (part_type), NULL_RTX); parts = tree_cons (to_be_saved, ! build (RTL_EXPR, part_type, NULL_TREE, ! (tree) target), parts); store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0); *************** *** 2734,2738 **** tree part = TREE_VALUE (tail); tree part_type = TREE_TYPE (part); ! tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part, 0); parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts); } --- 3039,3043 ---- tree part = TREE_VALUE (tail); tree part_type = TREE_TYPE (part); ! tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part); parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts); } *************** *** 2781,2785 **** case 'x': if (TREE_CODE (exp) == TREE_LIST) ! return (safe_from_p (x, TREE_VALUE (exp)) && (TREE_CHAIN (exp) == 0 || safe_from_p (x, TREE_CHAIN (exp)))); --- 3086,3091 ---- case 'x': if (TREE_CODE (exp) == TREE_LIST) ! return ((TREE_VALUE (exp) == 0 ! || safe_from_p (x, TREE_VALUE (exp))) && (TREE_CHAIN (exp) == 0 || safe_from_p (x, TREE_CHAIN (exp)))); *************** *** 2930,2933 **** --- 3236,3240 ---- EXPAND_INITIALIZER is much like EXPAND_SUM except that it also marks a label as absolutely required (it can't be dead). + It also makes a ZERO_EXTEND or SIGN_EXTEND instead of emitting extend insns. This is used for outputting expressions used in initializers. */ *************** *** 3003,3008 **** forced_labels = gen_rtx (EXPR_LIST, VOIDmode, label_rtx (exp), forced_labels); ! return gen_rtx (MEM, FUNCTION_MODE, gen_rtx (LABEL_REF, Pmode, label_rtx (exp))); } --- 3310,3318 ---- forced_labels = gen_rtx (EXPR_LIST, VOIDmode, label_rtx (exp), forced_labels); ! temp = gen_rtx (MEM, FUNCTION_MODE, gen_rtx (LABEL_REF, Pmode, label_rtx (exp))); + if (function != current_function_decl && function != 0) + LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1; + return temp; } *************** *** 3038,3042 **** /* Mark as non-local and addressable. */ ! TREE_NONLOCAL (exp) = 1; mark_addressable (exp); if (GET_CODE (DECL_RTL (exp)) != MEM) --- 3348,3352 ---- /* Mark as non-local and addressable. */ ! DECL_NONLOCAL (exp) = 1; mark_addressable (exp); if (GET_CODE (DECL_RTL (exp)) != MEM) *************** *** 3071,3074 **** --- 3381,3408 ---- copy_rtx (XEXP (DECL_RTL (exp), 0))); } + + /* If the mode of DECL_RTL does not match that of the decl, it + must be a promoted value. We return a SUBREG of the wanted mode, + but mark it so that we know that it was already extended. */ + + if (GET_CODE (DECL_RTL (exp)) == REG + && GET_MODE (DECL_RTL (exp)) != mode) + { + enum machine_mode decl_mode = DECL_MODE (exp); + + /* Get the signedness used for this variable. Ensure we get the + same mode we got when the variable was declared. */ + + PROMOTE_MODE (decl_mode, unsignedp, type); + + if (decl_mode != GET_MODE (DECL_RTL (exp))) + abort (); + + temp = gen_rtx (SUBREG, mode, DECL_RTL (exp), 0); + SUBREG_PROMOTED_VAR_P (temp) = 1; + SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; + return temp; + } + return DECL_RTL (exp); *************** *** 3141,3145 **** int_size_in_bytes (TREE_TYPE (exp)), 0); else ! temp = gen_reg_rtx (mode); SAVE_EXPR_RTL (exp) = temp; store_expr (TREE_OPERAND (exp, 0), temp, 0); --- 3475,3495 ---- int_size_in_bytes (TREE_TYPE (exp)), 0); else ! { ! enum machine_mode var_mode = mode; ! ! if (TREE_CODE (type) == INTEGER_TYPE ! || TREE_CODE (type) == ENUMERAL_TYPE ! || TREE_CODE (type) == BOOLEAN_TYPE ! || TREE_CODE (type) == CHAR_TYPE ! || TREE_CODE (type) == REAL_TYPE ! || TREE_CODE (type) == POINTER_TYPE ! || TREE_CODE (type) == OFFSET_TYPE) ! { ! PROMOTE_MODE (var_mode, unsignedp, type); ! } ! ! temp = gen_reg_rtx (var_mode); ! } ! SAVE_EXPR_RTL (exp) = temp; store_expr (TREE_OPERAND (exp, 0), temp, 0); *************** *** 3148,3151 **** --- 3498,3516 ---- save_expr_regs); } + + /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it + must be a promoted value. We return a SUBREG of the wanted mode, + but mark it so that we know that it was already extended. Note + that `unsignedp' was modified above in this case. */ + + if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG + && GET_MODE (SAVE_EXPR_RTL (exp)) != mode) + { + temp = gen_rtx (SUBREG, mode, SAVE_EXPR_RTL (exp), 0); + SUBREG_PROMOTED_VAR_P (temp) = 1; + SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp; + return temp; + } + return SAVE_EXPR_RTL (exp); *************** *** 3154,3159 **** { rtx label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), label, 0); ! expand_exit_loop (0); emit_label (label); } --- 3519,3524 ---- { rtx label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), label, NULL_RTX); ! expand_exit_loop (NULL_PTR); emit_label (label); } *************** *** 3176,3182 **** expand_start_bindings (0); ! /* Mark the corresponding BLOCK for output. */ ! if (TREE_OPERAND (exp, 2) != 0) ! TREE_USED (TREE_OPERAND (exp, 2)) = 1; /* If VARS have not yet been expanded, expand them now. */ --- 3541,3548 ---- expand_start_bindings (0); ! /* Mark the corresponding BLOCK for output in its proper place. */ ! if (TREE_OPERAND (exp, 2) != 0 ! && ! TREE_USED (TREE_OPERAND (exp, 2))) ! insert_block (TREE_OPERAND (exp, 2)); /* If VARS have not yet been expanded, expand them now. */ *************** *** 3266,3270 **** && TYPE_MODE (TREE_TYPE (exp2)) == Pmode) { ! temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, EXPAND_SUM); op0 = memory_address (mode, temp); op0 = copy_all_regs (op0); --- 3632,3637 ---- && TYPE_MODE (TREE_TYPE (exp2)) == Pmode) { ! temp = expand_expr (TREE_OPERAND (exp1, 0), NULL_RTX, ! VOIDmode, EXPAND_SUM); op0 = memory_address (mode, temp); op0 = copy_all_regs (op0); *************** *** 3273,3277 **** else { ! op0 = expand_expr (exp1, 0, VOIDmode, EXPAND_SUM); op0 = memory_address (mode, op0); } --- 3640,3644 ---- else { ! op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM); op0 = memory_address (mode, op0); } *************** *** 3427,3432 **** && i < TREE_STRING_LENGTH (init)) { ! temp = gen_rtx (CONST_INT, VOIDmode, ! TREE_STRING_POINTER (init)[i]); return convert_to_mode (mode, temp, 0); } --- 3794,3798 ---- && i < TREE_STRING_LENGTH (init)) { ! temp = GEN_INT (TREE_STRING_POINTER (init)[i]); return convert_to_mode (mode, temp, 0); } *************** *** 3462,3466 **** So get it as a sum, if possible. If we will be using it directly in an insn, we validate it. */ ! op0 = expand_expr (tem, 0, VOIDmode, EXPAND_SUM); /* If this is a constant, put it into a register if it is a --- 3828,3832 ---- So get it as a sum, if possible. If we will be using it directly in an insn, we validate it. */ ! op0 = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_SUM); /* If this is a constant, put it into a register if it is a *************** *** 3477,3481 **** if (offset != 0) { ! rtx offset_rtx = expand_expr (offset, 0, VOIDmode, 0); if (GET_CODE (op0) != MEM) --- 3843,3847 ---- if (offset != 0) { ! rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0); if (GET_CODE (op0) != MEM) *************** *** 3494,3497 **** --- 3860,3866 ---- if (mode1 == VOIDmode + || (mode1 != BLKmode && ! direct_load[(int) mode1] + && modifier != EXPAND_CONST_ADDRESS + && modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER) || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG) { *************** *** 3550,3554 **** tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0); tree addr = build (PLUS_EXPR, type, base, TREE_OPERAND (exp, 1)); ! op0 = expand_expr (addr, 0, VOIDmode, EXPAND_SUM); temp = gen_rtx (MEM, mode, memory_address (mode, op0)); MEM_IN_STRUCT_P (temp) = 1; --- 3919,3923 ---- tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0); tree addr = build (PLUS_EXPR, type, base, TREE_OPERAND (exp, 1)); ! op0 = expand_expr (addr, NULL_RTX, VOIDmode, EXPAND_SUM); temp = gen_rtx (MEM, mode, memory_address (mode, op0)); MEM_IN_STRUCT_P (temp) = 1; *************** *** 3568,3571 **** --- 3937,4052 ---- abort (); + /* IN_EXPR: Inlined pascal set IN expression. + + Algorithm: + rlo = set_low - (set_low%bits_per_word); + the_word = set [ (index - rlo)/bits_per_word ]; + bit_index = index % bits_per_word; + bitmask = 1 << bit_index; + return !!(the_word & bitmask); */ + case IN_EXPR: + preexpand_calls (exp); + { + tree set = TREE_OPERAND (exp, 0); + tree index = TREE_OPERAND (exp, 1); + tree set_type = TREE_TYPE (set); + + tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type)); + tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type)); + + rtx index_val; + rtx lo_r; + rtx hi_r; + rtx rlow; + rtx diff, quo, rem, addr, bit, result; + rtx setval, setaddr; + enum machine_mode index_mode = TYPE_MODE (TREE_TYPE (index)); + + if (target == 0) + target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + + /* If domain is empty, answer is no. */ + if (tree_int_cst_lt (set_high_bound, set_low_bound)) + return const0_rtx; + + index_val = expand_expr (index, 0, VOIDmode, 0); + lo_r = expand_expr (set_low_bound, 0, VOIDmode, 0); + hi_r = expand_expr (set_high_bound, 0, VOIDmode, 0); + setval = expand_expr (set, 0, VOIDmode, 0); + setaddr = XEXP (setval, 0); + + /* Compare index against bounds, if they are constant. */ + if (GET_CODE (index_val) == CONST_INT + && GET_CODE (lo_r) == CONST_INT) + { + if (INTVAL (index_val) < INTVAL (lo_r)) + return const0_rtx; + } + + if (GET_CODE (index_val) == CONST_INT + && GET_CODE (hi_r) == CONST_INT) + { + if (INTVAL (hi_r) < INTVAL (index_val)) + return const0_rtx; + } + + /* If we get here, we have to generate the code for both cases + (in range and out of range). */ + + op0 = gen_label_rtx (); + op1 = gen_label_rtx (); + + if (! (GET_CODE (index_val) == CONST_INT + && GET_CODE (lo_r) == CONST_INT)) + { + emit_cmp_insn (index_val, lo_r, LT, 0, GET_MODE (index_val), 0, 0); + emit_jump_insn (gen_blt (op1)); + } + + if (! (GET_CODE (index_val) == CONST_INT + && GET_CODE (hi_r) == CONST_INT)) + { + emit_cmp_insn (index_val, hi_r, GT, 0, GET_MODE (index_val), 0, 0); + emit_jump_insn (gen_bgt (op1)); + } + + /* Calculate the element number of bit zero in the first word + of the set. */ + if (GET_CODE (lo_r) == CONST_INT) + rlow = gen_rtx (CONST_INT, VOIDmode, + INTVAL (lo_r) & ~ (1 << BITS_PER_UNIT)); + else + rlow = expand_binop (index_mode, and_optab, + lo_r, gen_rtx (CONST_INT, VOIDmode, + ~ (1 << BITS_PER_UNIT)), + 0, 0, OPTAB_LIB_WIDEN); + + diff = expand_binop (index_mode, sub_optab, + index_val, rlow, 0, 0, OPTAB_LIB_WIDEN); + + quo = expand_divmod (0, TRUNC_DIV_EXPR, index_mode, diff, + gen_rtx (CONST_INT, VOIDmode, BITS_PER_UNIT), + 0, 0); + rem = expand_divmod (1, TRUNC_MOD_EXPR, index_mode, index_val, + gen_rtx (CONST_INT, VOIDmode, BITS_PER_UNIT), + 0, 0); + addr = memory_address (byte_mode, + expand_binop (index_mode, add_optab, + diff, setaddr)); + /* Extract the bit we want to examine */ + bit = expand_shift (RSHIFT_EXPR, byte_mode, + gen_rtx (MEM, byte_mode, addr), rem, 0, 1); + result = expand_binop (SImode, and_optab, bit, const1_rtx, target, + 1, OPTAB_LIB_WIDEN); + emit_move_insn (target, result); + + /* Output the code to handle the out-of-range case. */ + emit_jump (op0); + emit_label (op1); + emit_move_insn (target, const0_rtx); + emit_label (op0); + return target; + } + case WITH_CLEANUP_EXPR: if (RTL_EXPR_RTL (exp) == 0) *************** *** 3573,3577 **** RTL_EXPR_RTL (exp) = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); ! cleanups_this_call = tree_cons (0, TREE_OPERAND (exp, 2), cleanups_this_call); /* That's it for this cleanup. */ TREE_OPERAND (exp, 2) = 0; --- 4054,4059 ---- RTL_EXPR_RTL (exp) = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier); ! cleanups_this_call ! = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2), cleanups_this_call); /* That's it for this cleanup. */ TREE_OPERAND (exp, 2) = 0; *************** *** 3624,3627 **** --- 4106,4110 ---- store_expr (TREE_OPERAND (exp, 0), change_address (target, TYPE_MODE (valtype), 0), 0); + else if (GET_CODE (target) == REG) /* Store this field into a union of the proper type. */ *************** *** 3636,3642 **** return target; } ! op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0); if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode) return op0; if (flag_force_mem && GET_CODE (op0) == MEM) op0 = copy_to_reg (op0); --- 4119,4127 ---- return target; } ! op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0); if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode) return op0; + if (modifier == EXPAND_INITIALIZER) + return gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0); if (flag_force_mem && GET_CODE (op0) == MEM) op0 = copy_to_reg (op0); *************** *** 3686,3690 **** If this is an EXPAND_SUM call, always return the sum. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT && (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER || mode == Pmode)) --- 4171,4175 ---- If this is an EXPAND_SUM call, always return the sum. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT && (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER || mode == Pmode)) *************** *** 3723,3727 **** op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, modifier); /* Make sure any term that's a sum with a constant comes last. */ --- 4208,4212 ---- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier); /* Make sure any term that's a sum with a constant comes last. */ *************** *** 3778,3783 **** && really_constant_p (TREE_OPERAND (exp, 1))) { ! rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, modifier); ! rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, modifier); return gen_rtx (MINUS, mode, op0, op1); } --- 4263,4270 ---- && really_constant_p (TREE_OPERAND (exp, 1))) { ! rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, ! VOIDmode, modifier); ! rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, ! VOIDmode, modifier); return gen_rtx (MINUS, mode, op0, op1); } *************** *** 3810,3814 **** if (modifier == EXPAND_SUM && mode == Pmode && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT) { op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); --- 4297,4301 ---- if (modifier == EXPAND_SUM && mode == Pmode && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) { op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM); *************** *** 3819,3836 **** return gen_rtx (PLUS, mode, gen_rtx (MULT, mode, XEXP (op0, 0), ! gen_rtx (CONST_INT, VOIDmode, ! TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))), ! gen_rtx (CONST_INT, VOIDmode, ! (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! * INTVAL (XEXP (op0, 1))))); if (GET_CODE (op0) != REG) ! op0 = force_operand (op0, 0); if (GET_CODE (op0) != REG) op0 = copy_to_mode_reg (mode, op0); return gen_rtx (MULT, mode, op0, ! gen_rtx (CONST_INT, VOIDmode, ! TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))); } --- 4306,4320 ---- return gen_rtx (PLUS, mode, gen_rtx (MULT, mode, XEXP (op0, 0), ! GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))), ! GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) ! * INTVAL (XEXP (op0, 1)))); if (GET_CODE (op0) != REG) ! op0 = force_operand (op0, NULL_RTX); if (GET_CODE (op0) != REG) op0 = copy_to_mode_reg (mode, op0); return gen_rtx (MULT, mode, op0, ! GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))); } *************** *** 3851,3855 **** /* Don't use a widening multiply if a shift will do. */ && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)))) ! > HOST_BITS_PER_INT) || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)) || --- 4335,4339 ---- /* Don't use a widening multiply if a shift will do. */ && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)))) ! > HOST_BITS_PER_WIDE_INT) || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)) || *************** *** 3872,3886 **** { op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! 0, VOIDmode, 0); if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); else op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), ! 0, VOIDmode, 0); goto binop2; } } op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); return expand_mult (mode, op0, op1, target, unsignedp); --- 4356,4371 ---- { op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), ! NULL_RTX, VOIDmode, 0); if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, ! VOIDmode, 0); else op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), ! NULL_RTX, VOIDmode, 0); goto binop2; } } op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); return expand_mult (mode, op0, op1, target, unsignedp); *************** *** 3897,3901 **** where some terms of the dividend have coeffs divisible by it. */ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); return expand_divmod (0, code, mode, op0, op1, target, unsignedp); --- 4382,4386 ---- where some terms of the dividend have coeffs divisible by it. */ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); return expand_divmod (0, code, mode, op0, op1, target, unsignedp); *************** *** 3912,3916 **** subtarget = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); return expand_divmod (1, code, mode, op0, op1, target, unsignedp); --- 4397,4401 ---- subtarget = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); return expand_divmod (1, code, mode, op0, op1, target, unsignedp); *************** *** 3921,3925 **** case FIX_TRUNC_EXPR: ! op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); if (target == 0) target = gen_reg_rtx (mode); --- 4406,4410 ---- case FIX_TRUNC_EXPR: ! op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); if (target == 0) target = gen_reg_rtx (mode); *************** *** 3928,3932 **** case FLOAT_EXPR: ! op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); if (target == 0) target = gen_reg_rtx (mode); --- 4413,4417 ---- case FLOAT_EXPR: ! op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); if (target == 0) target = gen_reg_rtx (mode); *************** *** 3950,3953 **** --- 4435,4448 ---- op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); + /* Handle complex values specially. */ + { + enum machine_mode opmode + = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); + + if (GET_MODE_CLASS (opmode) == MODE_COMPLEX_INT + || GET_MODE_CLASS (opmode) == MODE_COMPLEX_FLOAT) + return expand_complex_abs (opmode, op0, target, unsignedp); + } + /* Unsigned abs is simply the operand. Testing here means we don't risk generating incorrect code below. */ *************** *** 3968,3972 **** rtx extended = expand_shift (RSHIFT_EXPR, mode, op0, size_int (GET_MODE_BITSIZE (mode) - 1), ! 0, 0); temp = expand_binop (mode, xor_optab, extended, op0, target, 0, --- 4463,4467 ---- rtx extended = expand_shift (RSHIFT_EXPR, mode, op0, size_int (GET_MODE_BITSIZE (mode) - 1), ! NULL_RTX, 0); temp = expand_binop (mode, xor_optab, extended, op0, target, 0, *************** *** 3990,3995 **** emit_cmp_insn (target, expand_expr (convert (type, integer_zero_node), ! 0, VOIDmode, 0), ! GE, 0, mode, 0, 0); NO_DEFER_POP; emit_jump_insn (gen_bge (temp)); --- 4485,4490 ---- emit_cmp_insn (target, expand_expr (convert (type, integer_zero_node), ! NULL_RTX, VOIDmode, 0), ! GE, NULL_RTX, mode, 0, 0); NO_DEFER_POP; emit_jump_insn (gen_bge (temp)); *************** *** 4008,4012 **** && REGNO (target) < FIRST_PSEUDO_REGISTER)) target = gen_reg_rtx (mode); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); --- 4503,4507 ---- && REGNO (target) < FIRST_PSEUDO_REGISTER)) target = gen_reg_rtx (mode); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0); *************** *** 4028,4037 **** if (code == MAX_EXPR) temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! ? compare_from_rtx (target, op1, GEU, 1, mode, 0, 0) ! : compare_from_rtx (target, op1, GE, 0, mode, 0, 0)); else temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! ? compare_from_rtx (target, op1, LEU, 1, mode, 0, 0) ! : compare_from_rtx (target, op1, LE, 0, mode, 0, 0)); if (temp == const0_rtx) emit_move_insn (target, op1); --- 4523,4532 ---- if (code == MAX_EXPR) temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! ? compare_from_rtx (target, op1, GEU, 1, mode, NULL_RTX, 0) ! : compare_from_rtx (target, op1, GE, 0, mode, NULL_RTX, 0)); else temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))) ! ? compare_from_rtx (target, op1, LEU, 1, mode, NULL_RTX, 0) ! : compare_from_rtx (target, op1, LE, 0, mode, NULL_RTX, 0)); if (temp == const0_rtx) emit_move_insn (target, op1); *************** *** 4127,4131 **** temp = copy_to_reg (temp); op1 = gen_label_rtx (); ! emit_cmp_insn (temp, const0_rtx, EQ, 0, GET_MODE (temp), unsignedp, 0); emit_jump_insn (gen_beq (op1)); --- 4622,4626 ---- temp = copy_to_reg (temp); op1 = gen_label_rtx (); ! emit_cmp_insn (temp, const0_rtx, EQ, NULL_RTX, GET_MODE (temp), unsignedp, 0); emit_jump_insn (gen_beq (op1)); *************** *** 4157,4162 **** /* The parser is careful to generate TRUTH_NOT_EXPR only with operands that are always zero or one. */ ! temp = expand_binop (mode, xor_optab, op0, ! gen_rtx (CONST_INT, mode, 1), target, 1, OPTAB_LIB_WIDEN); if (temp == 0) --- 4652,4656 ---- /* The parser is careful to generate TRUTH_NOT_EXPR only with operands that are always zero or one. */ ! temp = expand_binop (mode, xor_optab, op0, const1_rtx, target, 1, OPTAB_LIB_WIDEN); if (temp == 0) *************** *** 4279,4288 **** result = do_store_flag (TREE_OPERAND (exp, 0), ! safe_from_p (temp, singleton) ? temp : 0, mode, BRANCH_COST <= 1); if (result) { ! op1 = expand_expr (singleton, 0, VOIDmode, 0); return expand_binop (mode, boptab, op1, result, temp, unsignedp, OPTAB_LIB_WIDEN); --- 4773,4783 ---- result = do_store_flag (TREE_OPERAND (exp, 0), ! (safe_from_p (temp, singleton) ! ? temp : NULL_RTX), mode, BRANCH_COST <= 1); if (result) { ! op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0); return expand_binop (mode, boptab, op1, result, temp, unsignedp, OPTAB_LIB_WIDEN); *************** *** 4312,4316 **** } else ! expand_expr (singleton, ignore ? const1_rtx : 0, VOIDmode, 0); if (cleanups_this_call) { --- 4807,4812 ---- } else ! expand_expr (singleton, ! ignore ? const1_rtx : NULL_RTX, VOIDmode, 0); if (cleanups_this_call) { *************** *** 4326,4330 **** /* Just touch the other operand. */ expand_expr (TREE_OPERAND (binary_op, 1), ! ignore ? const0_rtx : 0, VOIDmode, 0); else if (binary_op) store_expr (build (TREE_CODE (binary_op), type, --- 4822,4826 ---- /* Just touch the other operand. */ expand_expr (TREE_OPERAND (binary_op, 1), ! ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); else if (binary_op) store_expr (build (TREE_CODE (binary_op), type, *************** *** 4409,4414 **** store_expr (TREE_OPERAND (exp, 1), temp, 0); else ! expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : 0, ! VOIDmode, 0); if (cleanups_this_call) { --- 4905,4910 ---- store_expr (TREE_OPERAND (exp, 1), temp, 0); else ! expand_expr (TREE_OPERAND (exp, 1), ! ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); if (cleanups_this_call) { *************** *** 4424,4429 **** store_expr (TREE_OPERAND (exp, 2), temp, 0); else ! expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : 0, ! VOIDmode, 0); } --- 4920,4925 ---- store_expr (TREE_OPERAND (exp, 2), temp, 0); else ! expand_expr (TREE_OPERAND (exp, 2), ! ignore ? const0_rtx : NULL_RTX, VOIDmode, 0); } *************** *** 4453,4456 **** --- 4949,4953 ---- tree slot = TREE_OPERAND (exp, 0); + tree exp1; if (TREE_CODE (slot) != VAR_DECL) *************** *** 4460,4464 **** { if (DECL_RTL (slot) != 0) ! target = DECL_RTL (slot); else { --- 4957,4967 ---- { if (DECL_RTL (slot) != 0) ! { ! target = DECL_RTL (slot); ! /* If we have already expanded the slot, so don't do ! it again. (mrs) */ ! if (TREE_OPERAND (exp, 1) == NULL_TREE) ! return target; ! } else { *************** *** 4470,4473 **** --- 4973,4985 ---- #if 0 + /* I bet this needs to be done, and I bet that it needs to + be above, inside the else clause. The reason is + simple, how else is it going to get cleaned up? (mrs) + + The reason is probably did not work before, and was + commented out is because this was re-expanding already + expanded target_exprs (target == 0 and DECL_RTL (slot) + != 0) also cleaning them up many times as well. :-( */ + /* Since SLOT is not known to the called function to belong to its stack frame, we must build an explicit *************** *** 4480,4485 **** TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot); if (TREE_OPERAND (exp, 2)) ! cleanups_this_call = tree_cons (0, TREE_OPERAND (exp, 2), ! cleanups_this_call); #endif } --- 4992,4997 ---- TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot); if (TREE_OPERAND (exp, 2)) ! cleanups_this_call = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2), ! cleanups_this_call); #endif } *************** *** 4494,4498 **** } ! return expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier); } --- 5006,5014 ---- } ! exp1 = TREE_OPERAND (exp, 1); ! /* Mark it as expanded. */ ! TREE_OPERAND (exp, 1) = NULL_TREE; ! ! return expand_expr (exp1, target, tmode, modifier); } *************** *** 4604,4608 **** else { ! op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, (modifier == EXPAND_INITIALIZER ? modifier : EXPAND_CONST_ADDRESS)); --- 5120,5124 ---- else { ! op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, (modifier == EXPAND_INITIALIZER ? modifier : EXPAND_CONST_ADDRESS)); *************** *** 4621,4624 **** --- 5137,5210 ---- abort (); + /* COMPLEX type for Extended Pascal & Fortran */ + case COMPLEX_EXPR: + { + enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp))); + + rtx prev; + + /* Get the rtx code of the operands. */ + op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); + op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); + + if (! target) + target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + + prev = get_last_insn (); + + /* Tell flow that the whole of the destination is being set. */ + if (GET_CODE (target) == REG) + emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); + + /* Move the real (op0) and imaginary (op1) parts to their location. */ + emit_move_insn (gen_realpart (mode, target), op0); + emit_move_insn (gen_imagpart (mode, target), op1); + + /* Complex construction should appear as a single unit. */ + group_insns (prev); + + return target; + } + + case REALPART_EXPR: + op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); + return gen_realpart (mode, op0); + + case IMAGPART_EXPR: + op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); + return gen_imagpart (mode, op0); + + case CONJ_EXPR: + { + enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp))); + rtx imag_t; + rtx prev; + + op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); + + if (! target) + target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + + prev = get_last_insn (); + + /* Tell flow that the whole of the destination is being set. */ + if (GET_CODE (target) == REG) + emit_insn (gen_rtx (CLOBBER, VOIDmode, target)); + + /* Store the realpart and the negated imagpart to target. */ + emit_move_insn (gen_realpart (mode, target), gen_realpart (mode, op0)); + + imag_t = gen_imagpart (mode, target); + temp = expand_unop (mode, neg_optab, + gen_imagpart (mode, op0), imag_t, 0); + if (temp != imag_t) + emit_move_insn (imag_t, temp); + + /* Conjugate should appear as a single unit */ + group_insns (prev); + + return target; + } + case ERROR_MARK: return const0_rtx; *************** *** 4635,4639 **** subtarget = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); binop2: temp = expand_binop (mode, this_optab, op0, op1, target, --- 5221,5225 ---- subtarget = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); binop2: temp = expand_binop (mode, this_optab, op0, op1, target, *************** *** 4838,4843 **** tree arglist = TREE_OPERAND (exp, 1); rtx op0; ! rtx lab1, lab2, insns; enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); switch (DECL_FUNCTION_CODE (fndecl)) --- 5424,5430 ---- tree arglist = TREE_OPERAND (exp, 1); rtx op0; ! rtx lab1, insns; enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); + optab builtin_optab; switch (DECL_FUNCTION_CODE (fndecl)) *************** *** 4849,4852 **** --- 5436,5441 ---- abort (); + case BUILT_IN_SIN: + case BUILT_IN_COS: case BUILT_IN_FSQRT: /* If not optimizing, call the library function. */ *************** *** 4873,4911 **** target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); ! /* Test the argument to make sure it is in the proper domain for ! the sqrt function. If it is not in the domain, branch to a ! library call. */ start_sequence (); - lab1 = gen_label_rtx (); - lab2 = gen_label_rtx (); - - /* By default check the arguments. If flag_fast_math is turned on, - then assume sqrt will always be called with valid arguments. - Note changing the test below from "> 0" to ">= 0" would cause - incorrect results when computing sqrt(-0.0). */ - - if (! flag_fast_math) - { - /* By checking op > 0 we are able to catch all of the - IEEE special cases with a single if conditional. */ - emit_cmp_insn (op0, CONST0_RTX (GET_MODE (op0)), GT, 0, - GET_MODE (op0), 0, 0); - emit_jump_insn (gen_bgt (lab1)); - - /* The argument was not in the domain; do this via library call. - Pop the arguments right away in case the call gets deleted. */ - NO_DEFER_POP; - expand_call (exp, target, 0); - OK_DEFER_POP; ! /* Branch around open coded version */ ! emit_jump_insn (gen_jump (lab2)); } ! emit_label (lab1); ! /* Arg is in the domain, compute sqrt, into TARGET. Set TARGET to wherever the result comes back. */ target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), ! sqrt_optab, op0, target, 0); /* If we were unable to expand via the builtin, stop the --- 5462,5484 ---- target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); ! emit_queue (); start_sequence (); ! switch (DECL_FUNCTION_CODE (fndecl)) ! { ! case BUILT_IN_SIN: ! builtin_optab = sin_optab; break; ! case BUILT_IN_COS: ! builtin_optab = cos_optab; break; ! case BUILT_IN_FSQRT: ! builtin_optab = sqrt_optab; break; ! default: ! abort (); } ! /* Compute into TARGET. Set TARGET to wherever the result comes back. */ target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))), ! builtin_optab, op0, target, 0); /* If we were unable to expand via the builtin, stop the *************** *** 4917,4922 **** break; } ! emit_label (lab2); /* Output the entire sequence. */ --- 5490,5532 ---- break; } ! ! /* Check the results by default. But if flag_fast_math is turned on, ! then assume sqrt will always be called with valid arguments. */ ! ! if (! flag_fast_math) ! { ! /* Don't define the builtin FP instructions ! if your machine is not IEEE. */ ! if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT) ! abort (); ! ! lab1 = gen_label_rtx (); ! ! /* Test the result; if it is NaN, set errno=EDOM because ! the argument was not in the domain. */ ! emit_cmp_insn (target, target, EQ, 0, GET_MODE (target), 0, 0); ! emit_jump_insn (gen_beq (lab1)); ! ! #if TARGET_EDOM ! { ! #ifdef GEN_ERRNO_RTX ! rtx errno_rtx = GEN_ERRNO_RTX; ! #else ! rtx errno_rtx ! = gen_rtx (MEM, word_mode, gen_rtx (SYMBOL_REF, Pmode, "*errno")); ! #endif ! ! emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM)); ! } ! #else ! /* We can't set errno=EDOM directly; let the library call do it. ! Pop the arguments right away in case the call gets deleted. */ ! NO_DEFER_POP; ! expand_call (exp, target, 0); ! OK_DEFER_POP; ! #endif + emit_label (lab1); + } /* Output the entire sequence. */ *************** *** 5010,5014 **** error ("argument of __builtin_args_info out of range"); else ! return gen_rtx (CONST_INT, VOIDmode, word_ptr[wordnum]); } } --- 5620,5624 ---- error ("argument of __builtin_args_info out of range"); else ! return GEN_INT (word_ptr[wordnum]); } } *************** *** 5029,5033 **** result = build (INDIRECT_REF, build_pointer_type (type), result); TREE_CONSTANT (result) = 1; ! return expand_expr (result, 0, VOIDmode, 0); #endif } --- 5639,5643 ---- result = build (INDIRECT_REF, build_pointer_type (type), result); TREE_CONSTANT (result) = 1; ! return expand_expr (result, NULL_RTX, VOIDmode, 0); #endif } *************** *** 5049,5053 **** current_function_internal_arg_pointer, current_function_arg_offset_rtx, ! 0, 0, OPTAB_LIB_WIDEN); case BUILT_IN_CLASSIFY_TYPE: --- 5659,5663 ---- current_function_internal_arg_pointer, current_function_arg_offset_rtx, ! NULL_RTX, 0, OPTAB_LIB_WIDEN); case BUILT_IN_CLASSIFY_TYPE: *************** *** 5057,5099 **** enum tree_code code = TREE_CODE (type); if (code == VOID_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, void_type_class); if (code == INTEGER_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, integer_type_class); if (code == CHAR_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, char_type_class); if (code == ENUMERAL_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, enumeral_type_class); if (code == BOOLEAN_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, boolean_type_class); if (code == POINTER_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, pointer_type_class); if (code == REFERENCE_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, reference_type_class); if (code == OFFSET_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, offset_type_class); if (code == REAL_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, real_type_class); if (code == COMPLEX_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, complex_type_class); if (code == FUNCTION_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, function_type_class); if (code == METHOD_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, method_type_class); if (code == RECORD_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, record_type_class); if (code == UNION_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, union_type_class); if (code == ARRAY_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, array_type_class); if (code == STRING_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, string_type_class); if (code == SET_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, set_type_class); if (code == FILE_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, file_type_class); if (code == LANG_TYPE) ! return gen_rtx (CONST_INT, VOIDmode, lang_type_class); } ! return gen_rtx (CONST_INT, VOIDmode, no_type_class); case BUILT_IN_CONSTANT_P: --- 5667,5709 ---- enum tree_code code = TREE_CODE (type); if (code == VOID_TYPE) ! return GEN_INT (void_type_class); if (code == INTEGER_TYPE) ! return GEN_INT (integer_type_class); if (code == CHAR_TYPE) ! return GEN_INT (char_type_class); if (code == ENUMERAL_TYPE) ! return GEN_INT (enumeral_type_class); if (code == BOOLEAN_TYPE) ! return GEN_INT (boolean_type_class); if (code == POINTER_TYPE) ! return GEN_INT (pointer_type_class); if (code == REFERENCE_TYPE) ! return GEN_INT (reference_type_class); if (code == OFFSET_TYPE) ! return GEN_INT (offset_type_class); if (code == REAL_TYPE) ! return GEN_INT (real_type_class); if (code == COMPLEX_TYPE) ! return GEN_INT (complex_type_class); if (code == FUNCTION_TYPE) ! return GEN_INT (function_type_class); if (code == METHOD_TYPE) ! return GEN_INT (method_type_class); if (code == RECORD_TYPE) ! return GEN_INT (record_type_class); if (code == UNION_TYPE) ! return GEN_INT (union_type_class); if (code == ARRAY_TYPE) ! return GEN_INT (array_type_class); if (code == STRING_TYPE) ! return GEN_INT (string_type_class); if (code == SET_TYPE) ! return GEN_INT (set_type_class); if (code == FILE_TYPE) ! return GEN_INT (file_type_class); if (code == LANG_TYPE) ! return GEN_INT (lang_type_class); } ! return GEN_INT (no_type_class); case BUILT_IN_CONSTANT_P: *************** *** 5101,5105 **** return const0_rtx; else ! return (TREE_CODE_CLASS (TREE_VALUE (arglist)) == 'c' ? const1_rtx : const0_rtx); --- 5711,5715 ---- return const0_rtx; else ! return (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (arglist))) == 'c' ? const1_rtx : const0_rtx); *************** *** 5165,5169 **** current_function_calls_alloca = 1; /* Compute the argument. */ ! op0 = expand_expr (TREE_VALUE (arglist), 0, VOIDmode, 0); /* Allocate the desired space. */ --- 5775,5779 ---- current_function_calls_alloca = 1; /* Compute the argument. */ ! op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); /* Allocate the desired space. */ *************** *** 5172,5176 **** /* Record the new stack level for nonlocal gotos. */ if (nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0); return target; --- 5782,5786 ---- /* Record the new stack level for nonlocal gotos. */ if (nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX); return target; *************** *** 5251,5255 **** src_rtx = memory_address (BLKmode, ! expand_expr (src, 0, Pmode, EXPAND_NORMAL)); if (! (*insn_operand_predicate[(int)icode][1]) (src_rtx, Pmode)) --- 5861,5865 ---- src_rtx = memory_address (BLKmode, ! expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL)); if (! (*insn_operand_predicate[(int)icode][1]) (src_rtx, Pmode)) *************** *** 5263,5268 **** emit_insn (GEN_FCN (icode) (result, gen_rtx (MEM, BLKmode, src_rtx), ! char_rtx, ! gen_rtx (CONST_INT, VOIDmode, align))); /* Return the value in the proper mode for this function. */ --- 5873,5877 ---- emit_insn (GEN_FCN (icode) (result, gen_rtx (MEM, BLKmode, src_rtx), ! char_rtx, GEN_INT (align))); /* Return the value in the proper mode for this function. */ *************** *** 5298,5302 **** len = size_binop (PLUS_EXPR, len, integer_one_node); ! chainon (arglist, build_tree_list (0, len)); } --- 5907,5911 ---- len = size_binop (PLUS_EXPR, len, integer_one_node); ! chainon (arglist, build_tree_list (NULL_TREE, len)); } *************** *** 5336,5340 **** } ! dest_rtx = expand_expr (dest, 0, Pmode, EXPAND_NORMAL); /* Copy word part most expediently. */ --- 5945,5949 ---- } ! dest_rtx = expand_expr (dest, NULL_RTX, Pmode, EXPAND_NORMAL); /* Copy word part most expediently. */ *************** *** 5343,5349 **** gen_rtx (MEM, BLKmode, memory_address (BLKmode, ! expand_expr (src, 0, Pmode, EXPAND_NORMAL))), ! expand_expr (len, 0, VOIDmode, 0), MIN (src_align, dest_align)); return dest_rtx; --- 5952,5959 ---- gen_rtx (MEM, BLKmode, memory_address (BLKmode, ! expand_expr (src, NULL_RTX, ! Pmode, EXPAND_NORMAL))), ! expand_expr (len, NULL_RTX, VOIDmode, 0), MIN (src_align, dest_align)); return dest_rtx; *************** *** 5403,5407 **** } ! chainon (arglist, build_tree_list (0, len)); } --- 6013,6017 ---- } ! chainon (arglist, build_tree_list (NULL_TREE, len)); } *************** *** 5452,5461 **** emit_insn (gen_cmpstrsi (result, gen_rtx (MEM, BLKmode, ! expand_expr (arg1, 0, Pmode, EXPAND_NORMAL)), gen_rtx (MEM, BLKmode, ! expand_expr (arg2, 0, Pmode, EXPAND_NORMAL)), ! expand_expr (len, 0, VOIDmode, 0), ! gen_rtx (CONST_INT, VOIDmode, ! MIN (arg1_align, arg2_align)))); /* Return the value in the proper mode for this function. */ --- 6062,6072 ---- emit_insn (gen_cmpstrsi (result, gen_rtx (MEM, BLKmode, ! expand_expr (arg1, NULL_RTX, Pmode, ! EXPAND_NORMAL)), gen_rtx (MEM, BLKmode, ! expand_expr (arg2, NULL_RTX, Pmode, ! EXPAND_NORMAL)), ! expand_expr (len, NULL_RTX, VOIDmode, 0), ! GEN_INT (MIN (arg1_align, arg2_align)))); /* Return the value in the proper mode for this function. */ *************** *** 5516,5525 **** Note whether OP0 is the actual lvalue or a copy of it: I believe it is a copy iff it is a register or subreg ! and insns were generated in computing it. */ temp = get_last_insn (); ! op0 = expand_expr (incremented, 0, VOIDmode, 0); op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) && temp != get_last_insn ()); ! op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); /* Decide whether incrementing or decrementing. */ --- 6127,6149 ---- Note whether OP0 is the actual lvalue or a copy of it: I believe it is a copy iff it is a register or subreg ! and insns were generated in computing it. */ ! temp = get_last_insn (); ! op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0); ! ! /* If OP0 is a SUBREG made for a promoted variable, we cannot increment ! in place but intead must do sign- or zero-extension during assignment, ! so we copy it into a new register and let the code below use it as ! a copy. ! ! Note that we can safely modify this SUBREG since it is know not to be ! shared (it was made by the expand_expr call above). */ ! ! if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0)) ! SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0)); ! op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG) && temp != get_last_insn ()); ! op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); /* Decide whether incrementing or decrementing. */ *************** *** 5553,5557 **** && GET_CODE (op1) == CONST_INT) { ! op1 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op1)); this_optab = add_optab; } --- 6177,6181 ---- && GET_CODE (op1) == CONST_INT) { ! op1 = GEN_INT (- INTVAL (op1)); this_optab = add_optab; } *************** *** 5632,5636 **** || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0); return; --- 6256,6260 ---- || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))) ! CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0); return; *************** *** 5685,5689 **** #ifdef EXIT_IGNORE_STACK if (! flag_omit_frame_pointer && EXIT_IGNORE_STACK ! && ! (TREE_INLINE (current_function_decl) && ! flag_no_inline) && ! flag_inline_functions) pending_stack_adjust = 0; --- 6309,6313 ---- #ifdef EXIT_IGNORE_STACK if (! flag_omit_frame_pointer && EXIT_IGNORE_STACK ! && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline) && ! flag_inline_functions) pending_stack_adjust = 0; *************** *** 5699,5703 **** { if (pending_stack_adjust != 0) ! adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust)); pending_stack_adjust = 0; } --- 6323,6327 ---- { if (pending_stack_adjust != 0) ! adjust_stack (GEN_INT (pending_stack_adjust)); pending_stack_adjust = 0; } *************** *** 5713,5717 **** while (cleanups_this_call != old_cleanups) { ! expand_expr (TREE_VALUE (cleanups_this_call), 0, VOIDmode, 0); cleanups_this_call = TREE_CHAIN (cleanups_this_call); } --- 6337,6341 ---- while (cleanups_this_call != old_cleanups) { ! expand_expr (TREE_VALUE (cleanups_this_call), NULL_RTX, VOIDmode, 0); cleanups_this_call = TREE_CHAIN (cleanups_this_call); } *************** *** 5729,5733 **** rtx label; { ! do_jump (exp, label, 0); } --- 6353,6357 ---- rtx label; { ! do_jump (exp, label, NULL_RTX); } *************** *** 5739,5743 **** rtx label; { ! do_jump (exp, 0, label); } --- 6363,6367 ---- rtx label; { ! do_jump (exp, NULL_RTX, label); } *************** *** 5840,5848 **** ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */ ! if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_INT && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0 && (type = type_for_size (i + 1, 1)) != 0 ! && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))) { do_jump (convert (type, exp), if_false_label, if_true_label); --- 6464,6475 ---- ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */ ! if (! SLOW_BYTE_ACCESS ! && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST ! && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0 && (type = type_for_size (i + 1, 1)) != 0 ! && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp)) ! && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code ! != CODE_FOR_nothing)) { do_jump (convert (type, exp), if_false_label, if_true_label); *************** *** 5858,5862 **** if (if_false_label == 0) if_false_label = drop_through_label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), if_false_label, 0); do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); break; --- 6485,6489 ---- if (if_false_label == 0) if_false_label = drop_through_label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX); do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); break; *************** *** 5865,5869 **** if (if_true_label == 0) if_true_label = drop_through_label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), 0, if_true_label); do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); break; --- 6492,6496 ---- if (if_true_label == 0) if_true_label = drop_through_label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label); do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label); break; *************** *** 5893,5898 **** type = type_for_size (bitsize, unsignedp); ! if (type != 0 && bitsize >= 0 ! && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))) { do_jump (convert (type, exp), if_false_label, if_true_label); --- 6520,6528 ---- type = type_for_size (bitsize, unsignedp); ! if (! SLOW_BYTE_ACCESS ! && type != 0 && bitsize >= 0 ! && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp)) ! && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code ! != CODE_FOR_nothing)) { do_jump (convert (type, exp), if_false_label, if_true_label); *************** *** 5916,5920 **** register rtx label1 = gen_label_rtx (); drop_through_label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), label1, 0); /* Now the THEN-expression. */ do_jump (TREE_OPERAND (exp, 1), --- 6546,6550 ---- register rtx label1 = gen_label_rtx (); drop_through_label = gen_label_rtx (); ! do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX); /* Now the THEN-expression. */ do_jump (TREE_OPERAND (exp, 1), *************** *** 5993,5997 **** default: normal: ! temp = expand_expr (exp, 0, VOIDmode, 0); #if 0 /* This is not needed any more and causes poor code since it causes --- 6623,6627 ---- default: normal: ! temp = expand_expr (exp, NULL_RTX, VOIDmode, 0); #if 0 /* This is not needed any more and causes poor code since it causes *************** *** 6014,6018 **** else if (GET_MODE (temp) != VOIDmode) comparison = compare_from_rtx (temp, CONST0_RTX (GET_MODE (temp)), ! NE, 1, GET_MODE (temp), 0, 0); else abort (); --- 6644,6649 ---- else if (GET_MODE (temp) != VOIDmode) comparison = compare_from_rtx (temp, CONST0_RTX (GET_MODE (temp)), ! NE, TREE_UNSIGNED (TREE_TYPE (exp)), ! GET_MODE (temp), NULL_RTX, 0); else abort (); *************** *** 6062,6067 **** rtx if_false_label, if_true_label; { ! rtx op0 = expand_expr (TREE_OPERAND (exp, swap), 0, VOIDmode, 0); ! rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), 0, VOIDmode, 0); enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); --- 6693,6698 ---- rtx if_false_label, if_true_label; { ! rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0); ! rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0); enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); *************** *** 6097,6113 **** comp = compare_from_rtx (op0_word, op1_word, (unsignedp || i > 0) ? GTU : GT, ! unsignedp, word_mode, 0, 0); if (comp == const_true_rtx) emit_jump (if_true_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, 0, if_true_label); /* Consider lower words only if these are equal. */ comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode, ! 0, 0); if (comp == const_true_rtx) emit_jump (if_false_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, 0, if_false_label); } --- 6728,6744 ---- comp = compare_from_rtx (op0_word, op1_word, (unsignedp || i > 0) ? GTU : GT, ! unsignedp, word_mode, NULL_RTX, 0); if (comp == const_true_rtx) emit_jump (if_true_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, NULL_RTX, if_true_label); /* Consider lower words only if these are equal. */ comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode, ! NULL_RTX, 0); if (comp == const_true_rtx) emit_jump (if_false_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, NULL_RTX, if_false_label); } *************** *** 6126,6131 **** rtx if_false_label, if_true_label; { ! rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); --- 6757,6762 ---- rtx if_false_label, if_true_label; { ! rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); ! rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD); *************** *** 6140,6148 **** rtx comp = compare_from_rtx (operand_subword_force (op0, i, mode), operand_subword_force (op1, i, mode), ! EQ, 0, word_mode, 0, 0); if (comp == const_true_rtx) emit_jump (if_false_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, if_false_label, 0); } --- 6771,6780 ---- rtx comp = compare_from_rtx (operand_subword_force (op0, i, mode), operand_subword_force (op1, i, mode), ! EQ, TREE_UNSIGNED (TREE_TYPE (exp)), ! word_mode, NULL_RTX, 0); if (comp == const_true_rtx) emit_jump (if_false_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, if_false_label, NULL_RTX); } *************** *** 6173,6181 **** rtx comp = compare_from_rtx (operand_subword_force (op0, i, GET_MODE (op0)), ! const0_rtx, EQ, 0, word_mode, 0, 0); if (comp == const_true_rtx) emit_jump (if_false_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, if_false_label, 0); } --- 6805,6813 ---- rtx comp = compare_from_rtx (operand_subword_force (op0, i, GET_MODE (op0)), ! const0_rtx, EQ, 1, word_mode, NULL_RTX, 0); if (comp == const_true_rtx) emit_jump (if_false_label); else if (comp != const0_rtx) ! do_jump_for_compare (comp, if_false_label, NULL_RTX); } *************** *** 6264,6269 **** enum rtx_code signed_code, unsigned_code; { ! register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0); ! register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0); register tree type = TREE_TYPE (TREE_OPERAND (exp, 0)); register enum machine_mode mode = TYPE_MODE (type); --- 6896,6903 ---- enum rtx_code signed_code, unsigned_code; { ! register rtx op0 ! = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); ! register rtx op1 ! = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0); register tree type = TREE_TYPE (TREE_OPERAND (exp, 0)); register enum machine_mode mode = TYPE_MODE (type); *************** *** 6273,6277 **** return compare_from_rtx (op0, op1, code, unsignedp, mode, ((mode == BLKmode) ! ? expr_size (TREE_OPERAND (exp, 0)) : 0), TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); } --- 6907,6911 ---- return compare_from_rtx (op0, op1, code, unsignedp, mode, ((mode == BLKmode) ! ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX), TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT); } *************** *** 6316,6333 **** return simplify_relational_operation (code, mode, op0, op1); /* If this is a signed equality comparison, we can do it as an unsigned comparison since zero-extension is cheaper than sign ! extension and comparisons with zero are done as unsigned. If we ! are comparing against a constant, we must convert it to what it ! would look like unsigned. */ if ((code == EQ || code == NE) && ! unsignedp ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_INT) { if (GET_CODE (op1) == CONST_INT && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) ! op1 = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))); unsignedp = 1; } emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align); --- 6950,6974 ---- return simplify_relational_operation (code, mode, op0, op1); + #if 0 + /* There's no need to do this now that combine.c can eliminate lots of + sign extensions. This can be less efficient in certain cases on other + machines. + /* If this is a signed equality comparison, we can do it as an unsigned comparison since zero-extension is cheaper than sign ! extension and comparisons with zero are done as unsigned. This is ! the case even on machines that can do fast sign extension, since ! zero-extension is easier to combinen with other operations than ! sign-extension is. If we are comparing against a constant, we must ! convert it to what it would look like unsigned. */ if ((code == EQ || code == NE) && ! unsignedp ! && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) { if (GET_CODE (op1) == CONST_INT && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) ! op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))); unsignedp = 1; } + #endif emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align); *************** *** 6393,6401 **** return 0; ! while (TREE_CODE (arg0) == NON_LVALUE_EXPR) ! arg0 = TREE_OPERAND (arg0, 0); ! ! while (TREE_CODE (arg1) == NON_LVALUE_EXPR) ! arg1 = TREE_OPERAND (arg1, 0); /* Get the rtx comparison code to use. We know that EXP is a comparison --- 7034,7039 ---- return 0; ! STRIP_NOPS (arg0); ! STRIP_NOPS (arg1); /* Get the rtx comparison code to use. We know that EXP is a comparison *************** *** 6458,6465 **** && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1) && integer_pow2p (TREE_OPERAND (arg0, 1)) ! && TYPE_PRECISION (type) <= HOST_BITS_PER_INT) { int bitnum = exact_log2 (INTVAL (expand_expr (TREE_OPERAND (arg0, 1), ! 0, VOIDmode, 0))); if (subtarget == 0 || GET_CODE (subtarget) != REG --- 7096,7103 ---- && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1) && integer_pow2p (TREE_OPERAND (arg0, 1)) ! && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT) { int bitnum = exact_log2 (INTVAL (expand_expr (TREE_OPERAND (arg0, 1), ! NULL_RTX, VOIDmode, 0))); if (subtarget == 0 || GET_CODE (subtarget) != REG *************** *** 6518,6528 **** op0 = expand_expr (arg0, subtarget, VOIDmode, 0); ! op1 = expand_expr (arg1, 0, VOIDmode, 0); if (target == 0) target = gen_reg_rtx (mode); ! result = emit_store_flag (target, code, op0, op1, operand_mode, ! unsignedp, 1); if (result) --- 7156,7172 ---- op0 = expand_expr (arg0, subtarget, VOIDmode, 0); ! op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); if (target == 0) target = gen_reg_rtx (mode); ! /* Pass copies of OP0 and OP1 in case they contain a QUEUED. This is safe ! because, if the emit_store_flag does anything it will succeed and ! OP0 and OP1 will not be used subsequently. */ ! ! result = emit_store_flag (target, code, ! queued_subexp_p (op0) ? copy_rtx (op0) : op0, ! queued_subexp_p (op1) ? copy_rtx (op1) : op1, ! operand_mode, unsignedp, 1); if (result) *************** *** 6540,6544 **** emit_move_insn (target, invert ? const0_rtx : const1_rtx); ! result = compare_from_rtx (op0, op1, code, unsignedp, operand_mode, 0, 0); if (GET_CODE (result) == CONST_INT) return (((result == const0_rtx && ! invert) --- 7184,7189 ---- emit_move_insn (target, invert ? const0_rtx : const1_rtx); ! result = compare_from_rtx (op0, op1, code, unsignedp, ! operand_mode, NULL_RTX, 0); if (GET_CODE (result) == CONST_INT) return (((result == const0_rtx && ! invert) *************** *** 6585,6589 **** the maximum value of the range. */ ! emit_cmp_insn (range, index, LTU, 0, mode, 0, 0); emit_jump_insn (gen_bltu (default_label)); --- 7230,7234 ---- the maximum value of the range. */ ! emit_cmp_insn (range, index, LTU, NULL_RTX, mode, 0, 0); emit_jump_insn (gen_bltu (default_label)); *************** *** 6605,6610 **** gen_rtx (PLUS, Pmode, gen_rtx (MULT, Pmode, index, ! gen_rtx (CONST_INT, VOIDmode, ! GET_MODE_SIZE (CASE_VECTOR_MODE))), gen_rtx (LABEL_REF, Pmode, table_label))); temp = gen_reg_rtx (CASE_VECTOR_MODE); --- 7250,7254 ---- gen_rtx (PLUS, Pmode, gen_rtx (MULT, Pmode, index, ! GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))), gen_rtx (LABEL_REF, Pmode, table_label))); temp = gen_reg_rtx (CASE_VECTOR_MODE); diff -rc2N gcc-2.2.2/expr.h gcc-2.3.1/expr.h *** gcc-2.2.2/expr.h Thu May 7 02:35:31 1992 --- gcc-2.3.1/expr.h Sat Oct 3 14:43:01 1992 *************** *** 30,33 **** --- 30,38 ---- #endif + /* The default is that we do not promote the mode of an object. */ + #ifndef PROMOTE_MODE + #define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) + #endif + /* Macros to access the slots of a QUEUED rtx. Here rather than in rtl.h because only the expansion pass *************** *** 154,161 **** /* Convert the implicit sum in a `struct args_size' into an rtx. */ #define ARGS_SIZE_RTX(SIZE) \ ! ((SIZE).var == 0 ? gen_rtx (CONST_INT, VOIDmode, (SIZE).constant) \ : expand_expr (size_binop (PLUS_EXPR, (SIZE).var, \ size_int ((SIZE).constant)), \ ! 0, VOIDmode, 0)) /* Convert the implicit sum in a `struct args_size' into a tree. */ --- 159,166 ---- /* Convert the implicit sum in a `struct args_size' into an rtx. */ #define ARGS_SIZE_RTX(SIZE) \ ! ((SIZE).var == 0 ? GEN_INT ((SIZE).constant) \ : expand_expr (size_binop (PLUS_EXPR, (SIZE).var, \ size_int ((SIZE).constant)), \ ! NULL_RTX, VOIDmode, 0)) /* Convert the implicit sum in a `struct args_size' into a tree. */ *************** *** 321,324 **** --- 326,331 ---- extern optab ffs_optab; /* Find first bit set */ extern optab sqrt_optab; /* Square root */ + extern optab sin_optab; /* Sine */ + extern optab cos_optab; /* Cosine */ extern optab strlen_optab; /* String length */ *************** *** 342,346 **** --- 349,363 ---- extern rtx extendsfdf2_libfunc; + extern rtx extendsfxf2_libfunc; + extern rtx extendsftf2_libfunc; + extern rtx extenddfxf2_libfunc; + extern rtx extenddftf2_libfunc; + extern rtx truncdfsf2_libfunc; + extern rtx truncxfsf2_libfunc; + extern rtx trunctfsf2_libfunc; + extern rtx truncxfdf2_libfunc; + extern rtx trunctfdf2_libfunc; + extern rtx memcpy_libfunc; extern rtx bcopy_libfunc; *************** *** 349,352 **** --- 366,370 ---- extern rtx memset_libfunc; extern rtx bzero_libfunc; + extern rtx eqsf2_libfunc; extern rtx nesf2_libfunc; *************** *** 355,358 **** --- 373,377 ---- extern rtx ltsf2_libfunc; extern rtx lesf2_libfunc; + extern rtx eqdf2_libfunc; extern rtx nedf2_libfunc; *************** *** 361,376 **** extern rtx ltdf2_libfunc; extern rtx ledf2_libfunc; ! extern rtx floatdisf_libfunc; extern rtx floatsisf_libfunc; ! extern rtx floatdidf_libfunc; extern rtx floatsidf_libfunc; extern rtx fixsfsi_libfunc; extern rtx fixsfdi_libfunc; extern rtx fixdfsi_libfunc; extern rtx fixdfdi_libfunc; extern rtx fixunssfsi_libfunc; extern rtx fixunssfdi_libfunc; extern rtx fixunsdfsi_libfunc; extern rtx fixunsdfdi_libfunc; typedef rtx (*rtxfun) (); --- 380,445 ---- extern rtx ltdf2_libfunc; extern rtx ledf2_libfunc; ! ! extern rtx eqxf2_libfunc; ! extern rtx nexf2_libfunc; ! extern rtx gtxf2_libfunc; ! extern rtx gexf2_libfunc; ! extern rtx ltxf2_libfunc; ! extern rtx lexf2_libfunc; ! ! extern rtx eqtf2_libfunc; ! extern rtx netf2_libfunc; ! extern rtx gttf2_libfunc; ! extern rtx getf2_libfunc; ! extern rtx lttf2_libfunc; ! extern rtx letf2_libfunc; ! extern rtx floatsisf_libfunc; ! extern rtx floatdisf_libfunc; ! extern rtx floattisf_libfunc; ! extern rtx floatsidf_libfunc; + extern rtx floatdidf_libfunc; + extern rtx floattidf_libfunc; + + extern rtx floatsixf_libfunc; + extern rtx floatdixf_libfunc; + extern rtx floattixf_libfunc; + + extern rtx floatsitf_libfunc; + extern rtx floatditf_libfunc; + extern rtx floattitf_libfunc; + extern rtx fixsfsi_libfunc; extern rtx fixsfdi_libfunc; + extern rtx fixsfti_libfunc; + extern rtx fixdfsi_libfunc; extern rtx fixdfdi_libfunc; + extern rtx fixdfti_libfunc; + + extern rtx fixxfsi_libfunc; + extern rtx fixxfdi_libfunc; + extern rtx fixxfti_libfunc; + + extern rtx fixtfsi_libfunc; + extern rtx fixtfdi_libfunc; + extern rtx fixtfti_libfunc; + extern rtx fixunssfsi_libfunc; extern rtx fixunssfdi_libfunc; + extern rtx fixunssfti_libfunc; + extern rtx fixunsdfsi_libfunc; extern rtx fixunsdfdi_libfunc; + extern rtx fixunsdfti_libfunc; + + extern rtx fixunsxfsi_libfunc; + extern rtx fixunsxfdi_libfunc; + extern rtx fixunsxfti_libfunc; + + extern rtx fixunstfsi_libfunc; + extern rtx fixunstfdi_libfunc; + extern rtx fixunstfti_libfunc; typedef rtx (*rtxfun) (); *************** *** 396,399 **** --- 465,471 ---- extern rtx expand_unop (); + /* Expand the complex absolute value operation. */ + extern rtx expand_complex_abs (); + /* Arguments MODE, RTX: return an rtx for the negation of that value. May emit insns. */ *************** *** 465,471 **** /* Return an rtx for the size in bytes of the value of an expr. */ extern rtx expr_size (); - - /* Return an rtx for the sum of an rtx and an integer. */ - extern rtx plus_constant (); extern rtx lookup_static_chain (); --- 537,540 ---- diff -rc2N gcc-2.2.2/extend.texi gcc-2.3.1/extend.texi *** gcc-2.2.2/extend.texi Thu Jun 4 17:44:11 1992 --- gcc-2.3.1/extend.texi Wed Oct 21 17:57:06 1992 *************** *** 290,293 **** --- 290,298 ---- containing function has exited, all hell will break loose. + GNU CC implements taking the address of a nested function using a + technique called @dfn{trampolines}. A paper describing them is + available from @samp{maya.idiap.ch} in the file + @file{pub/tmb/usenix88-lexic.ps.Z}. + A nested function can jump to a label inherited from a containing function, provided the label was explicitly declared in the containing *************** *** 1145,1148 **** --- 1150,1202 ---- @emph{anything}. + The keyword @code{__attribute__} allows you to specify special + attributes when making a declaration. This keyword is followed by an + attribute specification inside double parentheses. One attributes, + @code{format}, is currently defined for functions. Others are + implemented for variables and structure fields (@pxref{Function + Attributes}). + + @table @code + @item format (@var{archetype}, @var{string-index}, @var{first-to-check}) + @cindex @code{format} attribute + The @code{format} attribute specifies that a function takes @code{printf} + or @code{scanf} style arguments which should be type-checked against a + format string. For example, the declaration: + + @example + extern int + my_printf (void *my_object, const char *my_format, ...) + __attribute__ ((format (printf, 2, 3))); + @end example + + @noindent + causes the compiler to check the arguments in calls to @code{my_printf} + for consistency with the @code{printf} style format string argument + @code{my_format}. + + The parameter @var{archetype} determines how the format string is + interpreted, and should be either @code{printf} or @code{scanf}. The + parameter @var{string-index} specifies which argument is the format + string argument (starting from 1), while @var{first-to-check} is the + number of the first argument to check against the format string. For + functions where the arguments are not available to be checked (such as + @code{vprintf}), specify the third parameter as zero. In this case the + compiler only checks the format string for consistency. + + In the example above, the format string (@code{my_format}) is the second + argument of the function @code{my_print}, and the arguments to check + start with the third argument, so the correct parameters for the format + attribute are 2 and 3. + + The @code{format} attribute allows you to identify your own functions + which take format strings as arguments, so that GNU CC can check the + calls to these functions for errors. The compiler always checks formats + for the ANSI library functions @code{printf}, @code{fprintf}, + @code{sprintf}, @code{scanf}, @code{fscanf}, @code{sscanf}, + @code{vprintf}, @code{vfprintf} and @code{vsprintf} whenever such + warnings are requested (using @samp{-Wformat}), so there is no need to + modify the header file @file{stdio.h}. + @end table + @node Function Prototypes @section Prototypes and Old-Style Function Definitions *************** *** 1157,1163 **** /* @r{Use prototypes unless the compiler is old-fashioned.} */ #if __STDC__ ! #define P((x)) (x) #else ! #define P((x)) () #endif --- 1211,1217 ---- /* @r{Use prototypes unless the compiler is old-fashioned.} */ #if __STDC__ ! #define P(x) (x) #else ! #define P(x) () #endif *************** *** 1209,1216 **** many traditional C implementations allow such identifiers. ! Dollar signs are allowed on certain machines if you specify ! @samp{-traditional}. On a few systems they are allowed by default, even ! if @samp{-traditional} is not used. But they are never allowed if you ! specify @samp{-ansi}. There are certain ANSI C programs (obscure, to be sure) that would --- 1263,1270 ---- many traditional C implementations allow such identifiers. ! On some machines, dollar signs are allowed in identifiers if you specify ! @w{@samp{-traditional}}. On a few systems they are allowed by default, ! even if you do not use @w{@samp{-traditional}}. But they are never ! allowed if you specify @w{@samp{-ansi}}. There are certain ANSI C programs (obscure, to be sure) that would *************** *** 1265,1268 **** --- 1319,1326 ---- does not itself demand any alignment.@refill + A related feature which lets you specify the alignment of an object is + @code{__attribute__ ((aligned (@var{alignment})))}; see the following + section. + @node Variable Attributes @section Specifying Attributes of Variables *************** *** 1271,1280 **** The keyword @code{__attribute__} allows you to specify special ! attributes of variables or structure fields. The only attributes ! currently defined are the @code{aligned} and @code{format} attributes. - The @code{aligned} attribute specifies the alignment of the variable or - structure field. For example, the declaration: - @example int x __attribute__ ((aligned (16))) = 0; --- 1329,1344 ---- The keyword @code{__attribute__} allows you to specify special ! attributes of variables or structure fields. This keyword is followed ! by an attribute specification inside double parentheses. Four ! attributes are currently defined: @code{aligned}, @code{format}, ! @code{mode} and @code{packed}. @code{format} is used for functions, ! and thus not documented here; see @ref{Function Attributes}. ! ! @table @code ! @cindex @code{aligned} attribute ! @item aligned (@var{alignment}) ! This attribute specifies the alignment of the variable or structure ! field, measured in bytes. For example, the declaration: @example int x __attribute__ ((aligned (16))) = 0; *************** *** 1283,1287 **** @noindent causes the compiler to allocate the global variable @code{x} on a ! 16-byte boundary. On a 68000, this could be used in conjunction with an @code{asm} expression to access the @code{move16} instruction which requires 16-byte aligned operands. --- 1347,1351 ---- @noindent causes the compiler to allocate the global variable @code{x} on a ! 16-byte boundary. On a 68040, this could be used in conjunction with an @code{asm} expression to access the @code{move16} instruction which requires 16-byte aligned operands. *************** *** 1303,1344 **** name is just an alias, not a distinct type. ! The @code{format} attribute specifies that a function takes @code{printf} ! or @code{scanf} style arguments which should be type-checked against a ! format string. For example, the declaration: ! ! @example ! extern int ! my_printf (void *my_object, const char *my_format, ...) ! __attribute__ ((format (printf, 2, 3))); ! @end example ! ! @noindent ! causes the compiler to check the arguments in calls to @code{my_printf} ! for consistency with the @code{printf} style format string argument ! @code{my_format}. ! ! The first parameter of the @code{format} attribute determines how the ! format string is interpreted, and should be either @code{printf} or ! @code{scanf}. The second parameter specifies the number of the ! format string argument (starting from 1). The third parameter ! specifies the number of the first argument which should be ! checked against the format string. For functions where the ! arguments are not available to be checked (such as @code{vprintf}), ! specify the third parameter as zero. In this case the compiler only checks ! the format string for consistency. ! ! In the example above, the format string (@code{my_format}) is the second ! argument to @code{my_print} and the arguments to check start with the third ! argument, so the correct parameters for the format attribute are 2 and 3. ! ! The @code{format} attribute allows you to identify your own functions ! which take format strings as arguments, so that GNU CC can check the ! calls to these functions for errors. The compiler always ! checks formats for the ANSI library functions ! @code{printf}, @code{fprintf}, @code{sprintf}, ! @code{scanf}, @code{fscanf}, @code{sscanf}, ! @code{vprintf}, @code{vfprintf} and @code{vsprintf} ! whenever such warnings are requested (using @samp{-Wformat}), so there is no ! need to modify the header file @file{stdio.h}. @node Inline --- 1367,1391 ---- name is just an alias, not a distinct type. ! The linker of your operating system imposes a maximum alignment. If the ! linker aligns each object file on a four byte boundary, then it is ! beyond the compiler's power to cause anything to be aligned to a larger ! boundary than that. For example, if the linker happens to put this object ! file at address 136 (eight more than a multiple of 64), then the compiler ! cannot guarantee an alignment of more than 8 just by aligning variables in ! the object file. ! ! @item mode (@var{mode}) ! @cindex @code{mode} attribute ! This attribute specifies the data type for the declaration---whichever ! type corresponds to the mode @var{mode}. This in effect lets you ! request an integer or floating point type according to its width. ! ! @item packed ! @cindex @code{packed} attribute ! The @code{packed} attribute specifies that a variable or structure field ! should have the smallest possible alignment---one byte for a variable, ! and one bit for a field, unless you specify a larger value with the ! @code{aligned} attribute. ! @end table @node Inline *************** *** 1349,1358 **** @cindex macros, inline alternative ! By declaring a function @code{inline}, you can direct GNU CC to integrate ! that function's code into the code for its callers. This makes execution ! faster by eliminating the function-call overhead; in addition, if any of ! the actual argument values are constant, their known values may permit ! simplifications at compile time so that not all of the inline function's ! code needs to be included. To declare a function inline, use the @code{inline} keyword in its --- 1396,1407 ---- @cindex macros, inline alternative ! By declaring a function @code{inline}, you can direct GNU CC to ! integrate that function's code into the code for its callers. This ! makes execution faster by eliminating the function-call overhead; in ! addition, if any of the actual argument values are constant, their known ! values may permit simplifications at compile time so that not all of the ! inline function's code needs to be included. Inlining of functions is ! an optimization and it really ``works'' only in optimizing compilation. ! If you don't use @samp{-O}, no function is really inline. To declare a function inline, use the @code{inline} keyword in its *************** *** 1409,1412 **** --- 1458,1466 ---- the single copy in the library. + GNU C does not inline any functions when not optimizing. It is not + clear whether it is better to inline or not, in this case, but we found + that a correct implementation when not optimizing was difficult. So we + did the easy thing, and turned it off. + @node Extended Asm @section Assembler Instructions with C Expression Operands *************** *** 1536,1539 **** --- 1590,1598 ---- the condition code is handled differently, and specifying @samp{cc} has no effect. But it is valid no matter what the machine. + + If your assembler instruction modifies memory in an unpredicable + fashion, add @samp{memory} to the list of clobbered registers. + This will cause GNU CC to not keep memory values cached in + registers across the assembler instruction. You can put multiple assembler instructions together in a single @code{asm} diff -rc2N gcc-2.2.2/final.c gcc-2.3.1/final.c *** gcc-2.2.2/final.c Wed Jun 3 16:39:24 1992 --- gcc-2.3.1/final.c Sun Oct 18 04:16:21 1992 *************** *** 44,48 **** FUNCTION_EPILOGUE. Those instructions never exist as rtl. */ - #include #include "config.h" #include "gvarargs.h" --- 44,47 ---- *************** *** 50,53 **** --- 49,53 ---- #include "regs.h" #include "insn-config.h" + #include "insn-flags.h" #include "insn-attr.h" #include "insn-codes.h" *************** *** 56,66 **** #include "flags.h" #include "real.h" - #include "output.h" #include "hard-reg-set.h" ! #ifndef ASM_STABD_OP ! #define ASM_STABD_OP ".stabd" ! #endif /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) --- 56,66 ---- #include "flags.h" #include "real.h" #include "hard-reg-set.h" + #include "defaults.h" ! #include + #include "output.h" + /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) *************** *** 112,115 **** --- 112,116 ---- rtx final_scan_insn (); void profile_function (); + static void profile_after_prologue (); #ifdef HAVE_ATTR_length *************** *** 162,166 **** Final uses these sequence numbers to generate assembler label names LBBnnn and LBEnnn for the beginning and end of the symbol-block. ! Dbxout uses the sequence nunbers to generate references to the same labels from the dbx debugging information. --- 163,167 ---- Final uses these sequence numbers to generate assembler label names LBBnnn and LBEnnn for the beginning and end of the symbol-block. ! Dbxout uses the sequence numbers to generate references to the same labels from the dbx debugging information. *************** *** 285,290 **** ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! assemble_integer (gen_rtx (CONST_INT, VOIDmode, count_basic_blocks), ! UNITS_PER_WORD, 1); assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); --- 286,290 ---- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2); assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1); ! assemble_integer (GEN_INT (count_basic_blocks), UNITS_PER_WORD, 1); assemble_integer (const0_rtx, UNITS_PER_WORD, 1); ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3); *************** *** 312,315 **** --- 312,318 ---- /* Output the table of addresses. */ readonly_data_section (); + /* Realign in new section */ + ASM_OUTPUT_ALIGN (asm_out_file, + floor_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3); for (i = 0; i < count_basic_blocks; i++) *************** *** 525,535 **** { int i; ! /* Inside a delay slot sequence, we do not do any branch shortening ! (on the only machine known to have both variable-length branches ! and delay slots, the ROMP, branch-with-execute is the same size ! as the maximum branch anyway). So we only have to handle normal ! insns (actually, reorg never puts ASM insns in a delay slot, but ! we don't take advantage of that knowledge here). */ for (i = 0; i < XVECLEN (body, 0); i++) { --- 528,540 ---- { int i; ! int const_delay_slots; ! #ifdef DELAY_SLOTS ! const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0)); ! #else ! const_delay_slots = 0; ! #endif /* Inside a delay slot sequence, we do not do any branch shortening ! if the shortening could change the number of delay slots ! of the branch. */ for (i = 0; i < XVECLEN (body, 0); i++) { *************** *** 545,549 **** insn_lengths[inner_uid] = inner_length; ! varying_length[inner_uid] = 0; insn_lengths[uid] += inner_length; } --- 550,563 ---- insn_lengths[inner_uid] = inner_length; ! if (const_delay_slots) ! { ! if ((varying_length[inner_uid] ! = insn_variable_length_p (inner_insn)) != 0) ! varying_length[uid] = 1; ! insn_addresses[inner_uid] = (insn_current_address + ! insn_lengths[uid]); ! } ! else ! varying_length[inner_uid] = 0; insn_lengths[uid] += inner_length; } *************** *** 570,574 **** for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; insn != 0; ! insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn)) { int new_length; --- 584,588 ---- for (insn_current_address = FIRST_INSN_ADDRESS, insn = first; insn != 0; ! insn = NEXT_INSN (insn)) { int new_length; *************** *** 577,583 **** insn_addresses[uid] = insn_current_address; if (! varying_length[uid]) ! continue; ! ! new_length = insn_current_length (insn); if (new_length != insn_lengths[uid]) { --- 591,626 ---- insn_addresses[uid] = insn_current_address; if (! varying_length[uid]) ! { ! insn_current_address += insn_lengths[uid]; ! continue; ! } ! if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE) ! { ! int i; ! ! body = PATTERN (insn); ! new_length = 0; ! for (i = 0; i < XVECLEN (body, 0); i++) ! { ! rtx inner_insn = XVECEXP (body, 0, i); ! int inner_uid = INSN_UID (inner_insn); ! int inner_length; ! ! insn_addresses[inner_uid] = insn_current_address; ! inner_length = insn_current_length (inner_insn); ! if (inner_length != insn_lengths[inner_uid]) ! { ! insn_lengths[inner_uid] = inner_length; ! something_changed = 1; ! } ! insn_current_address += insn_lengths[inner_uid]; ! new_length += inner_length; ! } ! } ! else ! { ! new_length = insn_current_length (insn); ! insn_current_address += new_length; ! } if (new_length != insn_lengths[uid]) { *************** *** 602,606 **** int count = 1; ! for (template = decode_asm_operands (body, 0, 0, 0, 0); *template; template++) if (*template == ';' || *template == '\n') --- 645,650 ---- int count = 1; ! for (template = decode_asm_operands (body, NULL_PTR, NULL_PTR, ! NULL_PTR, NULL_PTR); *template; template++) if (*template == ';' || *template == '\n') *************** *** 690,693 **** --- 734,751 ---- #endif + /* If the machine represents the prologue as RTL, the profiling code must + be emitted when NOTE_INSN_PROLOGUE_END is scanned. */ + #ifdef HAVE_prologue + if (! HAVE_prologue) + #endif + profile_after_prologue (file); + + profile_label_no++; + } + + static void + profile_after_prologue (file) + FILE *file; + { #ifdef FUNCTION_BLOCK_PROFILER if (profile_block_flag) *************** *** 701,706 **** profile_function (file); #endif /* not PROFILE_BEFORE_PROLOGUE */ - - profile_label_no++; } --- 759,762 ---- *************** *** 788,791 **** --- 844,852 ---- #endif + #ifdef DWARF_DEBUGGING_INFO + if (write_symbols == DWARF_DEBUG) + dwarfout_end_function (); + #endif + #ifdef XCOFF_DEBUGGING_INFO if (write_symbols == XCOFF_DEBUG) *************** *** 927,930 **** --- 988,1008 ---- break; + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) + { + #ifdef FUNCTION_END_PROLOGUE + FUNCTION_END_PROLOGUE (file); + #endif + profile_after_prologue (file); + break; + } + + #ifdef FUNCTION_BEGIN_EPILOGUE + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) + { + FUNCTION_BEGIN_EPILOGUE (file); + break; + } + #endif + if (write_symbols == NO_DEBUG) break; *************** *** 939,942 **** --- 1017,1024 ---- xcoffout_begin_function (file, last_linenum); #endif + #ifdef DWARF_DEBUGGING_INFO + if (write_symbols == DWARF_DEBUG) + dwarfout_begin_function (); + #endif break; } *************** *** 950,954 **** if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG && (debug_info_level == DINFO_LEVEL_NORMAL ! || debug_info_level == DINFO_LEVEL_VERBOSE)) { /* Beginning of a symbol-block. Assign it a sequence number --- 1032,1041 ---- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG && (debug_info_level == DINFO_LEVEL_NORMAL ! || debug_info_level == DINFO_LEVEL_VERBOSE ! #ifdef DWARF_DEBUGGING_INFO ! || write_symbols == DWARF_DEBUG ! #endif ! ) ! ) { /* Beginning of a symbol-block. Assign it a sequence number *************** *** 988,992 **** else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END && (debug_info_level == DINFO_LEVEL_NORMAL ! || debug_info_level == DINFO_LEVEL_VERBOSE)) { /* End of a symbol-block. Pop its sequence number off --- 1075,1084 ---- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END && (debug_info_level == DINFO_LEVEL_NORMAL ! || debug_info_level == DINFO_LEVEL_VERBOSE ! #ifdef DWARF_DEBUGGING_INFO ! || write_symbols == DWARF_DEBUG ! #endif ! ) ! ) { /* End of a symbol-block. Pop its sequence number off *************** *** 1013,1016 **** --- 1105,1117 ---- #endif } + else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL + && (debug_info_level == DINFO_LEVEL_NORMAL + || debug_info_level == DINFO_LEVEL_VERBOSE)) + { + #ifdef DWARF_DEBUGGING_INFO + if (write_symbols == DWARF_DEBUG) + dwarfout_label (insn); + #endif + } else if (NOTE_LINE_NUMBER (insn) > 0) /* This note is a line-number. */ *************** *** 1030,1034 **** break; /* These types of notes can be significant ! so make sure the preceeding line number stays. */ else if (GET_CODE (note) == NOTE && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG --- 1131,1135 ---- break; /* These types of notes can be significant ! so make sure the preceding line number stays. */ else if (GET_CODE (note) == NOTE && (NOTE_LINE_NUMBER (note) == NOTE_INSN_BLOCK_BEG *************** *** 1047,1051 **** break; ! if (num == NOTE_LINE_NUMBER (note)) note_after = 1; break; --- 1148,1152 ---- break; ! if (num >= NOTE_LINE_NUMBER (note)) note_after = 1; break; *************** *** 1062,1066 **** case BARRIER: #ifdef ASM_OUTPUT_ALIGN_CODE ! ASM_OUTPUT_ALIGN_CODE (file); #endif break; --- 1163,1171 ---- case BARRIER: #ifdef ASM_OUTPUT_ALIGN_CODE ! /* Don't litter the assembler output with needless alignments. A ! BARRIER will be placed at the end of every function if HAVE_epilogue ! is true. */ ! if (NEXT_INSN (insn)) ! ASM_OUTPUT_ALIGN_CODE (file); #endif break; *************** *** 1098,1104 **** #ifndef JUMP_TABLES_IN_TEXT_SECTION readonly_data_section (); ! #else text_section (); ! #endif #ifdef ASM_OUTPUT_CASE_LABEL ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), --- 1203,1214 ---- #ifndef JUMP_TABLES_IN_TEXT_SECTION readonly_data_section (); ! #ifdef READONLY_DATA_SECTION ! ASM_OUTPUT_ALIGN (file, ! exact_log2 (BIGGEST_ALIGNMENT ! / BITS_PER_UNIT)); ! #endif /* READONLY_DATA_SECTION */ ! #else /* JUMP_TABLES_IN_TEXT_SECTION */ text_section (); ! #endif /* JUMP_TABLES_IN_TEXT_SECTION */ #ifdef ASM_OUTPUT_CASE_LABEL ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), *************** *** 1134,1138 **** from the insn that set it. */ ! note = find_reg_note (insn, REG_CC_SETTER, 0); if (note) { --- 1244,1248 ---- from the insn that set it. */ ! note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); if (note) { *************** *** 1162,1172 **** { if (GET_CODE (body) == ADDR_VEC) ! ASM_OUTPUT_ADDR_VEC_ELT ! (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); else ! ASM_OUTPUT_ADDR_DIFF_ELT ! (file, ! CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), ! CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); } #ifdef ASM_OUTPUT_CASE_END --- 1272,1294 ---- { if (GET_CODE (body) == ADDR_VEC) ! { ! #ifdef ASM_OUTPUT_ADDR_VEC_ELT ! ASM_OUTPUT_ADDR_VEC_ELT ! (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))); ! #else ! abort (); ! #endif ! } else ! { ! #ifdef ASM_OUTPUT_ADDR_DIFF_ELT ! ASM_OUTPUT_ADDR_DIFF_ELT ! (file, ! CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)), ! CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0))); ! #else ! abort (); ! #endif ! } } #ifdef ASM_OUTPUT_CASE_END *************** *** 1237,1241 **** /* Get out the operand values. */ ! string = decode_asm_operands (body, ops, 0, 0, 0); /* Inhibit aborts on what would otherwise be compiler bugs. */ insn_noperands = noperands; --- 1359,1364 ---- /* Get out the operand values. */ ! string = decode_asm_operands (body, ops, NULL_PTR, ! NULL_PTR, NULL_PTR); /* Inhibit aborts on what would otherwise be compiler bugs. */ insn_noperands = noperands; *************** *** 1625,1638 **** #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) ! { ! dbxout_source_file (file, filename); ! ! #ifdef ASM_OUTPUT_SOURCE_LINE ! ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn)); ! #else ! fprintf (file, "\t%s %d,0,%d\n", ASM_STABD_OP, ! N_SLINE, NOTE_LINE_NUMBER (insn)); ! #endif ! } #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ --- 1748,1752 ---- #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) ! dbxout_source_line (file, filename, NOTE_LINE_NUMBER (insn)); #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ *************** *** 1827,1831 **** break; } ! return value; } --- 1941,1971 ---- break; } ! ! if (cc_status.flags & CC_NOT_SIGNED) ! /* The flags are valid if signed condition operators are converted ! to unsigned. */ ! switch (GET_CODE (cond)) ! { ! case LE: ! PUT_CODE (cond, LEU); ! value = 2; ! break; ! ! case LT: ! PUT_CODE (cond, LTU); ! value = 2; ! break; ! ! case GT: ! PUT_CODE (cond, GTU); ! value = 2; ! break; ! ! case GE: ! PUT_CODE (cond, GEU); ! value = 2; ! break; ! } ! return value; } *************** *** 1912,1916 **** referred to more than once in a given insn. */ else if (*p == '=') ! fprintf (asm_out_file, "%d", insn_counter); /* % followed by a letter and some digits outputs an operand in a special way depending on the letter. --- 2052,2059 ---- referred to more than once in a given insn. */ else if (*p == '=') ! { ! p++; ! fprintf (asm_out_file, "%d", insn_counter); ! } /* % followed by a letter and some digits outputs an operand in a special way depending on the letter. *************** *** 1942,1946 **** { if (GET_CODE (operands[c]) == CONST_INT) ! fprintf (asm_out_file, "%d", - INTVAL (operands[c])); else { --- 2085,2095 ---- { if (GET_CODE (operands[c]) == CONST_INT) ! fprintf (asm_out_file, ! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! "%d", ! #else ! "%ld", ! #endif ! - INTVAL (operands[c])); else { *************** *** 1969,1973 **** #ifdef PRINT_OPERAND_PUNCT_VALID_P else if (PRINT_OPERAND_PUNCT_VALID_P (*p)) ! output_operand (0, *p++); #endif else --- 2118,2122 ---- #ifdef PRINT_OPERAND_PUNCT_VALID_P else if (PRINT_OPERAND_PUNCT_VALID_P (*p)) ! output_operand (NULL_RTX, *p++); #endif else *************** *** 2032,2035 **** --- 2181,2191 ---- if (x && GET_CODE (x) == SUBREG) x = alter_subreg (x); + + /* If X is a pseudo-register, abort now rather than writing trash to the + assembler file. */ + + if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER) + abort (); + PRINT_OPERAND (asm_out_file, x, code); } *************** *** 2074,2087 **** case LABEL_REF: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! assemble_name (asm_out_file, buf); break; case CODE_LABEL: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! assemble_name (asm_out_file, buf); break; case CONST_INT: ! fprintf (file, "%d", INTVAL (x)); break; --- 2230,2249 ---- case LABEL_REF: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); ! assemble_name (file, buf); break; case CODE_LABEL: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); ! assemble_name (file, buf); break; case CONST_INT: ! fprintf (file, ! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! "%d", ! #else ! "%ld", ! #endif ! INTVAL (x)); break; *************** *** 2095,2104 **** if (GET_MODE (x) == VOIDmode) { ! /* We can use %d if the number is <32 bits and positive. */ if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) ! fprintf (file, "0x%x%08x", CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); else ! fprintf (file, "%d", CONST_DOUBLE_LOW (x)); } else --- 2257,2285 ---- if (GET_MODE (x) == VOIDmode) { ! /* We can use %d if the number is one word and positive. */ if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) ! fprintf (file, ! #if HOST_BITS_PER_WIDE_INT == 64 ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%016lx", ! #else ! " 0x%x%016x", ! #endif ! #else ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%08lx", ! #else ! " 0x%x%08x", ! #endif ! #endif CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); else ! fprintf (file, ! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! "%d", ! #else ! "%ld", ! #endif ! CONST_DOUBLE_LOW (x)); } else *************** *** 2127,2133 **** case MINUS: output_addr_const (file, XEXP (x, 0)); fprintf (file, "-"); ! output_addr_const (file, XEXP (x, 1)); break; --- 2308,2333 ---- case MINUS: + /* Avoid outputting things like x-x or x+5-x, + since some assemblers can't handle that. */ + x = simplify_subtraction (x); + if (GET_CODE (x) != MINUS) + goto restart; + output_addr_const (file, XEXP (x, 0)); fprintf (file, "-"); ! if (GET_CODE (XEXP (x, 1)) == CONST_INT ! && INTVAL (XEXP (x, 1)) < 0) ! { ! fprintf (file, ASM_OPEN_PAREN); ! output_addr_const (file, XEXP (x, 1)); ! fprintf (file, ASM_CLOSE_PAREN); ! } ! else ! output_addr_const (file, XEXP (x, 1)); ! break; ! ! case ZERO_EXTEND: ! case SIGN_EXTEND: ! output_addr_const (file, XEXP (x, 0)); break; *************** *** 2280,2288 **** So order them by the target's convention. */ #if WORDS_BIG_ENDIAN ! *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); ! *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); #else ! *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); #endif } --- 2480,2488 ---- So order them by the target's convention. */ #if WORDS_BIG_ENDIAN ! *first = GEN_INT (CONST_DOUBLE_HIGH (value)); ! *second = GEN_INT (CONST_DOUBLE_LOW (value)); #else ! *first = GEN_INT (CONST_DOUBLE_LOW (value)); ! *second = GEN_INT (CONST_DOUBLE_HIGH (value)); #endif } *************** *** 2290,2294 **** { if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_INT != BITS_PER_WORD) && ! flag_pretend_float) abort (); --- 2490,2494 ---- { if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) && ! flag_pretend_float) abort (); *************** *** 2296,2304 **** #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN /* Host and target agree => no need to swap. */ ! *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); #else ! *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value)); ! *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value)); #endif } --- 2496,2504 ---- #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN /* Host and target agree => no need to swap. */ ! *first = GEN_INT (CONST_DOUBLE_LOW (value)); ! *second = GEN_INT (CONST_DOUBLE_HIGH (value)); #else ! *second = GEN_INT (CONST_DOUBLE_LOW (value)); ! *first = GEN_INT (CONST_DOUBLE_HIGH (value)); #endif } *************** *** 2360,2364 **** for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { ! if (regs_ever_live[i] > permitted_reg_in_leaf_functions[i]) return 0; } --- 2560,2565 ---- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { ! if ((regs_ever_live[i] || global_regs[i]) ! && ! permitted_reg_in_leaf_functions[i]) return 0; } *************** *** 2458,2461 **** --- 2659,2663 ---- case '0': case 'i': + case 'w': case 'n': case 'u': diff -rc2N gcc-2.2.2/fixinc.svr4 gcc-2.3.1/fixinc.svr4 *** gcc-2.2.2/fixinc.svr4 Fri Apr 3 05:00:45 1992 --- gcc-2.3.1/fixinc.svr4 Sat Oct 17 17:20:24 1992 *************** *** 32,35 **** --- 32,38 ---- # See README-fixinc for more information. + # Directory where gcc sources (and sometimes special include files) live. + SRCDIR=${3-${SRCDIR-.}} + # Directory containing the original header files. INPUT=${2-${INPUT-/usr/include}} *************** *** 42,46 **** # Directory in which to store the results. ! LIB=${1-${LIB-/usr/local/lib/gcc-include}} # Make sure it exists. --- 45,49 ---- # Directory in which to store the results. ! LIB=${1?"fixincludes: output directory not specified"} # Make sure it exists. *************** *** 56,61 **** # This prevents /bin/ex from failing if the current terminal type is # unrecognizable. ! TERM=unknown export TERM echo 'Building fixincludes in ' ${LIB} --- 59,68 ---- # This prevents /bin/ex from failing if the current terminal type is # unrecognizable. ! TERM=dumb export TERM + # This prevents /bin/ex from failing if the EXINIT environment variable + # was set to something invalid. + EXINIT="" + export EXINIT echo 'Building fixincludes in ' ${LIB} *************** *** 361,365 **** fi ! # Add some missing declarations to . file=sys/mman.h --- 368,372 ---- fi ! # Add a prototyped declaration of mmap to . file=sys/mman.h *************** *** 494,498 **** --- 501,539 ---- fi + # Disable apparent native compiler optimization cruft in SVR4.2 + # that is visible to any ANSI compiler using this include. Simply + # delete the lines the #define some string functions to internal forms. + + file=string.h + base=`basename $file` + if [ -r ${LIB}/$file ]; then + file_to_fix=${LIB}/$file + else + if [ -r ${INPUT}/$file ]; then + file_to_fix=${INPUT}/$file + else + file_to_fix="" + fi + fi + if [ \! -z "$file_to_fix" ]; then + echo Checking $file_to_fix + cp $file_to_fix /tmp/$base + chmod +w /tmp/$base + ex /tmp/$base </dev/null 2>&1; then \ + echo No change needed in $file_to_fix + else + echo Fixed $file_to_fix + rm -f ${LIB}/$file + cp /tmp/$base ${LIB}/$file + fi + rm -f /tmp/$base + fi + # Add a #define of _SIGACTION_ into . + # Also fix types of SIG_DFL, SIG_ERR, SIG_IGN, and SIG_HOLD. file=sys/signal.h *************** *** 516,519 **** --- 557,561 ---- struct sigaction { . + 1,\$s/(void *(\*)())/(void (*)(int))/ wq EOF *************** *** 854,857 **** --- 896,1007 ---- fi + # Remove useless extern keyword from struct forward declarations in + # and + + file=sys/stream.h + base=`basename $file` + if [ -r ${LIB}/$file ]; then + file_to_fix=${LIB}/$file + else + if [ -r ${INPUT}/$file ]; then + file_to_fix=${INPUT}/$file + else + file_to_fix="" + fi + fi + if [ \! -z "$file_to_fix" ]; then + echo Checking $file_to_fix + sed -e 's/extern struct \(stdata\|strevent\);/struct \1;/' $file_to_fix > /tmp/$base + if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \ + echo No change needed in $file_to_fix + else + echo Fixed $file_to_fix + rm -f ${LIB}/$file + cp /tmp/$base ${LIB}/$file + fi + rm -f /tmp/$base + fi + + file=sys/strsubr.h + base=`basename $file` + if [ -r ${LIB}/$file ]; then + file_to_fix=${LIB}/$file + else + if [ -r ${INPUT}/$file ]; then + file_to_fix=${INPUT}/$file + else + file_to_fix="" + fi + fi + if [ \! -z "$file_to_fix" ]; then + echo Checking $file_to_fix + sed -e 's/extern struct \(strbuf\|uio\|thread\|proc\);/struct \1;/' $file_to_fix > /tmp/$base + if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \ + echo No change needed in $file_to_fix + else + echo Fixed $file_to_fix + rm -f ${LIB}/$file + cp /tmp/$base ${LIB}/$file + fi + rm -f /tmp/$base + fi + + # Convert functions to prototype form, and fix arg names in . + + file=sys/stat.h + base=`basename $file` + if [ -r ${LIB}/$file ]; then + file_to_fix=${LIB}/$file + else + if [ -r ${INPUT}/$file ]; then + file_to_fix=${INPUT}/$file + else + file_to_fix="" + fi + fi + if [ \! -z "$file_to_fix" ]; then + echo Checking $file_to_fix + cp $file_to_fix /tmp/$base + chmod +w /tmp/$base + ex /tmp/$base <' rm -f ${LIB}/sys/byteorder.h ! cp byteorder.h ${LIB}/sys/byteorder.h exit 0 --- 1101,1105 ---- echo 'Replacing ' rm -f ${LIB}/sys/byteorder.h ! cp ${SRCDIR}/byteorder.h ${LIB}/sys/byteorder.h exit 0 diff -rc2N gcc-2.2.2/fixincludes gcc-2.3.1/fixincludes *** gcc-2.2.2/fixincludes Thu Jun 11 19:15:09 1992 --- gcc-2.3.1/fixincludes Mon Oct 19 21:20:47 1992 *************** *** 6,9 **** --- 6,14 ---- # See README-fixinc for more information. + # Directory where gcc sources (and sometimes special include files) live. + # fixincludes doesn't use this, but fixinc.svr4 does, and I want to make + # sure somebody doesn't try to use arg3 for something incompatible. -- gumby + SRCDIR=${3-${SRCDIR-.}} + # Directory containing the original header files. # (This was named INCLUDES, but that conflicts with a name in Makefile.in.) *************** *** 14,20 **** TERM=unknown export TERM # Directory in which to store the results. ! LIB=${1-${LIB-/usr/local/lib/gcc-include}} # Make sure it exists. --- 19,29 ---- TERM=unknown export TERM + # This prevents /bin/ex from failing if the EXINIT environment variable + # was set to something invalid. + EXINIT="" + export EXINIT # Directory in which to store the results. ! LIB=${1?"fixincludes: output directory not specified"} # Make sure it exists. *************** *** 32,36 **** fi ! echo 'Building fixincludes in ' ${LIB} # Determine whether this system has symbolic links. --- 41,45 ---- fi ! echo Building fixed headers in ${LIB} # Determine whether this system has symbolic links. *************** *** 42,50 **** fi ! echo 'Making directories:' cd ${INPUT} # Find all directories and all symlinks that point to directories. ! files=` find . -type d -print | sed '/^.$/d' ! $LINKS && find . -type l -exec test -d '{}' \; -print` for file in $files; do rm -rf $LIB/$file --- 51,106 ---- fi ! echo Finding directories and links to directories cd ${INPUT} # Find all directories and all symlinks that point to directories. ! # Put the list in $files. ! # Each time we find a symlink, add it to newdirs ! # so that we do another find within the dir the link points to. ! # Note that $files may have duplicates in it; ! # later parts of this file are supposed to ignore them. ! dirs="." ! levels=2 ! while [ -n "$dirs" ] && [ $levels -gt 0 ] ! do ! levels=`expr $levels - 1` ! newdirs= ! for d in $dirs ! do ! echo " Searching $INPUT/$d" ! if [ "$d" != . ] ! then ! d=$d/. ! fi ! ! # Find all directories under $d, relative to $d, excluding $d itself. ! files="$files `find $d -type d -print | \ ! sed -e '/\/\.$/d' -e '/^\.$/d'`" ! # Find all links to directories. ! # Using `-exec test -d' in find fails on some systems, ! # and trying to run test via sh fails on others, ! # so this is the simplest alternative left. ! # First find all the links, then test each one. ! theselinks= ! $LINKS && \ ! theselinks=`find $d -type l -print` ! for d1 in $theselinks --dummy-- ! do ! # If the link points to a directory, ! # add that dir to $newdirs ! if [ -d $d1 ] ! then ! newdirs="$newdirs $d1" ! fi ! done ! done ! ! files="$files $newdirs" ! dirs="$newdirs" ! done ! ! dirs= ! echo "All directories (including links to directories):" ! echo $files ! for file in $files; do rm -rf $LIB/$file *************** *** 53,56 **** --- 109,113 ---- fi done + mkdir $LIB/root # treetops gets an alternating list *************** *** 60,64 **** if $LINKS; then ! echo 'Making internal symbolic directory links' for file in $files; do dest=`ls -ld $file | sed -n 's/.*-> //p'` --- 117,121 ---- if $LINKS; then ! echo 'Making symbolic directory links' for file in $files; do dest=`ls -ld $file | sed -n 's/.*-> //p'` *************** *** 75,81 **** # X gets the dir that the link actually leads to. x=`pwd` # If link leads back into ${INPUT}, # make a similar link here. ! if expr $x : "${INPUT}/.*" > /dev/null; then # Y gets the actual target dir name, relative to ${INPUT}. y=`echo $x | sed -n "s&${INPUT}/&&p"` --- 132,143 ---- # X gets the dir that the link actually leads to. x=`pwd` + # If a link points to ., make a similar link to . + if [ $x = $INPUT ]; then + echo $file '->' . ': Making link' + rm -fr ${LIB}/$file > /dev/null 2>&1 + ln -s . ${LIB}/$file > /dev/null 2>&1 # If link leads back into ${INPUT}, # make a similar link here. ! elif expr $x : "${INPUT}/.*" > /dev/null; then # Y gets the actual target dir name, relative to ${INPUT}. y=`echo $x | sed -n "s&${INPUT}/&&p"` *************** *** 84,93 **** ln -s ${LIB}/$y ${LIB}/$file > /dev/null 2>&1 else ! # If the link is to outside ${INPUT}, # treat this directory as if it actually contained the files. ! # This line used to have $dest instead of $x. ! # $dest seemed to be wrong for links found in subdirectories ! # of ${INPUT}. Does this change break anything? ! treetops="$treetops $x ${LIB}/$file" fi fi --- 146,171 ---- ln -s ${LIB}/$y ${LIB}/$file > /dev/null 2>&1 else ! # If the link is to a dir $target outside ${INPUT}, ! # repoint the link at ${INPUT}/root$target ! # and process $target into ${INPUT}/root$target # treat this directory as if it actually contained the files. ! echo $file '->' root$x ': Making link' ! if [ -d $LIB/root$x ] ! then true ! else ! dirname=root$x/ ! dirmade=. ! cd $LIB ! while [ x$dirname != x ]; do ! component=`echo $dirname | sed -e 's|/.*$||'` ! mkdir $component >/dev/null 2>&1 ! cd $component ! dirmade=$dirmade/$component ! dirname=`echo $dirname | sed -e 's|[^/]*/||'` ! done ! fi ! rm -fr ${LIB}/$file > /dev/null 2>&1 ! ln -s ${LIB}/root$x ${LIB}/$file > /dev/null 2>&1 ! treetops="$treetops $x ${LIB}/root$x" fi fi *************** *** 100,108 **** while [ $# != 0 ]; do # $1 is an old directory to copy, and $2 is the new directory to copy to. - echo "Finding header files in $1:" cd ${INPUT} cd $1 ! files=`find . -name '*.h' -type f -print` ! echo 'Checking header files:' # Note that BSD43_* are used on recent MIPS systems. for file in $files; do --- 178,200 ---- while [ $# != 0 ]; do # $1 is an old directory to copy, and $2 is the new directory to copy to. cd ${INPUT} cd $1 ! # The same dir can appear more than once in treetops. ! # There's no need to scan it more than once. ! if [ -f $2/DONE ] ! then ! files= ! else ! touch $2/DONE ! echo Fixing directory $1 into $2 ! # Check .h files which are symlinks as well as those which are files. ! # A link to a header file will not be processed by anything but this. ! if $LINKS; then ! files=`find . -name '*.h' \( -type f -o -type l \) -print` ! else ! files=`find . -name '*.h' -type f -print` ! fi ! echo Checking header files ! fi # Note that BSD43_* are used on recent MIPS systems. for file in $files; do *************** *** 114,118 **** # won't be able to handle it. # rms: I removed `|#[el].*if.*[^/ ]' because it made egrep fail. ! if egrep '[ _]_IO|CTRL|#define.NULL|#[el]*if.*([0-9]|sparc|vax|sun|pyr)' $file > /dev/null; then echo Fixing $file if [ -r $file ]; then --- 206,210 ---- # won't be able to handle it. # rms: I removed `|#[el].*if.*[^/ ]' because it made egrep fail. ! if egrep '//|[ _]_IO|CTRL|#define.NULL|#[el]*if.*([0-9]|sparc|vax|sun|pyr)' $file > /dev/null; then echo Fixing $file if [ -r $file ]; then *************** *** 128,142 **** /\\$/ N /\\$/ b loop /[ ]_IO[A-Z]*[ ]*(/ s/(\(.\),/('\''\1'\'',/ /[ ]BSD43__IO[A-Z]*[ ]*(/ s/(\(.\),/('\''\1'\'',/ ! /#define._IO/ s/'\''x'\''/x/g /#define.BSD43__IO/ s/'\''x'\''/x/g ! /[^A-Z]CTRL[ ]*(/ s/\([^'\'']\))/'\''\1'\'')/ /#define.CTRL/ s/'\''c'\''/c/g /#define._CTRL/ s/'\''c'\''/c/g /#define.BSD43_CTRL/ s/'\''c'\''/c/g ! /#[a-z]*if.*[ (]m68k/ s/\([^_]\)m68k/\1__m68k__/g /#[a-z]*if.*[ (]__i386/ s/__i386/__i386__/g ! /#[a-z]*if.*[ (]i386/ s/\([^_]\)i386/\1__i386__/g /#[a-z]*if.*[ (]sparc/ s/\([^_]\)sparc/\1__sparc__/g /#[a-z]*if.*[ (]mc68000/ s/\([^_]\)mc68000/\1__mc68000__/g --- 220,235 ---- /\\$/ N /\\$/ b loop + /\/\// s|//\(.*\)$|/*\1*/| /[ ]_IO[A-Z]*[ ]*(/ s/(\(.\),/('\''\1'\'',/ /[ ]BSD43__IO[A-Z]*[ ]*(/ s/(\(.\),/('\''\1'\'',/ ! /#define._IO/ s/'\''x'\''/x/g /#define.BSD43__IO/ s/'\''x'\''/x/g ! /[^A-Z]CTRL[ ]*(/ s/\([^'\'']\))/'\''\1'\'')/ /#define.CTRL/ s/'\''c'\''/c/g /#define._CTRL/ s/'\''c'\''/c/g /#define.BSD43_CTRL/ s/'\''c'\''/c/g ! /#[a-z]*if.*[ (]m68k/ s/\([^_]\)m68k/\1__m68k__/g /#[a-z]*if.*[ (]__i386/ s/__i386/__i386__/g ! /#[a-z]*if.*[ (]i386/ s/\([^_]\)i386/\1__i386__/g /#[a-z]*if.*[ (]sparc/ s/\([^_]\)sparc/\1__sparc__/g /#[a-z]*if.*[ (]mc68000/ s/\([^_]\)mc68000/\1__mc68000__/g *************** *** 386,389 **** --- 479,507 ---- fi + # Incorrect sprintf declaration in X11/Xmu/Xmu.h + # (It's not clear whether the right file name is this or X11/Xmu.h.) + file=X11/Xmu/Xmu.h + if [ -r $file ] && [ ! -r ${LIB}/$file ]; then + mkdir ${LIB}/X11/Xmu 2>/dev/null + cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file" + chmod +w ${LIB}/$file 2>/dev/null + fi + + if [ -r ${LIB}/$file ]; then + echo Fixing $file sprintf declaration + ex ${LIB}/$file </dev/null 2>&1; then + echo Deleting ${LIB}/$file\; no fixes were needed. + rm ${LIB}/$file + fi + fi + # Check for missing ';' in struct file=netinet/ip.h *************** *** 606,610 **** # To ensure only Sun's is fixed, we grep for a likely unique string. file=memory.h ! if egrep '/\* @\(#\)memory.h 1.4 88/08/19 SMI; from S5R2 1.2 \*/' $file > /dev/null; then if [ -r $file ] && [ ! -r ${LIB}/$file ]; then cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file" --- 724,728 ---- # To ensure only Sun's is fixed, we grep for a likely unique string. file=memory.h ! if egrep '/\* @\(#\)memory\.h 1\.[2-4] 8./../.. SMI; from S5R2 1\.2 \*/' $file > /dev/null; then if [ -r $file ] && [ ! -r ${LIB}/$file ]; then cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file" *************** *** 661,664 **** --- 779,819 ---- fi + # Don't use or define the name va_list in stdio.h. + # This is for ANSI and also to interoperate properly with gvarargs.h. + file=stdio.h + if [ -r $file ] && [ ! -r ${LIB}/$file ]; then + cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file" + chmod +w ${LIB}/$file 2>/dev/null + fi + + if [ -r ${LIB}/$file ]; then + echo Fixing $file, use of va_list + # Arrange for stdio.h to use stdarg.h to define __gnuc_va_list + (echo "#define __need___va_list" + echo "#include ") > ${LIB}/${file}.sed + # Use __gnuc_va_list in arg types in place of va_list. + # Define __va_list__ (something harmless and unused) instead of va_list. + # Don't claim to have defined va_list. + sed -e 's@ va_list @ __gnuc_va_list @' \ + -e 's@ va_list@ __va_list__@' \ + -e 's@\*va_list@*__va_list__@' \ + -e 's@VA_LIST@DUMMY_VA_LIST@' \ + ${LIB}/$file >> ${LIB}/${file}.sed + + rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file + if cmp $file ${LIB}/$file >/dev/null 2>&1; then + echo Deleting ${LIB}/$file\; no fixes were needed. + rm -f ${LIB}/$file + fi + fi + + # Cancel out ansi_compat.h on Ultrix. Replace it with empty file. + file=ansi_compat.h + if [ -r $file ] && [ ! -r ${LIB}/$file ]; then + if grep -s ULTRIX $file; then + echo "/* This file intentionally left blank. */" > $LIB/$file + fi + fi + # parameter to atof not const on DECstation Ultrix V4.0. file=math.h *************** *** 677,680 **** --- 832,847 ---- rm -f ${LIB}/$file fi + fi + + # These two files on SunOS 4 are included by other files + # in the same directory, using "...". So we must make sure they exist + # in the same directory as the other fixed files. + if [ -r ${INPUT}/multimedia/audio_errno.h ] + then + ln -s ${INPUT}/multimedia/audio_errno.h ${LIB}/multimedia 2>/dev/null + fi + if [ -r ${INPUT}/multimedia/audio_hdr.h ] + then + ln -s ${INPUT}/multimedia/audio_hdr.h ${LIB}/multimedia 2>/dev/null fi diff -rc2N gcc-2.2.2/fixlimits.h gcc-2.3.1/fixlimits.h *** gcc-2.2.2/fixlimits.h --- gcc-2.3.1/fixlimits.h Thu Sep 24 02:43:16 1992 *************** *** 0 **** --- 1 ---- + #include_next diff -rc2N gcc-2.2.2/flags.h gcc-2.3.1/flags.h *** gcc-2.2.2/flags.h Fri Apr 24 21:51:10 1992 --- gcc-2.3.1/flags.h Sat Aug 1 22:42:10 1992 *************** *** 44,51 **** extern enum debug_info_level debug_info_level; ! #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) ! /* Nonzero means use GDB-only extensions of DBX format. */ ! extern int use_gdb_dbx_extensions; ! #endif /* Nonzero means do optimizations. -opt. */ --- 44,50 ---- extern enum debug_info_level debug_info_level; ! /* Nonzero means use GNU-only extensions in the generated symbolic ! debugging information. */ ! extern int use_gnu_debug_info_extensions; /* Nonzero means do optimizations. -opt. */ diff -rc2N gcc-2.2.2/flow.c gcc-2.3.1/flow.c *** gcc-2.2.2/flow.c Thu May 7 02:35:39 1992 --- gcc-2.3.1/flow.c Thu Oct 29 21:55:09 1992 *************** *** 122,128 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - /* List of labels that must never be deleted. */ extern rtx forced_labels; --- 122,125 ---- *************** *** 205,209 **** and is used infrequently enough that it should not get a hard register. -2 is used to mark a pseudo reg for a parameter, when a frame pointer ! is not required. global-alloc.c makes an allocno for this but does not try to assign a hard register to it. */ --- 202,206 ---- and is used infrequently enough that it should not get a hard register. -2 is used to mark a pseudo reg for a parameter, when a frame pointer ! is not required. global.c makes an allocno for this but does not try to assign a hard register to it. */ *************** *** 459,463 **** if (code == INSN || code == CALL_INSN) { ! rtx note = find_reg_note (insn, REG_LABEL, 0); if (note != 0) label_value_list = gen_rtx (EXPR_LIST, VOIDmode, XEXP (note, 0), --- 456,460 ---- if (code == INSN || code == CALL_INSN) { ! rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX); if (note != 0) label_value_list = gen_rtx (EXPR_LIST, VOIDmode, XEXP (note, 0), *************** *** 480,488 **** } ! /* Don't delete the labels that are referenced by non-jump instructions. */ { register rtx x; for (x = label_value_list; x; x = XEXP (x, 1)) ! block_live[BLOCK_NUM (XEXP (x, 0))] = 1; } --- 477,487 ---- } ! /* Don't delete the labels (in this function) ! that are referenced by non-jump instructions. */ { register rtx x; for (x = label_value_list; x; x = XEXP (x, 1)) ! if (! LABEL_REF_NONLOCAL_P (x)) ! block_live[BLOCK_NUM (XEXP (x, 0))] = 1; } *************** *** 791,795 **** REGNO (SET_SRC (PATTERN (insn))) /* Insns carrying these notes are useful later on. */ ! && ! find_reg_note (insn, REG_EQUAL, 0)) { PUT_CODE (insn, NOTE); --- 790,794 ---- REGNO (SET_SRC (PATTERN (insn))) /* Insns carrying these notes are useful later on. */ ! && ! find_reg_note (insn, REG_EQUAL, NULL_RTX)) { PUT_CODE (insn, NOTE); *************** *** 818,822 **** if (i == XVECLEN (PATTERN (insn), 0) /* Insns carrying these notes are useful later on. */ ! && ! find_reg_note (insn, REG_EQUAL, 0)) { PUT_CODE (insn, NOTE); --- 817,821 ---- if (i == XVECLEN (PATTERN (insn), 0) /* Insns carrying these notes are useful later on. */ ! && ! find_reg_note (insn, REG_EQUAL, NULL_RTX)) { PUT_CODE (insn, NOTE); *************** *** 857,864 **** basic_block_live_at_end[n_basic_blocks - 1] [STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS); basic_block_new_live_at_end[n_basic_blocks - 1] [STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS); } --- 856,877 ---- basic_block_live_at_end[n_basic_blocks - 1] [STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS); basic_block_new_live_at_end[n_basic_blocks - 1] [STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS); ! } ! ! /* Mark the frame pointer is needed at the end of the function. If ! we end up eliminating it, it will be removed from the live list ! of each basic block by reload. */ ! ! if (n_basic_blocks > 0) ! { ! basic_block_live_at_end[n_basic_blocks - 1] ! [FRAME_POINTER_REGNUM / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS); ! basic_block_new_live_at_end[n_basic_blocks - 1] ! [FRAME_POINTER_REGNUM / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS); } *************** *** 871,877 **** { basic_block_live_at_end[n_basic_blocks - 1] ! [i / REGSET_ELT_BITS] |= 1 << (i % REGSET_ELT_BITS); basic_block_new_live_at_end[n_basic_blocks - 1] ! [i / REGSET_ELT_BITS] |= 1 << (i % REGSET_ELT_BITS); } --- 884,892 ---- { basic_block_live_at_end[n_basic_blocks - 1] ! [i / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS); basic_block_new_live_at_end[n_basic_blocks - 1] ! [i / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS); } *************** *** 910,915 **** for (j = 0; j < regset_size; j++) { ! register int x = (basic_block_new_live_at_end[i][j] ! & ~basic_block_live_at_end[i][j]); if (x) consider = 1; --- 925,931 ---- for (j = 0; j < regset_size; j++) { ! register REGSET_ELT_TYPE x ! = (basic_block_new_live_at_end[i][j] ! & ~basic_block_live_at_end[i][j]); if (x) consider = 1; *************** *** 937,942 **** for (j = 0; j < regset_size; j++) { ! register int x = basic_block_new_live_at_end[i][j] ! & ~basic_block_live_at_end[i][j]; basic_block_live_at_start[i][j] |= x; basic_block_live_at_end[i][j] |= x; --- 953,959 ---- for (j = 0; j < regset_size; j++) { ! register REGSET_ELT_TYPE x ! = (basic_block_new_live_at_end[i][j] ! & ~basic_block_live_at_end[i][j]); basic_block_live_at_start[i][j] |= x; basic_block_live_at_end[i][j] |= x; *************** *** 953,957 **** propagate_block (basic_block_live_at_start[i], basic_block_head[i], basic_block_end[i], 0, ! first_pass ? basic_block_significant[i] : 0, i); } --- 970,975 ---- propagate_block (basic_block_live_at_start[i], basic_block_head[i], basic_block_end[i], 0, ! first_pass ? basic_block_significant[i] ! : (regset) 0, i); } *************** *** 1000,1004 **** for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (basic_block_live_at_start[0][i / REGSET_ELT_BITS] ! & (1 << (i % REGSET_ELT_BITS))) reg_basic_block[i] = REG_BLOCK_GLOBAL; --- 1018,1022 ---- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (basic_block_live_at_start[0][i / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))) reg_basic_block[i] = REG_BLOCK_GLOBAL; *************** *** 1018,1022 **** { propagate_block (basic_block_live_at_end[i], ! basic_block_head[i], basic_block_end[i], 1, 0, i); #ifdef USE_C_ALLOCA alloca (0); --- 1036,1041 ---- { propagate_block (basic_block_live_at_end[i], ! basic_block_head[i], basic_block_end[i], 1, ! (regset) 0, i); #ifdef USE_C_ALLOCA alloca (0); *************** *** 1032,1036 **** #ifdef LONGJMP_RESTORE_FROM_STACK for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) ! if (regs_live_at_setjmp[i / REGSET_ELT_BITS] & (1 << (i % REGSET_ELT_BITS)) && regno_reg_rtx[i] != 0 && ! REG_USERVAR_P (regno_reg_rtx[i])) { --- 1051,1056 ---- #ifdef LONGJMP_RESTORE_FROM_STACK for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) ! if (regs_live_at_setjmp[i / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)) && regno_reg_rtx[i] != 0 && ! REG_USERVAR_P (regno_reg_rtx[i])) { *************** *** 1051,1055 **** Conclusion: such a pseudo must not go in a hard reg. */ for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) ! if (regs_live_at_setjmp[i / REGSET_ELT_BITS] & (1 << (i % REGSET_ELT_BITS)) && regno_reg_rtx[i] != 0) { --- 1071,1076 ---- Conclusion: such a pseudo must not go in a hard reg. */ for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) ! if ((regs_live_at_setjmp[i / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))) && regno_reg_rtx[i] != 0) { *************** *** 1058,1062 **** } ! obstack_free (&flow_obstack, 0); } --- 1079,1083 ---- } ! obstack_free (&flow_obstack, NULL_PTR); } *************** *** 1165,1169 **** for the register described by the element, and BIT is a mask for that register's bit within the byte. */ ! register struct foo { short offset; short bit; } *regs_sometimes_live; int sometimes_max = 0; /* This regset has 1 for each reg that we have seen live so far. --- 1186,1190 ---- for the register described by the element, and BIT is a mask for that register's bit within the byte. */ ! register struct sometimes { short offset; short bit; } *regs_sometimes_live; int sometimes_max = 0; /* This regset has 1 for each reg that we have seen live so far. *************** *** 1197,1201 **** if (final) { ! register int i, offset, bit; num_scratch = 0; --- 1218,1223 ---- if (final) { ! register int i, offset; ! REGSET_ELT_TYPE bit; num_scratch = 0; *************** *** 1203,1207 **** bcopy (old, maxlive, regset_bytes); regs_sometimes_live ! = (struct foo *) alloca (max_regno * sizeof (struct foo)); /* Process the regs live at the end of the block. --- 1225,1229 ---- bcopy (old, maxlive, regset_bytes); regs_sometimes_live ! = (struct sometimes *) alloca (max_regno * sizeof (struct sometimes)); /* Process the regs live at the end of the block. *************** *** 1264,1268 **** { register int i; ! rtx note = find_reg_note (insn, REG_RETVAL, 0); int insn_is_dead = (insn_dead_p (PATTERN (insn), old, 0) --- 1286,1290 ---- { register int i; ! rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX); int insn_is_dead = (insn_dead_p (PATTERN (insn), old, 0) *************** *** 1341,1345 **** { /* Mark the dest reg as `significant'. */ ! mark_set_regs (old, dead, PATTERN (insn), 0, significant); insn = XEXP (note, 0); --- 1363,1367 ---- { /* Mark the dest reg as `significant'. */ ! mark_set_regs (old, dead, PATTERN (insn), NULL_RTX, significant); insn = XEXP (note, 0); *************** *** 1362,1367 **** live. */ ! mark_set_regs (old, dead, PATTERN (insn), final ? insn : 0, ! significant); /* If an insn doesn't use CC0, it becomes dead since we --- 1384,1389 ---- live. */ ! mark_set_regs (old, dead, PATTERN (insn), ! final ? insn : NULL_RTX, significant); /* If an insn doesn't use CC0, it becomes dead since we *************** *** 1392,1400 **** if (call_used_regs[i] && ! global_regs[i]) dead[i / REGSET_ELT_BITS] ! |= (1 << (i % REGSET_ELT_BITS)); /* The stack ptr is used (honorarily) by a CALL insn. */ live[STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= (1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS)); /* Calls may also reference any of the global registers, --- 1414,1423 ---- if (call_used_regs[i] && ! global_regs[i]) dead[i / REGSET_ELT_BITS] ! |= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)); /* The stack ptr is used (honorarily) by a CALL insn. */ live[STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= ((REGSET_ELT_TYPE) 1 ! << (STACK_POINTER_REGNUM % REGSET_ELT_BITS)); /* Calls may also reference any of the global registers, *************** *** 1404,1408 **** if (global_regs[i]) live[i / REGSET_ELT_BITS] ! |= (1 << (i % REGSET_ELT_BITS)); /* Calls also clobber memory. */ --- 1427,1431 ---- if (global_regs[i]) live[i / REGSET_ELT_BITS] ! |= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)); /* Calls also clobber memory. */ *************** *** 1423,1430 **** Find all regs now live and record this for them. */ ! register struct foo *p = regs_sometimes_live; for (i = 0; i < sometimes_max; i++, p++) ! if (old[p->offset] & (1 << p->bit)) reg_n_calls_crossed[p->offset * REGSET_ELT_BITS + p->bit]+= 1; } --- 1446,1453 ---- Find all regs now live and record this for them. */ ! register struct sometimes *p = regs_sometimes_live; for (i = 0; i < sometimes_max; i++, p++) ! if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit)) reg_n_calls_crossed[p->offset * REGSET_ELT_BITS + p->bit]+= 1; } *************** *** 1439,1443 **** for (i = 0; i < regset_size; i++) { ! register int diff = live[i] & ~maxlive[i]; if (diff) --- 1462,1466 ---- for (i = 0; i < regset_size; i++) { ! register REGSET_ELT_TYPE diff = live[i] & ~maxlive[i]; if (diff) *************** *** 1446,1454 **** maxlive[i] |= diff; for (regno = 0; diff && regno < REGSET_ELT_BITS; regno++) ! if (diff & (1 << regno)) { regs_sometimes_live[sometimes_max].offset = i; regs_sometimes_live[sometimes_max].bit = regno; ! diff &= ~ (1 << regno); sometimes_max++; } --- 1469,1477 ---- maxlive[i] |= diff; for (regno = 0; diff && regno < REGSET_ELT_BITS; regno++) ! if (diff & ((REGSET_ELT_TYPE) 1 << regno)) { regs_sometimes_live[sometimes_max].offset = i; regs_sometimes_live[sometimes_max].bit = regno; ! diff &= ~ ((REGSET_ELT_TYPE) 1 << regno); sometimes_max++; } *************** *** 1457,1464 **** { ! register struct foo *p = regs_sometimes_live; for (i = 0; i < sometimes_max; i++, p++) { ! if (old[p->offset] & (1 << p->bit)) reg_live_length[p->offset * REGSET_ELT_BITS + p->bit]++; } --- 1480,1487 ---- { ! register struct sometimes *p = regs_sometimes_live; for (i = 0; i < sometimes_max; i++, p++) { ! if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit)) reg_live_length[p->offset * REGSET_ELT_BITS + p->bit]++; } *************** *** 1517,1522 **** register int regno = REGNO (r); register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno]) /* Make sure insns to set frame pointer aren't deleted. */ --- 1540,1547 ---- register int regno = REGNO (r); register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); + /* Don't delete insns to set global regs. */ if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno]) /* Make sure insns to set frame pointer aren't deleted. */ *************** *** 1539,1543 **** while (--n > 0) if ((needed[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)) != 0) return 0; } --- 1564,1569 ---- while (--n > 0) if ((needed[(regno + n) / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 ! << ((regno + n) % REGSET_ELT_BITS))) != 0) return 0; } *************** *** 1632,1636 **** /* Return 1 if register REGNO was used before it was set. ! In other words, if it is live at function entry. */ int --- 1658,1663 ---- /* Return 1 if register REGNO was used before it was set. ! In other words, if it is live at function entry. ! Don't count global regster variables, though. */ int *************** *** 1638,1646 **** int regno; { ! if (n_basic_blocks == 0) return 0; return (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] ! & (1 << (regno % REGSET_ELT_BITS))); } --- 1665,1673 ---- int regno; { ! if (n_basic_blocks == 0 || global_regs[regno]) return 0; return (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))); } *************** *** 1658,1664 **** return ((reg_n_sets[regno] > 1 || (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] ! & (1 << (regno % REGSET_ELT_BITS)))) && (regs_live_at_setjmp[regno / REGSET_ELT_BITS] ! & (1 << (regno % REGSET_ELT_BITS)))); } --- 1685,1691 ---- return ((reg_n_sets[regno] > 1 || (basic_block_live_at_start[0][regno / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)))) && (regs_live_at_setjmp[regno / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)))); } *************** *** 1753,1759 **** { register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); ! int all_needed = (needed[offset] & bit) != 0; ! int some_needed = (needed[offset] & bit) != 0; /* Mark it as a significant register for this basic block. */ --- 1780,1787 ---- { register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); ! REGSET_ELT_TYPE all_needed = (needed[offset] & bit); ! REGSET_ELT_TYPE some_needed = (needed[offset] & bit); /* Mark it as a significant register for this basic block. */ *************** *** 1780,1790 **** if (significant) significant[(regno + n) / REGSET_ELT_BITS] ! |= 1 << ((regno + n) % REGSET_ELT_BITS); dead[(regno + n) / REGSET_ELT_BITS] ! |= 1 << ((regno + n) % REGSET_ELT_BITS); ! some_needed |= (needed[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)); ! all_needed &= (needed[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)); } } --- 1808,1820 ---- if (significant) significant[(regno + n) / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS); dead[(regno + n) / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS); ! some_needed ! |= (needed[(regno + n) / REGSET_ELT_BITS] ! & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS)); ! all_needed ! &= (needed[(regno + n) / REGSET_ELT_BITS] ! & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS)); } } *************** *** 1873,1877 **** i >= 0; i--) if ((needed[(regno + i) / REGSET_ELT_BITS] ! & 1 << ((regno + i) % REGSET_ELT_BITS)) == 0) REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_UNUSED, --- 1903,1908 ---- i >= 0; i--) if ((needed[(regno + i) / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 ! << ((regno + i) % REGSET_ELT_BITS))) == 0) REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_UNUSED, *************** *** 2005,2009 **** on this insn, which is incorrect. */ needed[regno / REGSET_ELT_BITS] ! |= 1 << (regno % REGSET_ELT_BITS); /* If there are any calls between INSN and INCR, show --- 2036,2040 ---- on this insn, which is incorrect. */ needed[regno / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); /* If there are any calls between INSN and INCR, show *************** *** 2122,2126 **** { register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); int all_needed = (needed[offset] & bit) != 0; int some_needed = (needed[offset] & bit) != 0; --- 2153,2158 ---- { register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); int all_needed = (needed[offset] & bit) != 0; int some_needed = (needed[offset] & bit) != 0; *************** *** 2155,2159 **** their values are live after this function exits. */ if (global_regs[regno]) ! return; n = HARD_REGNO_NREGS (regno, GET_MODE (x)); --- 2187,2195 ---- their values are live after this function exits. */ if (global_regs[regno]) ! { ! if (final) ! reg_next_use[regno] = insn; ! return; ! } n = HARD_REGNO_NREGS (regno, GET_MODE (x)); *************** *** 2161,2169 **** { live[(regno + n) / REGSET_ELT_BITS] ! |= 1 << ((regno + n) % REGSET_ELT_BITS); ! some_needed |= (needed[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)); ! all_needed &= (needed[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)); } } --- 2197,2207 ---- { live[(regno + n) / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS); ! some_needed ! |= (needed[(regno + n) / REGSET_ELT_BITS] ! & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS)); ! all_needed ! &= (needed[(regno + n) / REGSET_ELT_BITS] ! & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS)); } } *************** *** 2234,2238 **** i >= 0; i--) if ((needed[(regno + i) / REGSET_ELT_BITS] ! & 1 << ((regno + i) % REGSET_ELT_BITS)) == 0 && ! dead_or_set_regno_p (insn, regno + i)) REG_NOTES (insn) --- 2272,2277 ---- i >= 0; i--) if ((needed[(regno + i) / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 ! << ((regno + i) % REGSET_ELT_BITS))) == 0 && ! dead_or_set_regno_p (insn, regno + i)) REG_NOTES (insn) *************** *** 2296,2300 **** && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno]) #endif ! && ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])) { mark_used_regs (needed, live, SET_SRC (x), final, insn); --- 2335,2341 ---- && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno]) #endif ! ) ! /* We used to exclude global_regs here, but that seems wrong. ! Storing in them is like storing in mem. */ { mark_used_regs (needed, live, SET_SRC (x), final, insn); *************** *** 2316,2324 **** #endif live[STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (global_regs[i]) ! live[i / REGSET_ELT_BITS] |= 1 << (i % REGSET_ELT_BITS); break; } --- 2357,2366 ---- #endif live[STACK_POINTER_REGNUM / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (global_regs[i]) ! live[i / REGSET_ELT_BITS] ! |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS); break; } *************** *** 2361,2365 **** make it do pre-increment or pre-decrement if appropriate. */ rtx x = PATTERN (insn); ! int amount = ((GET_CODE (SET_SRC (x)) == PLUS ? 1 : -1) * INTVAL (XEXP (SET_SRC (x), 1))); int regno = REGNO (SET_DEST (x)); --- 2403,2407 ---- make it do pre-increment or pre-decrement if appropriate. */ rtx x = PATTERN (insn); ! HOST_WIDE_INT amount = ((GET_CODE (SET_SRC (x)) == PLUS ? 1 : -1) * INTVAL (XEXP (SET_SRC (x), 1))); int regno = REGNO (SET_DEST (x)); *************** *** 2399,2403 **** try_pre_increment (insn, reg, amount) rtx insn, reg; ! int amount; { register rtx use; --- 2441,2445 ---- try_pre_increment (insn, reg, amount) rtx insn, reg; ! HOST_WIDE_INT amount; { register rtx use; *************** *** 2507,2515 **** that is unacceptable. */ if (find_use_as_address (XEXP (x, 0), reg, 0) != 0) ! return (rtx) 1; } if (x == reg) ! return (rtx) 1; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) --- 2549,2557 ---- that is unacceptable. */ if (find_use_as_address (XEXP (x, 0), reg, 0) != 0) ! return (rtx) (HOST_WIDE_INT) 1; } if (x == reg) ! return (rtx) (HOST_WIDE_INT) 1; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) *************** *** 2521,2525 **** value = tem; else if (tem != 0) ! return (rtx) 1; } if (fmt[i] == 'E') --- 2563,2567 ---- value = tem; else if (tem != 0) ! return (rtx) (HOST_WIDE_INT) 1; } if (fmt[i] == 'E') *************** *** 2532,2536 **** value = tem; else if (tem != 0) ! return (rtx) 1; } } --- 2574,2578 ---- value = tem; else if (tem != 0) ! return (rtx) (HOST_WIDE_INT) 1; } } *************** *** 2555,2559 **** if (reg_n_refs[i]) { ! enum reg_class class; fprintf (file, "\nRegister %d used %d times across %d insns", i, reg_n_refs[i], reg_live_length[i]); --- 2597,2601 ---- if (reg_n_refs[i]) { ! enum reg_class class, altclass; fprintf (file, "\nRegister %d used %d times across %d insns", i, reg_n_refs[i], reg_live_length[i]); *************** *** 2569,2578 **** fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i)); class = reg_preferred_class (i); ! if (class != GENERAL_REGS) { ! if (reg_preferred_or_nothing (i)) fprintf (file, "; %s or none", reg_class_names[(int) class]); else ! fprintf (file, "; pref %s", reg_class_names[(int) class]); } if (REGNO_POINTER_FLAG (i)) --- 2611,2625 ---- fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i)); class = reg_preferred_class (i); ! altclass = reg_alternate_class (i); ! if (class != GENERAL_REGS || altclass != ALL_REGS) { ! if (altclass == ALL_REGS || class == ALL_REGS) ! fprintf (file, "; pref %s", reg_class_names[(int) class]); ! else if (altclass == NO_REGS) fprintf (file, "; %s or none", reg_class_names[(int) class]); else ! fprintf (file, "; pref %s, else %s", ! reg_class_names[(int) class], ! reg_class_names[(int) altclass]); } if (REGNO_POINTER_FLAG (i)) *************** *** 2611,2615 **** { register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); if (basic_block_live_at_start[i][offset] & bit) fprintf (file, " %d", regno); --- 2658,2663 ---- { register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); if (basic_block_live_at_start[i][offset] & bit) fprintf (file, " %d", regno); diff -rc2N gcc-2.2.2/fold-const.c gcc-2.3.1/fold-const.c *** gcc-2.2.2/fold-const.c Wed Jun 3 22:10:21 1992 --- gcc-2.3.1/fold-const.c Wed Oct 21 17:14:52 1992 *************** *** 49,64 **** static jmp_buf float_error; ! void lshift_double (); void rshift_double (); void lrotate_double (); void rrotate_double (); static tree const_binop (); ! /* To do constant folding on INTEGER_CST nodes requires 64-bit arithmetic. ! We do that by representing the 64-bit integer as 8 shorts, with only 8 bits stored in each short, as a positive number. */ ! /* Unpack a 64-bit integer into 8 shorts. ! LOW and HI are the integer, as two `int' pieces. SHORTS points to the array of shorts. */ --- 49,81 ---- static jmp_buf float_error; ! int lshift_double (); void rshift_double (); void lrotate_double (); void rrotate_double (); static tree const_binop (); + + #ifndef BRANCH_COST + #define BRANCH_COST 1 + #endif + + /* Yield nonzero if a signed left shift of A by B bits overflows. */ + #define left_shift_overflows(a, b) ((a) != ((a) << (b)) >> (b)) + + /* Yield nonzero if A and B have the same sign. */ + #define same_sign(a, b) ((a) ^ (b) >= 0) + + /* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow. + Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1. + Then this yields nonzero if overflow occurred during the addition. + Overflow occurs if A and B have the same sign, but A and SUM differ in sign. + Use `^' to test whether signs differ, and `< 0' to isolate the sign. */ + #define overflow_sum_sign(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0) ! /* To do constant folding on INTEGER_CST nodes requires two-word arithmetic. ! We do that by representing the two-word integer as MAX_SHORTS shorts, with only 8 bits stored in each short, as a positive number. */ ! /* Unpack a two-word integer into MAX_SHORTS shorts. ! LOW and HI are the integer, as two `HOST_WIDE_INT' pieces. SHORTS points to the array of shorts. */ *************** *** 66,96 **** encode (shorts, low, hi) short *shorts; ! int low, hi; { ! shorts[0] = low & 0xff; ! shorts[1] = (low >> 8) & 0xff; ! shorts[2] = (low >> 16) & 0xff; ! shorts[3] = (low >> 24) & 0xff; ! shorts[4] = hi & 0xff; ! shorts[5] = (hi >> 8) & 0xff; ! shorts[6] = (hi >> 16) & 0xff; ! shorts[7] = (hi >> 24) & 0xff; } ! /* Pack an array of 8 shorts into a 64-bit integer. SHORTS points to the array of shorts. ! The integer is stored into *LOW and *HI as two `int' pieces. */ static void decode (shorts, low, hi) short *shorts; ! int *low, *hi; { ! /* The casts in the following statement should not be ! needed, but they get around bugs in some C compilers. */ ! *low = (((long)shorts[3] << 24) | ((long)shorts[2] << 16) ! | ((long)shorts[1] << 8) | (long)shorts[0]); ! *hi = (((long)shorts[7] << 24) | ((long)shorts[6] << 16) ! | ((long)shorts[5] << 8) | (long)shorts[4]); } --- 83,116 ---- encode (shorts, low, hi) short *shorts; ! HOST_WIDE_INT low, hi; { ! register int i; ! ! for (i = 0; i < MAX_SHORTS / 2; i++) ! { ! shorts[i] = (low >> (i * 8)) & 0xff; ! shorts[i + MAX_SHORTS / 2] = (hi >> (i * 8) & 0xff); ! } } ! /* Pack an array of MAX_SHORTS shorts into a two-word integer. SHORTS points to the array of shorts. ! The integer is stored into *LOW and *HI as two `HOST_WIDE_INT' pieces. */ static void decode (shorts, low, hi) short *shorts; ! HOST_WIDE_INT *low, *hi; { ! register int i; ! HOST_WIDE_INT lv = 0, hv = 0; ! ! for (i = 0; i < MAX_SHORTS / 2; i++) ! { ! lv |= (HOST_WIDE_INT) shorts[i] << (i * 8); ! hv |= (HOST_WIDE_INT) shorts[i + MAX_SHORTS / 2] << (i * 8); ! } ! ! *low = lv, *hi = hv; } *************** *** 110,126 **** /* First clear all bits that are beyond the type's precision. */ ! if (prec == 2 * HOST_BITS_PER_INT) ; ! else if (prec > HOST_BITS_PER_INT) { TREE_INT_CST_HIGH (t) ! &= ~((-1) << (prec - HOST_BITS_PER_INT)); } else { TREE_INT_CST_HIGH (t) = 0; ! if (prec < HOST_BITS_PER_INT) ! TREE_INT_CST_LOW (t) ! &= ~((-1) << prec); } --- 130,145 ---- /* First clear all bits that are beyond the type's precision. */ ! if (prec == 2 * HOST_BITS_PER_WIDE_INT) ; ! else if (prec > HOST_BITS_PER_WIDE_INT) { TREE_INT_CST_HIGH (t) ! &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); } else { TREE_INT_CST_HIGH (t) = 0; ! if (prec < HOST_BITS_PER_WIDE_INT) ! TREE_INT_CST_LOW (t) &= ~((HOST_WIDE_INT) (-1) << prec); } *************** *** 128,166 **** if (! TREE_UNSIGNED (TREE_TYPE (t)) ! && prec != 2 * HOST_BITS_PER_INT ! && (prec > HOST_BITS_PER_INT ! ? TREE_INT_CST_HIGH (t) & (1 << (prec - HOST_BITS_PER_INT - 1)) ! : TREE_INT_CST_LOW (t) & (1 << (prec - 1)))) { /* Value is negative: set to 1 all the bits that are outside this type's precision. */ ! if (prec > HOST_BITS_PER_INT) { TREE_INT_CST_HIGH (t) ! |= ((-1) << (prec - HOST_BITS_PER_INT)); } else { TREE_INT_CST_HIGH (t) = -1; ! if (prec < HOST_BITS_PER_INT) ! TREE_INT_CST_LOW (t) ! |= ((-1) << prec); } } } ! /* Add two 64-bit integers with 64-bit result. ! Each argument is given as two `int' pieces. One argument is L1 and H1; the other, L2 and H2. ! The value is stored as two `int' pieces in *LV and *HV. We use the 8-shorts representation internally. */ ! void add_double (l1, h1, l2, h2, lv, hv) ! int l1, h1, l2, h2; ! int *lv, *hv; { ! short arg1[8]; ! short arg2[8]; register int carry = 0; register int i; --- 147,185 ---- if (! TREE_UNSIGNED (TREE_TYPE (t)) ! && prec != 2 * HOST_BITS_PER_WIDE_INT ! && (prec > HOST_BITS_PER_WIDE_INT ! ? (TREE_INT_CST_HIGH (t) ! & ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1))) ! : TREE_INT_CST_LOW (t) & ((HOST_WIDE_INT) 1 << (prec - 1)))) { /* Value is negative: set to 1 all the bits that are outside this type's precision. */ ! if (prec > HOST_BITS_PER_WIDE_INT) { TREE_INT_CST_HIGH (t) ! |= ((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); } else { TREE_INT_CST_HIGH (t) = -1; ! if (prec < HOST_BITS_PER_WIDE_INT) ! TREE_INT_CST_LOW (t) |= ((HOST_WIDE_INT) (-1) << prec); } } } ! /* Add two doubleword integers with doubleword result. ! Each argument is given as two `HOST_WIDE_INT' pieces. One argument is L1 and H1; the other, L2 and H2. ! The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. We use the 8-shorts representation internally. */ ! int add_double (l1, h1, l2, h2, lv, hv) ! HOST_WIDE_INT l1, h1, l2, h2; ! HOST_WIDE_INT *lv, *hv; { ! short arg1[MAX_SHORTS]; ! short arg2[MAX_SHORTS]; register int carry = 0; register int i; *************** *** 169,173 **** encode (arg2, l2, h2); ! for (i = 0; i < 8; i++) { carry += arg1[i] + arg2[i]; --- 188,192 ---- encode (arg2, l2, h2); ! for (i = 0; i < MAX_SHORTS; i++) { carry += arg1[i] + arg2[i]; *************** *** 177,191 **** decode (arg1, lv, hv); } ! /* Negate a 64-bit integers with 64-bit result. ! The argument is given as two `int' pieces in L1 and H1. ! The value is stored as two `int' pieces in *LV and *HV. We use the 8-shorts representation internally. */ ! void neg_double (l1, h1, lv, hv) ! int l1, h1; ! int *lv, *hv; { if (l1 == 0) --- 196,212 ---- decode (arg1, lv, hv); + return overflow_sum_sign (h1, h2, *hv); } ! /* Negate a doubleword integer with doubleword result. ! Return nonzero if the operation overflows, assuming it's signed. ! The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1. ! The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. We use the 8-shorts representation internally. */ ! int neg_double (l1, h1, lv, hv) ! HOST_WIDE_INT l1, h1; ! HOST_WIDE_INT *lv, *hv; { if (l1 == 0) *************** *** 193,196 **** --- 214,218 ---- *lv = 0; *hv = - h1; + return same_sign (h1, *hv); } else *************** *** 198,236 **** *lv = - l1; *hv = ~ h1; } } ! /* Multiply two 64-bit integers with 64-bit result. ! Each argument is given as two `int' pieces. One argument is L1 and H1; the other, L2 and H2. ! The value is stored as two `int' pieces in *LV and *HV. We use the 8-shorts representation internally. */ ! void mul_double (l1, h1, l2, h2, lv, hv) ! int l1, h1, l2, h2; ! int *lv, *hv; { ! short arg1[8]; ! short arg2[8]; ! short prod[16]; register int carry = 0; register int i, j, k; ! /* These two cases are used extensively, arising from pointer ! combinations. */ if (h2 == 0) { if (l2 == 2) { ! unsigned temp = l1 + l1; ! *hv = h1 * 2 + (temp < l1); *lv = temp; ! return; } if (l2 == 4) { ! unsigned temp = l1 + l1; ! h1 = h1 * 4 + ((temp < l1) << 1); l1 = temp; temp += temp; --- 220,262 ---- *lv = - l1; *hv = ~ h1; + return 0; } } ! /* Multiply two doubleword integers with doubleword result. ! Return nonzero if the operation overflows, assuming it's signed. ! Each argument is given as two `HOST_WIDE_INT' pieces. One argument is L1 and H1; the other, L2 and H2. ! The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. We use the 8-shorts representation internally. */ ! int mul_double (l1, h1, l2, h2, lv, hv) ! HOST_WIDE_INT l1, h1, l2, h2; ! HOST_WIDE_INT *lv, *hv; { ! short arg1[MAX_SHORTS]; ! short arg2[MAX_SHORTS]; ! short prod[MAX_SHORTS * 2]; register int carry = 0; register int i, j, k; + HOST_WIDE_INT toplow, tophigh, neglow, neghigh; ! /* These cases are used extensively, arising from pointer combinations. */ if (h2 == 0) { if (l2 == 2) { ! int overflow = left_shift_overflows (h1, 1); ! unsigned HOST_WIDE_INT temp = l1 + l1; ! *hv = (h1 << 1) + (temp < l1); *lv = temp; ! return overflow; } if (l2 == 4) { ! int overflow = left_shift_overflows (h1, 2); ! unsigned HOST_WIDE_INT temp = l1 + l1; ! h1 = (h1 << 2) + ((temp < l1) << 1); l1 = temp; temp += temp; *************** *** 238,247 **** *lv = temp; *hv = h1; ! return; } if (l2 == 8) { ! unsigned temp = l1 + l1; ! h1 = h1 * 8 + ((temp < l1) << 2); l1 = temp; temp += temp; --- 264,274 ---- *lv = temp; *hv = h1; ! return overflow; } if (l2 == 8) { ! int overflow = left_shift_overflows (h1, 3); ! unsigned HOST_WIDE_INT temp = l1 + l1; ! h1 = (h1 << 3) + ((temp < l1) << 2); l1 = temp; temp += temp; *************** *** 252,256 **** *lv = temp; *hv = h1; ! return; } } --- 279,283 ---- *lv = temp; *hv = h1; ! return overflow; } } *************** *** 261,266 **** bzero (prod, sizeof prod); ! for (i = 0; i < 8; i++) ! for (j = 0; j < 8; j++) { k = i + j; --- 288,293 ---- bzero (prod, sizeof prod); ! for (i = 0; i < MAX_SHORTS; i++) ! for (j = 0; j < MAX_SHORTS; j++) { k = i + j; *************** *** 275,301 **** } ! decode (prod, lv, hv); /* @@decode ignores prod[8] -> prod[15] */ } ! /* Shift the 64-bit integer in L1, H1 left by COUNT places keeping only PREC bits of result. Shift right if COUNT is negative. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. ! Store the value as two `int' pieces in *LV and *HV. */ ! void lshift_double (l1, h1, count, prec, lv, hv, arith) ! int l1, h1, count, prec; ! int *lv, *hv; int arith; { ! short arg1[8]; register int i; ! register int carry; if (count < 0) { rshift_double (l1, h1, - count, prec, lv, hv, arith); ! return; } --- 302,346 ---- } ! decode (prod, lv, hv); /* This ignores ! prod[MAX_SHORTS] -> prod[MAX_SHORTS*2-1] */ ! ! /* Check for overflow by calculating the top half of the answer in full; ! it should agree with the low half's sign bit. */ ! decode (prod+MAX_SHORTS, &toplow, &tophigh); ! if (h1 < 0) ! { ! neg_double (l2, h2, &neglow, &neghigh); ! add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh); ! } ! if (h2 < 0) ! { ! neg_double (l1, h1, &neglow, &neghigh); ! add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh); ! } ! return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0; } ! /* Shift the doubleword integer in L1, H1 left by COUNT places keeping only PREC bits of result. Shift right if COUNT is negative. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. ! Return nonzero if the arithmetic shift overflows, assuming it's signed. ! Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ ! int lshift_double (l1, h1, count, prec, lv, hv, arith) ! HOST_WIDE_INT l1, h1; ! int count, prec; ! HOST_WIDE_INT *lv, *hv; int arith; { ! short arg1[MAX_SHORTS]; register int i; ! register int carry, overflow; if (count < 0) { rshift_double (l1, h1, - count, prec, lv, hv, arith); ! return 0; } *************** *** 305,312 **** count = prec; while (count > 0) { carry = 0; ! for (i = 0; i < 8; i++) { carry += arg1[i] << 1; --- 350,358 ---- count = prec; + overflow = 0; while (count > 0) { carry = 0; ! for (i = 0; i < MAX_SHORTS; i++) { carry += arg1[i] << 1; *************** *** 315,335 **** } count--; } decode (arg1, lv, hv); } ! /* Shift the 64-bit integer in L1, H1 right by COUNT places keeping only PREC bits of result. COUNT must be positive. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. ! Store the value as two `int' pieces in *LV and *HV. */ void rshift_double (l1, h1, count, prec, lv, hv, arith) ! int l1, h1, count, prec; ! int *lv, *hv; int arith; { ! short arg1[8]; register int i; register int carry; --- 361,383 ---- } count--; + overflow |= carry ^ (arg1[7] >> 7); } decode (arg1, lv, hv); + return overflow; } ! /* Shift the doubleword integer in L1, H1 right by COUNT places keeping only PREC bits of result. COUNT must be positive. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. ! Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ void rshift_double (l1, h1, count, prec, lv, hv, arith) ! HOST_WIDE_INT l1, h1, count, prec; ! HOST_WIDE_INT *lv, *hv; int arith; { ! short arg1[MAX_SHORTS]; register int i; register int carry; *************** *** 343,347 **** { carry = arith && arg1[7] >> 7; ! for (i = 7; i >= 0; i--) { carry <<= 8; --- 391,395 ---- { carry = arith && arg1[7] >> 7; ! for (i = MAX_SHORTS - 1; i >= 0; i--) { carry <<= 8; *************** *** 355,369 **** } ! /* Rotate the 64-bit integer in L1, H1 left by COUNT places keeping only PREC bits of result. Rotate right if COUNT is negative. ! Store the value as two `int' pieces in *LV and *HV. */ void lrotate_double (l1, h1, count, prec, lv, hv) ! int l1, h1, count, prec; ! int *lv, *hv; { ! short arg1[8]; register int i; register int carry; --- 403,417 ---- } ! /* Rotate the doubldword integer in L1, H1 left by COUNT places keeping only PREC bits of result. Rotate right if COUNT is negative. ! Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ void lrotate_double (l1, h1, count, prec, lv, hv) ! HOST_WIDE_INT l1, h1, count, prec; ! HOST_WIDE_INT *lv, *hv; { ! short arg1[MAX_SHORTS]; register int i; register int carry; *************** *** 380,387 **** count = prec; ! carry = arg1[7] >> 7; while (count > 0) { ! for (i = 0; i < 8; i++) { carry += arg1[i] << 1; --- 428,435 ---- count = prec; ! carry = arg1[MAX_SHORTS - 1] >> 7; while (count > 0) { ! for (i = 0; i < MAX_SHORTS; i++) { carry += arg1[i] << 1; *************** *** 395,408 **** } ! /* Rotate the 64-bit integer in L1, H1 left by COUNT places keeping only PREC bits of result. COUNT must be positive. ! Store the value as two `int' pieces in *LV and *HV. */ void rrotate_double (l1, h1, count, prec, lv, hv) ! int l1, h1, count, prec; ! int *lv, *hv; { ! short arg1[8]; register int i; register int carry; --- 443,456 ---- } ! /* Rotate the doubleword integer in L1, H1 left by COUNT places keeping only PREC bits of result. COUNT must be positive. ! Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ void rrotate_double (l1, h1, count, prec, lv, hv) ! HOST_WIDE_INT l1, h1, count, prec; ! HOST_WIDE_INT *lv, *hv; { ! short arg1[MAX_SHORTS]; register int i; register int carry; *************** *** 416,420 **** while (count > 0) { ! for (i = 7; i >= 0; i--) { carry <<= 8; --- 464,468 ---- while (count > 0) { ! for (i = MAX_SHORTS - 1; i >= 0; i--) { carry <<= 8; *************** *** 428,432 **** } ! /* Divide 64 bit integer LNUM, HNUM by 64 bit integer LDEN, HDEN for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM). CODE is a tree code for a kind of division, one of --- 476,480 ---- } ! /* Divide doubleword integer LNUM, HNUM by doubleword integer LDEN, HDEN for a quotient (stored in *LQUO, *HQUO) and remainder (in *LREM, *HREM). CODE is a tree code for a kind of division, one of *************** *** 434,440 **** or EXACT_DIV_EXPR It controls how the quotient is rounded to a integer. UNS nonzero says do unsigned division. */ ! static void div_and_round_double (code, uns, lnum_orig, hnum_orig, lden_orig, hden_orig, --- 482,489 ---- or EXACT_DIV_EXPR It controls how the quotient is rounded to a integer. + Return nonzero if the operation overflows. UNS nonzero says do unsigned division. */ ! static int div_and_round_double (code, uns, lnum_orig, hnum_orig, lden_orig, hden_orig, *************** *** 442,457 **** enum tree_code code; int uns; ! int lnum_orig, hnum_orig; /* num == numerator == dividend */ ! int lden_orig, hden_orig; /* den == denominator == divisor */ ! int *lquo, *hquo, *lrem, *hrem; { int quo_neg = 0; ! short num[9], den[8], quo[8]; /* extra element for scaling. */ register int i, j, work; register int carry = 0; ! unsigned int lnum = lnum_orig; ! int hnum = hnum_orig; ! unsigned int lden = lden_orig; ! int hden = hden_orig; if ((hden == 0) && (lden == 0)) --- 491,508 ---- enum tree_code code; int uns; ! HOST_WIDE_INT lnum_orig, hnum_orig; /* num == numerator == dividend */ ! HOST_WIDE_INT lden_orig, hden_orig; /* den == denominator == divisor */ ! HOST_WIDE_INT *lquo, *hquo, *lrem, *hrem; { int quo_neg = 0; ! short num[MAX_SHORTS + 1]; /* extra element for scaling. */ ! short den[MAX_SHORTS], quo[MAX_SHORTS]; register int i, j, work; register int carry = 0; ! unsigned HOST_WIDE_INT lnum = lnum_orig; ! HOST_WIDE_INT hnum = hnum_orig; ! unsigned HOST_WIDE_INT lden = lden_orig; ! HOST_WIDE_INT hden = hden_orig; ! int overflow = 0; if ((hden == 0) && (lden == 0)) *************** *** 461,473 **** if (!uns) { ! if (hden < 0) { quo_neg = ~ quo_neg; ! neg_double (lden, hden, &lden, &hden); } ! if (hnum < 0) { quo_neg = ~ quo_neg; ! neg_double (lnum, hnum, &lnum, &hnum); } } --- 512,526 ---- if (!uns) { ! if (hnum < 0) { quo_neg = ~ quo_neg; ! /* (minimum integer) / (-1) is the only overflow case. */ ! if (neg_double (lnum, hnum, &lnum, &hnum) && (lden & hden) == -1) ! overflow = 1; } ! if (hden < 0) { quo_neg = ~ quo_neg; ! neg_double (lden, hden, &lden, &hden); } } *************** *** 504,508 **** { /* simpler algorithm */ /* hnum != 0 already checked. */ ! for (i = 7; i >= 0; i--) { work = num[i] + (carry << 8); --- 557,561 ---- { /* simpler algorithm */ /* hnum != 0 already checked. */ ! for (i = MAX_SHORTS - 1; i >= 0; i--) { work = num[i] + (carry << 8); *************** *** 518,527 **** /* Find the highest non-zero divisor digit. */ ! for (i = 7; ; i--) if (den[i] != 0) { den_hi_sig = i; break; } ! for (i = 7; ; i--) if (num[i] != 0) { num_hi_sig = i; --- 571,580 ---- /* Find the highest non-zero divisor digit. */ ! for (i = MAX_SHORTS - 1; ; i--) if (den[i] != 0) { den_hi_sig = i; break; } ! for (i = MAX_SHORTS - 1; ; i--) if (num[i] != 0) { num_hi_sig = i; *************** *** 536,540 **** if (scale > 1) { /* scale divisor and dividend */ carry = 0; ! for (i = 0; i <= 8; i++) { work = (num[i] * scale) + carry; num[i] = work & 0xff; --- 589,593 ---- if (scale > 1) { /* scale divisor and dividend */ carry = 0; ! for (i = 0; i <= MAX_SHORTS - 1; i++) { work = (num[i] * scale) + carry; num[i] = work & 0xff; *************** *** 543,547 **** } carry = 0; ! for (i = 0; i <= 7; i++) { work = (den[i] * scale) + carry; den[i] = work & 0xff; --- 596,600 ---- } carry = 0; ! for (i = 0; i <= MAX_SHORTS - 1; i++) { work = (den[i] * scale) + carry; den[i] = work & 0xff; *************** *** 642,646 **** case TRUNC_MOD_EXPR: /* round toward zero */ case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */ ! return; case FLOOR_DIV_EXPR: --- 695,699 ---- case TRUNC_MOD_EXPR: /* round toward zero */ case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */ ! return overflow; case FLOOR_DIV_EXPR: *************** *** 649,655 **** { /* quo = quo - 1; */ ! add_double (*lquo, *hquo, -1, -1, lquo, hquo); } ! else return; break; --- 702,709 ---- { /* quo = quo - 1; */ ! add_double (*lquo, *hquo, (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, ! lquo, hquo); } ! else return overflow; break; *************** *** 658,664 **** if (!quo_neg && (*lrem != 0 || *hrem != 0)) /* ratio > 0 && rem != 0 */ { ! add_double (*lquo, *hquo, 1, 0, lquo, hquo); } ! else return; break; --- 712,719 ---- if (!quo_neg && (*lrem != 0 || *hrem != 0)) /* ratio > 0 && rem != 0 */ { ! add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0, ! lquo, hquo); } ! else return overflow; break; *************** *** 666,671 **** case ROUND_MOD_EXPR: /* round to closest integer */ { ! int labs_rem = *lrem, habs_rem = *hrem; ! int labs_den = lden, habs_den = hden, ltwice, htwice; /* get absolute values */ --- 721,726 ---- case ROUND_MOD_EXPR: /* round to closest integer */ { ! HOST_WIDE_INT labs_rem = *lrem, habs_rem = *hrem; ! HOST_WIDE_INT labs_den = lden, habs_den = hden, ltwice, htwice; /* get absolute values */ *************** *** 674,690 **** /* if (2 * abs (lrem) >= abs (lden)) */ ! mul_double (2, 0, labs_rem, habs_rem, <wice, &htwice); ! if (((unsigned) habs_den < (unsigned) htwice) ! || (((unsigned) habs_den == (unsigned) htwice) ! && ((unsigned) labs_den < (unsigned) ltwice))) { if (*hquo < 0) /* quo = quo - 1; */ ! add_double (*lquo, *hquo, -1, -1, lquo, hquo); else /* quo = quo + 1; */ ! add_double (*lquo, *hquo, 1, 0, lquo, hquo); } ! else return; } break; --- 729,751 ---- /* if (2 * abs (lrem) >= abs (lden)) */ ! mul_double ((HOST_WIDE_INT) 2, (HOST_WIDE_INT) 0, ! labs_rem, habs_rem, <wice, &htwice); ! if (((unsigned HOST_WIDE_INT) habs_den ! < (unsigned HOST_WIDE_INT) htwice) ! || (((unsigned HOST_WIDE_INT) habs_den ! == (unsigned HOST_WIDE_INT) htwice) ! && ((HOST_WIDE_INT unsigned) labs_den ! < (unsigned HOST_WIDE_INT) ltwice))) { if (*hquo < 0) /* quo = quo - 1; */ ! add_double (*lquo, *hquo, ! (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, lquo, hquo); else /* quo = quo + 1; */ ! add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0, ! lquo, hquo); } ! else return overflow; } break; *************** *** 698,703 **** --- 759,795 ---- neg_double (*lrem, *hrem, lrem, hrem); add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem); + return overflow; } + /* Effectively truncate a real value to represent + the nearest possible value in a narrower mode. + The result is actually represented in the same data type as the argument, + but its value is usually different. */ + + REAL_VALUE_TYPE + real_value_truncate (mode, arg) + enum machine_mode mode; + REAL_VALUE_TYPE arg; + { + #ifdef __STDC__ + /* Make sure the value is actually stored in memory before we turn off + the handler. */ + volatile + #endif + REAL_VALUE_TYPE value; + jmp_buf handler, old_handler; + int handled; + + if (setjmp (handler)) + { + error ("floating overflow"); + return dconst0; + } + handled = push_float_handler (handler, old_handler); + value = REAL_VALUE_TRUNCATE (mode, arg); + pop_float_handler (handled, old_handler); + return value; + } + #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT *************** *** 949,960 **** if (TREE_CODE (arg1) == INTEGER_CST) { ! register int int1l = TREE_INT_CST_LOW (arg1); ! register int int1h = TREE_INT_CST_HIGH (arg1); ! int int2l = TREE_INT_CST_LOW (arg2); ! int int2h = TREE_INT_CST_HIGH (arg2); ! int low, hi; ! int garbagel, garbageh; register tree t; int uns = TREE_UNSIGNED (TREE_TYPE (arg1)); switch (code) --- 1041,1055 ---- if (TREE_CODE (arg1) == INTEGER_CST) { ! register HOST_WIDE_INT int1l = TREE_INT_CST_LOW (arg1); ! register HOST_WIDE_INT int1h = TREE_INT_CST_HIGH (arg1); ! HOST_WIDE_INT int2l = TREE_INT_CST_LOW (arg2); ! HOST_WIDE_INT int2h = TREE_INT_CST_HIGH (arg2); ! HOST_WIDE_INT low, hi; ! HOST_WIDE_INT garbagel, garbageh; register tree t; int uns = TREE_UNSIGNED (TREE_TYPE (arg1)); + /* Propagate overflow flags from operands; also record new overflow. */ + int overflow + = TREE_CONSTANT_OVERFLOW (arg1) | TREE_CONSTANT_OVERFLOW (arg2); switch (code) *************** *** 979,986 **** int2l = - int2l; case LSHIFT_EXPR: ! lshift_double (int1l, int1h, int2l, ! TYPE_PRECISION (TREE_TYPE (arg1)), ! &low, &hi, ! !uns); t = build_int_2 (low, hi); break; --- 1074,1081 ---- int2l = - int2l; case LSHIFT_EXPR: ! overflow = lshift_double (int1l, int1h, int2l, ! TYPE_PRECISION (TREE_TYPE (arg1)), ! &low, &hi, ! !uns); t = build_int_2 (low, hi); break; *************** *** 999,1004 **** { int2l += int1l; ! if ((unsigned) int2l < int1l) ! int2h += 1; t = build_int_2 (int2l, int2h); break; --- 1094,1102 ---- { int2l += int1l; ! if ((unsigned HOST_WIDE_INT) int2l < int1l) ! { ! hi = int2h++; ! overflow = ! same_sign (hi, int2h); ! } t = build_int_2 (int2l, int2h); break; *************** *** 1007,1016 **** { int1l += int2l; ! if ((unsigned) int1l < int2l) ! int1h += 1; t = build_int_2 (int1l, int1h); break; } ! add_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); break; --- 1105,1117 ---- { int1l += int2l; ! if ((unsigned HOST_WIDE_INT) int1l < int2l) ! { ! hi = int1h++; ! overflow = ! same_sign (hi, int1h); ! } t = build_int_2 (int1l, int1h); break; } ! overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); break; *************** *** 1022,1035 **** break; } ! neg_double (int2l, int2h, &int2l, &int2h); ! add_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); break; case MULT_EXPR: ! /* Optimize simple cases. */ if (int1h == 0) { ! unsigned temp; switch (int1l) --- 1123,1137 ---- break; } ! neg_double (int2l, int2h, &low, &hi); ! add_double (int1l, int1h, low, hi, &low, &hi); ! overflow = overflow_sum_sign (hi, int2h, int1h); t = build_int_2 (low, hi); break; case MULT_EXPR: ! /* Optimize simple cases. */ if (int1h == 0) { ! unsigned HOST_WIDE_INT temp; switch (int1l) *************** *** 1042,1049 **** goto got_it; case 2: temp = int2l + int2l; ! int2h = int2h * 2 + (temp < int2l); t = build_int_2 (temp, int2h); goto got_it; case 3: temp = int2l + int2l + int2l; --- 1144,1153 ---- goto got_it; case 2: + overflow = left_shift_overflows (int2h, 1); temp = int2l + int2l; ! int2h = (int2h << 1) + (temp < int2l); t = build_int_2 (temp, int2h); goto got_it; + #if 0 /* This code can lose carries. */ case 3: temp = int2l + int2l + int2l; *************** *** 1051,1057 **** t = build_int_2 (temp, int2h); goto got_it; case 4: temp = int2l + int2l; ! int2h = int2h * 4 + ((temp < int2l) << 1); int2l = temp; temp += temp; --- 1155,1163 ---- t = build_int_2 (temp, int2h); goto got_it; + #endif case 4: + overflow = left_shift_overflows (int2h, 2); temp = int2l + int2l; ! int2h = (int2h << 2) + ((temp < int2l) << 1); int2l = temp; temp += temp; *************** *** 1060,1065 **** goto got_it; case 8: temp = int2l + int2l; ! int2h = int2h * 8 + ((temp < int2l) << 2); int2l = temp; temp += temp; --- 1166,1172 ---- goto got_it; case 8: + overflow = left_shift_overflows (int2h, 3); temp = int2l + int2l; ! int2h = (int2h << 3) + ((temp < int2l) << 2); int2l = temp; temp += temp; *************** *** 1089,1093 **** } ! mul_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); break; --- 1196,1200 ---- } ! overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi); t = build_int_2 (low, hi); break; *************** *** 1120,1125 **** break; } ! div_and_round_double (code, uns, int1l, int1h, int2l, int2h, ! &low, &hi, &garbagel, &garbageh); t = build_int_2 (low, hi); break; --- 1227,1233 ---- break; } ! overflow = div_and_round_double (code, uns, ! int1l, int1h, int2l, int2h, ! &low, &hi, &garbagel, &garbageh); t = build_int_2 (low, hi); break; *************** *** 1127,1132 **** case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR: ! div_and_round_double (code, uns, int1l, int1h, int2l, int2h, ! &garbagel, &garbageh, &low, &hi); t = build_int_2 (low, hi); break; --- 1235,1241 ---- case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR: ! overflow = div_and_round_double (code, uns, ! int1l, int1h, int2l, int2h, ! &garbagel, &garbageh, &low, &hi); t = build_int_2 (low, hi); break; *************** *** 1136,1142 **** if (uns) { ! low = (((unsigned) int1h < (unsigned) int2h) ! || (((unsigned) int1h == (unsigned) int2h) ! && ((unsigned) int1l < (unsigned) int2l))); } else --- 1245,1254 ---- if (uns) { ! low = (((unsigned HOST_WIDE_INT) int1h ! < (unsigned HOST_WIDE_INT) int2h) ! || (((unsigned HOST_WIDE_INT) int1h ! == (unsigned HOST_WIDE_INT) int2h) ! && ((unsigned HOST_WIDE_INT) int1l ! < (unsigned HOST_WIDE_INT) int2l))); } else *************** *** 1144,1148 **** low = ((int1h < int2h) || ((int1h == int2h) ! && ((unsigned) int1l < (unsigned) int2l))); } if (low == (code == MIN_EXPR)) --- 1256,1261 ---- low = ((int1h < int2h) || ((int1h == int2h) ! && ((unsigned HOST_WIDE_INT) int1l ! < (unsigned HOST_WIDE_INT) int2l))); } if (low == (code == MIN_EXPR)) *************** *** 1158,1161 **** --- 1271,1275 ---- TREE_TYPE (t) = TREE_TYPE (arg1); force_fit_type (t); + TREE_CONSTANT_OVERFLOW (t) = overflow; return t; } *************** *** 1172,1176 **** if (setjmp (float_error)) { ! warning ("floating overflow in constant folding"); return build (code, TREE_TYPE (arg1), arg1, arg2); } --- 1286,1290 ---- if (setjmp (float_error)) { ! pedwarn ("floating overflow in constant expression"); return build (code, TREE_TYPE (arg1), arg1, arg2); } *************** *** 1216,1221 **** #endif /* no REAL_ARITHMETIC */ t = build_real (TREE_TYPE (arg1), ! REAL_VALUE_TRUNCATE (TYPE_MODE (TREE_TYPE (arg1)), value)); ! set_float_handler (0); return t; } --- 1330,1335 ---- #endif /* no REAL_ARITHMETIC */ t = build_real (TREE_TYPE (arg1), ! real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)), value)); ! set_float_handler (NULL_PTR); return t; } *************** *** 1286,1294 **** register tree t; /* Type-size nodes already made for small sizes. */ ! static tree size_table[2*HOST_BITS_PER_INT+1]; ! if (number >= 0 && number < 2*HOST_BITS_PER_INT+1 && size_table[number] != 0) return size_table[number]; ! if (number >= 0 && number < 2*HOST_BITS_PER_INT+1) { push_obstacks_nochange (); --- 1400,1409 ---- register tree t; /* Type-size nodes already made for small sizes. */ ! static tree size_table[2*HOST_BITS_PER_WIDE_INT + 1]; ! if (number >= 0 && number < 2*HOST_BITS_PER_WIDE_INT + 1 ! && size_table[number] != 0) return size_table[number]; ! if (number >= 0 && number < 2*HOST_BITS_PER_WIDE_INT + 1) { push_obstacks_nochange (); *************** *** 1363,1366 **** --- 1478,1484 ---- t = build_int_2 (TREE_INT_CST_LOW (arg1), TREE_INT_CST_HIGH (arg1)); + /* Carry forward overflow indication unless truncating. */ + if (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (t))) + TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg1); TREE_TYPE (t) = type; force_fit_type (t); *************** *** 1373,1380 **** x = TREE_REAL_CST (arg1), u = real_value_from_int_cst (TYPE_MAX_VALUE (type)); ! if (! ((REAL_VALUES_LESS (l, x) || REAL_VALUES_EQUAL (l, x)) ! && (REAL_VALUES_LESS (x, u) || REAL_VALUES_EQUAL (x, u)))) { ! warning ("real constant out of range for integer conversion"); return t; } --- 1491,1507 ---- x = TREE_REAL_CST (arg1), u = real_value_from_int_cst (TYPE_MAX_VALUE (type)); ! /* See if X will be in range after truncation towards 0. ! To compensate for truncation, move the bounds away from 0, ! but reject if X exactly equals the adjusted bounds. */ ! #ifdef REAL_ARITHMETIC ! REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1); ! REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1); ! #else ! l--; ! u++; ! #endif ! if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u))) { ! pedwarn ("real constant out of range for integer conversion"); return t; } *************** *** 1382,1387 **** { REAL_VALUE_TYPE d; ! int low, high; ! int half_word = 1 << (HOST_BITS_PER_INT / 2); d = TREE_REAL_CST (arg1); --- 1509,1515 ---- { REAL_VALUE_TYPE d; ! HOST_WIDE_INT low, high; ! HOST_WIDE_INT half_word ! = (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2); d = TREE_REAL_CST (arg1); *************** *** 1389,1395 **** d = -d; ! high = (int) (d / half_word / half_word); d -= (REAL_VALUE_TYPE) high * half_word * half_word; ! low = (unsigned) d; if (TREE_REAL_CST (arg1) < 0) neg_double (low, high, &low, &high); --- 1517,1529 ---- d = -d; ! high = (HOST_WIDE_INT) (d / half_word / half_word); d -= (REAL_VALUE_TYPE) high * half_word * half_word; ! if (d >= (REAL_VALUE_TYPE) half_word * half_word / 2) ! { ! low = d - (REAL_VALUE_TYPE) half_word * half_word / 2; ! low |= (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); ! } ! else ! low = (HOST_WIDE_INT) d; if (TREE_REAL_CST (arg1) < 0) neg_double (low, high, &low, &high); *************** *** 1398,1402 **** #else { ! int low, high; REAL_VALUE_TO_INT (low, high, TREE_REAL_CST (arg1)); t = build_int_2 (low, high); --- 1532,1536 ---- #else { ! HOST_WIDE_INT low, high; REAL_VALUE_TO_INT (low, high, TREE_REAL_CST (arg1)); t = build_int_2 (low, high); *************** *** 1419,1430 **** if (setjmp (float_error)) { ! warning ("floating overflow in constant folding"); return t; } set_float_handler (float_error); ! t = build_real (type, REAL_VALUE_TRUNCATE (TYPE_MODE (type), TREE_REAL_CST (arg1))); ! set_float_handler (0); return t; } --- 1553,1564 ---- if (setjmp (float_error)) { ! pedwarn ("floating overflow in constant expression"); return t; } set_float_handler (float_error); ! t = build_real (type, real_value_truncate (TYPE_MODE (type), TREE_REAL_CST (arg1))); ! set_float_handler (NULL_PTR); return t; } *************** *** 1507,1512 **** } ! /* Return nonzero if two operands are necessarily equal. ! If ONLY_CONST is non-zero, only return non-zero for constants. */ int --- 1641,1651 ---- } ! /* Return nonzero if two operands are necessarily equal. ! If ONLY_CONST is non-zero, only return non-zero for constants. ! This function tests whether the operands are indistinguishable; ! it does not test whether they are equal using C's == operation. ! The distinction is important for IEEE floating point, because ! (1) -0.0 and 0.0 are distinguishable, but -0.0==0.0, and ! (2) two NaNs may be indistinguishable, but NaN!=NaN. */ int *************** *** 1544,1559 **** return 1; ! /* Detect when real constants are equal. ! But reject weird values because we can't be sure what to do with them. */ if (TREE_CODE (arg0) == TREE_CODE (arg1) ! && TREE_CODE (arg0) == REAL_CST ! && !bcmp (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1), ! sizeof (REAL_VALUE_TYPE)) ! /* Some people say these are not necessary. ! But they do little harm, and taking them out would be risky. ! So leave them and let's not spend any more time on them--rms. */ ! && !REAL_VALUE_ISINF (TREE_REAL_CST (arg0)) ! && !REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))) ! return 1; if (only_const) --- 1683,1691 ---- return 1; ! /* Detect when real constants are equal. */ if (TREE_CODE (arg0) == TREE_CODE (arg1) ! && TREE_CODE (arg0) == REAL_CST) ! return !bcmp (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1), ! sizeof (REAL_VALUE_TYPE)); if (only_const) *************** *** 1666,1670 **** } ! /* See if ARG is an expression is either a comparison or is peforming arithmetic on comparisons. The comparisons must only be comparing two different values, which will be stored in *CVAL1 and *CVAL2; if --- 1798,1802 ---- } ! /* See if ARG is an expression that is either a comparison or is performing arithmetic on comparisons. The comparisons must only be comparing two different values, which will be stored in *CVAL1 and *CVAL2; if *************** *** 1752,1756 **** /* ARG is a tree that is known to contain just arithmetic operations and comparisons. Evaluate the operations in the tree substituting NEW0 for ! any occurrance of OLD0 as an operand of a comparison and likewise for NEW1 and OLD1. */ --- 1884,1888 ---- /* ARG is a tree that is known to contain just arithmetic operations and comparisons. Evaluate the operations in the tree substituting NEW0 for ! any occurrence of OLD0 as an operand of a comparison and likewise for NEW1 and OLD1. */ *************** *** 1849,1854 **** } ! /* Return a simplified tree node for the truth-negation of ARG ! (perhaps by altering ARG). It is known that ARG is an operation that returns a truth value (0 or 1). */ --- 1981,1986 ---- } ! /* Return a simplified tree node for the truth-negation of ARG. This ! never alters ARG itself. We assume that ARG is an operation that returns a truth value (0 or 1). */ *************** *** 1870,1877 **** return build1 (TRUTH_NOT_EXPR, type, arg); else ! { ! TREE_SET_CODE (arg, invert_tree_comparison (code)); ! return arg; ! } } --- 2002,2007 ---- return build1 (TRUTH_NOT_EXPR, type, arg); else ! return build (invert_tree_comparison (code), type, ! TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); } *************** *** 2106,2110 **** #if BYTES_BIG_ENDIAN lbitpos = lnbitsize - lbitsize - lbitpos; - rbitpos = rnbitsize - rbitsize - rbitpos; #endif --- 2236,2239 ---- *************** *** 2119,2129 **** and return. */ return build (code, compare_type, ! build (BIT_AND_EXPR, type, ! make_bit_field_ref (linner, type, ! lnbitsize, lnbitpos, lunsignedp), mask), ! build (BIT_AND_EXPR, type, ! make_bit_field_ref (rinner, type, ! rnbitsize, rnbitpos, runsignedp), mask)); --- 2248,2258 ---- and return. */ return build (code, compare_type, ! build (BIT_AND_EXPR, unsigned_type, ! make_bit_field_ref (linner, unsigned_type, ! lnbitsize, lnbitpos, 1), mask), ! build (BIT_AND_EXPR, unsigned_type, ! make_bit_field_ref (rinner, unsigned_type, ! rnbitsize, rnbitpos, 1), mask)); *************** *** 2174,2192 **** appropriate number of bits and mask it with the computed mask (in case this was a signed field). If we changed it, make a new one. */ ! lhs = make_bit_field_ref (linner, TREE_TYPE (lhs), lnbitsize, lnbitpos, ! lunsignedp); ! rhs = fold (build1 (NOP_EXPR, type, ! const_binop (BIT_AND_EXPR, ! const_binop (LSHIFT_EXPR, ! convert (unsigned_type, rhs), ! size_int (lbitpos)), mask))); return build (code, compare_type, ! build (BIT_AND_EXPR, type, lhs, mask), rhs); } ! /* Subroutine for the following routine: decode a field reference. If EXP is a comparison reference, we return the innermost reference. --- 2303,2320 ---- appropriate number of bits and mask it with the computed mask (in case this was a signed field). If we changed it, make a new one. */ ! lhs = make_bit_field_ref (linner, unsigned_type, lnbitsize, lnbitpos, 1); ! rhs = fold (const_binop (BIT_AND_EXPR, ! const_binop (LSHIFT_EXPR, ! convert (unsigned_type, rhs), ! size_int (lbitpos)), ! mask)); return build (code, compare_type, ! build (BIT_AND_EXPR, unsigned_type, lhs, mask), rhs); } ! /* Subroutine for fold_truthop: decode a field reference. If EXP is a comparison reference, we return the innermost reference. *************** *** 2276,2281 **** size_int (precision - size)), 0); } ! /* Try to merge two comparisons to the same innermost item. For example, if we have p->a == 2 && p->b == 4 and we can make an --- 2404,2568 ---- size_int (precision - size)), 0); } + + /* Subroutine for fold_truthop: determine if an operand is simple enough + to be evaluated unconditionally. */ + + #ifdef __GNUC__ + __inline + #endif + static int + simple_operand_p (exp) + tree exp; + { + /* Strip any conversions that don't change the machine mode. */ + while ((TREE_CODE (exp) == NOP_EXPR + || TREE_CODE (exp) == CONVERT_EXPR) + && (TYPE_MODE (TREE_TYPE (exp)) + == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) + exp = TREE_OPERAND (exp, 0); + + return (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c' + || (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd' + && ! TREE_ADDRESSABLE (exp) + && ! TREE_THIS_VOLATILE (exp) + && ! DECL_NONLOCAL (exp) + /* Don't regard global variables as simple. They may be + allocated in ways unknown to the compiler (shared memory, + #pragma weak, etc). */ + && ! TREE_PUBLIC (exp) + && ! DECL_EXTERNAL (exp) + /* Loading a static variable is unduly expensive, but global + registers aren't expensive. */ + && (! TREE_STATIC (exp) || DECL_REGISTER (exp)))); + } + + /* Subroutine for fold_truthop: try to optimize a range test. + + For example, "i >= 2 && i =< 9" can be done as "(unsigned) (i - 2) <= 7". + + JCODE is the logical combination of the two terms. It is TRUTH_AND_EXPR + (representing TRUTH_ANDIF_EXPR and TRUTH_AND_EXPR) or TRUTH_OR_EXPR + (representing TRUTH_ORIF_EXPR and TRUTH_OR_EXPR). TYPE is the type of + the result. + + VAR is the value being tested. LO_CODE and HI_CODE are the comparison + operators comparing VAR to LO_CST and HI_CST. LO_CST is known to be no + larger than HI_CST (they may be equal). + + We return the simplified tree or 0 if no optimization is possible. */ + + tree + range_test (jcode, type, lo_code, hi_code, var, lo_cst, hi_cst) + enum tree_code jcode, lo_code, hi_code; + tree type, var, lo_cst, hi_cst; + { + tree utype; + enum tree_code rcode; + + /* See if this is a range test and normalize the constant terms. */ + + if (jcode == TRUTH_AND_EXPR) + { + switch (lo_code) + { + case NE_EXPR: + /* See if we have VAR != CST && VAR != CST+1. */ + if (! (hi_code == NE_EXPR + && TREE_INT_CST_LOW (hi_cst) - TREE_INT_CST_LOW (lo_cst) == 1 + && tree_int_cst_equal (integer_one_node, + const_binop (MINUS_EXPR, + hi_cst, lo_cst)))) + return 0; + + rcode = GT_EXPR; + break; + + case GT_EXPR: + case GE_EXPR: + if (hi_code == LT_EXPR) + hi_cst = const_binop (MINUS_EXPR, hi_cst, integer_one_node); + else if (hi_code != LE_EXPR) + return 0; + + if (lo_code == GT_EXPR) + lo_cst = const_binop (PLUS_EXPR, lo_cst, integer_one_node); + + /* We now have VAR >= LO_CST && VAR <= HI_CST. */ + rcode = LE_EXPR; + break; + + default: + return 0; + } + } + else + { + switch (lo_code) + { + case EQ_EXPR: + /* See if we have VAR == CST || VAR == CST+1. */ + if (! (hi_code == EQ_EXPR + && TREE_INT_CST_LOW (hi_cst) - TREE_INT_CST_LOW (lo_cst) == 1 + && tree_int_cst_equal (integer_one_node, + const_binop (MINUS_EXPR, + hi_cst, lo_cst)))) + return 0; + + rcode = LE_EXPR; + break; + + case LE_EXPR: + case LT_EXPR: + if (hi_code == GE_EXPR) + hi_cst = const_binop (MINUS_EXPR, hi_cst, integer_one_node); + else if (hi_code != GT_EXPR) + return 0; + + if (lo_code == LE_EXPR) + lo_cst = const_binop (PLUS_EXPR, lo_cst, integer_one_node); + + /* We now have VAR < LO_CST || VAR > HI_CST. */ + rcode = GT_EXPR; + break; + + default: + return 0; + } + } + + /* When normalizing, it is possible to both increment the smaller constant + and decrement the larger constant. See if they are still ordered. */ + if (tree_int_cst_lt (hi_cst, lo_cst)) + return 0; + + /* Fail if VAR isn't an integer. */ + utype = TREE_TYPE (var); + if (TREE_CODE (utype) != INTEGER_TYPE + && TREE_CODE (utype) != ENUMERAL_TYPE) + return 0; + + /* The range test is invalid if subtracting the two constants results + in overflow. This can happen in traditional mode. */ + if (! int_fits_type_p (hi_cst, TREE_TYPE (var)) + || ! int_fits_type_p (lo_cst, TREE_TYPE (var))) + return 0; + + if (! TREE_UNSIGNED (utype)) + { + utype = unsigned_type (utype); + var = convert (utype, var); + } + + return fold (convert (type, + build (rcode, utype, + build (MINUS_EXPR, utype, var, lo_cst), + const_binop (MINUS_EXPR, hi_cst, lo_cst)))); + } ! /* Find ways of folding logical expressions of LHS and RHS: ! Try to merge two comparisons to the same innermost item. ! Look for range tests like "ch >= '0' && ch <= '9'". ! Look for combinations of simple terms on machines with expensive branches ! and evaluate the RHS unconditionally. For example, if we have p->a == 2 && p->b == 4 and we can make an *************** *** 2298,2302 **** static tree ! merge_component_references (code, truth_type, lhs, rhs) enum tree_code code; tree truth_type, lhs, rhs; --- 2585,2589 ---- static tree ! fold_truthop (code, truth_type, lhs, rhs) enum tree_code code; tree truth_type, lhs, rhs; *************** *** 2311,2317 **** comparison for one-bit fields. */ ! enum tree_code wanted_code ! = (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR) ? EQ_EXPR : NE_EXPR; enum tree_code lcode, rcode; tree ll_inner, lr_inner, rl_inner, rr_inner; int ll_bitsize, ll_bitpos, lr_bitsize, lr_bitpos; --- 2598,2604 ---- comparison for one-bit fields. */ ! enum tree_code wanted_code; enum tree_code lcode, rcode; + tree ll_arg, lr_arg, rl_arg, rr_arg; tree ll_inner, lr_inner, rl_inner, rr_inner; int ll_bitsize, ll_bitpos, lr_bitsize, lr_bitpos; *************** *** 2323,2352 **** enum machine_mode lnmode, rnmode; tree ll_mask, lr_mask, rl_mask, rr_mask; ! tree l_const = 0, r_const = 0; tree type, result; int first_bit, end_bit; ! int volatilep = 0; ! /* Start by getting the comparison codes and seeing if we may be able ! to do something. Then get all the parameters for each side. Fail ! if anything is volatile. */ lcode = TREE_CODE (lhs); rcode = TREE_CODE (rhs); if ((lcode != EQ_EXPR && lcode != NE_EXPR) ! || (rcode != EQ_EXPR && rcode != NE_EXPR) ! || TREE_SIDE_EFFECTS (lhs) || TREE_SIDE_EFFECTS (rhs)) return 0; ! ll_inner = decode_field_reference (TREE_OPERAND (lhs, 0), &ll_bitsize, &ll_bitpos, &ll_mode, &ll_unsignedp, &volatilep, &ll_mask); ! lr_inner = decode_field_reference (TREE_OPERAND (lhs, 1), &lr_bitsize, &lr_bitpos, &lr_mode, &lr_unsignedp, &volatilep, &lr_mask); ! rl_inner = decode_field_reference (TREE_OPERAND (rhs, 0), &rl_bitsize, &rl_bitpos, &rl_mode, &rl_unsignedp, &volatilep, &rl_mask); ! rr_inner = decode_field_reference (TREE_OPERAND (rhs, 1), &rr_bitsize, &rr_bitpos, &rr_mode, &rr_unsignedp, &volatilep, &rr_mask); --- 2610,2702 ---- enum machine_mode lnmode, rnmode; tree ll_mask, lr_mask, rl_mask, rr_mask; ! tree l_const, r_const; tree type, result; int first_bit, end_bit; ! int volatilep; ! ! /* Start by getting the comparison codes and seeing if this looks like ! a range test. Fail if anything is volatile. */ ! if (TREE_SIDE_EFFECTS (lhs) ! || TREE_SIDE_EFFECTS (rhs)) ! return 0; lcode = TREE_CODE (lhs); rcode = TREE_CODE (rhs); + + if (TREE_CODE_CLASS (lcode) != '<' + || TREE_CODE_CLASS (rcode) != '<') + return 0; + + code = ((code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR) + ? TRUTH_AND_EXPR : TRUTH_OR_EXPR); + + ll_arg = TREE_OPERAND (lhs, 0); + lr_arg = TREE_OPERAND (lhs, 1); + rl_arg = TREE_OPERAND (rhs, 0); + rr_arg = TREE_OPERAND (rhs, 1); + + if (TREE_CODE (lr_arg) == INTEGER_CST + && TREE_CODE (rr_arg) == INTEGER_CST + && operand_equal_p (ll_arg, rl_arg, 0)) + { + if (tree_int_cst_lt (lr_arg, rr_arg)) + result = range_test (code, truth_type, lcode, rcode, + ll_arg, lr_arg, rr_arg); + else + result = range_test (code, truth_type, rcode, lcode, + ll_arg, rr_arg, lr_arg); + + /* If this isn't a range test, it also isn't a comparison that + can be merged. However, it wins to evaluate the RHS unconditionally + on machines with expensive branches. */ + + if (result == 0 && BRANCH_COST >= 2) + { + if (TREE_CODE (ll_arg) != VAR_DECL + && TREE_CODE (ll_arg) != PARM_DECL) + { + /* Avoid evaluating the variable part twice. */ + ll_arg = save_expr (ll_arg); + lhs = build (lcode, TREE_TYPE (lhs), ll_arg, lr_arg); + rhs = build (rcode, TREE_TYPE (rhs), ll_arg, rr_arg); + } + return build (code, truth_type, lhs, rhs); + } + return result; + } + + /* If the RHS can be evaluated unconditionally and its operands are + simple, it wins to evaluate the RHS unconditionally on machines + with expensive branches. In this case, this isn't a comparison + that can be merged. */ + + /* @@ I'm not sure it wins on the m88110 to do this if the comparisons + are with zero (tmw). */ + + if (BRANCH_COST >= 2 + && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE + && simple_operand_p (rl_arg) + && simple_operand_p (rr_arg)) + return build (code, truth_type, lhs, rhs); + + /* See if the comparisons can be merged. Then get all the parameters for + each side. */ + if ((lcode != EQ_EXPR && lcode != NE_EXPR) ! || (rcode != EQ_EXPR && rcode != NE_EXPR)) return 0; ! volatilep = 0; ! ll_inner = decode_field_reference (ll_arg, &ll_bitsize, &ll_bitpos, &ll_mode, &ll_unsignedp, &volatilep, &ll_mask); ! lr_inner = decode_field_reference (lr_arg, &lr_bitsize, &lr_bitpos, &lr_mode, &lr_unsignedp, &volatilep, &lr_mask); ! rl_inner = decode_field_reference (rl_arg, &rl_bitsize, &rl_bitpos, &rl_mode, &rl_unsignedp, &volatilep, &rl_mask); ! rr_inner = decode_field_reference (rr_arg, &rr_bitsize, &rr_bitpos, &rr_mode, &rr_unsignedp, &volatilep, &rr_mask); *************** *** 2360,2373 **** return 0; ! if (TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST ! && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST) ! l_const = TREE_OPERAND (lhs, 1), r_const = TREE_OPERAND (rhs, 1); else if (lr_inner == 0 || rr_inner == 0 || ! operand_equal_p (lr_inner, rr_inner, 0)) return 0; /* If either comparison code is not correct for our logical operation, fail. However, we can convert a one-bit comparison against zero into the opposite comparison against that bit being set in the field. */ if (lcode != wanted_code) { --- 2710,2727 ---- return 0; ! if (TREE_CODE (lr_arg) == INTEGER_CST ! && TREE_CODE (rr_arg) == INTEGER_CST) ! l_const = lr_arg, r_const = rr_arg; else if (lr_inner == 0 || rr_inner == 0 || ! operand_equal_p (lr_inner, rr_inner, 0)) return 0; + else + l_const = r_const = 0; /* If either comparison code is not correct for our logical operation, fail. However, we can convert a one-bit comparison against zero into the opposite comparison against that bit being set in the field. */ + + wanted_code = (code == TRUTH_AND_EXPR ? EQ_EXPR : NE_EXPR); if (lcode != wanted_code) { *************** *** 2434,2438 **** { if (ll_bitsize != lr_bitsize || rl_bitsize != rr_bitsize ! || ll_unsignedp != lr_unsignedp || rl_unsignedp != rr_unsignedp) return 0; --- 2788,2795 ---- { if (ll_bitsize != lr_bitsize || rl_bitsize != rr_bitsize ! || ll_unsignedp != lr_unsignedp || rl_unsignedp != rr_unsignedp ! /* Make sure the two fields on the right ! correspond to the left without being swapped. */ ! || ll_bitpos - rl_bitpos != lr_bitpos - rr_bitpos) return 0; *************** *** 2570,2574 **** kind = TREE_CODE_CLASS (code); ! if (kind == 'e' || kind == '<' || kind == '1' || kind == '2' || kind == 'r') { register int len = tree_code_length[(int) code]; --- 2927,2951 ---- kind = TREE_CODE_CLASS (code); ! if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR) ! { ! /* Special case for conversion ops that can have fixed point args. */ ! arg0 = TREE_OPERAND (t, 0); ! ! /* Don't use STRIP_NOPS, because signedness of argument type matters. */ ! if (arg0 != 0) ! STRIP_TYPE_NOPS (arg0); ! ! if (arg0 != 0 && TREE_CODE (arg0) != INTEGER_CST ! #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) ! && TREE_CODE (arg0) != REAL_CST ! #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */ ! ) ! /* Note that TREE_CONSTANT isn't enough: ! static var addresses are constant but we can't ! do arithmetic on them. */ ! wins = 0; ! } ! else if (kind == 'e' || kind == '<' ! || kind == '1' || kind == '2' || kind == 'r') { register int len = tree_code_length[(int) code]; *************** *** 2630,2636 **** fold (build1 (code, type, TREE_OPERAND (arg0, 1)))); else if (TREE_CODE (arg0) == COND_EXPR) ! return fold (build (COND_EXPR, type, TREE_OPERAND (arg0, 0), ! fold (build1 (code, type, TREE_OPERAND (arg0, 1))), ! fold (build1 (code, type, TREE_OPERAND (arg0, 2))))); else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<') return fold (build (COND_EXPR, type, arg0, --- 3007,3035 ---- fold (build1 (code, type, TREE_OPERAND (arg0, 1)))); else if (TREE_CODE (arg0) == COND_EXPR) ! { ! t = fold (build (COND_EXPR, type, TREE_OPERAND (arg0, 0), ! fold (build1 (code, type, TREE_OPERAND (arg0, 1))), ! fold (build1 (code, type, TREE_OPERAND (arg0, 2))))); ! ! /* If this was a conversion, and all we did was to move into ! inside the COND_EXPR, bring it back out. Then return so we ! don't get into an infinite recursion loop taking the conversion ! out and then back in. */ ! ! if ((code == NOP_EXPR || code == CONVERT_EXPR ! || code == NON_LVALUE_EXPR) ! && TREE_CODE (t) == COND_EXPR ! && TREE_CODE (TREE_OPERAND (t, 1)) == code ! && TREE_CODE (TREE_OPERAND (t, 2)) == code ! && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)) ! == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 2), 0)))) ! t = build1 (code, type, ! build (COND_EXPR, ! TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0)), ! TREE_OPERAND (t, 0), ! TREE_OPERAND (TREE_OPERAND (t, 1), 0), ! TREE_OPERAND (TREE_OPERAND (t, 2), 0))); ! return t; ! } else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<') return fold (build (COND_EXPR, type, arg0, *************** *** 2778,2782 **** { /* Don't leave an assignment inside a conversion ! unless assiging a bitfield. */ tree prev = TREE_OPERAND (t, 0); TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1); --- 3177,3181 ---- { /* Don't leave an assignment inside a conversion ! unless assigning a bitfield. */ tree prev = TREE_OPERAND (t, 0); TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1); *************** *** 2821,2829 **** if (TREE_CODE (arg0) == INTEGER_CST) { ! if (TREE_INT_CST_LOW (arg0) == 0) ! t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0)); ! else ! t = build_int_2 (- TREE_INT_CST_LOW (arg0), ! ~ TREE_INT_CST_HIGH (arg0)); TREE_TYPE (t) = type; force_fit_type (t); --- 3220,3230 ---- if (TREE_CODE (arg0) == INTEGER_CST) { ! HOST_WIDE_INT low, high; ! int overflow = neg_double (TREE_INT_CST_LOW (arg0), ! TREE_INT_CST_HIGH (arg0), ! &low, &high); ! t = build_int_2 (low, high); ! TREE_CONSTANT_OVERFLOW (t) ! = overflow | TREE_CONSTANT_OVERFLOW (arg0); TREE_TYPE (t) = type; force_fit_type (t); *************** *** 2851,2859 **** && TREE_INT_CST_HIGH (arg0) < 0) { ! if (TREE_INT_CST_LOW (arg0) == 0) ! t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0)); ! else ! t = build_int_2 (- TREE_INT_CST_LOW (arg0), ! ~ TREE_INT_CST_HIGH (arg0)); } } --- 3252,3262 ---- && TREE_INT_CST_HIGH (arg0) < 0) { ! HOST_WIDE_INT low, high; ! int overflow = neg_double (TREE_INT_CST_LOW (arg0), ! TREE_INT_CST_HIGH (arg0), ! &low, &high); ! t = build_int_2 (low, high); ! TREE_TYPE (t) = type; ! force_fit_type (t, overflow); } } *************** *** 2878,2881 **** --- 3281,3285 ---- TREE_TYPE (t) = type; force_fit_type (t); + TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0); } else if (TREE_CODE (arg0) == BIT_NOT_EXPR) *************** *** 3035,3039 **** This is unsafe for certain floats even in non-IEEE formats. In IEEE, it is unsafe because it does wrong for NaNs. ! Also note that operand_equal_p is always false is an operand is volatile. */ --- 3439,3443 ---- This is unsafe for certain floats even in non-IEEE formats. In IEEE, it is unsafe because it does wrong for NaNs. ! Also note that operand_equal_p is always false if an operand is volatile. */ *************** *** 3114,3119 **** { int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))); ! if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT ! && (~TREE_INT_CST_LOW (arg0) & ((1 << prec) - 1)) == 0) return build1 (NOP_EXPR, type, TREE_OPERAND (arg1, 0)); } --- 3518,3524 ---- { int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))); ! if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT ! && (~TREE_INT_CST_LOW (arg0) ! & (((HOST_WIDE_INT) 1 << prec) - 1)) == 0) return build1 (NOP_EXPR, type, TREE_OPERAND (arg1, 0)); } *************** *** 3122,3127 **** { int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))); ! if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_INT ! && (~TREE_INT_CST_LOW (arg1) & ((1 << prec) - 1)) == 0) return build1 (NOP_EXPR, type, TREE_OPERAND (arg0, 0)); } --- 3527,3533 ---- { int prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))); ! if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT ! && (~TREE_INT_CST_LOW (arg1) ! & (((HOST_WIDE_INT) 1 << prec) - 1)) == 0) return build1 (NOP_EXPR, type, TREE_OPERAND (arg0, 0)); } *************** *** 3166,3170 **** tree new_op = build_int_2 (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) ! / TREE_INT_CST_LOW (arg1)); TREE_TYPE (new_op) = type; --- 3572,3576 ---- tree new_op = build_int_2 (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) ! / TREE_INT_CST_LOW (arg1), 0); TREE_TYPE (new_op) = type; *************** *** 3187,3191 **** tree new_op = build_int_2 (TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1)) ! / TREE_INT_CST_LOW (arg1)); TREE_TYPE (new_op) = type; --- 3593,3597 ---- tree new_op = build_int_2 (TREE_INT_CST_LOW (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1)) ! / TREE_INT_CST_LOW (arg1), 0); TREE_TYPE (new_op) = type; *************** *** 3274,3284 **** if (TREE_CODE (arg0) == code) { ! tem = merge_component_references (code, type, ! TREE_OPERAND (arg0, 1), arg1); if (tem) return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); } ! tem = merge_component_references (code, type, arg0, arg1); if (tem) return tem; --- 3680,3690 ---- if (TREE_CODE (arg0) == code) { ! tem = fold_truthop (code, type, ! TREE_OPERAND (arg0, 1), arg1); if (tem) return fold (build (code, type, TREE_OPERAND (arg0, 0), tem)); } ! tem = fold_truthop (code, type, arg0, arg1); if (tem) return tem; *************** *** 3724,3730 **** /* If we have A op B ? A : C, we may be able to convert this to a simpler expression, depending on the operation and the values ! of B and C. */ if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<' && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), arg1, TREE_OPERAND (arg0, 1))) --- 4130,4139 ---- /* If we have A op B ? A : C, we may be able to convert this to a simpler expression, depending on the operation and the values ! of B and C. IEEE floating point prevents this though, ! because A or B might be -0.0 or a NaN. */ if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<' + && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT + || TREE_CODE (TREE_TYPE (TREE_OPERAND (arg0, 0))) != REAL_TYPE) && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), arg1, TREE_OPERAND (arg0, 1))) *************** *** 3786,3792 **** we might still be able to simplify this. For example, if C1 is one less or one more than C2, this might have started ! out as a MIN or MAX and been transformed by this function. */ ! if (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST) switch (comp_code) --- 4195,4203 ---- we might still be able to simplify this. For example, if C1 is one less or one more than C2, this might have started ! out as a MIN or MAX and been transformed by this function. ! Only good for INTEGER_TYPE, because we need TYPE_MAX_VALUE. */ ! if (TREE_CODE (type) == INTEGER_TYPE ! && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST && TREE_CODE (arg2) == INTEGER_CST) switch (comp_code) diff -rc2N gcc-2.2.2/function.c gcc-2.3.1/function.c *** gcc-2.2.2/function.c Wed May 27 17:50:41 1992 --- gcc-2.3.1/function.c Mon Oct 26 14:38:37 1992 *************** *** 1,4 **** /* Expands front end tree to back end RTL for GNU C-Compiler ! Copyright (C) 1987, 1988, 1989, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Expands front end tree to back end RTL for GNU C-Compiler ! Copyright (C) 1987, 1988, 1989, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 54,57 **** --- 54,58 ---- #include "recog.h" #include "output.h" + #include "basic-block.h" /* Round a value to the lowest integer less than it that is a multiple of *************** *** 307,310 **** --- 308,312 ---- static void instantiate_decls (); static void instantiate_decls_1 (); + static void instantiate_decl (); static int instantiate_virtual_regs_1 (); static rtx fixup_memory_subreg (); *************** *** 423,426 **** --- 425,429 ---- p->temp_slot_level = temp_slot_level; p->fixup_var_refs_queue = 0; + p->epilogue_delay_list = current_function_epilogue_delay_list; save_tree_status (p); *************** *** 430,433 **** --- 433,437 ---- save_expr_status (p); save_stmt_status (p); + save_varasm_status (p); } *************** *** 482,485 **** --- 486,490 ---- temp_slots = p->temp_slots; temp_slot_level = p->temp_slot_level; + current_function_epilogue_delay_list = p->epilogue_delay_list; restore_tree_status (p); *************** *** 488,491 **** --- 493,497 ---- restore_emit_status (p); restore_stmt_status (p); + restore_varasm_status (p); /* Finish doing put_var_into_stack for any of our variables *************** *** 494,498 **** struct var_refs_queue *queue = p->fixup_var_refs_queue; for (; queue; queue = queue->next) ! fixup_var_refs (queue->modified); } --- 500,504 ---- struct var_refs_queue *queue = p->fixup_var_refs_queue; for (; queue; queue = queue->next) ! fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp); } *************** *** 811,820 **** register rtx reg; register rtx new = 0; struct function *function = 0; tree context = decl_function_context (decl); ! /* Get the current rtl used for this object. */ reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl); /* If this variable comes from an outer function, find that function's saved context. */ --- 817,839 ---- register rtx reg; register rtx new = 0; + enum machine_mode promoted_mode, decl_mode; struct function *function = 0; tree context = decl_function_context (decl); ! /* Get the current rtl used for this object and it's original mode. */ reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl); + /* No need to do anything if decl has no rtx yet + since in that case caller is setting TREE_ADDRESSABLE + and a stack slot will be assigned when the rtl is made. */ + if (reg == 0) + return; + + /* Get the declared mode for this object. */ + decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl)) + : DECL_MODE (decl)); + /* Get the mode it's actually stored in. */ + promoted_mode = GET_MODE (reg); + /* If this variable comes from an outer function, find that function's saved context. */ *************** *** 824,840 **** break; - /* No need to do anything if decl has no rtx yet - since in that case caller is setting TREE_ADDRESSABLE - and a stack slot will be assigned when the rtl is made. */ - if (reg == 0) - return; - /* If this is a variable-size object with a pseudo to address it, put that pseudo into the stack, if the var is nonlocal. */ ! if (TREE_NONLOCAL (decl) && GET_CODE (reg) == MEM && GET_CODE (XEXP (reg, 0)) == REG && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER) ! reg = XEXP (reg, 0); if (GET_CODE (reg) != REG) return; --- 843,856 ---- break; /* If this is a variable-size object with a pseudo to address it, put that pseudo into the stack, if the var is nonlocal. */ ! if (DECL_NONLOCAL (decl) && GET_CODE (reg) == MEM && GET_CODE (XEXP (reg, 0)) == REG && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER) ! { ! reg = XEXP (reg, 0); ! decl_mode = promoted_mode = GET_MODE (reg); ! } if (GET_CODE (reg) != REG) return; *************** *** 846,850 **** if (new == 0) new = assign_outer_stack_local (GET_MODE (reg), ! GET_MODE_SIZE (GET_MODE (reg)), 0, function); } --- 862,866 ---- if (new == 0) new = assign_outer_stack_local (GET_MODE (reg), ! GET_MODE_SIZE (decl_mode), 0, function); } *************** *** 855,860 **** if (new == 0) new = assign_stack_local (GET_MODE (reg), ! GET_MODE_SIZE (GET_MODE (reg)), ! 0); } --- 871,875 ---- if (new == 0) new = assign_stack_local (GET_MODE (reg), ! GET_MODE_SIZE (decl_mode), 0); } *************** *** 863,866 **** --- 878,882 ---- REG_USERVAR_P (reg) = 0; PUT_CODE (reg, MEM); + PUT_MODE (reg, decl_mode); /* If this is a memory ref that contains aggregate components, *************** *** 883,886 **** --- 899,904 ---- = (struct var_refs_queue *) oballoc (sizeof (struct var_refs_queue)); temp->modified = reg; + temp->promoted_mode = promoted_mode; + temp->unsignedp = TREE_UNSIGNED (TREE_TYPE (decl)); temp->next = function->fixup_var_refs_queue; function->fixup_var_refs_queue = temp; *************** *** 889,898 **** else /* Variable is local; fix it up now. */ ! fixup_var_refs (reg); } static void ! fixup_var_refs (var) rtx var; { tree pending; --- 907,918 ---- else /* Variable is local; fix it up now. */ ! fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (TREE_TYPE (decl))); } static void ! fixup_var_refs (var, promoted_mode, unsignedp) rtx var; + enum machine_mode promoted_mode; + int unsignedp; { tree pending; *************** *** 902,906 **** /* Must scan all insns for stack-refs that exceed the limit. */ ! fixup_var_refs_insns (var, first_insn, stack == 0); /* Scan all pending sequences too. */ --- 922,926 ---- /* Must scan all insns for stack-refs that exceed the limit. */ ! fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0); /* Scan all pending sequences too. */ *************** *** 908,912 **** { push_to_sequence (stack->first); ! fixup_var_refs_insns (var, stack->first, stack->next != 0); /* Update remembered end of sequence in case we added an insn at the end. */ --- 928,933 ---- { push_to_sequence (stack->first); ! fixup_var_refs_insns (var, promoted_mode, unsignedp, ! stack->first, stack->next != 0); /* Update remembered end of sequence in case we added an insn at the end. */ *************** *** 922,926 **** { push_to_sequence (seq); ! fixup_var_refs_insns (var, seq, 0); end_sequence (); } --- 943,947 ---- { push_to_sequence (seq); ! fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0); end_sequence (); } *************** *** 946,950 **** static struct fixup_replacement * ! find_replacement (replacements, x) struct fixup_replacement **replacements; rtx x; --- 967,971 ---- static struct fixup_replacement * ! find_fixup_replacement (replacements, x) struct fixup_replacement **replacements; rtx x; *************** *** 973,978 **** static void ! fixup_var_refs_insns (var, insn, toplevel) rtx var; rtx insn; int toplevel; --- 994,1001 ---- static void ! fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel) rtx var; + enum machine_mode promoted_mode; + int unsignedp; rtx insn; int toplevel; *************** *** 992,996 **** && rtx_equal_p (SET_SRC (PATTERN (insn)), var)) { ! next = delete_insn (insn); if (insn == last_parm_insn) last_parm_insn = PREV_INSN (next); --- 1015,1023 ---- && rtx_equal_p (SET_SRC (PATTERN (insn)), var)) { ! /* In unoptimized compilation, we shouldn't call delete_insn ! except in jump.c doing warnings. */ ! PUT_CODE (insn, NOTE); ! NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; ! NOTE_SOURCE_FILE (insn) = 0; if (insn == last_parm_insn) last_parm_insn = PREV_INSN (next); *************** *** 1011,1015 **** struct fixup_replacement *replacements = 0; ! fixup_var_refs_1 (var, &PATTERN (insn), insn, &replacements); while (replacements) --- 1038,1043 ---- struct fixup_replacement *replacements = 0; ! fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn, ! &replacements); while (replacements) *************** *** 1018,1021 **** --- 1046,1050 ---- { rtx insert_before; + rtx seq; /* OLD might be a (subreg (mem)). */ *************** *** 1041,1047 **** insert_before = insn; ! emit_insn_before (gen_move_insn (replacements->new, ! replacements->old), ! insert_before); } --- 1070,1091 ---- insert_before = insn; ! /* If we are changing the mode, do a conversion. ! This might be wasteful, but combine.c will ! eliminate much of the waste. */ ! ! if (GET_MODE (replacements->new) ! != GET_MODE (replacements->old)) ! { ! start_sequence (); ! convert_move (replacements->new, ! replacements->old, unsignedp); ! seq = gen_sequence (); ! end_sequence (); ! } ! else ! seq = gen_move_insn (replacements->new, ! replacements->old); ! ! emit_insn_before (seq, insert_before); } *************** *** 1061,1066 **** } ! /* VAR is a MEM that used to be a pseudo register. See if the rtx expression ! at *LOC in INSN needs to be changed. REPLACEMENTS is a pointer to a list head that starts out zero, but may --- 1105,1110 ---- } ! /* VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE. ! See if the rtx expression at *LOC in INSN needs to be changed. REPLACEMENTS is a pointer to a list head that starts out zero, but may *************** *** 1073,1078 **** static void ! fixup_var_refs_1 (var, loc, insn, replacements) register rtx var; register rtx *loc; rtx insn; --- 1117,1123 ---- static void ! fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) register rtx var; + enum machine_mode promoted_mode; register rtx *loc; rtx insn; *************** *** 1094,1098 **** try to fix up this address in case it is invalid. */ ! replacement = find_replacement (replacements, var); if (replacement->new) { --- 1139,1143 ---- try to fix up this address in case it is invalid. */ ! replacement = find_fixup_replacement (replacements, var); if (replacement->new) { *************** *** 1103,1114 **** *loc = replacement->new = x = fixup_stack_1 (x, insn); ! /* Unless we are forcing memory to register, we can leave things ! the way they are if the insn is valid. */ INSN_CODE (insn) = -1; ! if (! flag_force_mem && recog_memoized (insn) >= 0) return; ! *loc = replacement->new = gen_reg_rtx (GET_MODE (x)); return; } --- 1148,1160 ---- *loc = replacement->new = x = fixup_stack_1 (x, insn); ! /* Unless we are forcing memory to register or we changed the mode, ! we can leave things the way they are if the insn is valid. */ INSN_CODE (insn) = -1; ! if (! flag_force_mem && GET_MODE (x) == promoted_mode ! && recog_memoized (insn) >= 0) return; ! *loc = replacement->new = gen_reg_rtx (promoted_mode); return; } *************** *** 1121,1125 **** if (reg_mentioned_p (var, x)) { ! replacement = find_replacement (replacements, x); if (replacement->new == 0) replacement->new = copy_most_rtx (x, var); --- 1167,1171 ---- if (reg_mentioned_p (var, x)) { ! replacement = find_fixup_replacement (replacements, x); if (replacement->new == 0) replacement->new = copy_most_rtx (x, var); *************** *** 1205,1209 **** INSN_CODE (insn) = -1; XEXP (x, 0) = newmem; ! XEXP (x, 2) = gen_rtx (CONST_INT, VOIDmode, pos); if (recog_memoized (insn) >= 0) --- 1251,1255 ---- INSN_CODE (insn) = -1; XEXP (x, 0) = newmem; ! XEXP (x, 2) = GEN_INT (pos); if (recog_memoized (insn) >= 0) *************** *** 1229,1232 **** --- 1275,1290 ---- if (SUBREG_REG (x) == var) { + /* If this is a special SUBREG made because VAR was promoted + from a wider mode, replace it with VAR and call ourself + recursively, this time saying that the object previously + had its current mode (by virtue of the SUBREG). */ + + if (SUBREG_PROMOTED_VAR_P (x)) + { + *loc = var; + fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements); + return; + } + /* If this SUBREG makes VAR wider, it has become a paradoxical SUBREG with VAR in memory, but these aren't allowed at this *************** *** 1235,1239 **** if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var))) { ! replacement = find_replacement (replacements, var); if (replacement->new == 0) replacement->new = gen_reg_rtx (GET_MODE (var)); --- 1293,1297 ---- if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var))) { ! replacement = find_fixup_replacement (replacements, var); if (replacement->new == 0) replacement->new = gen_reg_rtx (GET_MODE (var)); *************** *** 1246,1250 **** is recognized. If not, or if we should force MEM into a register, make a pseudo for this SUBREG. */ ! replacement = find_replacement (replacements, x); if (replacement->new) { --- 1304,1308 ---- is recognized. If not, or if we should force MEM into a register, make a pseudo for this SUBREG. */ ! replacement = find_fixup_replacement (replacements, x); if (replacement->new) { *************** *** 1270,1274 **** if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT) ! optimize_bit_field (x, insn, 0); /* If SET_DEST is now a paradoxical SUBREG, put the result of this --- 1328,1332 ---- if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT) ! optimize_bit_field (x, insn, NULL_PTR); /* If SET_DEST is now a paradoxical SUBREG, put the result of this *************** *** 1313,1319 **** /* Since this case will return, ensure we fixup all the operands here. */ ! fixup_var_refs_1 (var, &XEXP (outerdest, 1), insn, replacements); ! fixup_var_refs_1 (var, &XEXP (outerdest, 2), insn, replacements); ! fixup_var_refs_1 (var, &SET_SRC (x), insn, replacements); tem = XEXP (outerdest, 0); --- 1371,1380 ---- /* Since this case will return, ensure we fixup all the operands here. */ ! fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1), ! insn, replacements); ! fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2), ! insn, replacements); ! fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x), ! insn, replacements); tem = XEXP (outerdest, 0); *************** *** 1362,1366 **** INSN_CODE (insn) = -1; XEXP (outerdest, 0) = newmem; ! XEXP (outerdest, 2) = gen_rtx (CONST_INT, VOIDmode, pos); if (recog_memoized (insn) >= 0) --- 1423,1427 ---- INSN_CODE (insn) = -1; XEXP (outerdest, 0) = newmem; ! XEXP (outerdest, 2) = GEN_INT (pos); if (recog_memoized (insn) >= 0) *************** *** 1406,1410 **** && recog_memoized (insn) >= 0) { ! replacement = find_replacement (replacements, SET_SRC (x)); if (replacement->new) { --- 1467,1471 ---- && recog_memoized (insn) >= 0) { ! replacement = find_fixup_replacement (replacements, SET_SRC (x)); if (replacement->new) { *************** *** 1438,1459 **** /* Otherwise, storing into VAR must be handled specially by storing into a temporary and copying that into VAR ! with a new insn after this one. */ if (dest == var) { rtx temp; ! rtx fixeddest; ! tem = SET_DEST (x); /* STRICT_LOW_PART can be discarded, around a MEM. */ ! if (GET_CODE (tem) == STRICT_LOW_PART) ! tem = XEXP (tem, 0); /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */ ! if (GET_CODE (tem) == SUBREG) ! fixeddest = fixup_memory_subreg (tem, insn, 0); else ! fixeddest = fixup_stack_1 (tem, insn); - temp = gen_reg_rtx (GET_MODE (tem)); - emit_insn_after (gen_move_insn (fixeddest, temp), insn); SET_DEST (x) = temp; } --- 1499,1533 ---- /* Otherwise, storing into VAR must be handled specially by storing into a temporary and copying that into VAR ! with a new insn after this one. Note that this case ! will be used when storing into a promoted scalar since ! the insn will now have different modes on the input ! and output and hence will be invalid (except for the case ! of setting it to a constant, which does not need any ! change if it is valid). We generate extra code in that case, ! but combine.c will eliminate it. */ if (dest == var) { rtx temp; ! rtx fixeddest = SET_DEST (x); ! /* STRICT_LOW_PART can be discarded, around a MEM. */ ! if (GET_CODE (fixeddest) == STRICT_LOW_PART) ! fixeddest = XEXP (fixeddest, 0); /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */ ! if (GET_CODE (fixeddest) == SUBREG) ! fixeddest = fixup_memory_subreg (fixeddest, insn, 0); else ! fixeddest = fixup_stack_1 (fixeddest, insn); ! ! temp = gen_reg_rtx (GET_MODE (SET_SRC (x)) == VOIDmode ! ? GET_MODE (fixeddest) ! : GET_MODE (SET_SRC (x))); ! ! emit_insn_after (gen_move_insn (fixeddest, ! gen_lowpart (GET_MODE (fixeddest), ! temp)), ! insn); SET_DEST (x) = temp; } *************** *** 1467,1476 **** { if (fmt[i] == 'e') ! fixup_var_refs_1 (var, &XEXP (x, i), insn, replacements); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) ! fixup_var_refs_1 (var, &XVECEXP (x, i, j), insn, replacements); } } --- 1541,1551 ---- { if (fmt[i] == 'e') ! fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) ! fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j), ! insn, replacements); } } *************** *** 1867,1871 **** { instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1); ! instantiate_virtual_regs_1 (®_NOTES (insn), 0, 0); } --- 1942,1946 ---- { instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1); ! instantiate_virtual_regs_1 (®_NOTES (insn), NULL_RTX, 0); } *************** *** 1892,1896 **** tree decl; ! if (TREE_INLINE (fndecl)) /* When compiling an inline function, the obstack used for rtl allocation is the maybepermanent_obstack. Calling --- 1967,1971 ---- tree decl; ! if (DECL_INLINE (fndecl)) /* When compiling an inline function, the obstack used for rtl allocation is the maybepermanent_obstack. Calling *************** *** 1902,1916 **** for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) { ! if (DECL_RTL (decl) && GET_CODE (DECL_RTL (decl)) == MEM) ! instantiate_virtual_regs_1 (&XEXP (DECL_RTL (decl), 0), ! valid_only ? DECL_RTL (decl) : 0, 0); ! #if 1 /* This is probably correct, but it seems to require fixes ! elsewhere in order to work. Let's fix them in 2.1. */ ! if (DECL_INCOMING_RTL (decl) ! && GET_CODE (DECL_INCOMING_RTL (decl)) == MEM) ! instantiate_virtual_regs_1 (&XEXP (DECL_INCOMING_RTL (decl), 0), ! valid_only ? DECL_INCOMING_RTL (decl) : 0, ! 0); ! #endif } --- 1977,1984 ---- for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) { ! instantiate_decl (DECL_RTL (decl), int_size_in_bytes (TREE_TYPE (decl)), ! valid_only); ! instantiate_decl (DECL_INCOMING_RTL (decl), ! int_size_in_bytes (TREE_TYPE (decl)), valid_only); } *************** *** 1918,1922 **** instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only); ! if (TREE_INLINE (fndecl)) { /* Save all rtl allocated for this function by raising the --- 1986,1990 ---- instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only); ! if (DECL_INLINE (fndecl)) { /* Save all rtl allocated for this function by raising the *************** *** 1939,1945 **** for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) ! if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM) ! instantiate_virtual_regs_1 (& XEXP (DECL_RTL (t), 0), ! valid_only ? DECL_RTL (t) : 0, 0); /* Process all subblocks. */ --- 2007,2012 ---- for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) ! instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)), ! valid_only); /* Process all subblocks. */ *************** *** 1947,1950 **** --- 2014,2081 ---- instantiate_decls_1 (t, valid_only); } + + /* Subroutine of the preceeding procedures: Given RTL representing a + decl and the size of the object, do any instantiation required. + + If VALID_ONLY is non-zero, it means that the RTL should only be + changed if the new address is valid. */ + + static void + instantiate_decl (x, size, valid_only) + rtx x; + int size; + int valid_only; + { + enum machine_mode mode; + rtx addr; + + /* If this is not a MEM, no need to do anything. Similarly if the + address is a constant or a register that is not a virtual register. */ + + if (x == 0 || GET_CODE (x) != MEM) + return; + + addr = XEXP (x, 0); + if (CONSTANT_P (addr) + || (GET_CODE (addr) == REG + && (REGNO (addr) < FIRST_VIRTUAL_REGISTER + || REGNO (addr) > LAST_VIRTUAL_REGISTER))) + return; + + /* If we should only do this if the address is valid, copy the address. + We need to do this so we can undo any changes that might make the + address invalid. This copy is unfortunate, but probably can't be + avoided. */ + + if (valid_only) + addr = copy_rtx (addr); + + instantiate_virtual_regs_1 (&addr, NULL_RTX, 0); + + if (! valid_only) + return; + + /* Now verify that the resulting address is valid for every integer or + floating-point mode up to and including SIZE bytes long. We do this + since the object might be accessed in any mode and frame addresses + are shared. */ + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); + mode != VOIDmode && GET_MODE_SIZE (mode) <= size; + mode = GET_MODE_WIDER_MODE (mode)) + if (! memory_address_p (mode, addr)) + return; + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); + mode != VOIDmode && GET_MODE_SIZE (mode) <= size; + mode = GET_MODE_WIDER_MODE (mode)) + if (! memory_address_p (mode, addr)) + return; + + /* Otherwise, put back the address, now that we have updated it and we + know it is valid. */ + + XEXP (x, 0) = addr; + } /* Given a pointer to a piece of rtx and an optional pointer to the *************** *** 2026,2033 **** start_sequence (); if (GET_CODE (SET_SRC (x)) != REG) ! temp = force_operand (SET_SRC (x), 0); else temp = SET_SRC (x); ! temp = force_operand (plus_constant (temp, offset), 0); seq = get_insns (); end_sequence (); --- 2157,2164 ---- start_sequence (); if (GET_CODE (SET_SRC (x)) != REG) ! temp = force_operand (SET_SRC (x), NULL_RTX); else temp = SET_SRC (x); ! temp = force_operand (plus_constant (temp, offset), NULL_RTX); seq = get_insns (); end_sequence (); *************** *** 2131,2135 **** start_sequence (); ! temp = force_operand (new, 0); seq = get_insns (); end_sequence (); --- 2262,2266 ---- start_sequence (); ! temp = force_operand (new, NULL_RTX); seq = get_insns (); end_sequence (); *************** *** 2270,2274 **** start_sequence (); ! temp = force_operand (temp, 0); seq = get_insns (); end_sequence (); --- 2401,2405 ---- start_sequence (); ! temp = force_operand (temp, NULL_RTX); seq = get_insns (); end_sequence (); *************** *** 2397,2400 **** --- 2528,2549 ---- } + /* Return the first NOTE_INSN_BLOCK_BEG note in the function. + Crash if there is none. */ + + rtx + get_first_block_beg () + { + register rtx searcher; + register rtx insn = get_first_nonparm_insn (); + + for (searcher = insn; searcher; searcher = NEXT_INSN (searcher)) + if (GET_CODE (searcher) == NOTE + && NOTE_LINE_NUMBER (searcher) == NOTE_INSN_BLOCK_BEG) + return searcher; + + abort (); /* Invalid call to this function. (See comments above.) */ + return NULL_RTX; + } + /* Return 1 if EXP returns an aggregate value, for which an address must be passed to the function or returned by the function. */ *************** *** 2404,2407 **** --- 2553,2558 ---- tree exp; { + int i, regno, nregs; + rtx reg; if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode) return 1; *************** *** 2412,2415 **** --- 2563,2574 ---- || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)) return 1; + /* Make sure we have suitable call-clobbered regs to return + the value in; if not, we must return it in memory. */ + reg = hard_function_value (TREE_TYPE (exp), 0); + regno = REGNO (reg); + nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (TREE_TYPE (exp))); + for (i = 0; i < nregs; i++) + if (! call_used_regs[regno + i]) + return 1; return 0; } *************** *** 2435,2439 **** register rtx stack_parm = 0; CUMULATIVE_ARGS args_so_far; ! enum machine_mode passed_mode, nominal_mode; /* Total space needed so far for args on the stack, given as a constant and a tree-expression. */ --- 2594,2599 ---- register rtx stack_parm = 0; CUMULATIVE_ARGS args_so_far; ! enum machine_mode promoted_mode, passed_mode, nominal_mode; ! int unsignedp; /* Total space needed so far for args on the stack, given as a constant and a tree-expression. */ *************** *** 2493,2497 **** tree type = build_pointer_type (fntype); ! function_result_decl = build_decl (PARM_DECL, 0, type); DECL_ARG_TYPE (function_result_decl) = type; --- 2653,2657 ---- tree type = build_pointer_type (fntype); ! function_result_decl = build_decl (PARM_DECL, NULL_TREE, type); DECL_ARG_TYPE (function_result_decl) = type; *************** *** 2504,2510 **** #ifdef INIT_CUMULATIVE_INCOMING_ARGS ! INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, 0); #else ! INIT_CUMULATIVE_ARGS (args_so_far, fntype, 0); #endif --- 2664,2670 ---- #ifdef INIT_CUMULATIVE_INCOMING_ARGS ! INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_PTR); #else ! INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_PTR); #endif *************** *** 2536,2540 **** || passed_type == NULL) { ! DECL_RTL (parm) = gen_rtx (MEM, BLKmode, const0_rtx); TREE_USED (parm) = 1; continue; --- 2696,2701 ---- || passed_type == NULL) { ! DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = gen_rtx (MEM, BLKmode, ! const0_rtx); TREE_USED (parm) = 1; continue; *************** *** 2551,2554 **** --- 2712,2723 ---- nominal_mode = TYPE_MODE (TREE_TYPE (parm)); + /* If the parm's mode is VOID, its value doesn't matter, + and avoid the usual things like emit_move_insn that could crash. */ + if (nominal_mode == VOIDmode) + { + DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = const0_rtx; + continue; + } + #ifdef FUNCTION_ARG_PASS_BY_REFERENCE /* See if this arg was passed by invisible reference. */ *************** *** 2562,2575 **** #endif /* Let machine desc say which reg (if any) the parm arrives in. 0 means it arrives on the stack. */ #ifdef FUNCTION_INCOMING_ARG ! entry_parm = FUNCTION_INCOMING_ARG (args_so_far, passed_mode, passed_type, ! last_named); #else ! entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, ! last_named); #endif #ifdef SETUP_INCOMING_VARARGS /* If this is the last named parameter, do any required setup for --- 2731,2764 ---- #endif + promoted_mode = passed_mode; + + #ifdef PROMOTE_FUNCTION_ARGS + /* Compute the mode in which the arg is actually extended to. */ + if (TREE_CODE (passed_type) == INTEGER_TYPE + || TREE_CODE (passed_type) == ENUMERAL_TYPE + || TREE_CODE (passed_type) == BOOLEAN_TYPE + || TREE_CODE (passed_type) == CHAR_TYPE + || TREE_CODE (passed_type) == REAL_TYPE + || TREE_CODE (passed_type) == POINTER_TYPE + || TREE_CODE (passed_type) == OFFSET_TYPE) + { + unsignedp = TREE_UNSIGNED (passed_type); + PROMOTE_MODE (promoted_mode, unsignedp, passed_type); + } + #endif + /* Let machine desc say which reg (if any) the parm arrives in. 0 means it arrives on the stack. */ #ifdef FUNCTION_INCOMING_ARG ! entry_parm = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode, passed_type, ! last_named); #else ! entry_parm = FUNCTION_ARG (args_so_far, promoted_mode, passed_type, ! last_named); #endif + if (entry_parm) + passed_mode = promoted_mode; + #ifdef SETUP_INCOMING_VARARGS /* If this is the last named parameter, do any required setup for *************** *** 2794,2799 **** if (stack_parm == 0) ! stack_parm ! = assign_stack_local (GET_MODE (entry_parm), size_stored, 0); else if (PARM_BOUNDARY % BITS_PER_WORD != 0) abort (); --- 2983,2994 ---- if (stack_parm == 0) ! { ! stack_parm ! = assign_stack_local (GET_MODE (entry_parm), size_stored, 0); ! /* If this is a memory ref that contains aggregate components, ! mark it as such for cse and loop optimize. */ ! MEM_IN_STRUCT_P (stack_parm) = aggregate; ! } ! else if (PARM_BOUNDARY % BITS_PER_WORD != 0) abort (); *************** *** 2805,2816 **** DECL_RTL (parm) = stack_parm; } ! else if (! ( ! #if 0 /* This change was turned off because it makes compilation bigger. */ ! !optimize ! #else /* It's not clear why the following was replaced. */ ! /* Obsoleted by preceding line. */ ! (obey_regdecls && ! TREE_REGDECL (parm) ! && ! TREE_INLINE (fndecl)) ! #endif /* layout_decl may set this. */ || TREE_ADDRESSABLE (parm) --- 3000,3005 ---- DECL_RTL (parm) = stack_parm; } ! else if (! ((obey_regdecls && ! DECL_REGISTER (parm) ! && ! DECL_INLINE (fndecl)) /* layout_decl may set this. */ || TREE_ADDRESSABLE (parm) *************** *** 2824,2830 **** || passed_pointer || parm == function_result_decl) { ! /* Store the parm in a pseudoregister during the function. */ ! register rtx parmreg = gen_reg_rtx (nominal_mode); REG_USERVAR_P (parmreg) = 1; --- 3013,3034 ---- || passed_pointer || parm == function_result_decl) { ! /* Store the parm in a pseudoregister during the function, but we ! may need to do it in a wider mode. */ ! ! register rtx parmreg; ! ! unsignedp = TREE_UNSIGNED (TREE_TYPE (parm)); ! if (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE ! || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE ! || TREE_CODE (TREE_TYPE (parm)) == BOOLEAN_TYPE ! || TREE_CODE (TREE_TYPE (parm)) == CHAR_TYPE ! || TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE ! || TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE ! || TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE) ! { ! PROMOTE_MODE (nominal_mode, unsignedp, TREE_TYPE (parm)); ! } + parmreg = gen_reg_rtx (nominal_mode); REG_USERVAR_P (parmreg) = 1; *************** *** 2852,2862 **** && ! HARD_REGNO_MODE_OK (REGNO (entry_parm), GET_MODE (entry_parm))) ! convert_move (parmreg, copy_to_reg (entry_parm)); else ! convert_move (parmreg, validize_mem (entry_parm), 0); } else emit_move_insn (parmreg, validize_mem (entry_parm)); /* In any case, record the parm's desired stack location in case we later discover it must live in the stack. */ --- 3056,3086 ---- && ! HARD_REGNO_MODE_OK (REGNO (entry_parm), GET_MODE (entry_parm))) ! convert_move (parmreg, copy_to_reg (entry_parm), unsignedp); else ! convert_move (parmreg, validize_mem (entry_parm), unsignedp); } else emit_move_insn (parmreg, validize_mem (entry_parm)); + /* If we were passed a pointer but the actual value + can safely live in a register, put it in one. */ + if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode + && ! ((obey_regdecls && ! DECL_REGISTER (parm) + && ! DECL_INLINE (fndecl)) + /* layout_decl may set this. */ + || TREE_ADDRESSABLE (parm) + || TREE_SIDE_EFFECTS (parm) + /* If -ffloat-store specified, don't put explicit + float variables into registers. */ + || (flag_float_store + && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))) + { + /* We can't use nominal_mode, because it will have been set to + Pmode above. We must use the actual mode of the parm. */ + parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm))); + emit_move_insn (parmreg, DECL_RTL (parm)); + DECL_RTL (parm) = parmreg; + } + /* In any case, record the parm's desired stack location in case we later discover it must live in the stack. */ *************** *** 2904,2908 **** entry_parm = copy_to_reg (entry_parm); ! entry_parm = convert_to_mode (nominal_mode, entry_parm, 0); } --- 3128,3133 ---- entry_parm = copy_to_reg (entry_parm); ! entry_parm = convert_to_mode (nominal_mode, entry_parm, ! TREE_UNSIGNED (TREE_TYPE (parm))); } *************** *** 2910,2915 **** { if (stack_parm == 0) ! stack_parm = assign_stack_local (GET_MODE (entry_parm), ! GET_MODE_SIZE (GET_MODE (entry_parm)), 0); emit_move_insn (validize_mem (stack_parm), validize_mem (entry_parm)); --- 3135,3147 ---- { if (stack_parm == 0) ! { ! stack_parm ! = assign_stack_local (GET_MODE (entry_parm), ! GET_MODE_SIZE (GET_MODE (entry_parm)), 0); ! /* If this is a memory ref that contains aggregate components, ! mark it as such for cse and loop optimize. */ ! MEM_IN_STRUCT_P (stack_parm) = aggregate; ! } ! emit_move_insn (validize_mem (stack_parm), validize_mem (entry_parm)); *************** *** 2956,2964 **** #ifdef ARGS_GROW_DOWNWARD current_function_arg_offset_rtx ! = (stack_args_size.var == 0 ? gen_rtx (CONST_INT, VOIDmode, ! -stack_args_size.constant) : expand_expr (size_binop (MINUS_EXPR, stack_args_size.var, size_int (-stack_args_size.constant)), ! 0, VOIDmode, 0)); #else current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size); --- 3188,3195 ---- #ifdef ARGS_GROW_DOWNWARD current_function_arg_offset_rtx ! = (stack_args_size.var == 0 ? GEN_INT (-stack_args_size.constant) : expand_expr (size_binop (MINUS_EXPR, stack_args_size.var, size_int (-stack_args_size.constant)), ! NULL_RTX, VOIDmode, 0)); #else current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size); *************** *** 3079,3083 **** sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT); SUB_PARM_SIZE (*offset_ptr, sizetree); ! pad_to_arg_alignment (offset_ptr, boundary); if (initial_offset_ptr->var) { --- 3310,3315 ---- sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT); SUB_PARM_SIZE (*offset_ptr, sizetree); ! if (where_pad != downward) ! pad_to_arg_alignment (offset_ptr, boundary); if (initial_offset_ptr->var) { *************** *** 3266,3270 **** || #endif ! ! TREE_REGDECL (decl))) put_var_into_stack (decl); for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub)) --- 3498,3502 ---- || #endif ! ! DECL_REGISTER (decl))) put_var_into_stack (decl); for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub)) *************** *** 3291,3295 **** || #endif ! ! TREE_REGDECL (decl))) put_var_into_stack (decl); } --- 3523,3527 ---- || #endif ! ! DECL_REGISTER (decl))) put_var_into_stack (decl); } *************** *** 3500,3507 **** rtx temp = gen_reg_rtx (Pmode); temp = expand_binop (Pmode, add_optab, tramp, ! gen_rtx (CONST_INT, VOIDmode, TRAMPOLINE_ALIGNMENT - 1), temp, 0, OPTAB_LIB_WIDEN); tramp = expand_binop (Pmode, and_optab, temp, ! gen_rtx (CONST_INT, VOIDmode, - TRAMPOLINE_ALIGNMENT), temp, 0, OPTAB_LIB_WIDEN); #endif --- 3732,3739 ---- rtx temp = gen_reg_rtx (Pmode); temp = expand_binop (Pmode, add_optab, tramp, ! GEN_INT (TRAMPOLINE_ALIGNMENT - 1), temp, 0, OPTAB_LIB_WIDEN); tramp = expand_binop (Pmode, and_optab, temp, ! GEN_INT (- TRAMPOLINE_ALIGNMENT), temp, 0, OPTAB_LIB_WIDEN); #endif *************** *** 3509,3512 **** --- 3741,3890 ---- } + /* The functions identify_blocks and reorder_blocks provide a way to + reorder the tree of BLOCK nodes, for optimizers that reshuffle or + duplicate portions of the RTL code. Call identify_blocks before + changing the RTL, and call reorder_blocks after. */ + + static int all_blocks (); + static tree blocks_nreverse (); + + /* Put all this function's BLOCK nodes into a vector, and return it. + Also store in each NOTE for the beginning or end of a block + the index of that block in the vector. + The arguments are TOP_BLOCK, the top-level block of the function, + and INSNS, the insn chain of the function. */ + + tree * + identify_blocks (top_block, insns) + tree top_block; + rtx insns; + { + int n_blocks; + tree *block_vector; + int *block_stack; + int depth = 0; + int next_block_number = 0; + int current_block_number = 0; + rtx insn; + + if (top_block == 0) + return 0; + + n_blocks = all_blocks (top_block, 0); + block_vector = (tree *) xmalloc (n_blocks * sizeof (tree)); + block_stack = (int *) alloca (n_blocks * sizeof (int)); + + all_blocks (top_block, block_vector); + + for (insn = insns; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE) + { + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) + { + block_stack[depth++] = current_block_number; + current_block_number = next_block_number; + NOTE_BLOCK_NUMBER (insn) = next_block_number++; + } + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) + { + current_block_number = block_stack[--depth]; + NOTE_BLOCK_NUMBER (insn) = current_block_number; + } + } + + return block_vector; + } + + /* Given BLOCK_VECTOR which was returned by identify_blocks, + and a revised instruction chain, rebuild the tree structure + of BLOCK nodes to correspond to the new order of RTL. + The new block tree is inserted below TOP_BLOCK. + Returns the current top-level block. */ + + tree + reorder_blocks (block_vector, top_block, insns) + tree *block_vector; + tree top_block; + rtx insns; + { + tree current_block = top_block; + rtx insn; + + if (block_vector == 0) + return top_block; + + /* Prune the old tree away, so that it doesn't get in the way. */ + BLOCK_SUBBLOCKS (current_block) = 0; + + for (insn = insns; insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE) + { + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) + { + tree block = block_vector[NOTE_BLOCK_NUMBER (insn)]; + /* If we have seen this block before, copy it. */ + if (TREE_ASM_WRITTEN (block)) + block = copy_node (block); + BLOCK_SUBBLOCKS (block) = 0; + TREE_ASM_WRITTEN (block) = 1; + BLOCK_SUPERCONTEXT (block) = current_block; + BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block); + BLOCK_SUBBLOCKS (current_block) = block; + current_block = block; + NOTE_SOURCE_FILE (insn) = 0; + } + if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) + { + BLOCK_SUBBLOCKS (current_block) + = blocks_nreverse (BLOCK_SUBBLOCKS (current_block)); + current_block = BLOCK_SUPERCONTEXT (current_block); + NOTE_SOURCE_FILE (insn) = 0; + } + } + + return current_block; + } + + /* Reverse the order of elements in the chain T of blocks, + and return the new head of the chain (old last element). */ + + static tree + blocks_nreverse (t) + tree t; + { + register tree prev = 0, decl, next; + for (decl = t; decl; decl = next) + { + next = BLOCK_CHAIN (decl); + BLOCK_CHAIN (decl) = prev; + prev = decl; + } + return prev; + } + + /* Count the subblocks of BLOCK, and list them all into the vector VECTOR. + Also clear TREE_ASM_WRITTEN in all blocks. */ + + static int + all_blocks (block, vector) + tree block; + tree *vector; + { + int n_blocks = 1; + tree subblocks; + + TREE_ASM_WRITTEN (block) = 0; + /* Record this block. */ + if (vector) + vector[0] = block; + + /* Record the subblocks, and their subblocks. */ + for (subblocks = BLOCK_SUBBLOCKS (block); + subblocks; subblocks = BLOCK_CHAIN (subblocks)) + n_blocks += all_blocks (subblocks, vector ? vector + n_blocks : 0); + + return n_blocks; + } + /* Generate RTL for the start of the function SUBR (a FUNCTION_DECL tree node) and initialize static variables for generating RTL for the statements *************** *** 3618,3622 **** This makes sure the first insn will never be deleted. Also, final expects a note to appear there. */ ! emit_note (0, NOTE_INSN_DELETED); /* Set flags used by final.c. */ --- 3996,4000 ---- This makes sure the first insn will never be deleted. Also, final expects a note to appear there. */ ! emit_note (NULL_PTR, NOTE_INSN_DELETED); /* Set flags used by final.c. */ *************** *** 3698,3703 **** Do this first, so it gets the first stack slot offset. */ if (current_function_needs_context) ! emit_move_insn (assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0), ! static_chain_incoming_rtx); /* If the parameters of this function need cleaning up, get a label --- 4076,4083 ---- Do this first, so it gets the first stack slot offset. */ if (current_function_needs_context) ! { ! last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); ! emit_move_insn (last_ptr, static_chain_incoming_rtx); ! } /* If the parameters of this function need cleaning up, get a label *************** *** 3760,3769 **** DECL_RTL (DECL_RESULT (subr)) = 0; else if (parms_have_cleanups) ! /* If function will end with cleanup code for parms, ! compute the return values into a pseudo reg, ! which we will copy into the true return register ! after the cleanups are done. */ ! DECL_RTL (DECL_RESULT (subr)) ! = gen_reg_rtx (DECL_MODE (DECL_RESULT (subr))); else /* Scalar, returned in a register. */ --- 4140,4165 ---- DECL_RTL (DECL_RESULT (subr)) = 0; else if (parms_have_cleanups) ! { ! /* If function will end with cleanup code for parms, ! compute the return values into a pseudo reg, ! which we will copy into the true return register ! after the cleanups are done. */ ! ! enum machine_mode mode = DECL_MODE (DECL_RESULT (subr)); ! #ifdef PROMOTE_FUNCTION_RETURN ! tree type = TREE_TYPE (DECL_RESULT (subr)); ! int unsignedp = TREE_UNSIGNED (type); ! ! if (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE ! || TREE_CODE (type) == BOOLEAN_TYPE || TREE_CODE (type) == CHAR_TYPE ! || TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == POINTER_TYPE ! || TREE_CODE (type) == OFFSET_TYPE) ! { ! PROMOTE_MODE (mode, unsignedp, type); ! } ! #endif ! ! DECL_RTL (DECL_RESULT (subr)) = gen_reg_rtx (mode); ! } else /* Scalar, returned in a register. */ *************** *** 3783,3787 **** /* Needed because we may need to move this to memory in case it's a named return value whose address is taken. */ ! TREE_REGDECL (DECL_RESULT (subr)) = 1; } } --- 4179,4183 ---- /* Needed because we may need to move this to memory in case it's a named return value whose address is taken. */ ! DECL_REGISTER (DECL_RESULT (subr)) = 1; } } *************** *** 3796,3805 **** /* Indicate the beginning of the function body, as opposed to parm setup. */ ! emit_note (0, NOTE_INSN_FUNCTION_BEG); /* If doing stupid allocation, mark parms as born here. */ if (GET_CODE (get_last_insn ()) != NOTE) ! emit_note (0, NOTE_INSN_DELETED); parm_birth_insn = get_last_insn (); --- 4192,4201 ---- /* Indicate the beginning of the function body, as opposed to parm setup. */ ! emit_note (NULL_PTR, NOTE_INSN_FUNCTION_BEG); /* If doing stupid allocation, mark parms as born here. */ if (GET_CODE (get_last_insn ()) != NOTE) ! emit_note (NULL_PTR, NOTE_INSN_DELETED); parm_birth_insn = get_last_insn (); *************** *** 3815,3819 **** /* Fetch static chain values for containing functions. */ tem = decl_function_context (current_function_decl); ! if (tem) last_ptr = copy_to_reg (static_chain_incoming_rtx); context_display = 0; --- 4211,4218 ---- /* Fetch static chain values for containing functions. */ tem = decl_function_context (current_function_decl); ! /* If not doing stupid register allocation, then start off with the static ! chain pointer in a pseudo register. Otherwise, we use the stack ! address that was generated above. */ ! if (tem && ! obey_regdecls) last_ptr = copy_to_reg (static_chain_incoming_rtx); context_display = 0; *************** *** 3839,3847 **** should go, if we end up needing one. Ensure we have a NOTE here since some things (like trampolines) get placed before this. */ ! tail_recursion_reentry = emit_note (0, NOTE_INSN_DELETED); /* Evaluate now the sizes of any types declared among the arguments. */ for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem)) ! expand_expr (TREE_VALUE (tem), 0, VOIDmode, 0); /* Make sure there is a line number after the function entry setup code. */ --- 4238,4246 ---- should go, if we end up needing one. Ensure we have a NOTE here since some things (like trampolines) get placed before this. */ ! tail_recursion_reentry = emit_note (NULL_PTR, NOTE_INSN_DELETED); /* Evaluate now the sizes of any types declared among the arguments. */ for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem)) ! expand_expr (TREE_VALUE (tem), NULL_RTX, VOIDmode, 0); /* Make sure there is a line number after the function entry setup code. */ *************** *** 3903,3908 **** tramp = change_address (initial_trampoline, BLKmode, round_trampoline_addr (XEXP (tramp, 0))); ! emit_block_move (tramp, initial_trampoline, ! gen_rtx (CONST_INT, VOIDmode, TRAMPOLINE_SIZE), FUNCTION_BOUNDARY / BITS_PER_UNIT); INITIALIZE_TRAMPOLINE (XEXP (tramp, 0), --- 4302,4306 ---- tramp = change_address (initial_trampoline, BLKmode, round_trampoline_addr (XEXP (tramp, 0))); ! emit_block_move (tramp, initial_trampoline, GEN_INT (TRAMPOLINE_SIZE), FUNCTION_BOUNDARY / BITS_PER_UNIT); INITIALIZE_TRAMPOLINE (XEXP (tramp, 0), *************** *** 3936,3940 **** /* End any sequences that failed to be closed due to syntax errors. */ while (in_sequence_p ()) ! end_sequence (0); /* Outside function body, can't compute type's actual size --- 4334,4338 ---- /* End any sequences that failed to be closed due to syntax errors. */ while (in_sequence_p ()) ! end_sequence (); /* Outside function body, can't compute type's actual size *************** *** 3969,3973 **** If control reaches this insn, the function can drop through without returning a value. */ ! emit_note (0, NOTE_INSN_FUNCTION_END); /* Output a linenumber for the end of the function. --- 4367,4371 ---- If control reaches this insn, the function can drop through without returning a value. */ ! emit_note (NULL_PTR, NOTE_INSN_FUNCTION_END); /* Output a linenumber for the end of the function. *************** *** 3995,3999 **** emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn); ! emit_stack_restore (SAVE_FUNCTION, tem, 0); } --- 4393,4397 ---- emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn); ! emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX); } *************** *** 4070,4073 **** and they need to create temporary variables, then you will lose. */ ! fixup_gotos (0, 0, 0, get_insns (), 0); } --- 4468,4695 ---- and they need to create temporary variables, then you will lose. */ ! fixup_gotos (NULL_PTR, NULL_RTX, NULL_TREE, get_insns (), 0); ! } ! ! /* These arrays record the INSN_UIDs of the prologue and epilogue insns. */ ! ! static int *prologue; ! static int *epilogue; ! ! /* Create an array that records the INSN_UIDs of INSNS (either a sequence ! or a single insn). */ ! ! static int * ! record_insns (insns) ! rtx insns; ! { ! int *vec; ! ! if (GET_CODE (insns) == SEQUENCE) ! { ! int len = XVECLEN (insns, 0); ! vec = (int *) oballoc ((len + 1) * sizeof (int)); ! vec[len] = 0; ! while (--len >= 0) ! vec[len] = INSN_UID (XVECEXP (insns, 0, len)); ! } ! else ! { ! vec = (int *) oballoc (2 * sizeof (int)); ! vec[0] = INSN_UID (insns); ! vec[1] = 0; ! } ! return vec; ! } ! ! /* Determine how many INSN_UIDs in VEC are part of INSN. */ ! ! static int ! contains (insn, vec) ! rtx insn; ! int *vec; ! { ! register int i, j; ! ! if (GET_CODE (insn) == INSN ! && GET_CODE (PATTERN (insn)) == SEQUENCE) ! { ! int count = 0; ! for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) ! for (j = 0; vec[j]; j++) ! if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == vec[j]) ! count++; ! return count; ! } ! else ! { ! for (j = 0; vec[j]; j++) ! if (INSN_UID (insn) == vec[j]) ! return 1; ! } ! return 0; ! } ! ! /* Generate the prologe and epilogue RTL if the machine supports it. Thread ! this into place with notes indicating where the prologue ends and where ! the epilogue begins. Update the basic block information when possible. */ ! ! void ! thread_prologue_and_epilogue_insns (f) ! rtx f; ! { ! #ifdef HAVE_prologue ! if (HAVE_prologue) ! { ! rtx head, seq, insn; ! ! /* The first insn (a NOTE_INSN_DELETED) is followed by zero or more ! prologue insns and a NOTE_INSN_PROLOGUE_END. */ ! emit_note_after (NOTE_INSN_PROLOGUE_END, f); ! seq = gen_prologue (); ! head = emit_insn_after (seq, f); ! ! /* Include the new prologue insns in the first block. Ignore them ! if they form a basic block unto themselves. */ ! if (basic_block_head && n_basic_blocks ! && GET_CODE (basic_block_head[0]) != CODE_LABEL) ! basic_block_head[0] = NEXT_INSN (f); ! ! /* Retain a map of the prologue insns. */ ! prologue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : head); ! } ! else ! #endif ! prologue = 0; ! ! #ifdef HAVE_epilogue ! if (HAVE_epilogue) ! { ! rtx insn = get_last_insn (); ! rtx prev = prev_nonnote_insn (insn); ! ! /* If we end with a BARRIER, we don't need an epilogue. */ ! if (! (prev && GET_CODE (prev) == BARRIER)) ! { ! rtx tail, seq; ! ! /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, ! the epilogue insns (this must include the jump insn that ! returns), USE insns ad the end of a function, and a BARRIER. */ ! ! emit_barrier_after (insn); ! ! /* Place the epilogue before the USE insns at the end of a ! function. */ ! while (prev ! && GET_CODE (prev) == INSN ! && GET_CODE (PATTERN (prev)) == USE) ! { ! insn = PREV_INSN (prev); ! prev = prev_nonnote_insn (prev); ! } ! ! seq = gen_epilogue (); ! tail = emit_jump_insn_after (seq, insn); ! emit_note_after (NOTE_INSN_EPILOGUE_BEG, insn); ! ! /* Include the new epilogue insns in the last block. Ignore ! them if they form a basic block unto themselves. */ ! if (basic_block_end && n_basic_blocks ! && GET_CODE (basic_block_end[n_basic_blocks - 1]) != JUMP_INSN) ! basic_block_end[n_basic_blocks - 1] = tail; ! ! /* Retain a map of the epilogue insns. */ ! epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail); ! return; ! } ! } ! #endif ! epilogue = 0; ! } ! ! /* Reposition the prologue-end and epilogue-begin notes after instruction ! scheduling and delayed branch scheduling. */ ! ! void ! reposition_prologue_and_epilogue_notes (f) ! rtx f; ! { ! #if defined (HAVE_prologue) || defined (HAVE_epilogue) ! /* Reposition the prologue and epilogue notes. */ ! if (n_basic_blocks) ! { ! rtx next, prev; ! int len; ! ! if (prologue) ! { ! register rtx insn, note = 0; ! ! /* Scan from the beginning until we reach the last prologue insn. ! We apparently can't depend on basic_block_{head,end} after ! reorg has run. */ ! for (len = 0; prologue[len]; len++) ! ; ! for (insn = f; insn; insn = NEXT_INSN (insn)) ! if (GET_CODE (insn) == NOTE) ! { ! if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) ! note = insn; ! } ! else if ((len -= contains (insn, prologue)) == 0) ! { ! /* Find the prologue-end note if we haven't already, and ! move it to just after the last prologue insn. */ ! if (note == 0) ! for (note = insn; note = NEXT_INSN (note);) ! if (GET_CODE (note) == NOTE ! && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END) ! break; ! next = NEXT_INSN (note); ! prev = PREV_INSN (note); ! if (prev) ! NEXT_INSN (prev) = next; ! if (next) ! PREV_INSN (next) = prev; ! add_insn_after (note, insn); ! break; ! } ! } ! ! if (epilogue) ! { ! register rtx insn, note = 0; ! ! /* Scan from the end until we reach the first epilogue insn. ! We apparently can't depend on basic_block_{head,end} after ! reorg has run. */ ! for (len = 0; epilogue[len]; len++) ! ; ! for (insn = get_last_insn (); insn; insn = PREV_INSN (insn)) ! if (GET_CODE (insn) == NOTE) ! { ! if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) ! note = insn; ! } ! else if ((len -= contains (insn, epilogue)) == 0) ! { ! /* Find the epilogue-begin note if we haven't already, and ! move it to just before the first epilogue insn. */ ! if (note == 0) ! for (note = insn; note = PREV_INSN (note);) ! if (GET_CODE (note) == NOTE ! && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG) ! break; ! next = NEXT_INSN (note); ! prev = PREV_INSN (note); ! if (prev) ! NEXT_INSN (prev) = next; ! if (next) ! PREV_INSN (next) = prev; ! add_insn_after (note, PREV_INSN (insn)); ! break; ! } ! } ! } ! #endif /* HAVE_prologue or HAVE_epilogue */ } diff -rc2N gcc-2.2.2/function.h gcc-2.3.1/function.h *** gcc-2.2.2/function.h Thu Mar 5 15:20:59 1992 --- gcc-2.3.1/function.h Sat Oct 10 05:36:29 1992 *************** *** 1,4 **** /* Structure for saving state for a nested function. ! Copyright (C) 1989 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Structure for saving state for a nested function. ! Copyright (C) 1989, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 29,33 **** { rtx modified; ! rtx original; struct var_refs_queue *next; }; --- 29,34 ---- { rtx modified; ! enum machine_mode promoted_mode; ! int unsignedp; struct var_refs_queue *next; }; *************** *** 158,161 **** --- 159,171 ---- /* For md files. */ int uses_pic_offset_table; + + /* For reorg. */ + rtx epilogue_delay_list; + + /* For varasm. */ + struct constant_descriptor **const_rtx_hash_table; + struct pool_sym **const_rtx_sym_hash_table; + struct pool_constant *first_pool, *last_pool; + int pool_offset; }; *************** *** 172,175 **** --- 182,197 ---- extern rtx stack_slot_list; + /* Given a function decl for a containing function, + return the `struct function' for it. */ + struct function *find_function_data (); + + /* Pointer to chain of `struct function' for containing functions. */ + extern struct function *outer_function_chain; + + /* Put all this function's BLOCK nodes into a vector and return it. + Also store in each NOTE for the beginning or end of a block + the index of that block in the vector. */ + tree *identify_blocks (); + #ifdef rtx #undef rtx *************** *** 179,188 **** #undef tree #endif - - - /* Given a function decl for a containing function, - return the `struct function' for it. */ - struct function *find_function_data (); - - /* Pointer to chain of `struct function' for containing functions. */ - extern struct function *outer_function_chain; --- 201,202 ---- diff -rc2N gcc-2.2.2/g++ gcc-2.3.1/g++ *** gcc-2.2.2/g++ Tue May 26 14:56:14 1992 --- gcc-2.3.1/g++ Mon Oct 5 18:09:12 1992 *************** *** 3,76 **** : || exec /bin/sh -f $0 $argv:q ! newargs= ! quote=no library=-lg++ ! havefiles= ! for arg in $*; ! do ! if [ $quote = yes ] then ! newargs="$newargs $arg" ! quote=no else ! quote=no case $arg in -nostdlib) # Inhibit linking with -lg++. - newargs="$newargs $arg" library= ;; -[bBVDUoeTuIYmLiA] | -Tdata) - newargs="$newargs $arg" # these switches take following word as argument, # so don't treat it as a file name. ! quote=yes ;; -[cSEM] | -MM) # Don't specify libraries if we won't link, # since that would cause a warning. - newargs="$newargs $arg" library= ;; - -xnone) - newargs="$newargs $arg" - speclang= - ;; -x*) ! newargs="$newargs $arg" ! speclang=yes ;; -*) # Pass other options through; they don't need -x and aren't inputs. - newargs="$newargs $arg" ;; *) - havefiles=yes # If file ends in .c or .i, put options around it. # But not if a specified -x option is currently active. ! temp=`expr $arg : '.*\.[ci]$'` ! if [ \( x$temp != x0 \) -a \( x$speclang = x \) ] ! then ! newargs="$newargs -xc++ $arg -xnone" ! else ! newargs="$newargs $arg" ! fi ;; esac fi done ! if [ x$havefiles = x ] then ! echo "$0: no input files specified" exit 1 fi ! progname=`echo $0 |sed -e 's|/[^/]*$|/gcc|'` ! if [ -f ${progname} ] ! then ! exec ${progname} $newargs $library ! else ! exec gcc $newargs $library ! fi --- 3,100 ---- : || exec /bin/sh -f $0 $argv:q ! # The compiler name might be different when doing cross-compilation ! # (this should be configured) ! gcc_name=gcc ! speclang=-xnone ! ! # replace the command name by the name of the new command ! progname=`basename $0` ! case "$0" in ! */*) ! gcc=`echo $0 | sed -e "s;/[^/]*$;;"`/$gcc_name ! ;; ! *) ! gcc=$gcc_name ! ;; ! esac ! ! # $first is yes for first arg, no afterwards. ! first=yes ! # If next arg is the argument of an option, $quote is non-empty. ! # More precisely, it is the option that wants an argument. ! quote= ! # $library is made empty to disable use of libg++. library=-lg++ ! numargs=$# ! for arg do ! if [ $first = yes ] ! then ! # Need some 1st arg to `set' which does not begin with `-'. ! # We get rid of it after the loop ends. ! set gcc ! first=no ! fi ! # If you have to ask what this does, you should not edit this file. :-) ! # The ``S'' at the start is so that echo -nostdinc does not eat the ! # -nostdinc. ! arg=`echo "S$arg" | sed "s/^S//; s/'/'\\\\\\\\''/g"` ! if [ x$quote != x ] then ! quote= else ! quote= case $arg in -nostdlib) # Inhibit linking with -lg++. library= ;; + -lm) + # Because libg++ uses things from the math library, make sure it + # always comes before the math library. + set "$@" $library + library="" + ;; -[bBVDUoeTuIYmLiA] | -Tdata) # these switches take following word as argument, # so don't treat it as a file name. ! quote=$arg ;; -[cSEM] | -MM) # Don't specify libraries if we won't link, # since that would cause a warning. library= ;; -x*) ! speclang=$arg ! ;; ! -v) ! # catch `g++ -v' ! if [ $numargs = 1 ] ; then library="" ; fi ;; -*) # Pass other options through; they don't need -x and aren't inputs. ;; *) # If file ends in .c or .i, put options around it. # But not if a specified -x option is currently active. ! case "$speclang $arg" in -xnone\ *.[ci]) ! set "$@" -xc++ "'$arg'" -xnone ! continue ! esac ;; esac fi + set "$@" "'$arg'" done ! # Get rid of that initial 1st arg ! shift ! ! if [ x$quote != x ] then ! echo "$0: argument to \`$quote' missing" exit 1 fi ! eval $gcc "$@" $library diff -rc2N gcc-2.2.2/g++.1 gcc-2.3.1/g++.1 *** gcc-2.2.2/g++.1 Fri Feb 28 13:38:30 1992 --- gcc-2.3.1/g++.1 Tue Jun 30 16:48:56 1992 *************** *** 14,18 **** .IR option " | " filename " ].\|.\|. .SH DESCRIPTION ! The C and C++ compilers are integrated. Both process input files through one or more of four stages: preprocessing, compilation, assembly, and linking. This man page contains full descriptions for --- 14,23 ---- .IR option " | " filename " ].\|.\|. .SH DESCRIPTION ! The C and C++ compilers are integrated; ! .B g++ ! is a script to call ! .B gcc with options to recognize C++. ! .B gcc ! processes input files through one or more of four stages: preprocessing, compilation, assembly, and linking. This man page contains full descriptions for *************** *** 29,32 **** --- 34,39 ---- \&\|', or `\|\c .B .cxx\c + \&\|'; preprocessed C++ files use the suffix `\|\c + .B .ii\c \&\|'. .SH OPTIONS *************** *** 406,412 **** .B \-static On systems that support dynamic linking, this prevents linking with the shared ! libraries. (`\|\c ! .B \-g\c ! \&\|' also has this effect.) On other systems, this option has no effect. .TP .B \-traditional --- 413,417 ---- .B \-static On systems that support dynamic linking, this prevents linking with the shared ! libraries. On other systems, this option has no effect. .TP .B \-traditional *************** *** 661,665 **** .SH BUGS Report bugs to ! .BR bug\-gcc@prep.ai.mit.edu . Bugs tend actually to be fixed if they can be isolated, so it is in your interest to report them in such a way that they can be easily reproduced. --- 666,670 ---- .SH BUGS Report bugs to ! .BR bug\-g++@prep.ai.mit.edu . Bugs tend actually to be fixed if they can be isolated, so it is in your interest to report them in such a way that they can be easily reproduced. diff -rc2N gcc-2.2.2/g++int.texi gcc-2.3.1/g++int.texi *** gcc-2.2.2/g++int.texi --- gcc-2.3.1/g++int.texi Tue Aug 4 17:38:33 1992 *************** *** 0 **** --- 1,240 ---- + @node internals + @chapter Internal Architecture of the Compiler + + This is meant to describe the C++ frontend for gcc in detail. + Questions and comments to mrs@cygnus.com. + + @index delete, two argument + For two argument delete, the second argument is always calculated by + ``virtual_size ='' in the source. It currently has a problem, in that + object size is not calculated by the virtual destructor and passed back + for the second parameter to delete. Destructors need to return a value + just like constructors. + + @index visibility checking + Visibility checking in general is unimplemented, there are a few cases + where it is implemented. grok_enum_decls should be used in more places + to do visibility checking, but this is only the tip of a bigger problem. + + @index volatile + volatile is not implemented in general. + + @index const + const is completely implemented except for function overload selection. + + @index protected base classes + Protected base classes are not fully implemented. + + @item BLOCK_SUPERCONTEXT + In the outermost scope of each function, it points to the FUNCTION_DECL + node. It aids in better DWARF support of inline functions. + + @item DECL_CLASS_CONTEXT + Identifys the context that the _DECL was found in. + + Has values of: + + RECORD_TYPE, or UNION_TYPE. + + What things can this be used on: + + TYPE_DECLs, *_DECLs + + @item DECL_NESTED_TYPENAME + Holds the fully qualified type name. Example, Base::Derived. + + Has values of: + + IDENTIFIER_NODE + + What things can this be used on: + + TYPE_DECLs + + @item TYPE_NAME + Names the type. + + Has values of: + + 0 for things that don't have names. + should be IDENTIFIER_NODE for RECORD_TYPEs UNION_TYPEs and ENUM_TYPEs. + TYPE_DECL for RECORD_TYPEs, UNION_TYPEs and ENUM_TYPEs, but shouldn't + be. + TYPE_DECL for typedefs, unsure why. + + What things can one use this on: + + TYPE_DECLs + RECORD_TYPEs + UNION_TYPEs + ENUM_TYPEs + + How is it used: + + Used by dwarfout.c to fetch the name of structs, unoins and enums + to create AT_name fields. + + History: + + It currently points to the TYPE_DECL for RECORD_TYPEs, + UNION_TYPEs and ENUM_TYPEs, but it should be history soon. + + @item DECL_NAME + + Has values of: + + 0 for things that don't have names. + IDENTIFIER_NODE for TYPE_DECLs. + + @item TYPE_DECL + Used to represent typedefs, and used to represent bindings layers. + + Components: + + DECL_NAME is the name of the typedef. For example, foo would + be found in the DECL_NAME slot when @code{typedef int foo;} is + seen. + + DECL_SOURCE_LINE identifies what source line number in the + source file the declaration was found at. A value of 0 + indicates that this TYPE_DECL is just an internal binding layer + marker, and does not correspond to a user suppiled typedef. + + DECL_SOURCE_FILE @xref{DECL_SOURCE_FILE}. + + @item DECL_IGNORED_P + A bit that can be set to inform the debug information output routines in + the backend that a certain _DECL node should be totally ignored. + + Used in cases where it is known that the debugging information will be + output in another file, or where a sub-type is known not to be needed + because the enclosing type is not needed. + + A compiler constructed virtual destructor in derived classes that do not + define an exlicit destructor that was defined exlicit in a base class + has this bit set as well. Also used on __FUNCTION__ and + __PRETTY_FUNCTION__ to mark they are ``compiler generated.'' c-decl and + c-lex.c both want DECL_IGNORED_P set for ``internally generated vars,'' + and ``user-invisible variable.'' + + Functions built by the C++ front-end such as default destructors, + virtual desctructors and default constructors want to be marked that + they are compiler generated, but unsure why. + + Currently, it is used in an absolute way in the C++ front-end, as an + optimization, to tell the debug information output routines to not + generate debugging information that will be output by another separately + compiled file. + + @findex DECL_SOURCE_FILE + @item DECL_SOURCE_FILE + Identifies what source file a particular declaration was found in. + + Has values of: + + "" on TYPE_DECLs to mean the typedef is built in. + + @item DECL_SOURCE_LINE + Identifies what source line number in the source file the declaration + was found at. + + Has values of: + + 0 for an undefined label. + + 0 for TYPE_DECLs that are internally generated. + + 0 for FUNCTION_DECLs for functions generated by the compiler. + (not yet, but should be.) + + @item DECL_VIRTUAL_P + A flag used on FIELD_DECLs and VAR_DECLs. (Documentation in tree.h is + wrong.) Used in VAR_DECLs to indicate that the variable is a vtable. + It is also used in FIELD_DECLs for vtable pointers. + + What things can this be used on: + + FIELD_DECLs and VAR_DECLs. + + @item DECL_VINDEX + Used for FUNCTION_DECLs in two different ways. Before the structure + containing the FUNCTION_DECL is laid out, DECL_VINDEX may point to a + FUNCTION_DECL in a base class which is the FUNCTION_DECL which this + FUNCTION_DECL will replace as a virtual function. When the class is + laid out, this pointer is changed to an INTEGER_CST node which is + suitable for use as an index into the virtual function table. + + DECL_VINDEX may be a TREE_LIST, that would seem to be a list of + overridden FUNCTION_DECLs. add_virtual_function has code to deal with + this when it uses the variable base_fndecl_list, but it would seem that + somehow, it is possible for the TREE_LIST to pursist until method_call, + and it should not. + + @item TREE_USED + + Has values of: + + 0 for unused labels. + + @item TREE_ADDRESSABLE + A flag that is set for any type that has a constructor. + + @item CLASSTYPE_METHOD_VEC + The following is true after finish_struct has been called (on the + class?) but not before. Before finish_struct is called, things are + different to some extent. Contains a TREE_VEC of methods of the class. + The TREE_VEC_LENGTH is the number of differently named methods plus one + for the 0th entry. The 0th entry is always allocated, and reserved for + ctors and dtors. If there are none, TREE_VEC_ELT(N,0) == NULL_TREE. + Each entry of the TREE_VEC is a FUNCTION_DECL. For each FUNCTION_DECL, + there is a DECL_CHAIN slot. If the FUNCTION_DECL is the last one with a + given name, the DECL_CHAIN slot is NULL_TREE. Otherwise it is the next + method that has the same name (but a different signature). It would + seem that it is not true that because the DECL_CHAIN slot is used in + this way, we cannot call pushdecl to put the method in the global scope + (cause that would overwrite the TREE_CHAIN slot), because they use + different _CHAINs. + + friends are kept in TREE_LISTs, so that there's no need to use their + TREE_CHAIN slot for anything. + + Has values of: + + TREE_VEC + + @item TYPE_METHOD + Related to CLASSTYPE_METHOD_VEC. Chained together with TREE_CHAIN. + dbxout.c uses this to get at the methods of a class. + + @item CLASSTYPE_TAGS + CLASSTYPE_TAGS is a linked (via TREE_CHAIN) list of member classes of a + class. TREE_PURPOSE is the name, TREE_VALUE is the type (pushclass scans + these and calls pushtag on them.) + + finish_struct scans these to produce TYPE_DECLs to add to the + TYPE_FIELDS of the type. + + It is expected that name found in the TREE_PURPOSE slot is unique, + resolve_scope_to_name is one such place that depends upon this + uniqueness. + + @item TYPE_FIELDS + TYPE_FIELDS is a linked list (via TREE_CHAIN) of member types of a + class. The list can contain TYPE_DECLs, but there can also be other + things in the list apparently. See also CLASSTYPE_TAGS. + + @item TREE_PRIVATE + Set for FIELD_DECLs by finish_struct. But not uniformly set. + + The following routines do something with PRIVATE visibility: + build_method_call, alter_visibility, finish_struct_methods, + finish_struct, convert_to_aggr, CWriteLanguageDecl, CWriteLanguageType, + CWriteUseObject, compute_visibility, lookup_field, dfs_pushdecl, + GNU_xref_member, dbxout_type_fields, dbxout_type_method_1 + + @item TREE_PROTECTED + The following routines do something with PROTECTED visibility: + build_method_call, alter_visibility, finish_struct, convert_to_aggr, + CWriteLanguageDecl, CWriteLanguageType, CWriteUseObject, + compute_visibility, lookup_field, GNU_xref_member, dbxout_type_fields, + dbxout_type_method_1 diff -rc2N gcc-2.2.2/gbl-ctors.h gcc-2.3.1/gbl-ctors.h *** gcc-2.2.2/gbl-ctors.h Sat Mar 14 00:03:55 1992 --- gcc-2.3.1/gbl-ctors.h Sat Aug 1 22:43:11 1992 *************** *** 32,42 **** */ - #ifdef sun - extern void on_exit (void*, void*); - #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG)) - #else #ifdef HAVE_ATEXIT extern void atexit (void (*) (void)); #define ON_EXIT(FUNC,ARG) atexit ((FUNC)) #endif #endif --- 32,42 ---- */ #ifdef HAVE_ATEXIT extern void atexit (void (*) (void)); #define ON_EXIT(FUNC,ARG) atexit ((FUNC)) + #else + #ifdef sun + extern void on_exit (void*, void*); + #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG)) #endif #endif diff -rc2N gcc-2.2.2/gcc.1 gcc-2.3.1/gcc.1 *** gcc-2.2.2/gcc.1 Thu May 28 14:28:39 1992 --- gcc-2.3.1/gcc.1 Tue Sep 22 14:51:41 1992 *************** *** 2,6 **** .\" See section COPYING for conditions for redistribution .\" FIXME: no info here on predefines. Should there be? extra for C++... ! .TH GCC 1 "27dec1991" "GNU Tools" "GNU Tools" .de BP .sp --- 2,6 ---- .\" See section COPYING for conditions for redistribution .\" FIXME: no info here on predefines. Should there be? extra for C++... ! .TH GCC 1 "28may1992" "GNU Tools" "GNU Tools" .de BP .sp *************** *** 19,25 **** The information in this man page is an extract from the full documentation of the GNU C compiler, and is limited to the meaning of ! the options. ! For complete, current documentation, refer to the Info file `\|\c .B gcc\c \&\|' or the manual --- 19,26 ---- The information in this man page is an extract from the full documentation of the GNU C compiler, and is limited to the meaning of ! the options. This man page is not kept up to date except when ! volunteers want to maintain it. ! For complete and current documentation, refer to the Info file `\|\c .B gcc\c \&\|' or the manual *************** *** 65,70 **** .br .B .i\c ! \& preprocessed C or C++; compile, assemble .br .B .s\c \& Assembler source; assemble --- 66,74 ---- .br .B .i\c ! \& preprocessed C; compile, assemble .br + .B .ii\c + \& preprocessed C++; compile, assemble + .br .B .s\c \& Assembler source; assemble *************** *** 1164,1170 **** .B \-static On systems that support dynamic linking, this prevents linking with the shared ! libraries. (`\|\c ! .B \-g\c ! \&\|' also has this effect.) On other systems, this option has no effect. .PP --- 1168,1172 ---- .B \-static On systems that support dynamic linking, this prevents linking with the shared ! libraries. On other systems, this option has no effect. .PP diff -rc2N gcc-2.2.2/gcc.c gcc-2.3.1/gcc.c *** gcc-2.2.2/gcc.c Wed Jun 10 17:23:54 1992 --- gcc-2.3.1/gcc.c Sat Oct 31 19:25:02 1992 *************** *** 31,35 **** compilation is specified by a string called a "spec". */ - #include #include #include --- 31,34 ---- *************** *** 41,44 **** --- 40,44 ---- #include "obstack.h" #include "gvarargs.h" + #include #ifndef R_OK *************** *** 48,51 **** --- 48,69 ---- #endif + /* Define a generic NULL if one hasn't already been defined. */ + + #ifndef NULL + #define NULL 0 + #endif + + #ifndef GENERIC_PTR + #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) + #define GENERIC_PTR void * + #else + #define GENERIC_PTR char * + #endif + #endif + + #ifndef NULL_PTR + #define NULL_PTR ((GENERIC_PTR)0) + #endif + #ifdef USG #define vfork fork *************** *** 187,190 **** --- 205,210 ---- concatenation of constant strings on the end, as in `%g.s'. %g also has the same effect of %d. + %u like %g, but make the temporary file name unique. + %U returns the last file name generated with %u. %d marks the argument containing or following the %d as a temporary file name, so that that file will be deleted if CC exits *************** *** 216,219 **** --- 236,240 ---- %x{OPTION} Accumulate an option for %X. %X Output the accumulated linker options specified by compilations. + %Y Output the accumulated assembler options specified by compilations. %a process ASM_SPEC as a spec. This allows config.h to specify part of the spec for running as. *************** *** 336,342 **** /* This spec is used for telling cpp whether char is signed or not. */ #ifndef SIGNED_CHAR_SPEC ! #define SIGNED_CHAR_SPEC \ ! (DEFAULT_SIGNED_CHAR ? "%{funsigned-char:-D__CHAR_UNSIGNED__}" \ ! : "%{!fsigned-char:-D__CHAR_UNSIGNED__}") #endif --- 357,367 ---- /* This spec is used for telling cpp whether char is signed or not. */ #ifndef SIGNED_CHAR_SPEC ! /* Use #if rather than ?: ! because MIPS C compiler rejects like ?: in initializers. */ ! #if DEFAULT_SIGNED_CHAR ! #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" ! #else ! #define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}" ! #endif #endif *************** *** 368,372 **** #ifndef WORD_SWITCH_TAKES_ARG #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info")) #endif --- 393,398 ---- #ifndef WORD_SWITCH_TAKES_ARG #define WORD_SWITCH_TAKES_ARG(STR) \ ! (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ ! || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \ || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info")) #endif *************** *** 378,383 **** char *suffix; /* Use this compiler for input files whose names end in this suffix. */ ! char *spec; /* To use this compiler, pass this spec ! to do_spec. */ }; --- 404,410 ---- char *suffix; /* Use this compiler for input files whose names end in this suffix. */ ! ! char *spec[4]; /* To use this compiler, concatenate these ! specs and pass to do_spec. */ }; *************** *** 411,416 **** %{traditional-cpp:-traditional}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\ ! %{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \ %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \ --- 438,443 ---- %{traditional-cpp:-traditional}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", ! "%{!M:%{!MM:%{!E:cc1 %{!pipe:%g.i} %1 \ %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \ *************** *** 419,424 **** %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\ %{!pipe:%g.s} %A\n }}}}"}, {"-", --- 446,451 ---- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\ %{!pipe:%g.s} %A\n }}}}"}, {"-", *************** *** 443,448 **** %{traditional-cpp:-traditional}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\ ! %{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \ %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \ --- 470,475 ---- %{traditional-cpp:-traditional}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", ! "%{!M:%{!MM:%{!E:cc1obj %{!pipe:%g.i} %1 \ %{!Q:-quiet} -dumpbase %b.m %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} \ *************** *** 452,457 **** %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\ %{!pipe:%g.s} %A\n }}}}"}, {".h", "@c-header"}, --- 479,484 ---- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\ %{!pipe:%g.s} %A\n }}}}"}, {".h", "@c-header"}, *************** *** 479,492 **** %{traditional-cpp:-traditional} %{trigraphs}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\ ! %{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.i} %1 %2\ %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\ ! %{v:-version} %{pg:-p} %{p} %{f*}\ %{aux-info*}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\ %{!pipe:%g.s} %A\n }}}}"}, {".i", "@cpp-output"}, --- 506,519 ---- %{traditional-cpp:-traditional} %{trigraphs}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.i}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", ! "%{!M:%{!MM:%{!E:cc1plus %{!pipe:%g.i} %1 %2\ %{!Q:-quiet} -dumpbase %b.cc %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\ ! %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\ %{aux-info*}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\ %{!pipe:%g.s} %A\n }}}}"}, {".i", "@cpp-output"}, *************** *** 498,518 **** %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %{!pipe:%g.s} %A\n }"}, {".ii", "@c++-cpp-output"}, {"@c++-cpp-output", "cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\ ! %{v:-version} %{pg:-p} %{p} %{f*}\ %{aux-info*}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\ %{!pipe:%g.s} %A\n }"}, {".s", "@assembler"}, {"@assembler", ! "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o} %i %A\n }"}, {".S", "@assembler-with-cpp"}, {"@assembler-with-cpp", --- 525,545 ---- %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %{!pipe:%g.s} %A\n }"}, {".ii", "@c++-cpp-output"}, {"@c++-cpp-output", "cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi} %{traditional}\ ! %{v:-version} %{pg:-p} %{p} %{f*} %{+e*}\ %{aux-info*}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ ! %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\ %{!pipe:%g.s} %A\n }"}, {".s", "@assembler"}, {"@assembler", ! "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o} %i %A\n }"}, {".S", "@assembler-with-cpp"}, {"@assembler-with-cpp", *************** *** 524,530 **** %{traditional-cpp:-traditional}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n\ ! %{!M:%{!MM:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\ %{!pipe:%g.s} %A\n }}}}"}, /* Mark end of table */ --- 551,557 ---- %{traditional-cpp:-traditional}\ %{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C\ ! %i %{!M:%{!MM:%{!E:%{!pipe:%g.s}}}}%{E:%W{o*}}%{M:%W{o*}}%{MM:%W{o*}} |\n", ! "%{!M:%{!MM:%{!E:%{!S:as %{R} %{j} %{J} %{h} %{d2} %a %Y\ ! %{c:%W{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%u.o}\ %{!pipe:%g.s} %A\n }}}}"}, /* Mark end of table */ *************** *** 542,550 **** /* Have gcc do the search for libgcc.a. */ /* -u* was put back because both BSD and SysV seem to support it. */ static char *link_command_spec = "\ %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\ ! %{!A:%{!nostdlib:%S}} \ ! %{L*} %D %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}"; #else /* Use -L and have the linker do the search for -lgcc. */ --- 569,579 ---- /* Have gcc do the search for libgcc.a. */ /* -u* was put back because both BSD and SysV seem to support it. */ + /* %{static:} simply prevents an error message if the target machine + doesn't handle -static. */ static char *link_command_spec = "\ %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\ ! %{!A:%{!nostdlib:%S}} %{static:}\ ! %{L*} %o %{!nostdlib:libgcc.a%s %L libgcc.a%s %{!A:%E}}\n }}}}}"; #else /* Use -L and have the linker do the search for -lgcc. */ *************** *** 552,564 **** %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\ ! %{!A:%{!nostdlib:%S}} \ %{L*} %D %o %{!nostdlib:-lgcc %L -lgcc %{!A:%E}}\n }}}}}"; #endif /* A vector of options to give to the linker. ! These options are accumulated by %x and substituted into the linker command with %X. */ static int n_linker_options; static char **linker_options; /* Read compilation specs from a file named FILENAME, --- 581,599 ---- %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \ %{r} %{s} %{T*} %{t} %{u*} %{x} %{z}\ ! %{!A:%{!nostdlib:%S}} %{static:}\ %{L*} %D %o %{!nostdlib:-lgcc %L -lgcc %{!A:%E}}\n }}}}}"; #endif /* A vector of options to give to the linker. ! These options are accumulated by -Xlinker and -Wl, and substituted into the linker command with %X. */ static int n_linker_options; static char **linker_options; + + /* A vector of options to give to the assembler. + These options are accumulated by -Wa, + and substituted into the assembler command with %X. */ + static int n_assembler_options; + static char **assembler_options; /* Read compilation specs from a file named FILENAME, *************** *** 593,598 **** /* Read contents of file into BUFFER. */ ! buffer = xmalloc (statbuf.st_size + 1); ! read (desc, buffer, statbuf.st_size); buffer[statbuf.st_size] = 0; close (desc); --- 628,633 ---- /* Read contents of file into BUFFER. */ ! buffer = xmalloc ((unsigned) statbuf.st_size + 1); ! read (desc, buffer, (unsigned) statbuf.st_size); buffer[statbuf.st_size] = 0; close (desc); *************** *** 663,667 **** xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler))); compilers[n_compilers].suffix = suffix; ! compilers[n_compilers].spec = spec; n_compilers++; } --- 698,704 ---- xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler))); compilers[n_compilers].suffix = suffix; ! bzero (compilers[n_compilers].spec, ! sizeof compilers[n_compilers].spec); ! compilers[n_compilers].spec[0] = spec; n_compilers++; } *************** *** 795,798 **** --- 832,839 ---- static int execution_count; + /* Number of commands that exited with a signal. */ + + static int signal_count; + /* Name with which this program was invoked. */ *************** *** 806,809 **** --- 847,851 ---- struct prefix_list *next; /* Next in linked list. */ int require_machine_suffix; /* Don't use without machine_suffix. */ + /* 2 means try both machine_suffix and just_machine_suffix. */ int *used_flag_ptr; /* 1 if a file was found with this prefix. */ }; *************** *** 828,835 **** static struct path_prefix library_prefix = { 0, 0, "libraryfile" }; ! /* Suffix to attach to directories searched for commands. */ static char *machine_suffix = 0; /* Adjusted value of GCC_EXEC_PREFIX envvar. */ --- 870,883 ---- static struct path_prefix library_prefix = { 0, 0, "libraryfile" }; ! /* Suffix to attach to directories searched for commands. ! This looks like `MACHINE/VERSION/'. */ static char *machine_suffix = 0; + /* Suffix to attach to directories searched for commands. + This is just `MACHINE/'. */ + + static char *just_machine_suffix = 0; + /* Adjusted value of GCC_EXEC_PREFIX envvar. */ *************** *** 1157,1160 **** --- 1205,1218 ---- } + if (just_machine_suffix && pprefix->require_machine_suffix == 2) + { + if (!first_time) + obstack_grow (&collect_obstack, ":", 1); + + first_time = FALSE; + obstack_grow (&collect_obstack, pprefix->prefix, len); + obstack_grow (&collect_obstack, machine_suffix, suffix_len); + } + if (!pprefix->require_machine_suffix) { *************** *** 1228,1231 **** --- 1286,1315 ---- } } + /* Certain prefixes are tried with just the machine type, + not the version. This is used for finding as, ld, etc. */ + if (just_machine_suffix && pl->require_machine_suffix == 2) + { + strcpy (temp, pl->prefix); + strcat (temp, just_machine_suffix); + strcat (temp, name); + if (access (temp, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; + return temp; + } + /* Some systems have a suffix for executable files. + So try appending that. */ + if (file_suffix[0] != 0) + { + strcat (temp, file_suffix); + if (access (temp, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; + return temp; + } + } + } /* Certain prefixes can't be used without the machine suffix when the machine or version is explicitly specified. */ *************** *** 1264,1268 **** If WARN is nonzero, we will warn if no file is found through this prefix. WARN should point to an int ! which will be set to 1 if this entry is used. */ static void --- 1348,1356 ---- If WARN is nonzero, we will warn if no file is found through this prefix. WARN should point to an int ! which will be set to 1 if this entry is used. ! ! REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without ! the complete value of machine_suffix. ! 2 means try both machine_suffix and just_machine_suffix. */ static void *************** *** 1648,1653 **** if ((status & 0x7F) != 0) ! fatal ("Internal compiler error: program %s got fatal signal %d", ! prog, (status & 0x7F)); if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS) ret_code = -1; --- 1736,1744 ---- if ((status & 0x7F) != 0) ! { ! fatal ("Internal compiler error: program %s got fatal signal %d", ! prog, (status & 0x7F)); ! signal_count++; ! } if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS) ret_code = -1; *************** *** 1711,1722 **** n_switches = 0; n_infiles = 0; - spec_version = version_string; /* Set up the default search paths. */ if (gcc_exec_prefix) { ! add_prefix (&exec_prefix, gcc_exec_prefix, 0, 0, 0); ! add_prefix (&startfile_prefix, gcc_exec_prefix, 0, 0, 0); } --- 1802,1817 ---- n_switches = 0; n_infiles = 0; + /* Default for -V is our version number, ending at first space. */ + spec_version = save_string (version_string, strlen (version_string)); + for (temp = spec_version; *temp && *temp != ' '; temp++); + if (*temp) *temp = '\0'; + /* Set up the default search paths. */ if (gcc_exec_prefix) { ! add_prefix (&exec_prefix, gcc_exec_prefix, 0, 0, NULL_PTR); ! add_prefix (&startfile_prefix, gcc_exec_prefix, 0, 0, NULL_PTR); } *************** *** 1747,1751 **** else nstore[endp-startp] = 0; ! add_prefix (&exec_prefix, nstore, 0, 0, 0); if (*endp == 0) break; --- 1842,1846 ---- else nstore[endp-startp] = 0; ! add_prefix (&exec_prefix, nstore, 0, 0, NULL_PTR); if (*endp == 0) break; *************** *** 1780,1786 **** else nstore[endp-startp] = 0; ! add_prefix (&startfile_prefix, nstore, 0, 0, 0); /* Make separate list of dirs that came from LIBRARY_PATH. */ ! add_prefix (&library_prefix, nstore, 0, 0, 0); if (*endp == 0) break; --- 1875,1881 ---- else nstore[endp-startp] = 0; ! add_prefix (&startfile_prefix, nstore, 0, 0, NULL_PTR); /* Make separate list of dirs that came from LIBRARY_PATH. */ ! add_prefix (&library_prefix, nstore, 0, 0, NULL_PTR); if (*endp == 0) break; *************** *** 1816,1822 **** else nstore[endp-startp] = 0; ! add_prefix (&startfile_prefix, nstore, 0, 0, 0); /* Make separate list of dirs that came from LIBRARY_PATH. */ ! add_prefix (&library_prefix, nstore, 0, 0, 0); if (*endp == 0) break; --- 1911,1917 ---- else nstore[endp-startp] = 0; ! add_prefix (&startfile_prefix, nstore, 0, 0, NULL_PTR); /* Make separate list of dirs that came from LIBRARY_PATH. */ ! add_prefix (&library_prefix, nstore, 0, 0, NULL_PTR); if (*endp == 0) break; *************** *** 1879,1882 **** --- 1974,2040 ---- linker_options[n_linker_options - 1] = argv[++i]; } + else if (! strncmp (argv[i], "-Wl,", 4)) + { + int prev, j; + /* Pass the rest of this option to the linker when we link. */ + + n_linker_options++; + if (!linker_options) + linker_options + = (char **) xmalloc (n_linker_options * sizeof (char **)); + else + linker_options + = (char **) xrealloc (linker_options, + n_linker_options * sizeof (char **)); + + /* Split the argument at commas. */ + prev = 4; + for (j = 4; argv[i][j]; j++) + if (argv[i][j] == ',') + { + linker_options[n_linker_options - 1] + = save_string (argv[i] + prev, j - prev); + n_linker_options++; + linker_options + = (char **) xrealloc (linker_options, + n_linker_options * sizeof (char **)); + prev = j + 1; + } + /* Record the part after the last comma. */ + linker_options[n_linker_options - 1] = argv[i] + prev; + } + else if (! strncmp (argv[i], "-Wa,", 4)) + { + int prev, j; + /* Pass the rest of this option to the assembler. */ + + n_assembler_options++; + if (!assembler_options) + assembler_options + = (char **) xmalloc (n_assembler_options * sizeof (char **)); + else + assembler_options + = (char **) xrealloc (assembler_options, + n_assembler_options * sizeof (char **)); + + /* Split the argument at commas. */ + prev = 4; + for (j = 4; argv[i][j]; j++) + if (argv[i][j] == ',') + { + assembler_options[n_assembler_options - 1] + = save_string (argv[i] + prev, j - prev); + n_assembler_options++; + assembler_options + = (char **) xrealloc (assembler_options, + n_assembler_options * sizeof (char **)); + prev = j + 1; + } + /* Record the part after the last comma. */ + assembler_options[n_assembler_options - 1] = argv[i] + prev; + } + else if (argv[i][0] == '+' && argv[i][1] == 'e') + /* Compensate for the +e options to the C++ front-end. */ + n_switches++; else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l') { *************** *** 1911,1916 **** case 'v': /* Print our subcommands and print versions. */ - verbose_flag++; n_switches++; break; --- 2069,2078 ---- case 'v': /* Print our subcommands and print versions. */ n_switches++; + /* If they do anything other than exactly `-v', don't set + verbose_flag; rather, continue on to give the error. */ + if (p[1] != 0) + break; + verbose_flag++; break; *************** *** 1948,1956 **** /* These come before the md prefixes so that we will find gcc's subcommands (such as cpp) rather than those of the host system. */ ! add_prefix (&exec_prefix, standard_exec_prefix, 0, 1, 0); ! add_prefix (&exec_prefix, standard_exec_prefix_1, 0, 1, 0); ! add_prefix (&startfile_prefix, standard_exec_prefix, 0, 1, 0); ! add_prefix (&startfile_prefix, standard_exec_prefix_1, 0, 1, 0); /* More prefixes are enabled in main, after we read the specs file --- 2110,2120 ---- /* These come before the md prefixes so that we will find gcc's subcommands (such as cpp) rather than those of the host system. */ ! /* Use 2 as fourth arg meaning try just the machine as a suffix, ! as well as trying the machine and the version. */ ! add_prefix (&exec_prefix, standard_exec_prefix, 0, 2, NULL_PTR); ! add_prefix (&exec_prefix, standard_exec_prefix_1, 0, 2, NULL_PTR); ! add_prefix (&startfile_prefix, standard_exec_prefix, 0, 1, NULL_PTR); ! add_prefix (&startfile_prefix, standard_exec_prefix_1, 0, 1, NULL_PTR); /* More prefixes are enabled in main, after we read the specs file *************** *** 1973,1980 **** for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "-Xlinker")) i++; else if (! strcmp (argv[i], "-print-libgcc-file-name")) ! i++; else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l') { --- 2137,2161 ---- for (i = 1; i < argc; i++) { + /* Just skip the switches that were handled by the preceding loop. */ if (!strcmp (argv[i], "-Xlinker")) i++; + else if (! strncmp (argv[i], "-Wl,", 4)) + ; + else if (! strncmp (argv[i], "-Wa,", 4)) + ; else if (! strcmp (argv[i], "-print-libgcc-file-name")) ! ; ! else if (argv[i][0] == '+' && argv[i][1] == 'e') ! { ! /* Compensate for the +e options to the C++ front-end; ! they're there simply for cfront call-compatability. We do ! some magic in default_compilers to pass them down properly. ! Note we deliberately start at the `+' here, to avoid passing ! -e0 or -e1 down into the linker. */ ! switches[n_switches].part1 = &argv[i][0]; ! switches[n_switches].args = 0; ! switches[n_switches].valid = 0; ! n_switches++; ! } else if (argv[i][0] == '-' && argv[i][1] != 0 && argv[i][1] != 'l') { *************** *** 2017,2020 **** --- 2198,2203 ---- n_args = SWITCH_TAKES_ARG (c) - (p[1] != 0); } + if (i + n_args >= argc) + fatal ("argument to `-%s' is missing", p); switches[n_switches].args = (char **) xmalloc ((n_args + 1) * sizeof (char *)); *************** *** 2116,2120 **** this_is_library_file = 0; ! value = do_spec_1 (spec, 0, NULL); /* Force out any unfinished command. --- 2299,2303 ---- this_is_library_file = 0; ! value = do_spec_1 (spec, 0, NULL_PTR); /* Force out any unfinished command. *************** *** 2288,2296 **** if (is_linker_dir (pl->prefix, machine_suffix)) { ! do_spec_1 ("-L", 0, 0); #ifdef SPACE_AFTER_L_OPTION ! do_spec_1 (" ", 0, 0); #endif ! do_spec_1 (pl->prefix, 1, 0); /* Remove slash from machine_suffix. */ if (strlen (machine_suffix) >= bufsize) --- 2471,2479 ---- if (is_linker_dir (pl->prefix, machine_suffix)) { ! do_spec_1 ("-L", 0, NULL_PTR); #ifdef SPACE_AFTER_L_OPTION ! do_spec_1 (" ", 0, NULL_PTR); #endif ! do_spec_1 (pl->prefix, 1, NULL_PTR); /* Remove slash from machine_suffix. */ if (strlen (machine_suffix) >= bufsize) *************** *** 2301,2307 **** if (buffer[idx - 1] == '/') buffer[idx - 1] = 0; ! do_spec_1 (buffer, 1, 0); /* Make this a separate argument. */ ! do_spec_1 (" ", 0, 0); } } --- 2484,2490 ---- if (buffer[idx - 1] == '/') buffer[idx - 1] = 0; ! do_spec_1 (buffer, 1, NULL_PTR); /* Make this a separate argument. */ ! do_spec_1 (" ", 0, NULL_PTR); } } *************** *** 2310,2316 **** if (is_linker_dir (pl->prefix, "")) { ! do_spec_1 ("-L", 0, 0); #ifdef SPACE_AFTER_L_OPTION ! do_spec_1 (" ", 0, 0); #endif /* Remove slash from pl->prefix. */ --- 2493,2499 ---- if (is_linker_dir (pl->prefix, "")) { ! do_spec_1 ("-L", 0, NULL_PTR); #ifdef SPACE_AFTER_L_OPTION ! do_spec_1 (" ", 0, NULL_PTR); #endif /* Remove slash from pl->prefix. */ *************** *** 2322,2328 **** if (buffer[idx - 1] == '/') buffer[idx - 1] = 0; ! do_spec_1 (buffer, 1, 0); /* Make this a separate argument. */ ! do_spec_1 (" ", 0, 0); } } --- 2505,2511 ---- if (buffer[idx - 1] == '/') buffer[idx - 1] = 0; ! do_spec_1 (buffer, 1, NULL_PTR); /* Make this a separate argument. */ ! do_spec_1 (" ", 0, NULL_PTR); } } *************** *** 2348,2351 **** --- 2531,2536 ---- case 'g': + case 'u': + case 'U': if (save_temps_flag) obstack_grow (&obstack, input_basename, basename_length); *************** *** 2353,2356 **** --- 2538,2550 ---- { obstack_grow (&obstack, temp_filename, temp_filename_length); + if (c == 'u' || c == 'U') + { + static int unique; + char buff[9]; + if (c == 'u') + unique++; + sprintf (buff, "%d", unique); + obstack_grow (&obstack, buff, strlen (buff)); + } delete_this_arg = 1; } *************** *** 2366,2374 **** if (gcc_exec_prefix) { ! do_spec_1 ("-imacros", 1, 0); /* Make this a separate argument. */ ! do_spec_1 (" ", 0, 0); ! do_spec_1 (gcc_exec_prefix, 1, 0); ! do_spec_1 (" ", 0, 0); } break; --- 2560,2568 ---- if (gcc_exec_prefix) { ! do_spec_1 ("-iprefix", 1, NULL_PTR); /* Make this a separate argument. */ ! do_spec_1 (" ", 0, NULL_PTR); ! do_spec_1 (gcc_exec_prefix, 1, NULL_PTR); ! do_spec_1 (" ", 0, NULL_PTR); } break; *************** *** 2441,2491 **** break; ! /* Dump out the options accumulated previously using %x. */ case 'X': for (i = 0; i < n_linker_options; i++) { ! do_spec_1 (linker_options[i], 1, NULL); /* Make each accumulated option a separate argument. */ ! do_spec_1 (" ", 0, NULL); } break; /* Here are digits and numbers that just process a certain constant string as a spec. */ case '1': ! do_spec_1 (cc1_spec, 0, NULL); break; case '2': ! do_spec_1 (cc1plus_spec, 0, NULL); break; case 'a': ! do_spec_1 (asm_spec, 0, NULL); break; case 'A': ! do_spec_1 (asm_final_spec, 0, NULL); break; case 'c': ! do_spec_1 (signed_char_spec, 0, NULL); break; case 'C': ! do_spec_1 (cpp_spec, 0, NULL); break; case 'E': ! do_spec_1 (endfile_spec, 0, NULL); break; case 'l': ! do_spec_1 (link_spec, 0, NULL); break; case 'L': ! do_spec_1 (lib_spec, 0, NULL); break; --- 2635,2698 ---- break; ! /* Dump out the options accumulated previously using %x, ! -Xlinker and -Wl,. */ case 'X': for (i = 0; i < n_linker_options; i++) { ! do_spec_1 (linker_options[i], 1, NULL_PTR); /* Make each accumulated option a separate argument. */ ! do_spec_1 (" ", 0, NULL_PTR); } break; + /* Dump out the options accumulated previously using -Wa,. */ + case 'Y': + for (i = 0; i < n_assembler_options; i++) + { + do_spec_1 (assembler_options[i], 1, NULL_PTR); + /* Make each accumulated option a separate argument. */ + do_spec_1 (" ", 0, NULL_PTR); + } + break; + + /* Here are digits and numbers that just process + a certain constant string as a spec. /* Here are digits and numbers that just process a certain constant string as a spec. */ case '1': ! do_spec_1 (cc1_spec, 0, NULL_PTR); break; case '2': ! do_spec_1 (cc1plus_spec, 0, NULL_PTR); break; case 'a': ! do_spec_1 (asm_spec, 0, NULL_PTR); break; case 'A': ! do_spec_1 (asm_final_spec, 0, NULL_PTR); break; case 'c': ! do_spec_1 (signed_char_spec, 0, NULL_PTR); break; case 'C': ! do_spec_1 (cpp_spec, 0, NULL_PTR); break; case 'E': ! do_spec_1 (endfile_spec, 0, NULL_PTR); break; case 'l': ! do_spec_1 (link_spec, 0, NULL_PTR); break; case 'L': ! do_spec_1 (lib_spec, 0, NULL_PTR); break; *************** *** 2514,2518 **** *x = 0; ! do_spec_1 (buf, 0, NULL); } break; --- 2721,2725 ---- *x = 0; ! do_spec_1 (buf, 0, NULL_PTR); } break; *************** *** 2620,2629 **** *x = 0; ! do_spec_1 (buf, 0, NULL); } break; case 'S': ! do_spec_1 (startfile_spec, 0, NULL); break; --- 2827,2836 ---- *x = 0; ! do_spec_1 (buf, 0, NULL_PTR); } break; case 'S': ! do_spec_1 (startfile_spec, 0, NULL_PTR); break; *************** *** 2641,2646 **** case '*': ! do_spec_1 (soft_matched_part, 1, NULL); ! do_spec_1 (" ", 0, NULL); break; --- 2848,2853 ---- case '*': ! do_spec_1 (soft_matched_part, 1, NULL_PTR); ! do_spec_1 (" ", 0, NULL_PTR); break; *************** *** 2673,2677 **** { if (c == '(') ! do_spec_1 (name, 0, NULL); else { --- 2880,2884 ---- { if (c == '(') ! do_spec_1 (name, 0, NULL_PTR); else { *************** *** 2706,2710 **** *x = 0; ! do_spec_1 (buf, 0, NULL); } } --- 2913,2917 ---- *x = 0; ! do_spec_1 (buf, 0, NULL_PTR); } } *************** *** 2798,2802 **** if (negate != found ! && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL) < 0) return 0; --- 3005,3009 ---- if (negate != found ! && do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0) return 0; *************** *** 2896,2900 **** else { ! if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL) < 0) return 0; } --- 3103,3107 ---- else { ! if (do_spec_1 (save_string (p + 1, q - p - 2), 0, NULL_PTR) < 0) return 0; } *************** *** 2904,2908 **** /* Here if a %{|...} conditional fails: output a minus sign, which means "standard output" or "standard input". */ ! do_spec_1 ("-", 0, NULL); } } --- 3111,3115 ---- /* Here if a %{|...} conditional fails: output a minus sign, which means "standard output" or "standard input". */ ! do_spec_1 ("-", 0, NULL_PTR); } } *************** *** 2926,2933 **** if (!omit_first_word) { ! do_spec_1 ("-", 0, NULL); ! do_spec_1 (switches[switchnum].part1, 1, NULL); } ! do_spec_1 (" ", 0, NULL); if (switches[switchnum].args != 0) { --- 3133,3140 ---- if (!omit_first_word) { ! do_spec_1 ("-", 0, NULL_PTR); ! do_spec_1 (switches[switchnum].part1, 1, NULL_PTR); } ! do_spec_1 (" ", 0, NULL_PTR); if (switches[switchnum].args != 0) { *************** *** 2935,2940 **** for (p = switches[switchnum].args; *p; p++) { ! do_spec_1 (*p, 1, NULL); ! do_spec_1 (" ", 0, NULL); } } --- 3142,3147 ---- for (p = switches[switchnum].args; *p; p++) { ! do_spec_1 (*p, 1, NULL_PTR); ! do_spec_1 (" ", 0, NULL_PTR); } } *************** *** 3009,3012 **** --- 3216,3220 ---- { register int i; + int j; int value; int error_count = 0; *************** *** 3060,3063 **** --- 3268,3272 ---- machine_suffix = concat (spec_machine, "/", concat (spec_version, "/", "")); + just_machine_suffix = concat (spec_machine, "/", ""); specs_file = find_a_file (&startfile_prefix, "specs", R_OK); *************** *** 3073,3093 **** { #ifdef MD_EXEC_PREFIX ! add_prefix (&exec_prefix, md_exec_prefix, 0, 0, 0); ! add_prefix (&startfile_prefix, md_exec_prefix, 0, 0, 0); #endif #ifdef MD_STARTFILE_PREFIX ! add_prefix (&startfile_prefix, md_startfile_prefix, 0, 0, 0); #endif #ifdef MD_STARTFILE_PREFIX_1 ! add_prefix (&startfile_prefix, md_startfile_prefix_1, 0, 0, 0); #endif ! add_prefix (&startfile_prefix, standard_startfile_prefix, 0, 0, 0); ! add_prefix (&startfile_prefix, standard_startfile_prefix_1, 0, 0, 0); ! add_prefix (&startfile_prefix, standard_startfile_prefix_2, 0, 0, 0); #if 0 /* Can cause surprises, and one can use -B./ instead. */ ! add_prefix (&startfile_prefix, "./", 0, 1, 0); #endif } --- 3282,3305 ---- { #ifdef MD_EXEC_PREFIX ! add_prefix (&exec_prefix, md_exec_prefix, 0, 0, NULL_PTR); ! add_prefix (&startfile_prefix, md_exec_prefix, 0, 0, NULL_PTR); #endif #ifdef MD_STARTFILE_PREFIX ! add_prefix (&startfile_prefix, md_startfile_prefix, 0, 0, NULL_PTR); #endif #ifdef MD_STARTFILE_PREFIX_1 ! add_prefix (&startfile_prefix, md_startfile_prefix_1, 0, 0, NULL_PTR); #endif ! add_prefix (&startfile_prefix, standard_startfile_prefix, 0, 0, ! NULL_PTR); ! add_prefix (&startfile_prefix, standard_startfile_prefix_1, 0, 0, ! NULL_PTR); ! add_prefix (&startfile_prefix, standard_startfile_prefix_2, 0, 0, ! NULL_PTR); #if 0 /* Can cause surprises, and one can use -B./ instead. */ ! add_prefix (&startfile_prefix, "./", 0, 1, NULL_PTR); #endif } *************** *** 3158,3161 **** --- 3370,3374 ---- /* First say how much of input_filename to substitute for %b */ register char *p; + int len; input_basename = input_filename; *************** *** 3177,3181 **** input_suffix = ""; ! value = do_spec (cp->spec); if (value < 0) this_file_error = 1; --- 3390,3410 ---- input_suffix = ""; ! len = 0; ! for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) ! if (cp->spec[j]) ! len += strlen (cp->spec[j]); ! ! p = (char *) xmalloc (len + 1); ! ! len = 0; ! for (j = 0; j < sizeof cp->spec / sizeof cp->spec[0]; j++) ! if (cp->spec[j]) ! { ! strcpy (p + len, cp->spec[j]); ! len += strlen (cp->spec[j]); ! } ! ! value = do_spec (p); ! free (p); if (value < 0) this_file_error = 1; *************** *** 3264,3268 **** delete_temp_files (); ! exit (error_count); /* NOTREACHED */ return 0; --- 3493,3497 ---- delete_temp_files (); ! exit (error_count > 0 ? (signal_count ? 2 : 1) : 0); /* NOTREACHED */ return 0; *************** *** 3306,3310 **** && !(!strcmp (cp->suffix, "-") && length != 1)) { ! if (cp->spec[0] == '@') { struct compiler *new; --- 3535,3539 ---- && !(!strcmp (cp->suffix, "-") && length != 1)) { ! if (cp->spec[0][0] == '@') { struct compiler *new; *************** *** 3313,3320 **** to avoid infinite recursion if language not found. Construct the new compiler spec. */ ! language = cp->spec + 1; new = (struct compiler *) xmalloc (sizeof (struct compiler)); new->suffix = cp->suffix; ! new->spec = lookup_compiler (0, 0, language)->spec; return new; } --- 3542,3550 ---- to avoid infinite recursion if language not found. Construct the new compiler spec. */ ! language = cp->spec[0] + 1; new = (struct compiler *) xmalloc (sizeof (struct compiler)); new->suffix = cp->suffix; ! bcopy (lookup_compiler (NULL_PTR, 0, language)->spec, ! new->spec, sizeof new->spec); return new; } *************** *** 3494,3508 **** struct spec_list *spec; ! for (comp = compilers; comp->spec; comp++) { ! p = comp->spec; ! while (c = *p++) ! if (c == '%' && *p == '{') ! /* We have a switch spec. */ ! validate_switches (p + 1); } /* look through the linked list of extra specs read from the specs file */ ! for (spec = specs ; spec ; spec = spec->next) { p = spec->spec; --- 3724,3742 ---- struct spec_list *spec; ! for (comp = compilers; comp->spec[0]; comp++) { ! int i; ! for (i = 0; i < sizeof comp->spec / sizeof comp->spec[0] && comp->spec[i]; i++) ! { ! p = comp->spec[i]; ! while (c = *p++) ! if (c == '%' && *p == '{') ! /* We have a switch spec. */ ! validate_switches (p + 1); ! } } /* look through the linked list of extra specs read from the specs file */ ! for (spec = specs; spec ; spec = spec->next) { p = spec->spec; diff -rc2N gcc-2.2.2/gcc.texi gcc-2.3.1/gcc.texi *** gcc-2.2.2/gcc.texi Sun Jun 14 17:46:00 1992 --- gcc-2.3.1/gcc.texi Fri Oct 30 01:27:42 1992 *************** *** 41,55 **** Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the ! sections entitled ``GNU General Public License'' and ``Boycott'' are ! included exactly as in the original, and provided that the entire ! resulting derived work is distributed under the terms of a permission ! notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the sections entitled ``GNU General Public License'' and ! ``Boycott'', and this permission notice, may be included in translations ! approved by the Free Software Foundation instead of in the original ! English. @end ifinfo --- 41,56 ---- Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the ! sections entitled ``GNU General Public License'' and ``Protect Your ! Freedom---Fight `Look And Feel'@w{}'' are included exactly as in the ! original, and provided that the entire resulting derived work is ! distributed under the terms of a permission notice identical to this ! one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the sections entitled ``GNU General Public License'' and ! ``Protect Your Freedom---Fight `Look And Feel'@w{}'', and this permission ! notice, may be included in translations approved by the Free Software ! Foundation instead of in the original English. @end ifinfo *************** *** 66,73 **** @center Richard M. Stallman @sp 3 ! @center last updated 22 May 1992 @sp 1 @c The version number appears twice more in this file. ! @center for version 2.2 @center (preliminary draft, which will change) @page --- 67,74 ---- @center Richard M. Stallman @sp 3 ! @center last updated 30 Oct 1992 @sp 1 @c The version number appears twice more in this file. ! @center for version 2.3 @center (preliminary draft, which will change) @page *************** *** 104,108 **** This manual documents how to run, install and port the GNU C compiler, as well as its new features and incompatibilities, and how to report bugs. ! It corresponds to GNU CC version 2.2. @end ifset --- 105,109 ---- This manual documents how to run, install and port the GNU C compiler, as well as its new features and incompatibilities, and how to report bugs. ! It corresponds to GNU CC version 2.3. @end ifset *************** *** 110,114 **** This manual documents how to run and install the GNU C compiler, as well as its new features and incompatibilities, and how to report bugs. ! It corresponds to GNU CC version 2.2. @end ifclear --- 111,115 ---- This manual documents how to run and install the GNU C compiler, as well as its new features and incompatibilities, and how to report bugs. ! It corresponds to GNU CC version 2.3. @end ifclear *************** *** 479,483 **** @page ! @unnumberedsec Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest --- 480,484 ---- @page ! @unnumberedsec How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest *************** *** 491,501 **** @smallexample ! @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) 19@var{yy} @var{name of author} ! 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 of the License, or ! (at your option) any later version. This program is distributed in the hope that it will be useful, --- 492,502 ---- @smallexample ! @var{one line to give the program's name and an idea of what it does.} Copyright (C) 19@var{yy} @var{name of author} ! 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 ! of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, *************** *** 516,522 **** @smallexample Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author} ! Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ! This is free software, and you are welcome to redistribute it ! under certain conditions; type `show c' for details. @end smallexample --- 517,524 ---- @smallexample Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author} ! Gnomovision comes with ABSOLUTELY NO WARRANTY; for details ! type `show w'. This is free software, and you are welcome ! to redistribute it under certain conditions; type `show c' ! for details. @end smallexample *************** *** 532,540 **** @example ! Yoyodyne, Inc., hereby disclaims all copyright interest in the program ! `Gnomovision' (which makes passes at compilers) written by James Hacker. @var{signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice @end example --- 534,546 ---- @example ! @group ! Yoyodyne, Inc., hereby disclaims all copyright ! interest in the program `Gnomovision' ! (which makes passes at compilers) written ! by James Hacker. @var{signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice + @end group @end example *************** *** 630,636 **** @item ! Richard Kenner of New York University wrote the machine descriptions for ! the AMD 29000, the IBM RT PC, and the IBM RS/6000 as well as the support ! for instruction attributes. He also made changes to better support RISC processors including changes to common subexpression elimination, strength reduction, function calling sequence handling, and condition --- 636,643 ---- @item ! Richard Kenner of the New York University Ultracomputer Research ! Laboratory wrote the machine descriptions for the AMD 29000, the DEC ! Alpha, the IBM RT PC, and the IBM RS/6000 as well as the support for ! instruction attributes. He also made changes to better support RISC processors including changes to common subexpression elimination, strength reduction, function calling sequence handling, and condition *************** *** 665,672 **** @item ! Ron Guilmette implemented the protoize and unprotoize tools, the support ! for Dwarf symbolic debugging information, and much of the support for ! System V Release 4. He has also worked heavily on the Intel 386 and 860 ! support. @item --- 672,679 ---- @item ! Ron Guilmette implemented the @code{protoize} and @code{unprotoize} ! tools, the support for Dwarf symbolic debugging information, and much of ! the support for System V Release 4. He has also worked heavily on the ! Intel 386 and 860 support. @item *************** *** 674,677 **** --- 681,687 ---- implemented multiply-by-constant optimization and better long long support, and improved leaf function register allocation. + + @item + Mike Stump implemented the support for Elxsi 64 bit CPU. @end itemize *************** *** 764,768 **** dues. ! To join, or for more information, phone (617) 492-0023 or write to: @display --- 774,778 ---- dues. ! To join, or for more information, phone (617) 243-4091 or write to: @display *************** *** 849,852 **** --- 859,863 ---- * Incompatibilities:: GNU CC is incompatible with traditional C. * Disappointments:: Regrettable things we can't change, but not quite bugs. + * Protoize Caveats:: Things to watch out for when using @code{protoize}. * Non-bugs:: Things we think are right, but some others disagree. @end menu *************** *** 857,876 **** @itemize @bullet @item ! Loop unrolling doesn't work properly for certain programs. This is because of difficulty in updating the debugging information within the loop being unrolled. We plan to revamp the representation of debugging information so that this will work properly, but we have not done this ! in version 2.2 because we don't want to delay it any further. ! ! @item ! There is a bug in producing DBX output which outputs a structure tag ! even when a structure doesn't have a tag. The reason we aren't fixing ! this now is that a clean fix requires reorganizations that seem risky. ! We will do them after 2.2 is released. @end itemize @node Installation Problems @section Installation Problems ! This is a list of problems (and some apparent problems which don't really mean anything is wrong) that show up during installation of GNU --- 868,881 ---- @itemize @bullet @item ! Loop unrolling doesn't work properly for certain C++ programs. This is because of difficulty in updating the debugging information within the loop being unrolled. We plan to revamp the representation of debugging information so that this will work properly, but we have not done this ! in version 2.3 because we don't want to delay it any further. @end itemize @node Installation Problems @section Installation Problems ! This is a list of problems (and some apparent problems which don't really mean anything is wrong) that show up during installation of GNU *************** *** 915,933 **** @code{make}. Either ignore the problem or switch to GNU Make. @cindex @code{genflags}, crash on Sun 4 @item Sometimes on a Sun 4 you may observe a crash in the program ! @code{genflags} or @code{genoutput} while building GCC. This is said to be due to a bug in @code{sh}. You can probably get around it by running @code{genflags} or @code{genoutput} manually and then retrying the @code{make}. - @item - On some versions of Ultrix, the system supplied compiler cannot compile - @file{cp-parse.c} because it cannot handle so many cases in a - @code{switch} statement. You can avoid this problem by specifying - @samp{LANGUAGES=c} when you compile GNU CC with the Ultrix compiler. - Then you can compile the entire GNU compiler with GNU CC. - @item If you use the 1.31 version of the MIPS assembler (such as was shipped --- 920,940 ---- @code{make}. Either ignore the problem or switch to GNU Make. + @item + On some 386 systems, building the compiler never finishes because + @code{enquire} hangs due to a hardware problem in the motherboard---it + reports floating point exceptions to the kernel incorrectly. You can + install GNU CC except for @file{float.h} by patching out the command to + run @code{enquire}. You may also be able to fix the problem for real by + getting a replacement motherboard. This problem was observed in + Revision E of the Micronics motherboard, and is fixed in Revision F. + @cindex @code{genflags}, crash on Sun 4 @item Sometimes on a Sun 4 you may observe a crash in the program ! @code{genflags} or @code{genoutput} while building GNU CC. This is said to be due to a bug in @code{sh}. You can probably get around it by running @code{genflags} or @code{genoutput} manually and then retrying the @code{make}. @item If you use the 1.31 version of the MIPS assembler (such as was shipped *************** *** 943,946 **** --- 950,973 ---- @item + Some versions of the MIPS linker will issue an assertion failure + when linking code that uses @code{alloca} against shared + libraries on RISC-OS 5.0, and DEC's OSF/1 systems. This is a bug + in the linker, that is supposed to be fixed in future revisions. + To protect against this, GCC passes @samp{-non_shared} to the + linker unless you pass an explicit @samp{-shared} switch. + + @item + On System V release 3, you may get this error message + while linking: + + @smallexample + ld fatal: failed to write symbol name @var{something} + in strings table for file @var{whatever} + @end smallexample + + This indicates that the disk is full or your ULIMIT won't allow + the file to be as large as it needs to be. + + @item On HP 9000 series 300 or 400 running HP-UX release 8.0, there is a bug in the assembler that must be fixed before GNU CC can be built. This *************** *** 1018,1021 **** --- 1045,1053 ---- V.2.2 1.0e and perhaps later versions as well. See the file @file{README.ALTOS}. + + @item + You will get several sorts of compilation and linking errors on the + we32k if you don't follow the special instructions. @xref{WE32K + Install}. @end itemize *************** *** 1063,1068 **** This section lists various difficulties encountered in using GNU C or ! GNU C++ together with other compilers or with the assemblers, linkers ! and debuggers on certain systems. @itemize @bullet --- 1095,1100 ---- This section lists various difficulties encountered in using GNU C or ! GNU C++ together with other compilers or with the assemblers, linkers, ! libraries and debuggers on certain systems. @itemize @bullet *************** *** 1072,1076 **** larger structures and unions. This can lead to trouble when you link together code compiled by different compilers. To avoid the problem, you ! can use the option @samp{-fpcc-struct-value} when compiling with GNU CC. @item --- 1104,1108 ---- larger structures and unions. This can lead to trouble when you link together code compiled by different compilers. To avoid the problem, you ! can use the option @samp{-fpcc-struct-return} when compiling with GNU CC. @item *************** *** 1103,1106 **** --- 1135,1154 ---- be run. + @item + Use of @samp{-I/usr/include} may cause trouble. + + Many systems come with header files that won't work with GNU CC unless + corrected by @code{fixincludes}. The corrected header files go in a new + directory; GNU CC searches this directory before @file{/usr/include}. + If you use @samp{-I/usr/include}, this tells GNU CC to search + @file{/usr/include} earlier on, before the corrected headers. The + result is that you get the uncorrected header files. + + Instead, you should use these options: + + @example + -I/usr/local/lib/gcc-lib/@var{target}/@var{version}/include -I/usr/include + @end example + @ignore @cindex @code{vfork}, for the Sun-4 *************** *** 1120,1123 **** --- 1168,1208 ---- @item + On a Sparc, GNU CC aligns all values of type @code{double} on an 8-byte + boundary, and it expects every @code{double} to be so aligned. The Sun + compiler usually gives @code{double} values 8-byte alignment, with one + exception: function arguments of type @code{double} may not be aligned. + + As a result, if a function compiled with Sun CC takes the address of an + argument of type @code{double} and passes this pointer of type + @code{double *} to a function compiled with GNU CC, dereferencing the + pointer may cause a fatal signal. + + One way to solve this problem is to compile your entire program with GNU + CC. Another solution is to modify the function that is compiled with + Sun CC to copy the argument into a local variable; local variables + are always properly aligned. A third solution is to modify the function + that uses the pointer to dereference it via the following function + @code{access_double} instead of directly with @samp{*}: + + @example + inline double + access_double (double *unaligned_ptr) + @{ + union d2i @{ double d; int i[2]; @}; + + union d2i *p = (union d2i *) unaligned_ptr; + union d2i u; + + u.i[0] = p->i[0]; + u.i[1] = p->i[1]; + + return u.d; + @} + @end example + + @noindent + Storing into the pointer can be done likewise with the same union. + + @item On a Sun, linking using GNU CC fails to find a shared library and reports that the library doesn't exist at all. *************** *** 1143,1147 **** with GNU CC. Specifically, it fails to work on functions that use @code{alloca} or variable-size arrays. This is because GNU CC doesn't ! generate HPUX unwind descriptors for such functions. It may even be impossible to generate them. --- 1228,1232 ---- with GNU CC. Specifically, it fails to work on functions that use @code{alloca} or variable-size arrays. This is because GNU CC doesn't ! generate HP-UX unwind descriptors for such functions. It may even be impossible to generate them. *************** *** 1158,1161 **** --- 1243,1270 ---- @item + The HP-UX linker has a bug which can cause programs which make use of + @code{const} variables to fail in unusual ways. If your program makes + use of global @code{const} variables, we suggest you compile with the + following additional options: + + @example + -Dconst="" -D__const="" -D__const__="" -fwritable-strings + @end example + + This will force the @code{const} variables into the DATA subspace which + will avoid the linker bug. + + Another option one might use to work around this problem is + @samp{-mkernel}. @samp{-mkernel} changes how the address of variables + is computed to a sequence less likely to tickle the HP-UX linker bug. + + We hope to work around this problem in GNU CC 2.4, if HP does not fix + it. + + @item + Taking the address of a label may generate errors from the HP-UX + PA assembler. GAS for the PA does not have this problem. + + @item The current version of the assembler (@file{/bin/as}) for the RS/6000 has certain problems that prevent the @samp{-g} option in GCC from *************** *** 1192,1195 **** --- 1301,1317 ---- psect attributes. You can ignore them. @xref{VMS Install}. + @item + On NewsOS version 3, if you include both @file{stddef.h} and + @file{sys/types.h}, you get an error because there are two typedefs of + @code{size_t}. You should change @file{sys/types.h} by adding these + lines around the definition of @code{size_t}: + + @example + #ifndef _SIZE_T + #define _SIZE_T + @var{actual typedef here} + #endif + @end example + @cindex Alliant @item *************** *** 1219,1222 **** --- 1341,1362 ---- -fcall-saved-r2 -fcall-saved-r3 -fcall-saved-r4 -fcall-saved-r5 @end smallexample + + @item + On the WE32k, you may find that programs compiled with GNU CC do not + work with the standard shared C ilbrary. You may need to link with + the ordinary C compiler. If you do so, you must specify the following + options: + + @smallexample + -L/usr/local/lib/gcc-lib/we32k-att-sysv/2.3 -lgcc -lc_s + @end smallexample + + The first specifies where to find the library @file{libgcc.a} + specified with the @samp{-lgcc} option. + + GNU CC does linking by invoking @code{ld}, just as @code{cc} does, and + there is no reason why it @emph{should} matter which compilation program + you use to invoke @code{ld}. If someone tracks this problem down, + it can probably be fixed easily. @end itemize *************** *** 1376,1384 **** @cindex ' @item ! GNU CC will flag unterminated character constants inside of preprocessor ! conditionals that fail. Some programs have English comments enclosed in ! conditionals that are guaranteed to fail; if these comments contain ! apostrophes, GNU CC will probably report an error. For example, ! this code would produce an error: @example --- 1516,1524 ---- @cindex ' @item ! GNU CC complains about unterminated character constants inside of ! preprocessor conditionals that fail. Some programs have English ! comments enclosed in conditionals that are guaranteed to fail; if these ! comments contain apostrophes, GNU CC will probably report an error. For ! example, this code would produce an error: @example *************** *** 1392,1395 **** --- 1532,1546 ---- @samp{-traditional} suppresses these error messages. + @item + Many user programs contain the declaration @samp{long time ();}. In the + past, the system header files on many systems did not actually declare + @code{time}, so it did not matter what type your program declared it to + return. But in systems with ANSI C headers, @code{time} is declared to + return @code{time_t}, and if that is not the same as @code{long}, then + @samp{long time ();} is erroneous. + + The solution is to change your program to use @code{time_t} as the return + type of @code{time}. + @cindex @code{float} as function value type @item *************** *** 1466,1470 **** This code really is erroneous, because the scope of @code{struct ! mumble} the prototype is limited to the argument list containing it. It does not refer to the @code{struct mumble} defined with file scope immediately below---they are two unrelated types with similar names in --- 1617,1621 ---- This code really is erroneous, because the scope of @code{struct ! mumble} in the prototype is limited to the argument list containing it. It does not refer to the @code{struct mumble} defined with file scope immediately below---they are two unrelated types with similar names in *************** *** 1480,1486 **** being incompatible with ANSI C just to avoid an error for the example shown above. @end itemize ! @node Non-bugs,, Disappointments, Trouble @section Certain Changes We Don't Want to Make --- 1631,1754 ---- being incompatible with ANSI C just to avoid an error for the example shown above. + + @item + Accesses to bitfields even in volatile objects works by accessing larger + objects, such as a byte or a word. You cannot rely on what size of + object is accessed in order to read or write the bitfield; it may even + vary for a given bitfield according to the precise usage. + + If you care about controlling the amount of memory that is accessed, use + volatile but do not use bitfields. + + @item + On 68000 systems, you can get paradoxical results if you test the + precise values of floating point numbers. For example, you can find + that a floating point value which is not a NaN is not equal to itself. + This results from the fact that the the floating point registers hold a + few more bits of precision than fit in a @code{double} in memory. + Compiled code moves values between memory and floating point registers + at its convenience, and moving them into memory truncates them. + + You can partially avoid this problem by using the option + @samp{-ffloat-store} (@pxref{Optimize Options}). + + @item + On the MIPS, variable argument functions using @file{varargs.h} + cannot have a floating point value for the first argument. The + reason for this is that in the absence of a prototype in scope, + if the first argument is a floating point, it is passed in a + floating point register, rather than an integer resgister. + + If the code is rewritten to use the ANSI standard @file{stdarg.h} + method of variable arguments, and the prototype is in scope at + the time of the call, everything will work fine. + @end itemize + + @node Protoize Caveats + @section Caveats of using @code{protoize} + + The conversion programs @code{protoize} and @code{unprotoize} can + sometimes change a source file in a way that won't work unless you + rearrange it. + + @itemize @bullet + @item + @code{protoize} can insert references to a type name or type tag before + the definition, or in a file where they are not defined. + + If this happens, compiler error messages should show you where the new + references are, so fixing the file by hand is straightforward. + + @item + There are some C constructs which @code{protoize} cannot figure out. + For example, it can't determine argument types for declaring a + pointer-to-function variable; this you must do by hand. @code{protoize} + inserts a comment containing @samp{???} each time it finds such a + variable; so you can find all such variables by searching for this + string. ANSI C does not require declaring the argument types of + pointer-to-function types. + + @item + Using @code{unprotoize} can easily introduce bugs. If the program + relied on prototypes to bring about conversion of arguments, these + conversions will not take place in the program without prototypes. + One case in which you can be sure @code{unprotoize} is safe is when + you are removing prototypes that were made with @code{protoize}; if + the program worked before without any prototypes, it will work again + without them. + + You can find all the places where this problem might occur by compiling + the program with the @samp{-Wconversion} option. It prints a warning + whenever an argument is converted. + + @item + Both conversion programs can be confused if there are macro calls in and + around the text to be converted. In other words, the standard syntax + for a declaration or definition must not result from expanding a macro. + This problem is inherent in the design of C and cannot be fixed. If + only a few functions have confusing macro calls, you can easily convert + them manually. + + @item + @code{protoize} cannot get the argument types for a function whose + definition was not actually compiled due to preprocessor conditionals. + When this happens, @code{protoize} changes nothing in regard to such + a function. @code{protoize} tries to detect such instances and warn + about them. + + You can generally work around this problem by using @code{protoize} step + by step, each time specifying a different set of @samp{-D} options for + compilation, until all of the functions have been converted. There is + no automatic way to verify that you have got them all, however. + + @item + Confusion may result if there is an occasion to convert a function + declaration or definition in a region of source code where there is more + than one formal parameter list present. Thus, attempts to convert code + containing multiple (conditionally compiled) versions of a single + function header (in the same vicinity) may not produce the desired (or + expected) results. + + If you plan on converting source files which contain such code, it is + recommended that you first make sure that each conditionally compiled + region of source code which contains an alternative function header also + contains at least one additional follower token (past the final right + parenthesis of the function header). This should circumvent the + problem. + + @item + @code{unprotoize} can become confused when trying to convert a function + definition or declaration which contains a declaration for a + pointer-to-function formal argument which has the same name as the + function being defined or declared. We recommand you avoid such choices + of formal parameter names. + + @item + You might also want to correct some of the indentation by hand and break + long lines. (The conversion programs don't write lines longer than + eighty characters in any case.) @end itemize ! @node Non-bugs @section Certain Changes We Don't Want to Make *************** *** 1511,1514 **** --- 1779,1789 ---- more annoyance than good. + @item + Warning about unreachable code. + + It's very common to have unreachable code in machine-generated + programs. For example, this happens normally in some files of GNU C + itself. + @item Warning when a non-void function value is ignored. *************** *** 1777,1781 **** mailing them. This appears to work, but it has one problem which can be crucial: a newsgroup posting does not contain a mail path back to the ! sender. Thus, if maintaners need more information, they may be unable to reach you. For this reason, you should always send bug reports by mail to the proper mailing list. --- 2052,2056 ---- mailing them. This appears to work, but it has one problem which can be crucial: a newsgroup posting does not contain a mail path back to the ! sender. Thus, if maintainers need more information, they may be unable to reach you. For this reason, you should always send bug reports by mail to the proper mailing list. *************** *** 1843,1849 **** compilation.) ! A single statement is not enough of an example. In order to compile ! it, it must be embedded in a function definition; and the bug might ! depend on the details of how this is done. Without a real example one can compile, all anyone can do about your bug --- 2118,2124 ---- compilation.) ! A single statement is not enough of an example. In order to compile it, ! it must be embedded in a complete file of compiler input; and the bug ! might depend on the details of how this is done. Without a real example one can compile, all anyone can do about your bug *************** *** 1852,1855 **** --- 2127,2138 ---- frequently depend on every little detail of the function they happen in. + Even if the input file that fails comes from a GNU program, you should + still send the complete test case. Don't ask the GNU CC maintainers to + do the extra work of obtaining the program in question---they are all + overworked as it is. Also, the problem may depend on what is in the + header files on your system; it is unreliable for the GNU CC maintainers + to try the problem with the header files available to them. By sending + CPP output, you can eliminate this source of uncertainty. + @item The command arguments you gave GNU CC or GNU C++ to compile that example *************** *** 1874,1878 **** us, then you are sending us on a wild goose chase.) ! Be precise about these changes---show a context diff for them. Adding files of your own (such as a machine description for a machine we --- 2157,2162 ---- us, then you are sending us on a wild goose chase.) ! Be precise about these changes. A description in English is not ! enough---send a context diff for them. Adding files of your own (such as a machine description for a machine we *************** *** 1892,1896 **** not notice unless it is glaringly wrong. None of us has time to study all the assembler code from a 50-line C program just on the chance that ! one instruction might be wrong. We need @code{you} to do this part! Even if the problem you experience is a fatal signal, you should still --- 2176,2180 ---- not notice unless it is glaringly wrong. None of us has time to study all the assembler code from a 50-line C program just on the chance that ! one instruction might be wrong. We need @emph{you} to do this part! Even if the problem you experience is a fatal signal, you should still *************** *** 1920,1926 **** @item ! If you wish to suggest changes to the GNU CC source, send them as ! context diffs. If you even discuss something in the GNU CC source, ! refer to it by context, not by line number. The line numbers in the development sources don't match those in your --- 2204,2209 ---- @item ! If you wish to mention something in the GNU CC source, refer to it by ! context, not by line number. The line numbers in the development sources don't match those in your *************** *** 1996,1999 **** --- 2279,2288 ---- @item + In particular, some people insert conditionals @samp{#ifdef BUG} around + a statement which, if removed, makes the bug not happen. These are just + clutter; we won't pay any attention to them anyway. Besides, you should + send us cpp output, and that can't have conditionals. + + @item A patch for the bug. *************** *** 2114,2118 **** @item ! When you write the fix, keep in mind that I can't install a change that would break other systems. --- 2403,2407 ---- @item ! When you write the fix, keep in mind that we can't install a change that would break other systems. *************** *** 2267,2270 **** --- 2556,2563 ---- and using an editor to construct a C header file. + A @code{#include} file name cannot contain a DECNET node name. The + preprocessor reports an I/O error if you attempt to use a node name, + whether explicitly, or implicitly via a logical name. + @node Global Declarations @section Global Declarations and VMS *************** *** 2419,2429 **** @cindex case sensitivity and VMS @cindex VMS and case sensitivity ! The VMS linker does not distinguish between upper and lower case letters ! in function and variable names. However, usual practice in C is to ! distinguish case. Normally GNU CC (by means of the assembler GAS) ! implements usual C behavior by augmenting each name that is not all ! lower-case. A name is augmented by truncating it to at most 23 ! characters and then adding more characters at the end which encode the ! case pattern the rest. Name augmentation yields bad results for programs that use precompiled --- 2712,2727 ---- @cindex case sensitivity and VMS @cindex VMS and case sensitivity ! Although the VMS linker does distinguish between upper and lower case ! letters in global symbols, most VMS compilers convert all such symbols ! into upper case and most run-time library routines also have upper case ! names. To be able to reliably call such routines, GNU CC (by means of ! the assembler GAS) converts global symbols into upper case like other ! VMS compilers. However, since the usual practice in C is to distinguish ! case, GNU CC (via GAS) tries to preserve usual C behavior by augmenting ! each name that is not all lower case. This means truncating the name ! to at most 23 characters and then adding more characters at the end ! which encode the case pattern of those 23. Names which contain at ! least one dollar sign are an exception; they are converted directly into ! upper case without augmentation. Name augmentation yields bad results for programs that use precompiled *************** *** 2433,2437 **** on VMS. Alternatively, you could write all references to the functions and variables in such libraries using lower case; this will work on VMS, ! but is not portable to other systems. Function and variable names are handled somewhat differently with GNU --- 2731,2736 ---- on VMS. Alternatively, you could write all references to the functions and variables in such libraries using lower case; this will work on VMS, ! but is not portable to other systems. The compiler option @samp{/NAMES} ! also provides control over global name handling. Function and variable names are handled somewhat differently with GNU *************** *** 2681,2686 **** The source files for parsing C++ are @file{cp-parse.y}, ! @file{cp-class.c}, @file{cp-cvt.c},@* ! @file{cp-decl.c}, @file{cp-decl.c}, @file{cp-decl2.c}, @file{cp-dem.c}, @file{cp-except.c},@* @file{cp-expr.c}, @file{cp-init.c}, @file{cp-lex.c}, --- 2980,2985 ---- The source files for parsing C++ are @file{cp-parse.y}, ! @file{cp-class.c},@* ! @file{cp-cvt.c}, @file{cp-decl.c}, @file{cp-decl2.c}, @file{cp-dem.c}, @file{cp-except.c},@* @file{cp-expr.c}, @file{cp-init.c}, @file{cp-lex.c}, *************** *** 2903,2907 **** @cindex global register allocation @item ! Global register allocation (@file{global-alloc.c}). This pass allocates hard registers for the remaining pseudo registers (those whose life spans are not contained in one basic block). --- 3202,3206 ---- @cindex global register allocation @item ! Global register allocation (@file{global.c}). This pass allocates hard registers for the remaining pseudo registers (those whose life spans are not contained in one basic block). *************** *** 3195,3198 **** --- 3494,3525 ---- Define this if your system @emph{does not} provide the variable @code{sys_siglist}. + + @findex USE_PROTOTYPES + @item USE_PROTOTYPES + Define this to be 1 if you know that the host compiler supports + prototypes, even if it doesn't define __STDC__, or define + it to be 0 if you do not want any prototypes used in compiling + GNU CC. If @samp{USE_PROTOTYPES} is not defined, it will be + determined automatically whether your compiler supports + prototypes by checking if @samp{__STDC__} is defined. + + @findex NO_MD_PROTOTYPES + @item NO_MD_PROTOTYPES + Define this if you wish suppression of prototypes generated from + the machine description file, but to use other prototypes within + GNU CC. If @samp{USE_PROTOTYPES} is defined to be 0, or the + host compiler does not support prototypes, this macro has no + effect. + + @findex MD_CALL_PROTOTYPES + @item MD_CALL_PROTOTYPES + Define this if you wish to generate prototypes for the + @code{gen_call} or @code{gen_call_value} functions generated from + the machine description file. If @samp{USE_PROTOTYPES} is + defined to be 0, or the host compiler does not support + prototypes, or @samp{NO_MD_PROTOTYPES} is defined, this macro has + no effect. As soon as all of the machine descriptions are + modified to have the appropriate number of arguments, this macro + will be removed. @vindex sys_siglist diff -rc2N gcc-2.2.2/genattr.c gcc-2.3.1/genattr.c *** gcc-2.2.2/genattr.c Mon Apr 27 15:08:59 1992 --- gcc-2.3.1/genattr.c Tue Oct 13 00:11:25 1992 *************** *** 21,25 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 21,25 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 39,42 **** --- 39,82 ---- void fancy_abort (); + /* A range of values. */ + + struct range + { + int min; + int max; + }; + + /* Record information about each function unit mentioned in a + DEFINE_FUNCTION_UNIT. */ + + struct function_unit + { + char *name; /* Function unit name. */ + struct function_unit *next; /* Next function unit. */ + int multiplicity; /* Number of units of this type. */ + int simultaneity; /* Maximum number of simultaneous insns + on this function unit or 0 if unlimited. */ + struct range ready_cost; /* Range of ready cost values. */ + struct range issue_delay; /* Range of issue delay values. */ + }; + + static void + extend_range (range, min, max) + struct range *range; + int min; + int max; + { + if (range->min > min) range->min = min; + if (range->max < max) range->max = max; + } + + static void + init_range (range) + struct range *range; + { + range->min = 100000; + range->max = -1; + } + static void write_upcase (str) *************** *** 101,106 **** static void ! write_units () { printf ("#define INSN_SCHEDULING\n\n"); printf ("extern int result_ready_cost ();\n"); --- 141,155 ---- static void ! write_units (num_units, multiplicity, simultaneity, ! ready_cost, issue_delay, blockage) ! int num_units; ! struct range *multiplicity; ! struct range *simultaneity; ! struct range *ready_cost; ! struct range *issue_delay; ! struct range *blockage; { + int i, q_size; + printf ("#define INSN_SCHEDULING\n\n"); printf ("extern int result_ready_cost ();\n"); *************** *** 113,119 **** --- 162,193 ---- printf (" int simultaneity;\n"); printf (" int default_cost;\n"); + printf (" int max_issue_delay;\n"); printf (" int (*ready_cost_function) ();\n"); printf (" int (*conflict_cost_function) ();\n"); + printf (" int max_blockage;\n"); + printf (" unsigned int (*blockage_range_function) ();\n"); + printf (" int (*blockage_function) ();\n"); printf ("} function_units[];\n\n"); + printf ("#define FUNCTION_UNITS_SIZE %d\n", num_units); + printf ("#define MIN_MULTIPLICITY %d\n", multiplicity->min); + printf ("#define MAX_MULTIPLICITY %d\n", multiplicity->max); + printf ("#define MIN_SIMULTANEITY %d\n", simultaneity->min); + printf ("#define MAX_SIMULTANEITY %d\n", simultaneity->max); + printf ("#define MIN_READY_COST %d\n", ready_cost->min); + printf ("#define MAX_READY_COST %d\n", ready_cost->max); + printf ("#define MIN_ISSUE_DELAY %d\n", issue_delay->min); + printf ("#define MAX_ISSUE_DELAY %d\n", issue_delay->max); + printf ("#define MIN_BLOCKAGE %d\n", blockage->min); + printf ("#define MAX_BLOCKAGE %d\n", blockage->max); + for (i = 0; (1 << i) < blockage->max; i++) + ; + printf ("#define BLOCKAGE_BITS %d\n", i + 1); + + /* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and + MAX_READY_COST. This is the longest time an isnsn may be queued. */ + i = MAX (blockage->max, ready_cost->max); + for (q_size = 1; q_size <= i; q_size <<= 1) + ; + printf ("#define INSN_QUEUE_SIZE %d\n", q_size); } *************** *** 170,176 **** int have_annul_true = 0; int have_annul_false = 0; ! int have_units = 0; int i; obstack_init (rtl_obstack); --- 244,259 ---- int have_annul_true = 0; int have_annul_false = 0; ! int num_units = 0; ! struct range all_simultaneity, all_multiplicity; ! struct range all_ready_cost, all_issue_delay, all_blockage; ! struct function_unit *units = 0, *unit; int i; + init_range (&all_multiplicity); + init_range (&all_simultaneity); + init_range (&all_ready_cost); + init_range (&all_issue_delay); + init_range (&all_blockage); + obstack_init (rtl_obstack); *************** *** 216,219 **** --- 299,303 ---- printf ("extern int num_delay_slots ();\n"); printf ("extern int eligible_for_delay ();\n\n"); + printf ("extern int const_num_delay_slots ();\n\n"); have_delay = 1; } *************** *** 237,245 **** } ! else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT && ! have_units) { ! have_units = 1; ! write_units (); } } --- 321,409 ---- } ! else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT) ! { ! char *name = XSTR (desc, 0); ! int multiplicity = XINT (desc, 1); ! int simultaneity = XINT (desc, 2); ! int ready_cost = MAX (XINT (desc, 4), 1); ! int issue_delay = MAX (XINT (desc, 5), 1); ! int issueexp_p = (XVEC (desc, 6) != 0); ! ! for (unit = units; unit; unit = unit->next) ! if (strcmp (unit->name, name) == 0) ! break; ! ! if (unit == 0) ! { ! int len = strlen (name) + 1; ! unit = (struct function_unit *) ! alloca (sizeof (struct function_unit)); ! unit->name = (char *) alloca (len); ! bcopy (name, unit->name, len); ! unit->multiplicity = multiplicity; ! unit->simultaneity = simultaneity; ! unit->ready_cost.min = unit->ready_cost.max = ready_cost; ! unit->issue_delay.min = unit->issue_delay.max = issue_delay; ! unit->next = units; ! units = unit; ! num_units++; ! ! extend_range (&all_multiplicity, multiplicity, multiplicity); ! extend_range (&all_simultaneity, simultaneity, simultaneity); ! } ! else if (unit->multiplicity != multiplicity ! || unit->simultaneity != simultaneity) ! fatal ("Differing specifications given for `%s' function unit.", ! unit->name); ! ! extend_range (&unit->ready_cost, ready_cost, ready_cost); ! extend_range (&unit->issue_delay, ! issueexp_p ? 1 : issue_delay, issue_delay); ! extend_range (&all_ready_cost, ! unit->ready_cost.min, unit->ready_cost.max); ! extend_range (&all_issue_delay, ! unit->issue_delay.min, unit->issue_delay.max); ! } ! } ! ! if (num_units > 0) ! { ! /* Compute the range of blockage cost values. See genattrtab.c ! for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is ! ! MAX (ISSUE-DELAY (E,C), ! READY-COST (E) - (READY-COST (C) - 1)) ! ! and otherwise ! ! MAX (ISSUE-DELAY (E,C), ! READY-COST (E) - (READY-COST (C) - 1), ! READY-COST (E) - FILL-TIME) */ ! ! for (unit = units; unit; unit = unit->next) { ! struct range blockage; ! int max_issue_time = MAX (unit->issue_delay.max, 1); ! ! blockage = unit->issue_delay; ! blockage.max = MAX (unit->ready_cost.max ! - (unit->ready_cost.min - 1), ! blockage.max); ! blockage.min = MAX (1, blockage.min); ! ! if (unit->simultaneity != 0) ! { ! int fill_time = ((unit->simultaneity - 1) ! * unit->issue_delay.min); ! blockage.min = MAX (unit->ready_cost.min - fill_time, ! blockage.min); ! blockage.max = MAX (unit->ready_cost.max - fill_time, ! blockage.max); ! } ! extend_range (&all_blockage, blockage.min, blockage.max); } + + write_units (num_units, &all_multiplicity, &all_simultaneity, + &all_ready_cost, &all_issue_delay, &all_blockage); } *************** *** 249,251 **** return 0; } - --- 413,414 ---- diff -rc2N gcc-2.2.2/genattrtab.c gcc-2.3.1/genattrtab.c *** gcc-2.2.2/genattrtab.c Tue May 19 22:47:28 1992 --- gcc-2.3.1/genattrtab.c Tue Oct 13 00:11:40 1992 *************** *** 90,102 **** for the insn code currently being processed (see optimize_attrs). `integrated' (RTX_INTEGRATED_P): This rtx is permanent and unique ! (see attr_rtx). */ - #include #include "gvarargs.h" ! #include "config.h" #include "rtl.h" #include "obstack.h" #include "insn-config.h" /* For REGISTER_CONSTRAINTS */ static struct obstack obstack, obstack1, obstack2; --- 90,104 ---- for the insn code currently being processed (see optimize_attrs). `integrated' (RTX_INTEGRATED_P): This rtx is permanent and unique ! (see attr_rtx). ! `volatil' (MEM_VOLATILE_P): During simplify_by_exploding the value of an ! EQ_ATTR rtx is true if !volatil and false if volatil. */ #include "gvarargs.h" ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" #include "insn-config.h" /* For REGISTER_CONSTRAINTS */ + #include static struct obstack obstack, obstack1, obstack2; *************** *** 117,120 **** --- 119,125 ---- void fancy_abort (); + /* enough space to reserve for printing out ints */ + #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3) + /* Define structures used to record attributes and values. */ *************** *** 165,168 **** --- 170,175 ---- struct attr_desc *next; /* Next attribute. */ int is_numeric; /* Values of this attribute are numeric. */ + int negative_ok; /* Allow negative numeric values. */ + int unsigned_p; /* Make the output function unsigned int. */ int is_const; /* Attribute value constant for each run. */ int is_special; /* Don't call `write_attr_set'. */ *************** *** 171,174 **** --- 178,191 ---- }; + #define NULL_ATTR (struct attr_desc *) NULL + + /* A range of values. */ + + struct range + { + int min; + int max; + }; + /* Structure for each DEFINE_DELAY. */ *************** *** 188,192 **** int num; /* Ordinal for this operation type in unit. */ int ready; /* Cost until data is ready. */ ! rtx busyexp; /* Expression computing conflict cost. */ }; --- 205,211 ---- int num; /* Ordinal for this operation type in unit. */ int ready; /* Cost until data is ready. */ ! int issue_delay; /* Cost until unit can accept another insn. */ ! rtx conflict_exp; /* Expression TRUE for insns incurring issue delay. */ ! rtx issue_exp; /* Expression computing issue delay. */ }; *************** *** 203,211 **** on this function unit or 0 if unlimited. */ rtx condexp; /* Expression TRUE for insn needing unit. */ - rtx costexp; /* Worst-case cost as function of insn. */ int num_opclasses; /* Number of different operation types. */ struct function_unit_op *ops; /* Pointer to first operation type. */ int needs_conflict_function; /* Nonzero if a conflict function required. */ rtx default_cost; /* Conflict cost, if constant. */ }; --- 222,233 ---- on this function unit or 0 if unlimited. */ rtx condexp; /* Expression TRUE for insn needing unit. */ int num_opclasses; /* Number of different operation types. */ struct function_unit_op *ops; /* Pointer to first operation type. */ int needs_conflict_function; /* Nonzero if a conflict function required. */ + int needs_blockage_function; /* Nonzero if a blockage function required. */ + int needs_range_function; /* Nonzero if a blockage range function required. */ rtx default_cost; /* Conflict cost, if constant. */ + struct range issue_delay; /* Range of issue delay values. */ + int max_blockage; /* Maximum time an insn blocks the unit. */ }; *************** *** 227,230 **** --- 249,253 ---- static int must_constrain; static int address_used; + static int length_used; static int num_delays; static int have_annul_true, have_annul_false; *************** *** 233,237 **** /* Used as operand to `operate_exp': */ ! enum operator {PLUS_OP, MINUS_OP, OR_OP, MAX_OP}; /* Stores, for each insn code, the number of constraint alternatives. */ --- 256,260 ---- /* Used as operand to `operate_exp': */ ! enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, MAX_OP, MIN_OP, RANGE_OP}; /* Stores, for each insn code, the number of constraint alternatives. */ *************** *** 294,297 **** --- 317,322 ---- static rtx operate_exp (); static void expand_units (); + static rtx simplify_knowing (); + static rtx encode_units_mask (); static void fill_attr (); static rtx substitute_address (); *************** *** 303,306 **** --- 328,339 ---- static rtx simplify_cond (); static rtx simplify_by_alternatives (); + static rtx simplify_by_exploding (); + static int find_and_mark_used_attributes (); + static void unmark_used_attributes (); + static int add_values_to_cover (); + static int increment_current_value (); + static rtx test_for_current_value (); + static rtx simplify_with_current_value (); + static rtx simplify_with_current_value_aux (); static void remove_insn_ent (); static void insert_insn_ent (); *************** *** 333,336 **** --- 366,370 ---- static void write_eligible_delay (); static void write_function_unit_info (); + static void write_complex_function (); static int n_comma_elts (); static char *next_comma_elt (); *************** *** 340,346 **** --- 374,384 ---- static rtx find_single_value (); static rtx make_numeric_value (); + static void extend_range (); char *xrealloc (); char *xmalloc (); static void fatal (); + + #define oballoc(size) obstack_alloc (hash_obstack, size) + /* Hash table for sharing RTL and strings. */ *************** *** 373,377 **** /* Here is how primitive or already-shared RTL's hash codes are made. */ ! #define RTL_HASH(RTL) ((int) (RTL) & 0777777) /* Add an entry to the hash table for RTL with hash code HASHCODE. */ --- 411,415 ---- /* Here is how primitive or already-shared RTL's hash codes are made. */ ! #define RTL_HASH(RTL) ((HOST_WIDE_INT) (RTL) & 0777777) /* Add an entry to the hash table for RTL with hash code HASHCODE. */ *************** *** 453,457 **** } ! hashcode = ((int) code + RTL_HASH (arg0)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode --- 491,495 ---- } ! hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode *************** *** 484,488 **** } ! hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode --- 522,526 ---- } ! hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode *************** *** 508,512 **** arg0 = attr_string (arg0, strlen (arg0)); ! hashcode = ((int) code + RTL_HASH (arg0)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode --- 546,550 ---- arg0 = attr_string (arg0, strlen (arg0)); ! hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode *************** *** 529,533 **** char *arg1 = va_arg (p, char *); ! hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode --- 567,571 ---- char *arg1 = va_arg (p, char *); ! hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode *************** *** 547,551 **** else if (code == CONST_INT) { ! int arg0 = va_arg (p, int); if (arg0 == 0) return false_rtx; --- 585,589 ---- else if (code == CONST_INT) { ! HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT); if (arg0 == 0) return false_rtx; *************** *** 571,574 **** --- 609,616 ---- break; + case 'w': /* A wide integer? */ + XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT); + break; + case 's': /* A string? */ XSTR (rt_val, i) = va_arg (p, char *); *************** *** 773,779 **** break; ! default: XINT (copy, i) = XINT (orig, i); break; } } --- 815,834 ---- break; ! case 'n': ! case 'i': XINT (copy, i) = XINT (orig, i); break; + + case 'w': + XWINT (copy, i) = XWINT (orig, i); + break; + + case 's': + case 'S': + XSTR (copy, i) = XSTR (orig, i); + break; + + default: + abort (); } } *************** *** 839,843 **** exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1)); ! /* It shouldn't be possible to simplfy the value given to a constant attribute, so don't expand this until it's time to write the test expression. */ --- 894,898 ---- exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1)); ! /* It shouldn't be possible to simplify the value given to a constant attribute, so don't expand this until it's time to write the test expression. */ *************** *** 881,885 **** case CONST_INT: /* Either TRUE or FALSE. */ ! if (XINT (exp, 0)) return true_rtx; else --- 936,940 ---- case CONST_INT: /* Either TRUE or FALSE. */ ! if (XWINT (exp, 0)) return true_rtx; else *************** *** 967,971 **** if (attr == 0 || attr->is_numeric) { ! for (p = XSTR (exp, 0); *p; p++) if (*p > '9' || *p < '0') fatal ("Non-numeric value for numeric `%s' attribute", --- 1022,1029 ---- if (attr == 0 || attr->is_numeric) { ! p = XSTR (exp, 0); ! if (attr && attr->negative_ok && *p == '-') ! p++; ! for (; *p; p++) if (*p > '9' || *p < '0') fatal ("Non-numeric value for numeric `%s' attribute", *************** *** 1031,1035 **** int insn_code, insn_index; { - rtx newexp; rtx condexp; int i; --- 1089,1092 ---- *************** *** 1182,1186 **** rtx value; ! string = p = (char *) xmalloc (2 + strlen (attr->name) + strlen (XSTR (av->value, 0))); --- 1239,1243 ---- rtx value; ! string = p = (char *) oballoc (2 + strlen (attr->name) + strlen (XSTR (av->value, 0))); *************** *** 1329,1333 **** return av; ! av = (struct attr_value *) xmalloc (sizeof (struct attr_value)); av->value = value; av->next = attr->first_value; --- 1386,1390 ---- return av; ! av = (struct attr_value *) oballoc (sizeof (struct attr_value)); av->value = value; av->next = attr->first_value; *************** *** 1406,1410 **** make_numeric_value (1), make_numeric_value (0)); ! p = attr_printf (13, "*delay_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); --- 1463,1468 ---- make_numeric_value (1), make_numeric_value (0)); ! p = attr_printf (sizeof ("*delay__") + MAX_DIGITS*2, "*delay_%d_%d", ! delay->num, i / 3); make_internal_attr (p, newexp, 1); *************** *** 1416,1420 **** make_numeric_value (1), make_numeric_value (0)); ! p = attr_printf (18, "*annul_true_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); } --- 1474,1479 ---- make_numeric_value (1), make_numeric_value (0)); ! p = attr_printf (sizeof ("*annul_true__") + MAX_DIGITS*2, ! "*annul_true_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); } *************** *** 1427,1431 **** make_numeric_value (1), make_numeric_value (0)); ! p = attr_printf (18, "*annul_false_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); } --- 1486,1491 ---- make_numeric_value (1), make_numeric_value (0)); ! p = attr_printf (sizeof ("*annul_false__") + MAX_DIGITS*2, ! "*annul_false_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); } *************** *** 1469,1476 **** --- 1529,1551 ---- break; + case POS_MINUS_OP: /* The positive part of LEFT - RIGHT. */ + if (left_value > right_value) + i = left_value - right_value; + else + i = 0; + break; + case OR_OP: i = left_value | right_value; break; + case EQ_OP: + i = left_value == right_value; + break; + + case RANGE_OP: + i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value; + break; + case MAX_OP: if (left_value > right_value) *************** *** 1480,1483 **** --- 1555,1565 ---- break; + case MIN_OP: + if (left_value < right_value) + i = left_value; + else + i = right_value; + break; + default: abort (); *************** *** 1593,1598 **** The first produces a function `function_units_used' which is given an ! insn and produces a mask showing which function units are required for ! the execution of that insn. The second produces a function `result_ready_cost' which is used to --- 1675,1682 ---- The first produces a function `function_units_used' which is given an ! insn and produces an encoding showing which function units are required ! for the execution of that insn. If the value is non-negative, the insn ! uses that unit; otherwise, the value is a one's compliment mask of units ! used. The second produces a function `result_ready_cost' which is used to *************** *** 1606,1666 **** For each unit, a `_unit_ready_cost' function will take an insn and give the delay until that unit will be ready with the result ! and a `_unit_busy_delay' function is given an insn already executing on the unit and a candidate to execute and will give the cost from the time the executing insn started until the candidate ! can start (ignore limitations on the number of simultaneous insns). */ static void expand_units () { ! struct function_unit *unit; ! struct function_unit_op *op; rtx unitsmask; rtx readycost; rtx newexp; char *str; ! /* Initially, cost and masks are zero. */ ! unitsmask = readycost = make_numeric_value (0); ! /* Set up a conditional for costs and unit mask. */ newexp = rtx_alloc (IF_THEN_ELSE); XEXP (newexp, 2) = make_numeric_value (0); ! /* For each unit, insert its contribution to the above three values. */ for (unit = units; unit; unit = unit->next) { ! /* An expression that computes the ready cost for this unit. */ ! rtx readyexp = rtx_alloc (COND); ! /* An expression that maps insns to operation number for conflicts. */ ! rtx caseexp = rtx_alloc (COND); ! XVEC (readyexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); for (op = unit->ops; op; op = op->next) { ! /* Validate the expressions we were given for the conditions ! and busy cost. Then make an attribute for use in the conflict ! function. */ ! op->condexp = check_attr_test (op->condexp, 0); ! op->busyexp = check_attr_value (op->busyexp, 0); ! str = attr_printf (strlen (unit->name) + 11, "*%s_case_%d", ! unit->name, op->num); ! make_internal_attr (str, make_canonical (0, op->busyexp)); ! ! /* Make our adjustment to the two COND's being computed. If we are ! the last operation class, place our values into the default of ! the COND. */ if (op->num == unit->num_opclasses - 1) { - XEXP (readyexp, 1) = make_numeric_value (op->ready); XEXP (caseexp, 1) = make_numeric_value (op->num); } else { - XVECEXP (readyexp, 0, op->num * 2) = op->condexp; - XVECEXP (readyexp, 0, op->num * 2 + 1) - = make_numeric_value (op->ready); XVECEXP (caseexp, 0, op->num * 2) = op->condexp; XVECEXP (caseexp, 0, op->num * 2 + 1) --- 1690,2023 ---- For each unit, a `_unit_ready_cost' function will take an insn and give the delay until that unit will be ready with the result ! and a `_unit_conflict_cost' function is given an insn already executing on the unit and a candidate to execute and will give the cost from the time the executing insn started until the candidate ! can start (ignore limitations on the number of simultaneous insns). ! ! For each unit, a `_unit_blockage' function is given an insn ! already executing on the unit and a candidate to execute and will ! give the delay incurred due to function unit conflicts. The range of ! blockage cost values for a given executing insn is given by the ! `_unit_blockage_range' function. These values are encoded in ! an int where the upper half gives the minimum value and the lower ! half gives the maximum value. */ static void expand_units () { ! struct function_unit *unit, **unit_num; ! struct function_unit_op *op, **op_array, ***unit_ops; rtx unitsmask; rtx readycost; rtx newexp; char *str; + int i, j, u, num, nvalues; + + /* Rebuild the condition for the unit to share the RTL expressions. + Sharing is required by simplify_by_exploding. Build the issue delay + expressions. Validate the expressions we were given for the conditions + and conflict vector. Then make attributes for use in the conflict + function. */ + + for (unit = units; unit; unit = unit->next) + { + rtx min_issue = make_numeric_value (unit->issue_delay.min); + + unit->condexp = check_attr_test (unit->condexp, 0); + + for (op = unit->ops; op; op = op->next) + { + rtx issue_delay = make_numeric_value (op->issue_delay); + rtx issue_exp = issue_delay; + + /* Build, validate, and simplify the issue delay expression. */ + if (op->conflict_exp != true_rtx) + issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp, + issue_exp, make_numeric_value (0)); + issue_exp = check_attr_value (make_canonical (NULL_ATTR, + issue_exp), + NULL_ATTR); + issue_exp = simplify_knowing (issue_exp, unit->condexp); + op->issue_exp = issue_exp; + + /* Make an attribute for use in the conflict function if needed. */ + unit->needs_conflict_function = (unit->issue_delay.min + != unit->issue_delay.max); + if (unit->needs_conflict_function) + { + str = attr_printf (strlen (unit->name) + sizeof ("*_cost_") + MAX_DIGITS, + "*%s_cost_%d", unit->name, op->num); + make_internal_attr (str, issue_exp, 1); + } ! /* Validate the condition. */ ! op->condexp = check_attr_test (op->condexp, 0); ! } ! } ! /* Compute the mask of function units used. Initially, the unitsmask is ! zero. Set up a conditional to compute each unit's contribution. */ ! unitsmask = make_numeric_value (0); newexp = rtx_alloc (IF_THEN_ELSE); XEXP (newexp, 2) = make_numeric_value (0); ! /* Merge each function unit into the unit mask attributes. */ ! for (unit = units; unit; unit = unit->next) ! { ! XEXP (newexp, 0) = unit->condexp; ! XEXP (newexp, 1) = make_numeric_value (1 << unit->num); ! unitsmask = operate_exp (OR_OP, unitsmask, newexp); ! } ! ! /* Simplify the unit mask expression, encode it, and make an attribute ! for the function_units_used function. */ ! unitsmask = simplify_by_exploding (unitsmask); ! unitsmask = encode_units_mask (unitsmask); ! make_internal_attr ("*function_units_used", unitsmask, 2); ! ! /* Create an array of ops for each unit. Add an extra unit for the ! result_ready_cost function that has the ops of all other units. */ ! unit_ops = (struct function_unit_op ***) ! alloca ((num_units + 1) * sizeof (struct function_unit_op **)); ! unit_num = (struct function_unit **) ! alloca ((num_units + 1) * sizeof (struct function_unit *)); ! ! unit_num[num_units] = unit = (struct function_unit *) ! alloca (sizeof (struct function_unit)); ! unit->num = num_units; ! unit->num_opclasses = 0; ! ! for (unit = units; unit; unit = unit->next) ! { ! unit_num[num_units]->num_opclasses += unit->num_opclasses; ! unit_num[unit->num] = unit; ! unit_ops[unit->num] = op_array = (struct function_unit_op **) ! alloca (unit->num_opclasses * sizeof (struct function_unit_op *)); ! ! for (op = unit->ops; op; op = op->next) ! op_array[op->num] = op; ! } ! ! /* Compose the array of ops for the extra unit. */ ! unit_ops[num_units] = op_array = (struct function_unit_op **) ! alloca (unit_num[num_units]->num_opclasses ! * sizeof (struct function_unit_op *)); ! ! for (unit = units, i = 0; unit; i += unit->num_opclasses, unit = unit->next) ! bcopy (unit_ops[unit->num], &op_array[i], ! unit->num_opclasses * sizeof (struct function_unit_op *)); ! ! /* Compute the ready cost function for each unit by computing the ! condition for each non-default value. */ ! for (u = 0; u <= num_units; u++) ! { ! rtx orexp; ! int value; ! ! unit = unit_num[u]; ! op_array = unit_ops[unit->num]; ! num = unit->num_opclasses; ! ! /* Sort the array of ops into increasing ready cost order. */ ! for (i = 0; i < num; i++) ! for (j = num - 1; j > i; j--) ! if (op_array[j-1]->ready < op_array[j]->ready) ! { ! op = op_array[j]; ! op_array[j] = op_array[j-1]; ! op_array[j-1] = op; ! } ! ! /* Determine how many distinct non-default ready cost values there ! are. We use a default ready cost value of 1. */ ! nvalues = 0; value = 1; ! for (i = num - 1; i >= 0; i--) ! if (op_array[i]->ready > value) ! { ! value = op_array[i]->ready; ! nvalues++; ! } ! ! if (nvalues == 0) ! readycost = make_numeric_value (1); ! else ! { ! /* Construct the ready cost expression as a COND of each value from ! the largest to the smallest. */ ! readycost = rtx_alloc (COND); ! XVEC (readycost, 0) = rtvec_alloc (nvalues * 2); ! XEXP (readycost, 1) = make_numeric_value (1); ! ! nvalues = 0; orexp = false_rtx; value = op_array[0]->ready; ! for (i = 0; i < num; i++) ! { ! op = op_array[i]; ! if (op->ready <= 1) ! break; ! else if (op->ready == value) ! orexp = insert_right_side (IOR, orexp, op->condexp, -2); ! else ! { ! XVECEXP (readycost, 0, nvalues * 2) = orexp; ! XVECEXP (readycost, 0, nvalues * 2 + 1) ! = make_numeric_value (value); ! nvalues++; ! value = op->ready; ! orexp = op->condexp; ! } ! } ! XVECEXP (readycost, 0, nvalues * 2) = orexp; ! XVECEXP (readycost, 0, nvalues * 2 + 1) = make_numeric_value (value); ! } ! ! if (u < num_units) ! { ! rtx max_blockage = 0, min_blockage = 0; ! ! /* Simplify the readycost expression by only considering insns ! that use the unit. */ ! readycost = simplify_knowing (readycost, unit->condexp); ! ! /* Determine the blockage cost the executing insn (E) given ! the candidate insn (C). This is the maximum of the issue ! delay, the pipeline delay, and the simultaneity constraint. ! Each function_unit_op represents the characteristics of the ! candidate insn, so in the expressions below, C is a known ! term and E is an unknown term. ! ! The issue delay function for C is op->issue_exp and is used to ! write the `_unit_conflict_cost' function. Symbolicly ! this is "ISSUE-DELAY (E,C)". ! ! The pipeline delay results form the FIFO constraint on the ! function unit and is "READY-COST (E) + 1 - READY-COST (C)". ! ! The simultaneity constraint is based on how long it takes to ! fill the unit given the minimum issue delay. FILL-TIME is the ! constant "MIN (ISSUE-DELAY (*,*)) * (SIMULTANEITY - 1)", and ! the simultaneity constraint is "READY-COST (E) - FILL-TIME" ! if SIMULTANEITY is non-zero and zero otherwise. ! ! Thus, BLOCKAGE (E,C) when SIMULTANEITY is zero is ! ! MAX (ISSUE-DELAY (E,C), ! READY-COST (E) - (READY-COST (C) - 1)) ! ! and otherwise ! ! MAX (ISSUE-DELAY (E,C), ! READY-COST (E) - (READY-COST (C) - 1), ! READY-COST (E) - FILL-TIME) ! ! The `_unit_blockage' function is computed by determining ! this value for each candidate insn. As these values are ! computed, we also compute the upper and lower bounds for ! BLOCKAGE (E,*). These are combined to form the function ! `_unit_blockage_range'. Finally, the maximum blockage ! cost, MAX (BLOCKAGE (*,*)), is computed. */ ! ! for (op = unit->ops; op; op = op->next) ! { ! rtx blockage = readycost; ! int delay = op->ready - 1; ! ! if (unit->simultaneity != 0) ! delay = MIN (delay, ((unit->simultaneity - 1) ! * unit->issue_delay.min)); ! ! if (delay > 0) ! blockage = operate_exp (POS_MINUS_OP, blockage, ! make_numeric_value (delay)); ! ! blockage = operate_exp (MAX_OP, blockage, op->issue_exp); ! blockage = simplify_knowing (blockage, unit->condexp); ! ! /* Add this op's contribution to MAX (BLOCKAGE (E,*)) and ! MIN (BLOCKAGE (E,*)). */ ! if (max_blockage == 0) ! max_blockage = min_blockage = blockage; ! else ! { ! max_blockage ! = simplify_knowing (operate_exp (MAX_OP, max_blockage, ! blockage), ! unit->condexp); ! min_blockage ! = simplify_knowing (operate_exp (MIN_OP, min_blockage, ! blockage), ! unit->condexp); ! } ! ! /* Make an attribute for use in the blockage function. */ ! str = attr_printf (strlen (unit->name) + sizeof ("*_block_") + MAX_DIGITS, ! "*%s_block_%d", unit->name, op->num); ! make_internal_attr (str, blockage, 1); ! } ! ! /* Record MAX (BLOCKAGE (*,*)). */ ! unit->max_blockage = max_attr_value (max_blockage); ! ! /* See if the upper and lower bounds of BLOCKAGE (E,*) are the ! same. If so, the blockage function carries no additional ! information and is not written. */ ! newexp = operate_exp (EQ_OP, max_blockage, min_blockage); ! newexp = simplify_knowing (newexp, unit->condexp); ! unit->needs_blockage_function ! = (GET_CODE (newexp) != CONST_STRING ! || atoi (XSTR (newexp, 0)) != 1); ! ! /* If the all values of BLOCKAGE (E,C) have the same value, ! neither blockage function is written. */ ! unit->needs_range_function ! = (unit->needs_blockage_function ! || GET_CODE (max_blockage) != CONST_STRING); ! ! if (unit->needs_range_function) ! { ! /* Compute the blockage range function and make an attribute ! for writing it's value. */ ! newexp = operate_exp (RANGE_OP, min_blockage, max_blockage); ! newexp = simplify_knowing (newexp, unit->condexp); ! ! str = attr_printf (strlen (unit->name) + sizeof ("*_unit_blockage_range"), ! "*%s_unit_blockage_range", unit->name); ! make_internal_attr (str, newexp, 4); ! } ! ! str = attr_printf (strlen (unit->name) + sizeof ("*_unit_ready_cost"), ! "*%s_unit_ready_cost", unit->name); ! } ! else ! str = "*result_ready_cost"; ! ! /* Make an attribute for the ready_cost function. Simplifying ! further with simplify_by_exploding doesn't win. */ ! make_internal_attr (str, readycost, 0); ! } ! ! /* For each unit that requires a conflict cost function, make an attribute ! that maps insns to the operation number. */ for (unit = units; unit; unit = unit->next) { ! rtx caseexp; ! ! if (! unit->needs_conflict_function ! && ! unit->needs_blockage_function) ! continue; ! caseexp = rtx_alloc (COND); XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); for (op = unit->ops; op; op = op->next) { ! /* Make our adjustment to the COND being computed. If we are the ! last operation class, place our values into the default of the ! COND. */ if (op->num == unit->num_opclasses - 1) { XEXP (caseexp, 1) = make_numeric_value (op->num); } else { XVECEXP (caseexp, 0, op->num * 2) = op->condexp; XVECEXP (caseexp, 0, op->num * 2 + 1) *************** *** 1669,1692 **** } ! /* Make an attribute for the case number and ready delay. */ ! str = attr_printf (strlen (unit->name) + 8, "*%s_cases", unit->name); make_internal_attr (str, caseexp, 1); ! str = attr_printf (strlen (unit->name) + 20, "*%s_unit_ready_cost", ! unit->name); ! make_internal_attr (str, readyexp, 0); ! ! /* Merge this function unit into the ready cost and unit mask ! attributes. */ ! XEXP (newexp, 0) = check_attr_test (unit->condexp, 0); ! XEXP (newexp, 1) = make_numeric_value (1 << unit->num); ! unitsmask = operate_exp (OR_OP, unitsmask, newexp); ! XEXP (newexp, 1) = readyexp; ! readycost = operate_exp (MAX_OP, readycost, newexp); } ! make_internal_attr ("*function_units_used", unitsmask, 0); ! make_internal_attr ("*result_ready_cost", readycost, 0); } --- 2026,2113 ---- } ! /* Simplifying caseexp with simplify_by_exploding doesn't win. */ ! str = attr_printf (strlen (unit->name) + sizeof ("*_cases"), ! "*%s_cases", unit->name); make_internal_attr (str, caseexp, 1); + } + } ! /* Simplify EXP given KNOWN_TRUE. */ ! ! static rtx ! simplify_knowing (exp, known_true) ! rtx exp, known_true; ! { ! if (GET_CODE (exp) != CONST_STRING) ! { ! exp = attr_rtx (IF_THEN_ELSE, known_true, exp, ! make_numeric_value (max_attr_value (exp))); ! exp = simplify_by_exploding (exp); ! } ! return exp; ! } ! ! /* Translate the CONST_STRING expressions in X to change the encoding of ! value. On input, the value is a bitmask with a one bit for each unit ! used; on output, the value is the unit number (zero based) if one ! and only one unit is used or the one's compliment of the bitmask. */ ! ! static rtx ! encode_units_mask (x) ! rtx x; ! { ! register int i; ! register int j; ! register enum rtx_code code; ! register char *fmt; ! ! code = GET_CODE (x); ! ! switch (code) ! { ! case CONST_STRING: ! i = atoi (XSTR (x, 0)); ! if (i < 0) ! abort (); /* The sign bit encodes a one's compliment mask. */ ! else if (i != 0 && i == (i & -i)) ! /* Only one bit is set, so yield that unit number. */ ! for (j = 0; (i >>= 1) != 0; j++) ! ; ! else ! j = ~i; ! return attr_rtx (CONST_STRING, attr_printf (MAX_DIGITS, "%d", j)); ! case REG: ! case QUEUED: ! case CONST_INT: ! case CONST_DOUBLE: ! case SYMBOL_REF: ! case CODE_LABEL: ! case PC: ! case CC0: ! case EQ_ATTR: ! return x; } ! /* Compare the elements. If any pair of corresponding elements ! fail to match, return 0 for the whole things. */ ! ! fmt = GET_RTX_FORMAT (code); ! for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! { ! switch (fmt[i]) ! { ! case 'V': ! case 'E': ! for (j = 0; j < XVECLEN (x, i); j++) ! XVECEXP (x, i, j) = encode_units_mask (XVECEXP (x, i, j)); ! break; ! ! case 'e': ! XEXP (x, i) = encode_units_mask (XEXP (x, i)); ! break; ! } ! } ! return x; } *************** *** 1726,1730 **** av = get_attr_value (value, attr, id->insn_code); ! ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent)); ie->insn_code = id->insn_code; ie->insn_index = id->insn_code; --- 2147,2151 ---- av = get_attr_value (value, attr, id->insn_code); ! ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent)); ie->insn_code = id->insn_code; ie->insn_index = id->insn_code; *************** *** 1854,1858 **** address_fn[i]), new_attr, ie->insn_code); ! new_ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent)); new_ie->insn_code = ie->insn_code; new_ie->insn_index = ie->insn_index; --- 2275,2279 ---- address_fn[i]), new_attr, ie->insn_code); ! new_ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent)); new_ie->insn_code = ie->insn_code; new_ie->insn_index = ie->insn_index; *************** *** 1914,1918 **** rtx *tests = (rtx *) alloca (len * sizeof (rtx)); int allsame = 1; ! char *spacer, *first_spacer; /* This lets us free all storage allocated below, if appropriate. */ --- 2335,2339 ---- rtx *tests = (rtx *) alloca (len * sizeof (rtx)); int allsame = 1; ! char *first_spacer; /* This lets us free all storage allocated below, if appropriate. */ *************** *** 2166,2170 **** rtx newexp; int i; - char *alternative; /* Find the bit. */ --- 2587,2590 ---- *************** *** 2789,2793 **** struct attr_desc *attr; struct attr_value *av; ! struct insn_ent *ie, *nextie; rtx newexp; int something_changed = 1; --- 3209,3213 ---- struct attr_desc *attr; struct attr_value *av; ! struct insn_ent *ie; rtx newexp; int something_changed = 1; *************** *** 2877,2880 **** --- 3297,3301 ---- } + #if 0 static rtx simplify_by_alternatives (exp, insn_code, insn_index) *************** *** 2908,2911 **** --- 3329,3810 ---- return simplify_cond (newexp, insn_code, insn_index); } + #endif + + /* An expression where all the unknown terms are EQ_ATTR tests can be + rearranged into a COND provided we can enumerate all possible + combinations of the unknown values. The set of combinations become the + tests of the COND; the value of the expression given that combination is + computed and becomes the corresponding value. To do this, we must be + able to enumerate all values for each attribute used in the expression + (currently, we give up if we find a numeric attribute). + + If the set of EQ_ATTR tests used in an expression tests the value of N + different attributes, the list of all possible combinations can be made + by walking the N-dimensional attribute space defined by those + attributes. We record each of these as a struct dimension. + + The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an + expression are the same, the will also have the same address. We find + all the EQ_ATTR nodes by marking them MEM_VOLATILE_P. This bit later + represents the value of an EQ_ATTR node, so once all nodes are marked, + they are also given an initial value of FALSE. + + We then separate the set of EQ_ATTR nodes into dimensions for each + attribute and put them on the VALUES list. Terms are added as needed by + `add_values_to_cover' so that all possible values of the attribute are + tested. + + Each dimension also has a current value. This is the node that is + currently considered to be TRUE. If this is one of the nodes added by + `add_values_to_cover', all the EQ_ATTR tests in the original expression + will be FALSE. Otherwise, only the CURRENT_VALUE will be true. + + NUM_VALUES is simply the length of the VALUES list and is there for + convenience. + + Once the dimensions are created, the algorithm enumerates all possible + values and computes the current value of the given expression. */ + + struct dimension + { + struct attr_desc *attr; /* Attribute for this dimension. */ + rtx values; /* List of attribute values used. */ + rtx current_value; /* Position in the list for the TRUE value. */ + int num_values; /* Length of the values list. */ + }; + + /* If EXP is a suitable expression, reorganize it by constructing an + equivalent expression that is a COND with the tests being all combinations + of attribute values and the values being simple constants. */ + + static rtx + simplify_by_exploding (exp) + rtx exp; + { + rtx list = 0, link, condexp, defval; + struct dimension *space; + rtx *condtest, *condval; + int i, j, total, ndim = 0; + int most_tests, num_marks, new_marks; + + /* Locate all the EQ_ATTR expressions. */ + if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0) + { + unmark_used_attributes (list, 0, 0); + return exp; + } + + /* Create an attribute space from the list of used attributes. For each + dimension in the attribute space, record the attribute, list of values + used, and number of values used. Add members to the list of values to + cover the domain of the attribute. This makes the expanded COND form + order independent. */ + + space = (struct dimension *) alloca (ndim * sizeof (struct dimension)); + + total = 1; + for (ndim = 0; list; ndim++) + { + /* Pull the first attribute value from the list and record that + attribute as another dimension in the attribute space. */ + char *name = XSTR (XEXP (list, 0), 0); + rtx *prev; + + if ((space[ndim].attr = find_attr (name, 0)) == 0 + || space[ndim].attr->is_numeric) + { + unmark_used_attributes (list, space, ndim); + return exp; + } + + /* Add all remaining attribute values that refer to this attribute. */ + space[ndim].num_values = 0; + space[ndim].values = 0; + prev = &list; + for (link = list; link; link = *prev) + if (! strcmp (XSTR (XEXP (link, 0), 0), name)) + { + space[ndim].num_values++; + *prev = XEXP (link, 1); + XEXP (link, 1) = space[ndim].values; + space[ndim].values = link; + } + else + prev = &XEXP (link, 1); + + /* Add sufficient members to the list of values to make the list + mutually exclusive and record the total size of the attribute + space. */ + total *= add_values_to_cover (&space[ndim]); + } + + /* Sort the attribute space so that the attributes go from non-constant + to constant and from most values to least values. */ + for (i = 0; i < ndim; i++) + for (j = ndim - 1; j > i; j--) + if ((space[j-1].attr->is_const && !space[j].attr->is_const) + || space[j-1].num_values < space[j].num_values) + { + struct dimension tmp; + tmp = space[j]; + space[j] = space[j-1]; + space[j-1] = tmp; + } + + /* Establish the initial current value. */ + for (i = 0; i < ndim; i++) + space[i].current_value = space[i].values; + + condtest = (rtx *) alloca (total * sizeof (rtx)); + condval = (rtx *) alloca (total * sizeof (rtx)); + + /* Expand the tests and values by iterating over all values in the + attribute space. */ + for (i = 0;; i++) + { + condtest[i] = test_for_current_value (space, ndim); + condval[i] = simplify_with_current_value (exp, space, ndim); + if (! increment_current_value (space, ndim)) + break; + } + if (i != total - 1) + abort (); + + /* We are now finished with the original expression. */ + unmark_used_attributes (0, space, ndim); + + /* Find the most used constant value and make that the default. */ + most_tests = -1; + for (i = num_marks = 0; i < total; i++) + if (GET_CODE (condval[i]) == CONST_STRING + && ! MEM_VOLATILE_P (condval[i])) + { + /* Mark the unmarked constant value and count how many are marked. */ + MEM_VOLATILE_P (condval[i]) = 1; + for (j = new_marks = 0; j < total; j++) + if (GET_CODE (condval[j]) == CONST_STRING + && MEM_VOLATILE_P (condval[j])) + new_marks++; + if (new_marks - num_marks > most_tests) + { + most_tests = new_marks - num_marks; + defval = condval[i]; + } + num_marks = new_marks; + } + /* Clear all the marks. */ + for (i = 0; i < total; i++) + MEM_VOLATILE_P (condval[i]) = 0; + + /* Give up if nothing is constant. */ + if (num_marks == 0) + return exp; + + /* If all values are the default, use that. */ + if (total == most_tests) + return defval; + + /* Make a COND with the most common constant value the default. (A more + complex method where tests with the same value were combined didn't + seem to improve things.) */ + condexp = rtx_alloc (COND); + XVEC (condexp, 0) = rtvec_alloc ((total - most_tests) * 2); + XEXP (condexp, 1) = defval; + for (i = j = 0; i < total; i++) + if (condval[i] != defval) + { + XVECEXP (condexp, 0, 2 * j) = condtest[i]; + XVECEXP (condexp, 0, 2 * j + 1) = condval[i]; + j++; + } + + return condexp; + } + + /* Set the MEM_VOLATILE_P flag for all EQ_ATTR expressions in EXP and + verify that EXP can be simplified to a constant term if all the EQ_ATTR + tests have known value. */ + + static int + find_and_mark_used_attributes (exp, terms, nterms) + rtx exp, *terms; + int *nterms; + { + int i; + + switch (GET_CODE (exp)) + { + case EQ_ATTR: + if (! MEM_VOLATILE_P (exp)) + { + rtx link = rtx_alloc (EXPR_LIST); + XEXP (link, 0) = exp; + XEXP (link, 1) = *terms; + *terms = link; + *nterms += 1; + MEM_VOLATILE_P (exp) = 1; + } + case CONST_STRING: + return 1; + + case IF_THEN_ELSE: + if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms)) + return 0; + case IOR: + case AND: + if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms)) + return 0; + case NOT: + if (! find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms)) + return 0; + return 1; + + case COND: + for (i = 0; i < XVECLEN (exp, 0); i++) + if (! find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms)) + return 0; + if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms)) + return 0; + return 1; + } + + return 0; + } + + /* Clear the MEM_VOLATILE_P flag in all EQ_ATTR expressions on LIST and + in the values of the NDIM-dimensional attribute space SPACE. */ + + static void + unmark_used_attributes (list, space, ndim) + rtx list; + struct dimension *space; + int ndim; + { + rtx link, exp; + int i; + + for (i = 0; i < ndim; i++) + unmark_used_attributes (space[i].values, 0, 0); + + for (link = list; link; link = XEXP (link, 1)) + { + exp = XEXP (link, 0); + if (GET_CODE (exp) == EQ_ATTR) + MEM_VOLATILE_P (exp) = 0; + } + } + + /* Update the attribute dimension DIM so that all values of the attribute + are tested. Return the updated number of values. */ + + static int + add_values_to_cover (dim) + struct dimension *dim; + { + struct attr_value *av; + rtx exp, link, *prev; + int nalt = 0; + + for (av = dim->attr->first_value; av; av = av->next) + if (GET_CODE (av->value) == CONST_STRING) + nalt++; + + if (nalt < dim->num_values) + abort (); + else if (nalt == dim->num_values) + ; /* Ok. */ + else if (nalt * 2 < dim->num_values * 3) + { + /* Most all the values of the attribute are used, so add all the unused + values. */ + prev = &dim->values; + for (link = dim->values; link; link = *prev) + prev = &XEXP (link, 1); + + for (av = dim->attr->first_value; av; av = av->next) + if (GET_CODE (av->value) == CONST_STRING) + { + exp = attr_eq (dim->attr->name, XSTR (av->value, 0)); + if (MEM_VOLATILE_P (exp)) + continue; + + link = rtx_alloc (EXPR_LIST); + XEXP (link, 0) = exp; + XEXP (link, 1) = 0; + *prev = link; + prev = &XEXP (link, 1); + } + dim->num_values = nalt; + } + else + { + rtx orexp = false_rtx; + + /* Very few values are used, so compute a mutually exclusive + expression. (We could do this for numeric values if that becomes + important.) */ + prev = &dim->values; + for (link = dim->values; link; link = *prev) + { + orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2); + prev = &XEXP (link, 1); + } + link = rtx_alloc (EXPR_LIST); + XEXP (link, 0) = attr_rtx (NOT, orexp); + XEXP (link, 1) = 0; + *prev = link; + dim->num_values++; + } + return dim->num_values; + } + + /* Increment the current value for the NDIM-dimensional attribute space SPACE + and return FALSE if the increment overflowed. */ + + static int + increment_current_value (space, ndim) + struct dimension *space; + int ndim; + { + int i; + + for (i = ndim - 1; i >= 0; i--) + { + if ((space[i].current_value = XEXP (space[i].current_value, 1)) == 0) + space[i].current_value = space[i].values; + else + return 1; + } + return 0; + } + + /* Construct an expression corresponding to the current value for the + NDIM-dimensional attribute space SPACE. */ + + static rtx + test_for_current_value (space, ndim) + struct dimension *space; + int ndim; + { + int i; + rtx exp = true_rtx; + + for (i = 0; i < ndim; i++) + exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0), -2); + + return exp; + } + + /* Given the current value of the NDIM-dimensional attribute space SPACE, + set the corresponding EQ_ATTR expressions to that value and reduce + the expression EXP as much as possible. On input [and output], all + known EQ_ATTR expressions are set to FALSE. */ + + static rtx + simplify_with_current_value (exp, space, ndim) + rtx exp; + struct dimension *space; + int ndim; + { + int i; + rtx x; + + /* Mark each current value as TRUE. */ + for (i = 0; i < ndim; i++) + { + x = XEXP (space[i].current_value, 0); + if (GET_CODE (x) == EQ_ATTR) + MEM_VOLATILE_P (x) = 0; + } + + exp = simplify_with_current_value_aux (exp); + + /* Change each current value back to FALSE. */ + for (i = 0; i < ndim; i++) + { + x = XEXP (space[i].current_value, 0); + if (GET_CODE (x) == EQ_ATTR) + MEM_VOLATILE_P (x) = 1; + } + + return exp; + } + + /* Reduce the expression EXP based on the MEM_VOLATILE_P settings of + all EQ_ATTR expressions. */ + + static rtx + simplify_with_current_value_aux (exp) + rtx exp; + { + register int i; + rtx cond; + + switch (GET_CODE (exp)) + { + case EQ_ATTR: + if (MEM_VOLATILE_P (exp)) + return false_rtx; + else + return true_rtx; + case CONST_STRING: + return exp; + + case IF_THEN_ELSE: + cond = simplify_with_current_value_aux (XEXP (exp, 0)); + if (cond == true_rtx) + return simplify_with_current_value_aux (XEXP (exp, 1)); + else if (cond == false_rtx) + return simplify_with_current_value_aux (XEXP (exp, 2)); + else + return attr_rtx (IF_THEN_ELSE, cond, + simplify_with_current_value_aux (XEXP (exp, 1)), + simplify_with_current_value_aux (XEXP (exp, 2))); + + case IOR: + cond = simplify_with_current_value_aux (XEXP (exp, 1)); + if (cond == true_rtx) + return cond; + else if (cond == false_rtx) + return simplify_with_current_value_aux (XEXP (exp, 0)); + else + return attr_rtx (IOR, cond, + simplify_with_current_value_aux (XEXP (exp, 0))); + + case AND: + cond = simplify_with_current_value_aux (XEXP (exp, 1)); + if (cond == true_rtx) + return simplify_with_current_value_aux (XEXP (exp, 0)); + else if (cond == false_rtx) + return cond; + else + return attr_rtx (AND, cond, + simplify_with_current_value_aux (XEXP (exp, 0))); + + case NOT: + cond = simplify_with_current_value_aux (XEXP (exp, 0)); + if (cond == true_rtx) + return false_rtx; + else if (cond == false_rtx) + return true_rtx; + else + return attr_rtx (NOT, cond); + + case COND: + for (i = 0; i < XVECLEN (exp, 0); i += 2) + { + cond = simplify_with_current_value_aux (XVECEXP (exp, 0, i)); + if (cond == true_rtx) + return simplify_with_current_value_aux (XVECEXP (exp, 0, i + 1)); + else if (cond == false_rtx) + continue; + else + abort (); /* With all EQ_ATTR's of known value, a case should + have been selected. */ + } + return simplify_with_current_value_aux (XEXP (exp, 1)); + } + abort (); + } /* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */ *************** *** 3039,3043 **** while ((p = next_comma_elt (&name_ptr)) != NULL) { ! av = (struct attr_value *) xmalloc (sizeof (struct attr_value)); av->value = attr_rtx (CONST_STRING, p); av->next = attr->first_value; --- 3938,3942 ---- while ((p = next_comma_elt (&name_ptr)) != NULL) { ! av = (struct attr_value *) oballoc (sizeof (struct attr_value)); av->value = attr_rtx (CONST_STRING, p); av->next = attr->first_value; *************** *** 3179,3183 **** struct insn_def *id; ! id = (struct insn_def *) xmalloc (sizeof (struct insn_def)); id->next = defs; defs = id; --- 4078,4082 ---- struct insn_def *id; ! id = (struct insn_def *) oballoc (sizeof (struct insn_def)); id->next = defs; defs = id; *************** *** 3235,3239 **** } ! delay = (struct delay_desc *) xmalloc (sizeof (struct delay_desc)); delay->def = def; delay->num = ++num_delays; --- 4134,4138 ---- } ! delay = (struct delay_desc *) oballoc (sizeof (struct delay_desc)); delay->def = def; delay->num = ++num_delays; *************** *** 3254,3257 **** --- 4153,4162 ---- struct function_unit *unit; struct function_unit_op *op; + char *name = XSTR (def, 0); + int multiplicity = XINT (def, 1); + int simultaneity = XINT (def, 2); + rtx condexp = XEXP (def, 3); + int ready_cost = MAX (XINT (def, 4), 1); + int issue_delay = MAX (XINT (def, 5), 1); /* See if we have already seen this function unit. If so, check that *************** *** 3259,3266 **** a structure for this function unit. */ for (unit = units; unit; unit = unit->next) ! if (! strcmp (unit->name, XSTR (def, 0))) { ! if (unit->multiplicity != XINT (def, 1) ! || unit->simultaneity != XINT (def, 2)) fatal ("Differing specifications given for `%s' function unit.", unit->name); --- 4164,4171 ---- a structure for this function unit. */ for (unit = units; unit; unit = unit->next) ! if (! strcmp (unit->name, name)) { ! if (unit->multiplicity != multiplicity ! || unit->simultaneity != simultaneity) fatal ("Differing specifications given for `%s' function unit.", unit->name); *************** *** 3270,3277 **** if (unit == 0) { ! unit = (struct function_unit *) xmalloc (sizeof (struct function_unit)); ! unit->name = XSTR (def, 0); ! unit->multiplicity = XINT (def, 1); ! unit->simultaneity = XINT (def, 2); unit->num = num_units++; unit->num_opclasses = 0; --- 4175,4183 ---- if (unit == 0) { ! unit = (struct function_unit *) oballoc (sizeof (struct function_unit)); ! unit->name = name; ! unit->multiplicity = multiplicity; ! unit->simultaneity = simultaneity; ! unit->issue_delay.min = unit->issue_delay.max = issue_delay; unit->num = num_units++; unit->num_opclasses = 0; *************** *** 3283,3294 **** /* Make a new operation class structure entry and initialize it. */ ! op = (struct function_unit_op *) xmalloc (sizeof (struct function_unit_op)); ! op->condexp = XEXP (def, 3); op->num = unit->num_opclasses++; ! op->ready = XINT (def, 4); op->next = unit->ops; unit->ops = op; ! /* Set our busy expression based on whether or not an optional conflict vector was specified. */ if (XVEC (def, 6)) --- 4189,4201 ---- /* Make a new operation class structure entry and initialize it. */ ! op = (struct function_unit_op *) oballoc (sizeof (struct function_unit_op)); ! op->condexp = condexp; op->num = unit->num_opclasses++; ! op->ready = ready_cost; ! op->issue_delay = issue_delay; op->next = unit->ops; unit->ops = op; ! /* Set our issue expression based on whether or not an optional conflict vector was specified. */ if (XVEC (def, 6)) *************** *** 3301,3310 **** orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2); ! op->busyexp = attr_rtx (IF_THEN_ELSE, orexp, ! make_numeric_value (XINT (def, 5)), ! make_numeric_value (0)); } else ! op->busyexp = make_numeric_value (XINT (def, 5)); /* Merge our conditional into that of the function unit so we can determine --- 4208,4219 ---- orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2); ! op->conflict_exp = orexp; ! extend_range (&unit->issue_delay, 1, issue_delay); } else ! { ! op->conflict_exp = true_rtx; ! extend_range (&unit->issue_delay, issue_delay, issue_delay); ! } /* Merge our conditional into that of the function unit so we can determine *************** *** 3500,3504 **** /* Constant integer. */ case CONST_INT: ! printf ("%d", XINT (exp, 0)); break; --- 4409,4417 ---- /* Constant integer. */ case CONST_INT: ! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! printf ("%d", XWINT (exp, 0)); ! #else ! printf ("%ld", XWINT (exp, 0)); ! #endif break; *************** *** 3557,3560 **** --- 4470,4481 ---- } + else if (GET_CODE (exp) == IF_THEN_ELSE) + { + current_max = max_attr_value (XEXP (exp, 1)); + n = max_attr_value (XEXP (exp, 2)); + if (n > current_max) + current_max = n; + } + else abort (); *************** *** 3570,3573 **** --- 4491,4495 ---- `must_constrain' if we must compute `which_alternative' `address_used' if an address expression was used + `length_used' if an (eq_attr "length" ...) was used */ *************** *** 3601,3604 **** --- 4523,4528 ---- if (XSTR (exp, 0) == alternative_name) must_extract = must_constrain = 1; + else if (strcmp (XSTR (exp, 0), "length") == 0) + length_used = 1; return; *************** *** 3639,3646 **** /* Write out start of function, then all values with explicit `case' lines, then a `default', then the value with the most uses. */ ! if (attr->is_numeric) ! printf ("int\n"); ! else printf ("enum attr_%s\n", attr->name); /* If the attribute name starts with a star, the remainder is the name of --- 4563,4572 ---- /* Write out start of function, then all values with explicit `case' lines, then a `default', then the value with the most uses. */ ! if (!attr->is_numeric) printf ("enum attr_%s\n", attr->name); + else if (attr->unsigned_p) + printf ("unsigned int\n"); + else + printf ("int\n"); /* If the attribute name starts with a star, the remainder is the name of *************** *** 3851,3855 **** } ! /* See what we have to do to handle output this value. */ must_extract = must_constrain = address_used = 0; walk_attr_value (av->value); --- 4777,4781 ---- } ! /* See what we have to do to output this value. */ must_extract = must_constrain = address_used = 0; walk_attr_value (av->value); *************** *** 3891,3895 **** { if (attr->is_numeric) ! printf ("%s", s); else { --- 4817,4826 ---- { if (attr->is_numeric) ! { ! printf ("%s", s); ! /* Make the blockage range values easier to read. */ ! if (strlen (s) > 1) ! printf (" /* 0x%x */", atoi (s)); ! } else { *************** *** 4066,4201 **** { struct function_unit *unit; - struct attr_desc *case_attr, *attr; - struct attr_value *av, *common_av; - rtx value; - char *str; - int using_case; int i; /* Write out conflict routines for function units. Don't bother writing ! one if there is only one busy value. */ for (unit = units; unit; unit = unit->next) { ! /* See if only one case exists and if there is a constant value for ! that case. If so, we don't need a function. */ ! str = (char *) alloca (strlen (unit->name) + 10); ! sprintf (str, "*%s_cases", unit->name); ! attr = find_attr (str, 0); ! if (! attr) abort (); ! value = find_single_value (attr); ! if (value && GET_CODE (value) == CONST_STRING) { ! sprintf (str, "*%s_case_%s", unit->name, XSTR (value, 0)); ! attr = find_attr (str, 0); ! if (! attr) abort (); ! value = find_single_value (attr); ! if (value && GET_CODE (value) == CONST_STRING) ! { ! unit->needs_conflict_function = 0; ! unit->default_cost = value; ! continue; ! } } /* The function first computes the case from the candidate insn. */ - unit->needs_conflict_function = 1; unit->default_cost = make_numeric_value (0); ! printf ("static int\n"); ! printf ("%s_unit_conflict_cost (executing_insn, candidate_insn)\n", ! unit->name); ! printf (" rtx executing_insn;\n"); ! printf (" rtx candidate_insn;\n"); ! printf ("{\n"); ! printf (" rtx insn;\n"); ! printf (" int casenum;\n\n"); ! printf (" insn = candidate_insn;\n"); ! printf (" switch (recog_memoized (insn))\n"); ! printf (" {\n"); ! /* Write the `switch' statement to get the case value. */ ! sprintf (str, "*%s_cases", unit->name); ! case_attr = find_attr (str, 0); ! if (! case_attr) abort (); ! common_av = find_most_used (case_attr); ! for (av = case_attr->first_value; av; av = av->next) ! if (av != common_av) ! write_attr_case (case_attr, av, 1, ! "casenum =", ";", 4, unit->condexp); ! write_attr_case (case_attr, common_av, 0, ! "casenum =", ";", 4, unit->condexp); ! printf (" }\n\n"); ! /* Now write an outer switch statement on each case. Then write ! the tests on the executing function within each. */ ! printf (" insn = executing_insn;\n"); ! printf (" switch (casenum)\n"); ! printf (" {\n"); ! for (i = 0; i < unit->num_opclasses; i++) ! { ! /* Ensure using this case. */ ! using_case = 0; ! for (av = case_attr->first_value; av; av = av->next) ! if (av->num_insns ! && contained_in_p (make_numeric_value (i), av->value)) ! using_case = 1; ! if (! using_case) ! continue; ! printf (" case %d:\n", i); ! sprintf (str, "*%s_case_%d", unit->name, i); ! attr = find_attr (str, 0); ! if (! attr) abort (); ! ! /* If single value, just write it. */ ! value = find_single_value (attr); ! if (value) ! write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2); ! else ! { ! common_av = find_most_used (attr); ! printf (" switch (recog_memoized (insn))\n"); ! printf ("\t{\n"); ! for (av = attr->first_value; av; av = av->next) ! if (av != common_av) ! write_attr_case (attr, av, 1, ! "return", ";", 8, unit->condexp); ! write_attr_case (attr, common_av, 0, ! "return", ";", 8, unit->condexp); ! printf (" }\n\n"); ! } ! } ! printf (" }\n}\n\n"); ! } ! /* Now that all functions have been written, write the table describing ! the function units. The name is included for documentation purposes ! only. */ ! printf ("struct function_unit_desc function_units[] = {\n"); ! for (unit = units; unit; unit = unit->next) { ! printf (" {\"%s\", %d, %d, %d, %s, %s_unit_ready_cost, ", ! unit->name, 1 << unit->num, unit->multiplicity, ! unit->simultaneity, XSTR (unit->default_cost, 0), unit->name); ! if (unit->needs_conflict_function) ! printf ("%s_unit_conflict_cost", unit->name); else ! printf ("0"); ! printf ("}, \n"); } ! printf ("};\n\n"); } --- 4997,5150 ---- { struct function_unit *unit; int i; /* Write out conflict routines for function units. Don't bother writing ! one if there is only one issue delay value. */ for (unit = units; unit; unit = unit->next) { ! if (unit->needs_blockage_function) ! write_complex_function (unit, "blockage", "block"); ! ! /* If the minimum and maximum conflict costs are the same, there ! is only one value, so we don't need a function. */ ! if (! unit->needs_conflict_function) { ! unit->default_cost = make_numeric_value (unit->issue_delay.max); ! continue; } /* The function first computes the case from the candidate insn. */ unit->default_cost = make_numeric_value (0); + write_complex_function (unit, "conflict_cost", "cost"); + } ! /* Now that all functions have been written, write the table describing ! the function units. The name is included for documentation purposes ! only. */ ! printf ("struct function_unit_desc function_units[] = {\n"); ! /* Write out the descriptions in numeric order, but don't force that order ! on the list. Doing so increases the runtime of genattrtab.c. */ ! for (i = 0; i < num_units; i++) ! { ! for (unit = units; unit; unit = unit->next) ! if (unit->num == i) ! break; ! printf (" {\"%s\", %d, %d, %d, %s, %d, %s_unit_ready_cost, ", ! unit->name, 1 << unit->num, unit->multiplicity, ! unit->simultaneity, XSTR (unit->default_cost, 0), ! unit->issue_delay.max, unit->name); ! if (unit->needs_conflict_function) ! printf ("%s_unit_conflict_cost, ", unit->name); ! else ! printf ("0, "); ! printf ("%d, ", unit->max_blockage); ! if (unit->needs_range_function) ! printf ("%s_unit_blockage_range, ", unit->name); ! else ! printf ("0, "); ! if (unit->needs_blockage_function) ! printf ("%s_unit_blockage", unit->name); ! else ! printf ("0"); ! printf ("}, \n"); ! } ! printf ("};\n\n"); ! } ! static void ! write_complex_function (unit, name, connection) ! struct function_unit *unit; ! char *name, *connection; ! { ! struct attr_desc *case_attr, *attr; ! struct attr_value *av, *common_av; ! rtx value; ! char *str; ! int using_case; ! int i; ! printf ("static int\n"); ! printf ("%s_unit_%s (executing_insn, candidate_insn)\n", ! unit->name, name); ! printf (" rtx executing_insn;\n"); ! printf (" rtx candidate_insn;\n"); ! printf ("{\n"); ! printf (" rtx insn;\n"); ! printf (" int casenum;\n\n"); ! printf (" insn = candidate_insn;\n"); ! printf (" switch (recog_memoized (insn))\n"); ! printf (" {\n"); ! /* Write the `switch' statement to get the case value. */ ! str = (char *) alloca (strlen (unit->name) + strlen (name) + strlen (connection) + 10); ! sprintf (str, "*%s_cases", unit->name); ! case_attr = find_attr (str, 0); ! if (! case_attr) abort (); ! common_av = find_most_used (case_attr); ! for (av = case_attr->first_value; av; av = av->next) ! if (av != common_av) ! write_attr_case (case_attr, av, 1, ! "casenum =", ";", 4, unit->condexp); ! ! write_attr_case (case_attr, common_av, 0, ! "casenum =", ";", 4, unit->condexp); ! printf (" }\n\n"); ! ! /* Now write an outer switch statement on each case. Then write ! the tests on the executing function within each. */ ! printf (" insn = executing_insn;\n"); ! printf (" switch (casenum)\n"); ! printf (" {\n"); ! ! for (i = 0; i < unit->num_opclasses; i++) { ! /* Ensure using this case. */ ! using_case = 0; ! for (av = case_attr->first_value; av; av = av->next) ! if (av->num_insns ! && contained_in_p (make_numeric_value (i), av->value)) ! using_case = 1; ! if (! using_case) ! continue; ! ! printf (" case %d:\n", i); ! sprintf (str, "*%s_%s_%d", unit->name, connection, i); ! attr = find_attr (str, 0); ! if (! attr) abort (); ! ! /* If single value, just write it. */ ! value = find_single_value (attr); ! if (value) ! write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2); else ! { ! common_av = find_most_used (attr); ! printf (" switch (recog_memoized (insn))\n"); ! printf ("\t{\n"); ! ! for (av = attr->first_value; av; av = av->next) ! if (av != common_av) ! write_attr_case (attr, av, 1, ! "return", ";", 8, unit->condexp); ! write_attr_case (attr, common_av, 0, ! "return", ";", 8, unit->condexp); ! printf (" }\n\n"); ! } } ! printf (" }\n}\n\n"); } *************** *** 4277,4284 **** return NULL; ! attr = (struct attr_desc *) xmalloc (sizeof (struct attr_desc)); attr->name = attr_string (name, strlen (name)); attr->first_value = attr->default_val = NULL; ! attr->is_numeric = attr->is_const = attr->is_special = 0; attr->next = attrs[index]; attrs[index] = attr; --- 5226,5233 ---- return NULL; ! attr = (struct attr_desc *) oballoc (sizeof (struct attr_desc)); attr->name = attr_string (name, strlen (name)); attr->first_value = attr->default_val = NULL; ! attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0; attr->next = attrs[index]; attrs[index] = attr; *************** *** 4303,4307 **** attr->is_numeric = 1; attr->is_const = 0; ! attr->is_special = special; attr->default_val = get_attr_value (value, attr, -2); } --- 5252,5258 ---- attr->is_numeric = 1; attr->is_const = 0; ! attr->is_special = (special & 1) != 0; ! attr->negative_ok = (special & 2) != 0; ! attr->unsigned_p = (special & 4) != 0; attr->default_val = get_attr_value (value, attr, -2); } *************** *** 4366,4370 **** return int_values[n]; ! p = attr_printf ((n < 1000 ? 4 : HOST_BITS_PER_INT * 3 / 10 + 3), "%d", n); exp = attr_rtx (CONST_STRING, p); --- 5317,5321 ---- return int_values[n]; ! p = attr_printf (MAX_DIGITS, "%d", n); exp = attr_rtx (CONST_STRING, p); *************** *** 4375,4378 **** --- 5326,5339 ---- } + static void + extend_range (range, min, max) + struct range *range; + int min; + int max; + { + if (range->min > min) range->min = min; + if (range->max < max) range->max = max; + } + char * xrealloc (ptr, size) *************** *** 4401,4406 **** --- 5362,5369 ---- register rtx orig; { + #if 0 register rtx copy; register RTX_CODE code; + #endif if (RTX_UNCHANGING_P (orig) || MEM_IN_STRUCT_P (orig)) *************** *** 4449,4452 **** --- 5412,5454 ---- fatal ("Internal gcc abort."); } + + /* Determine if an insn has a constant number of delay slots, i.e., the + number of delay slots is not a function of the length of the insn. */ + + void + write_const_num_delay_slots () + { + struct attr_desc *attr = find_attr ("*num_delay_slots", 0); + struct attr_value *av; + struct insn_ent *ie; + int i; + + if (attr) + { + printf ("int\nconst_num_delay_slots (insn)\n"); + printf (" rtx *insn;\n"); + printf ("{\n"); + printf (" switch (recog_memoized (insn))\n"); + printf (" {\n"); + + for (av = attr->first_value; av; av = av->next) + { + length_used = 0; + walk_attr_value (av->value); + if (length_used) + { + for (ie = av->first_insn; ie; ie = ie->next) + if (ie->insn_code != -1) + printf (" case %d:\n", ie->insn_code); + printf (" return 0;\n"); + } + } + + printf (" default:\n"); + printf (" return 1;\n"); + printf (" }\n}\n"); + } + } + int *************** *** 4459,4463 **** register int c; struct attr_desc *attr; - struct attr_value *av; struct insn_def *id; rtx tem; --- 5461,5464 ---- *************** *** 4482,4488 **** /* Set up true and false rtx's */ true_rtx = rtx_alloc (CONST_INT); ! XINT (true_rtx, 0) = 1; false_rtx = rtx_alloc (CONST_INT); ! XINT (false_rtx, 0) = 0; RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1; RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1; --- 5483,5489 ---- /* Set up true and false rtx's */ true_rtx = rtx_alloc (CONST_INT); ! XWINT (true_rtx, 0) = 1; false_rtx = rtx_alloc (CONST_INT); ! XWINT (false_rtx, 0) = 0; RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1; RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1; *************** *** 4561,4565 **** /* Make `insn_alternatives'. */ ! insn_alternatives = (int *) xmalloc (insn_code_number * sizeof (int)); for (id = defs; id; id = id->next) if (id->insn_code >= 0) --- 5562,5566 ---- /* Make `insn_alternatives'. */ ! insn_alternatives = (int *) oballoc (insn_code_number * sizeof (int)); for (id = defs; id; id = id->next) if (id->insn_code >= 0) *************** *** 4567,4571 **** /* Make `insn_n_alternatives'. */ ! insn_n_alternatives = (int *) xmalloc (insn_code_number * sizeof (int)); for (id = defs; id; id = id->next) if (id->insn_code >= 0) --- 5568,5572 ---- /* Make `insn_n_alternatives'. */ ! insn_n_alternatives = (int *) oballoc (insn_code_number * sizeof (int)); for (id = defs; id; id = id->next) if (id->insn_code >= 0) *************** *** 4616,4619 **** --- 5617,5623 ---- if (num_units) write_function_unit_info (); + + /* Write out constant delay slot info */ + write_const_num_delay_slots (); fflush (stdout); diff -rc2N gcc-2.2.2/gencodes.c gcc-2.3.1/gencodes.c *** gcc-2.2.2/gencodes.c Mon Apr 27 15:09:04 1992 --- gcc-2.3.1/gencodes.c Tue Oct 13 00:11:44 1992 *************** *** 23,27 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 23,27 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" diff -rc2N gcc-2.2.2/genconfig.c gcc-2.3.1/genconfig.c *** gcc-2.2.2/genconfig.c Sat May 23 14:15:06 1992 --- gcc-2.3.1/genconfig.c Tue Oct 13 00:11:48 1992 *************** *** 22,26 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 22,26 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 41,44 **** --- 41,45 ---- static int register_constraint_flag; static int have_cc0_flag; + static int have_cmove_flag; static int have_lo_sum_flag; *************** *** 54,62 **** /* RECOG_P will be non-zero if this pattern was seen in a context where it will ! be used to recognize, rather than just generate an insn. */ static void ! walk_insn_part (part, recog_p) rtx part; { register int i, j; --- 55,68 ---- /* RECOG_P will be non-zero if this pattern was seen in a context where it will ! be used to recognize, rather than just generate an insn. + NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC + of a SET whose destination is not (pc). */ + static void ! walk_insn_part (part, recog_p, non_pc_set_src) rtx part; + int recog_p; + int non_pc_set_src; { register int i, j; *************** *** 82,85 **** --- 88,92 ---- case MATCH_OP_DUP: + case MATCH_PAR_DUP: ++dup_operands_seen_this_insn; case MATCH_SCRATCH: *************** *** 113,116 **** --- 120,142 ---- return; + case SET: + walk_insn_part (SET_DEST (part), 0, recog_p); + walk_insn_part (SET_SRC (part), recog_p, + GET_CODE (SET_DEST (part)) != PC); + return; + + case IF_THEN_ELSE: + /* Only consider this machine as having a conditional move if the + two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, + we have some specific IF_THEN_ELSE construct (like the doz + instruction on the RS/6000) that can't be used in the general + context we want it for. */ + + if (recog_p && non_pc_set_src + && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND + && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) + have_cmove_flag = 1; + break; + case REG: case CONST_INT: case SYMBOL_REF: case PC: *************** *** 125,134 **** case 'e': case 'u': ! walk_insn_part (XEXP (part, i), recog_p); break; case 'E': if (XVEC (part, i) != NULL) for (j = 0; j < XVECLEN (part, i); j++) ! walk_insn_part (XVECEXP (part, i, j), recog_p); break; } --- 151,160 ---- case 'e': case 'u': ! walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); break; case 'E': if (XVEC (part, i) != NULL) for (j = 0; j < XVECLEN (part, i); j++) ! walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); break; } *************** *** 146,150 **** if (XVEC (insn, 1) != 0) for (i = 0; i < XVECLEN (insn, 1); i++) ! walk_insn_part (XVECEXP (insn, 1, i), 1); if (clobbers_seen_this_insn > max_clobbers_per_insn) --- 172,176 ---- if (XVEC (insn, 1) != 0) for (i = 0; i < XVECLEN (insn, 1); i++) ! walk_insn_part (XVECEXP (insn, 1, i), 1, 0); if (clobbers_seen_this_insn > max_clobbers_per_insn) *************** *** 174,178 **** clobbers_seen_this_insn = 0; ! walk_insn_part (XVECEXP (insn, 1, i), 0); if (clobbers_seen_this_insn > max_clobbers_per_insn) --- 200,204 ---- clobbers_seen_this_insn = 0; ! walk_insn_part (XVECEXP (insn, 1, i), 0, 0); if (clobbers_seen_this_insn > max_clobbers_per_insn) *************** *** 192,196 **** to compute the maximum operand number. */ for (i = 0; i < XVECLEN (split, 0); i++) ! walk_insn_part (XVECEXP (split, 0, i), 1); /* Look at the number of insns this insn could split into. */ if (XVECLEN (split, 2) > max_insns_per_split) --- 218,222 ---- to compute the maximum operand number. */ for (i = 0; i < XVECLEN (split, 0); i++) ! walk_insn_part (XVECEXP (split, 0, i), 1, 0); /* Look at the number of insns this insn could split into. */ if (XVECLEN (split, 2) > max_insns_per_split) *************** *** 207,211 **** to compute the maximum operand number. */ for (i = 0; i < XVECLEN (peep, 0); i++) ! walk_insn_part (XVECEXP (peep, 0, i), 1); } --- 233,237 ---- to compute the maximum operand number. */ for (i = 0; i < XVECLEN (peep, 0); i++) ! walk_insn_part (XVECEXP (peep, 0, i), 1, 0); } *************** *** 316,319 **** --- 342,348 ---- if (have_cc0_flag) printf ("#define HAVE_cc0\n"); + + if (have_cmove_flag) + printf ("#define HAVE_conditional_move\n"); if (have_lo_sum_flag) diff -rc2N gcc-2.2.2/genemit.c gcc-2.3.1/genemit.c *** gcc-2.2.2/genemit.c Mon Apr 27 15:09:07 1992 --- gcc-2.3.1/genemit.c Tue Oct 13 00:11:52 1992 *************** *** 20,24 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 20,24 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 84,88 **** || code == MATCH_PARALLEL) max_opno = MAX (max_opno, XINT (x, 0)); ! if (code == MATCH_DUP || code == MATCH_OP_DUP) max_dup_opno = MAX (max_dup_opno, XINT (x, 0)); --- 84,88 ---- || code == MATCH_PARALLEL) max_opno = MAX (max_opno, XINT (x, 0)); ! if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP) max_dup_opno = MAX (max_dup_opno, XINT (x, 0)); *************** *** 147,151 **** if (x == 0) { ! printf ("0"); return; } --- 147,151 ---- if (x == 0) { ! printf ("NULL_RTX"); return; } *************** *** 183,186 **** --- 183,187 ---- case MATCH_PARALLEL: + case MATCH_PAR_DUP: printf ("operand%d", XINT (x, 0)); return; *************** *** 203,225 **** case CONST_INT: if (INTVAL (x) == 0) ! { ! printf ("const0_rtx"); ! return; ! } ! if (INTVAL (x) == 1) ! { ! printf ("const1_rtx"); ! return; ! } ! if (INTVAL (x) == -1) ! { ! printf ("constm1_rtx"); ! return; ! } ! if (INTVAL (x) == STORE_FLAG_VALUE) ! { ! printf ("const_true_rtx"); ! return; ! } } --- 204,228 ---- case CONST_INT: if (INTVAL (x) == 0) ! printf ("const0_rtx"); ! else if (INTVAL (x) == 1) ! printf ("const1_rtx"); ! else if (INTVAL (x) == -1) ! printf ("constm1_rtx"); ! else if (INTVAL (x) == STORE_FLAG_VALUE) ! printf ("const_true_rtx"); ! else ! printf ( ! #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT ! "GEN_INT (%d)", ! #else ! "GEN_INT (%ld)", ! #endif ! INTVAL (x)); ! return; ! ! case CONST_DOUBLE: ! /* These shouldn't be written in MD files. Instead, the appropriate ! routines in varasm.c should be called. */ ! abort (); } *************** *** 238,242 **** gen_exp (XEXP (x, i)); else if (fmt[i] == 'i') ! printf ("%u", (unsigned) XINT (x, i)); else if (fmt[i] == 's') printf ("\"%s\"", XSTR (x, i)); --- 241,245 ---- gen_exp (XEXP (x, i)); else if (fmt[i] == 'i') ! printf ("%u", XINT (x, i)); else if (fmt[i] == 's') printf ("\"%s\"", XSTR (x, i)); diff -rc2N gcc-2.2.2/genextract.c gcc-2.3.1/genextract.c *** gcc-2.2.2/genextract.c Mon May 4 10:04:43 1992 --- gcc-2.3.1/genextract.c Tue Oct 13 00:11:57 1992 *************** *** 20,24 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 20,24 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 218,221 **** --- 218,222 ---- case MATCH_DUP: case MATCH_OP_DUP: + case MATCH_PAR_DUP: duplocs[dup_count] = copystr (path); dupnums[dup_count] = XINT (x, 0); diff -rc2N gcc-2.2.2/genflags.c gcc-2.3.1/genflags.c *** gcc-2.2.2/genflags.c Mon Apr 27 15:09:11 1992 --- gcc-2.3.1/genflags.c Tue Oct 13 00:12:01 1992 *************** *** 23,27 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 23,27 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 40,55 **** void fancy_abort (); static void gen_insn (insn) rtx insn; { char *p; /* Don't mention instructions whose names are the null string. They are in the machine description just to be recognized. */ ! if (strlen (XSTR (insn, 0)) == 0) return; ! printf ("#define HAVE_%s ", XSTR (insn, 0)); if (strlen (XSTR (insn, 2)) == 0) printf ("1\n"); --- 40,137 ---- void fancy_abort (); + /* Names for patterns. Need to allow linking with print-rtl. */ + char **insn_name_ptr; + + /* Obstacks to remember normal, and call insns. */ + static struct obstack call_obstack, normal_obstack; + + /* Max size of names encountered. */ + static int max_id_len; + + /* Count the number of match_operand's found. */ + static int + num_operands (x) + rtx x; + { + int count = 0; + int i, j; + enum rtx_code code = GET_CODE (x); + char *format_ptr = GET_RTX_FORMAT (code); + + if (code == MATCH_OPERAND) + return 1; + + if (code == MATCH_OPERATOR || code == MATCH_PARALLEL) + count++; + + for (i = 0; i < GET_RTX_LENGTH (code); i++) + { + switch (*format_ptr++) + { + case 'u': + case 'e': + count += num_operands (XEXP (x, i)); + break; + + case 'E': + if (XVEC (x, i) != NULL) + for (j = 0; j < XVECLEN (x, i); j++) + count += num_operands (XVECEXP (x, i, j)); + + break; + } + } + + return count; + } + + /* Print out prototype information for a function. */ + static void + gen_proto (insn) + rtx insn; + { + int num = num_operands (insn); + printf ("extern rtx gen_%-*s PROTO((", max_id_len, XSTR (insn, 0)); + + if (num == 0) + printf ("void"); + else + { + while (num-- > 1) + printf ("rtx, "); + + printf ("rtx"); + } + + printf ("));\n"); + } + + /* Print out a function declaration without a prototype. */ + static void + gen_nonproto (insn) + rtx insn; + { + printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); + } + static void gen_insn (insn) rtx insn; { + char *name = XSTR (insn, 0); char *p; + struct obstack *obstack_ptr; + int len; /* Don't mention instructions whose names are the null string. They are in the machine description just to be recognized. */ ! len = strlen (name); ! if (len == 0) return; ! if (len > max_id_len) ! max_id_len = len; ! ! printf ("#define HAVE_%s ", name); if (strlen (XSTR (insn, 2)) == 0) printf ("1\n"); *************** *** 68,73 **** printf (")\n"); } ! ! printf ("extern rtx gen_%s ();\n", XSTR (insn, 0)); } --- 150,168 ---- printf (")\n"); } ! ! /* Save the current insn, so that we can later put out appropriate ! prototypes. At present, most md files have the wrong number of ! arguments for the call insns (call, call_value, call_pop, ! call_value_pop) ignoring the extra arguments that are passed for ! some machines, so by default, turn off the prototype. */ ! ! obstack_ptr = (name[0] == 'c' ! && (!strcmp (name, "call") ! || !strcmp (name, "call_value") ! || !strcmp (name, "call_pop") ! || !strcmp (name, "call_value_pop"))) ! ? &call_obstack : &normal_obstack; ! ! obstack_grow (obstack_ptr, &insn, sizeof (rtx)); } *************** *** 120,127 **** --- 215,228 ---- { rtx desc; + rtx dummy; + rtx *call_insns; + rtx *normal_insns; + rtx *insn_ptr; FILE *infile; register int c; obstack_init (rtl_obstack); + obstack_init (&call_obstack); + obstack_init (&normal_obstack); if (argc <= 1) *************** *** 153,156 **** --- 254,287 ---- gen_insn (desc); } + + /* Print out the prototypes now. */ + dummy = (rtx)0; + obstack_grow (&call_obstack, &dummy, sizeof (rtx)); + call_insns = (rtx *) obstack_finish (&call_obstack); + + obstack_grow (&normal_obstack, &dummy, sizeof (rtx)); + normal_insns = (rtx *) obstack_finish (&normal_obstack); + + printf ("\n#ifndef NO_MD_PROTOTYPES\n"); + for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) + gen_proto (*insn_ptr); + + printf ("\n#ifdef MD_CALL_PROTOTYPES\n"); + for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) + gen_proto (*insn_ptr); + + printf ("\n#else /* !MD_CALL_PROTOTYPES */\n"); + for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) + gen_nonproto (*insn_ptr); + + printf ("#endif /* !MD_CALL_PROTOTYPES */\n"); + printf ("\n#else /* NO_MD_PROTOTYPES */\n"); + for (insn_ptr = normal_insns; *insn_ptr; insn_ptr++) + gen_nonproto (*insn_ptr); + + for (insn_ptr = call_insns; *insn_ptr; insn_ptr++) + gen_nonproto (*insn_ptr); + + printf ("#endif /* NO_MD_PROTOTYPES */\n"); fflush (stdout); diff -rc2N gcc-2.2.2/genoutput.c gcc-2.3.1/genoutput.c *** gcc-2.2.2/genoutput.c Mon Apr 27 15:09:13 1992 --- gcc-2.3.1/genoutput.c Tue Oct 13 00:12:06 1992 *************** *** 91,95 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 91,95 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 498,501 **** --- 498,502 ---- case MATCH_DUP: case MATCH_OP_DUP: + case MATCH_PAR_DUP: ++num_dups; return; *************** *** 847,850 **** --- 848,852 ---- d->n_dups = 0; + d->n_alternatives = 0; d->template = 0; d->outfun = 0; diff -rc2N gcc-2.2.2/genpeep.c gcc-2.3.1/genpeep.c *** gcc-2.2.2/genpeep.c Mon Apr 27 15:09:15 1992 --- gcc-2.3.1/genpeep.c Tue Oct 13 00:12:10 1992 *************** *** 20,24 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 20,24 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 107,111 **** down to the walking point. */ ! match_rtx (XVECEXP (peep, 0, i), 0, insn_code_number); } --- 107,111 ---- down to the walking point. */ ! match_rtx (XVECEXP (peep, 0, i), NULL_PTR, insn_code_number); } *************** *** 187,190 **** --- 187,191 ---- case MATCH_DUP: + case MATCH_PAR_DUP: printf (" x = "); print_path (path); *************** *** 311,314 **** --- 312,333 ---- printf (" if (XINT (x, %d) != %d) goto L%d;\n", i, XINT (x, i), fail_label); + } + else if (fmt[i] == 'w') + { + /* Make sure that at run time `x' is the RTX we want to test. */ + if (i != 0) + { + printf (" x = "); + print_path (path); + printf (";\n"); + } + + #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + printf (" if (XWINT (x, %d) != %d) goto L%d;\n", + i, XWINT (x, i), fail_label); + #else + printf (" if (XWINT (x, %d) != %ld) goto L%d;\n", + i, XWINT (x, i), fail_label); + #endif } else if (fmt[i] == 's') diff -rc2N gcc-2.2.2/genrecog.c gcc-2.3.1/genrecog.c *** gcc-2.2.2/genrecog.c Thu May 7 02:36:15 1992 --- gcc-2.3.1/genrecog.c Tue Oct 20 03:51:06 1992 *************** *** 47,51 **** #include ! #include "config.h" #include "rtl.h" #include "obstack.h" --- 47,51 ---- #include ! #include "hconfig.h" #include "rtl.h" #include "obstack.h" *************** *** 84,87 **** --- 84,89 ---- int test_elt_one_int; /* Nonzero if should test XINT (rtl, 1) */ int elt_one_int; /* Required value for XINT (rtl, 1) */ + int test_elt_zero_wide; /* Nonzero if should test XWINT (rtl, 0) */ + HOST_WIDE_INT elt_zero_wide; /* Required value for XWINT (rtl, 0) */ char *tests; /* If nonzero predicate to call */ int pred; /* `preds' index of predicate or -1 */ *************** *** 304,309 **** --- 306,313 ---- new->test_elt_zero_int = 0; new->test_elt_one_int = 0; + new->test_elt_zero_wide = 0; new->elt_zero_int = 0; new->elt_one_int = 0; + new->elt_zero_wide = 0; new->tests = 0; new->pred = -1; *************** *** 397,402 **** &new->success, newpos); } - - this->success.first->enforce_mode = 0; } --- 401,404 ---- *************** *** 414,421 **** &new->success, newpos); } - this->success.first->enforce_mode = 0; return new; case MATCH_DUP: new->dupno = XINT (pattern, 0); new->code = UNKNOWN; --- 416,423 ---- &new->success, newpos); } return new; case MATCH_DUP: + case MATCH_PAR_DUP: new->dupno = XINT (pattern, 0); new->code = UNKNOWN; *************** *** 504,507 **** --- 506,514 ---- this->elt_one_int = XINT (pattern, i); } + else if (fmt[i] == 'w' && i == 0) + { + this->test_elt_zero_wide = 1; + this->elt_zero_wide = XWINT (pattern, i); + } else if (fmt[i] == 'E') { *************** *** 553,556 **** --- 560,565 ---- || (d1->test_elt_one_int && d2->test_elt_one_int && d1->elt_one_int != d2->elt_one_int) + || (d1->test_elt_zero_wide && d2->test_elt_zero_wide + && d1->elt_zero_wide != d2->elt_zero_wide) || (d1->veclen && d2->veclen && d1->veclen != d2->veclen)) return 1; *************** *** 580,584 **** if (d2->code != UNKNOWN) { ! for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i]; i++) if (preds[d1->pred].codes[i] == d2->code) break; --- 589,593 ---- if (d2->code != UNKNOWN) { ! for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++) if (preds[d1->pred].codes[i] == d2->code) break; *************** *** 592,596 **** else if (d2->pred >= 0) { ! for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i]; i++) { for (j = 0; j < NUM_RTX_CODE; j++) --- 601,605 ---- else if (d2->pred >= 0) { ! for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++) { for (j = 0; j < NUM_RTX_CODE; j++) *************** *** 746,749 **** --- 755,759 ---- if (old->tests == 0 && old->test_elt_zero_int == 0 && old->test_elt_one_int == 0 && old->veclen == 0 + && old->test_elt_zero_wide == 0 && old->dupno == -1 && old->mode == VOIDmode && old->code == UNKNOWN *************** *** 755,768 **** || (old->tests && add->tests && !strcmp (old->tests, add->tests))) ! && old->test_elt_zero_int == add->test_elt_zero_int ! && old->elt_zero_int == add->elt_zero_int ! && old->test_elt_one_int == add->test_elt_one_int ! && old->elt_one_int == add->elt_one_int ! && old->veclen == add->veclen ! && old->dupno == add->dupno ! && old->opno == add->opno ! && old->code == add->code ! && old->enforce_mode == add->enforce_mode ! && old->mode == add->mode) { /* If the additional test is not the same, split both nodes --- 765,780 ---- || (old->tests && add->tests && !strcmp (old->tests, add->tests))) ! && old->test_elt_zero_int == add->test_elt_zero_int ! && old->elt_zero_int == add->elt_zero_int ! && old->test_elt_one_int == add->test_elt_one_int ! && old->elt_one_int == add->elt_one_int ! && old->test_elt_zero_wide == add->test_elt_zero_wide ! && old->elt_zero_wide == add->elt_zero_wide ! && old->veclen == add->veclen ! && old->dupno == add->dupno ! && old->opno == add->opno ! && old->code == add->code ! && old->enforce_mode == add->enforce_mode ! && old->mode == add->mode) { /* If the additional test is not the same, split both nodes *************** *** 797,802 **** --- 809,816 ---- split->test_elt_zero_int = 0; split->test_elt_one_int = 0; + split->test_elt_zero_wide = 0; split->tests = 0; split->pred = -1; + split->dupno = -1; } *************** *** 821,826 **** --- 835,842 ---- split->test_elt_zero_int = 0; split->test_elt_one_int = 0; + split->test_elt_zero_wide = 0; split->tests = 0; split->pred = -1; + split->dupno = -1; } } *************** *** 877,881 **** abort (); ! if (old == 0 && position_merit (0, add_mode, add->code) < best_merit) { add->prev = 0; --- 893,898 ---- abort (); ! if (old == 0 ! && position_merit (NULL_PTR, add_mode, add->code) < best_merit) { add->prev = 0; *************** *** 968,972 **** printf ("x%d;\n", max_depth); printf (" %s tem;\n", type == SPLIT ? "rtx" : "int"); ! write_tree (tree, "", 0, 1, type); printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1); } --- 985,989 ---- printf ("x%d;\n", max_depth); printf (" %s tem;\n", type == SPLIT ? "rtx" : "int"); ! write_tree (tree, "", NULL_PTR, 1, type); printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1); } *************** *** 1103,1107 **** if (p->pred >= 0) { ! for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i]; i++) if (codemap[(int) preds[p->pred].codes[i]]) break; --- 1120,1124 ---- if (p->pred >= 0) { ! for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++) if (codemap[(int) preds[p->pred].codes[i]]) break; *************** *** 1126,1130 **** if (code == MATCH_OPERAND) { ! for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i]; i++) { printf ("%scase ", indents[indent - 2]); --- 1143,1147 ---- if (code == MATCH_OPERAND) { ! for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++) { printf ("%scase ", indents[indent - 2]); *************** *** 1282,1286 **** if ((mode != switch_mode && ! p->ignore_mode) || (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code) ! || p->test_elt_zero_int || p->test_elt_one_int || p->veclen || p->dupno >= 0 || p->tests || p->num_clobbers_to_add) { --- 1299,1304 ---- if ((mode != switch_mode && ! p->ignore_mode) || (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code) ! || p->test_elt_zero_int || p->test_elt_one_int ! || p->test_elt_zero_wide || p->veclen || p->dupno >= 0 || p->tests || p->num_clobbers_to_add) { *************** *** 1301,1304 **** --- 1319,1330 ---- if (p->test_elt_one_int) printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int); + if (p->test_elt_zero_wide) + printf ( + #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + "XWINT (x%d, 0) == %d && ", + #else + "XWINT (x%d, 0) == %ld && ", + #endif + depth, p->elt_zero_wide); if (p->veclen) printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen); *************** *** 1496,1500 **** printf (" tem = %s_%d (x0, insn%s);\n", name_prefix, tree->subroutine_number, call_suffix); ! printf (" if (tem >= 0) return tem;\n"); change_state (tree->position, afterward->position, 2); printf (" goto L%d;\n", afterward->number); --- 1522,1529 ---- printf (" tem = %s_%d (x0, insn%s);\n", name_prefix, tree->subroutine_number, call_suffix); ! if (type == SPLIT) ! printf (" if (tem != 0) return tem;\n"); ! else ! printf (" if (tem >= 0) return tem;\n"); change_state (tree->position, afterward->position, 2); printf (" goto L%d;\n", afterward->number); diff -rc2N gcc-2.2.2/getopt.c gcc-2.3.1/getopt.c *** gcc-2.2.2/getopt.c Sun Jun 14 18:17:12 1992 --- gcc-2.3.1/getopt.c Sun Nov 1 03:44:12 1992 *************** *** 7,28 **** This program is free software; you can redistribute it and/or modify it ! under the terms of the GNU Library 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 Library General Public ! License along with this program; if not, write to the Free Software ! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ! /* AIX requires this to be the first thing in the file. */ #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not __GNUC__ */ ! #if defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))) #include #else --- 7,28 ---- 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! /* AIX requires this to be the first thing in the file. */ #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not __GNUC__ */ ! #if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) #include #else *************** *** 32,36 **** char *alloca (); #endif ! #endif /* sparc */ #endif /* not __GNUC__ */ --- 32,36 ---- char *alloca (); #endif ! #endif /* alloca.h */ #endif /* not __GNUC__ */ *************** *** 41,52 **** #ifdef __GNU_LIBRARY__ #undef alloca #include - #include #else /* Not GNU C library. */ #define __alloca alloca #endif /* GNU C library. */ ! ! #ifndef __STDC__ #define const #endif --- 41,52 ---- #ifdef __GNU_LIBRARY__ #undef alloca + /* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ #include #else /* Not GNU C library. */ #define __alloca alloca #endif /* GNU C library. */ ! #if !__STDC__ #define const #endif *************** *** 54,58 **** /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a long-named option. Because this is not POSIX.2 compliant, it is ! being phased out. */ #define GETOPT_COMPAT --- 54,58 ---- /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a long-named option. Because this is not POSIX.2 compliant, it is ! being phased out. */ #define GETOPT_COMPAT *************** *** 144,147 **** --- 144,151 ---- #ifdef __GNU_LIBRARY__ + /* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ #include #define my_index strchr *************** *** 206,213 **** /* Interchange the two blocks of data in ARGV. */ ! my_bcopy (&argv[first_nonopt], temp, nonopts_size); ! my_bcopy (&argv[last_nonopt], &argv[first_nonopt], (optind - last_nonopt) * sizeof (char *)); ! my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size); /* Update records for the slots the non-options now occupy. */ --- 210,219 ---- /* Interchange the two blocks of data in ARGV. */ ! my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); ! my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], (optind - last_nonopt) * sizeof (char *)); ! my_bcopy ((char *) temp, ! (char *) &argv[first_nonopt + optind - last_nonopt], ! nonopts_size); /* Update records for the slots the non-options now occupy. */ *************** *** 453,457 **** { /* Don't test has_arg with >, because some C compilers don't ! allow it to be used on enums. */ if (pfound->has_arg) optarg = s + 1; --- 459,463 ---- { /* Don't test has_arg with >, because some C compilers don't ! allow it to be used on enums. */ if (pfound->has_arg) optarg = s + 1; *************** *** 501,505 **** or the option starts with '--' or is not a valid short option, then it's an error. ! Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' #ifdef GETOPT_COMPAT --- 507,511 ---- or the option starts with '--' or is not a valid short option, then it's an error. ! Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' #ifdef GETOPT_COMPAT diff -rc2N gcc-2.2.2/getopt.h gcc-2.3.1/getopt.h *** gcc-2.2.2/getopt.h Sun Jun 14 18:17:13 1992 --- gcc-2.3.1/getopt.h Sun Nov 1 03:44:13 1992 *************** *** 3,18 **** This program is free software; you can redistribute it and/or modify it ! under the terms of the GNU Library 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 Library General Public ! License along with this program; if not, write to the Free Software ! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H --- 3,18 ---- 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H *************** *** 87,99 **** /* Names for the values of the `has_arg' field of `struct option'. */ ! enum _argtype ! { ! no_argument, ! required_argument, ! optional_argument ! }; #if __STDC__ extern int getopt (int argc, char *const *argv, const char *shortopts); extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); --- 87,103 ---- /* Names for the values of the `has_arg' field of `struct option'. */ ! #define no_argument 0 ! #define required_argument 1 ! #define optional_argument 2 #if __STDC__ + #if defined(__GNU_LIBRARY__) + /* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); + #else /* not __GNU_LIBRARY__ */ + extern int getopt (); + #endif /* not __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); diff -rc2N gcc-2.2.2/getopt1.c gcc-2.3.1/getopt1.c *** gcc-2.2.2/getopt1.c Sun Jun 14 18:17:13 1992 --- gcc-2.3.1/getopt1.c Sun Nov 1 03:44:13 1992 *************** *** 3,24 **** This program is free software; you can redistribute it and/or modify it ! under the terms of the GNU Library 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 Library General Public ! License along with this program; if not, write to the Free Software ! Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #ifdef LIBC - /* For when compiled as part of the GNU C library. */ - #include - #endif - #include "getopt.h" --- 3,19 ---- 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "getopt.h" *************** *** 33,37 **** #endif /* STDC_HEADERS or __GNU_LIBRARY__ */ ! #if !defined (NULL) #define NULL 0 #endif --- 28,32 ---- #endif /* STDC_HEADERS or __GNU_LIBRARY__ */ ! #ifndef NULL #define NULL 0 #endif *************** *** 51,55 **** If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option ! instead. */ int --- 46,50 ---- If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option ! instead. */ int diff -rc2N gcc-2.2.2/getpwd.c gcc-2.3.1/getpwd.c *** gcc-2.2.2/getpwd.c Fri Mar 20 17:28:18 1992 --- gcc-2.3.1/getpwd.c Thu Aug 20 14:49:22 1992 *************** *** 29,32 **** --- 29,34 ---- char *xmalloc (); + #ifndef VMS + /* Get the working directory. Use the PWD environment variable if it's set correctly, since this is faster and gives more uniform answers *************** *** 72,73 **** --- 74,92 ---- return p; } + + #else /* VMS */ + + #ifndef MAXPATHLEN + #define MAXPATHLEN 255 + #endif + + char * + getpwd () + { + static char *pwd = 0; + + if (!pwd) pwd = getcwd (xmalloc (MAXPATHLEN+1), MAXPATHLEN+1); + return pwd; + } + + #endif /* VMS */ diff -rc2N gcc-2.2.2/global.c gcc-2.3.1/global.c *** gcc-2.2.2/global.c Thu May 7 02:36:19 1992 --- gcc-2.3.1/global.c Sat Aug 1 23:42:09 1992 *************** *** 97,100 **** --- 97,107 ---- static int *reg_may_share; + /* Define the number of bits in each element of `conflicts' and what + type that element has. We use the largest integer format on the + host machine. */ + + #define INT_BITS HOST_BITS_PER_WIDE_INT + #define INT_TYPE HOST_WIDE_INT + /* max_allocno by max_allocno array of bits, recording whether two allocno's conflict (can't go in the same *************** *** 104,108 **** is recorded either in element i,j or in element j,i. */ ! static int *conflicts; /* Number of ints require to hold max_allocno bits. --- 111,115 ---- is recorded either in element i,j or in element j,i. */ ! static INT_TYPE *conflicts; /* Number of ints require to hold max_allocno bits. *************** *** 115,123 **** #define CONFLICTP(I, J) \ (conflicts[(I) * allocno_row_words + (J) / INT_BITS] \ ! & (1 << ((J) % INT_BITS))) #define SET_CONFLICT(I, J) \ (conflicts[(I) * allocno_row_words + (J) / INT_BITS] \ ! |= (1 << ((J) % INT_BITS))) /* Set of hard regs currently live (during scan of all insns). */ --- 122,130 ---- #define CONFLICTP(I, J) \ (conflicts[(I) * allocno_row_words + (J) / INT_BITS] \ ! & ((INT_TYPE) 1 << ((J) % INT_BITS))) #define SET_CONFLICT(I, J) \ (conflicts[(I) * allocno_row_words + (J) / INT_BITS] \ ! |= ((INT_TYPE) 1 << ((J) % INT_BITS))) /* Set of hard regs currently live (during scan of all insns). */ *************** *** 195,201 **** /* Bit mask for allocnos live at current point in the scan. */ ! static int *allocnos_live; ! ! #define INT_BITS HOST_BITS_PER_INT /* Test, set or clear bit number I in allocnos_live, --- 202,206 ---- /* Bit mask for allocnos live at current point in the scan. */ ! static INT_TYPE *allocnos_live; /* Test, set or clear bit number I in allocnos_live, *************** *** 203,213 **** #define ALLOCNO_LIVE_P(I) \ ! (allocnos_live[(I) / INT_BITS] & (1 << ((I) % INT_BITS))) #define SET_ALLOCNO_LIVE(I) \ ! (allocnos_live[(I) / INT_BITS] |= (1 << ((I) % INT_BITS))) #define CLEAR_ALLOCNO_LIVE(I) \ ! (allocnos_live[(I) / INT_BITS] &= ~(1 << ((I) % INT_BITS))) /* This is turned off because it doesn't work right for DImode. --- 208,218 ---- #define ALLOCNO_LIVE_P(I) \ ! (allocnos_live[(I) / INT_BITS] & ((INT_TYPE) 1 << ((I) % INT_BITS))) #define SET_ALLOCNO_LIVE(I) \ ! (allocnos_live[(I) / INT_BITS] |= ((INT_TYPE) 1 << ((I) % INT_BITS))) #define CLEAR_ALLOCNO_LIVE(I) \ ! (allocnos_live[(I) / INT_BITS] &= ~((INT_TYPE) 1 << ((I) % INT_BITS))) /* This is turned off because it doesn't work right for DImode. *************** *** 263,269 **** /* Perform allocation of pseudo-registers not allocated by local_alloc. FILE is a file to output debugging information on, ! or zero if such output is not desired. */ ! void global_alloc (file) FILE *file; --- 268,277 ---- /* Perform allocation of pseudo-registers not allocated by local_alloc. FILE is a file to output debugging information on, ! or zero if such output is not desired. ! Return value is nonzero if reload failed ! and we must not do any more for this function. */ ! ! int global_alloc (file) FILE *file; *************** *** 455,462 **** allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS; ! conflicts = (int *) alloca (max_allocno * allocno_row_words * sizeof (int)); ! bzero (conflicts, max_allocno * allocno_row_words * sizeof (int)); ! allocnos_live = (int *) alloca (allocno_row_words * sizeof (int)); /* If there is work to be done (at least one reg to allocate), --- 463,472 ---- allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS; ! conflicts = (INT_TYPE *) alloca (max_allocno * allocno_row_words ! * sizeof (INT_TYPE)); ! bzero (conflicts, max_allocno * allocno_row_words ! * sizeof (INT_TYPE)); ! allocnos_live = (INT_TYPE *) alloca (allocno_row_words * sizeof (INT_TYPE)); /* If there is work to be done (at least one reg to allocate), *************** *** 532,536 **** continue; } ! if (!reg_preferred_or_nothing (allocno_reg[allocno_order[i]])) find_reg (allocno_order[i], HARD_CONST (0), 1, 0, 0); } --- 542,546 ---- continue; } ! if (reg_alternate_class (allocno_reg[allocno_order[i]]) != NO_REGS) find_reg (allocno_order[i], HARD_CONST (0), 1, 0, 0); } *************** *** 544,548 **** if (n_basic_blocks > 0) #endif ! reload (get_insns (), 1, file); } --- 554,558 ---- if (n_basic_blocks > 0) #endif ! return reload (get_insns (), 1, file); } *************** *** 591,595 **** for (b = 0; b < n_basic_blocks; b++) { ! bzero (allocnos_live, allocno_row_words * sizeof (int)); /* Initialize table of registers currently live --- 601,605 ---- for (b = 0; b < n_basic_blocks; b++) { ! bzero (allocnos_live, allocno_row_words * sizeof (INT_TYPE)); /* Initialize table of registers currently live *************** *** 607,611 **** { ! register int offset, bit; register regset old = basic_block_live_at_start[b]; int ax = 0; --- 617,622 ---- { ! register int offset; ! REGSET_ELT_TYPE bit; register regset old = basic_block_live_at_start[b]; int ax = 0; *************** *** 618,622 **** for (offset = 0, i = 0; offset < regset_size; offset++) if (old[offset] == 0) ! i += HOST_BITS_PER_INT; else for (bit = 1; bit; bit <<= 1, i++) --- 629,633 ---- for (offset = 0, i = 0; offset < regset_size; offset++) if (old[offset] == 0) ! i += REGSET_ELT_BITS; else for (bit = 1; bit; bit <<= 1, i++) *************** *** 697,701 **** for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_INC) ! mark_reg_store (XEXP (link, 0), 0); #endif --- 708,712 ---- for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_INC) ! mark_reg_store (XEXP (link, 0), NULL_RTX); #endif *************** *** 855,860 **** be used for this allocation. ! If ALL_REGS_P is zero, consider only the preferred class of ALLOCNO's reg. ! Otherwise ignore that preferred class. If ACCEPT_CALL_CLOBBERED is nonzero, accept a call-clobbered hard reg that --- 866,871 ---- be used for this allocation. ! If ALT_REGS_P is zero, consider only the preferred class of ALLOCNO's reg. ! Otherwise ignore that preferred class and use the alternate class. If ACCEPT_CALL_CLOBBERED is nonzero, accept a call-clobbered hard reg that *************** *** 867,874 **** static void ! find_reg (allocno, losers, all_regs_p, accept_call_clobbered, retrying) int allocno; HARD_REG_SET losers; ! int all_regs_p; int accept_call_clobbered; int retrying; --- 878,885 ---- static void ! find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying) int allocno; HARD_REG_SET losers; ! int alt_regs_p; int accept_call_clobbered; int retrying; *************** *** 880,885 **** HARD_REG_SET used, used1, used2; ! enum reg_class class ! = all_regs_p ? ALL_REGS : reg_preferred_class (allocno_reg[allocno]); enum machine_mode mode = PSEUDO_REGNO_MODE (allocno_reg[allocno]); --- 891,897 ---- HARD_REG_SET used, used1, used2; ! enum reg_class class = (alt_regs_p ! ? reg_alternate_class (allocno_reg[allocno]) ! : reg_preferred_class (allocno_reg[allocno])); enum machine_mode mode = PSEUDO_REGNO_MODE (allocno_reg[allocno]); *************** *** 1040,1044 **** allocno_calls_crossed[allocno])) { ! find_reg (allocno, losers, all_regs_p, 1, retrying); if (reg_renumber[allocno_reg[allocno]] >= 0) { --- 1052,1056 ---- allocno_calls_crossed[allocno])) { ! find_reg (allocno, losers, alt_regs_p, 1, retrying); if (reg_renumber[allocno_reg[allocno]] >= 0) { *************** *** 1144,1148 **** find_reg (allocno, forbidden_regs, 0, 0, 1); if (reg_renumber[regno] < 0 ! && !reg_preferred_or_nothing (regno)) find_reg (allocno, forbidden_regs, 1, 0, 1); --- 1156,1160 ---- find_reg (allocno, forbidden_regs, 0, 0, 1); if (reg_renumber[regno] < 0 ! && reg_alternate_class (regno) != NO_REGS) find_reg (allocno, forbidden_regs, 1, 0, 1); *************** *** 1561,1571 **** for (i = 0; i < n_basic_blocks; i++) ! if ((basic_block_live_at_start[i][from / HOST_BITS_PER_INT] ! & (1 << (from % HOST_BITS_PER_INT))) != 0) { ! basic_block_live_at_start[i][from / HOST_BITS_PER_INT] ! &= ~ (1 << (from % HOST_BITS_PER_INT)); ! basic_block_live_at_start[i][to / HOST_BITS_PER_INT] ! |= (1 << (to % HOST_BITS_PER_INT)); } } --- 1573,1583 ---- for (i = 0; i < n_basic_blocks; i++) ! if ((basic_block_live_at_start[i][from / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 << (from % REGSET_ELT_BITS))) != 0) { ! basic_block_live_at_start[i][from / REGSET_ELT_BITS] ! &= ~ ((REGSET_ELT_TYPE) 1 << (from % REGSET_ELT_BITS)); ! basic_block_live_at_start[i][to / REGSET_ELT_BITS] ! |= ((REGSET_ELT_TYPE) 1 << (to % REGSET_ELT_BITS)); } } diff -rc2N gcc-2.2.2/gplus.gperf gcc-2.3.1/gplus.gperf *** gcc-2.2.2/gplus.gperf Thu Mar 19 13:33:17 1992 --- gcc-2.3.1/gplus.gperf Tue Aug 4 17:32:12 1992 *************** *** 26,29 **** --- 26,30 ---- __volatile, TYPE_QUAL, RID_VOLATILE __volatile__, TYPE_QUAL, RID_VOLATILE + __wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */, all, ALL, NORID /* Extension */, except, EXCEPT, NORID /* Extension */, diff -rc2N gcc-2.2.2/gstdarg.h gcc-2.3.1/gstdarg.h *** gcc-2.2.2/gstdarg.h Sat Jun 6 14:46:14 1992 --- gcc-2.3.1/gstdarg.h Fri Oct 30 04:42:45 1992 *************** *** 5,50 **** #ifndef _STDARG_H #define _STDARG_H #ifndef __GNUC__ ! /* Use the system's macros with the system's compiler. */ #include #else #ifdef __m88k__ ! #include "va-m88k.h" #else #ifdef __i860__ ! #include "va-i860.h" #else ! #ifdef __hp9000s800__ ! #include "va-hp800.h" #else #ifdef __mips__ ! #include "va-mips.h" #else #ifdef __sparc__ ! #include "va-sparc.h" #else #ifdef __i960__ ! #include "va-i960.h" #else ! #ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ ! #undef _VA_LIST ! #endif ! /* The macro _VA_LIST_ is the same thing used by this file in Ultrix. */ ! #ifndef _VA_LIST_ ! /* The macro _VA_LIST is used in SCO Unix 3.2. */ ! #ifndef _VA_LIST ! #define _VA_LIST_ ! #define _VA_LIST ! #ifndef __svr4__ ! typedef char *va_list; #else ! typedef void *va_list; #endif ! #endif /* _VA_LIST */ ! #endif /* _VA_LIST_ */ /* Amount of space required in an argument list for an arg of type TYPE. --- 5,56 ---- #ifndef _STDARG_H + #ifndef _ANSI_STDARG_H_ + #ifndef __need___va_list #define _STDARG_H + #define _ANSI_STDARG_H_ + #endif /* not __need___va_list */ + #undef __need___va_list #ifndef __GNUC__ ! /* Use the system's macros with the system's compiler. ! This is relevant only when building GCC with some other compiler. */ #include #else #ifdef __m88k__ ! #include #else #ifdef __i860__ ! #include #else ! #ifdef __hppa__ ! #include #else #ifdef __mips__ ! #include #else #ifdef __sparc__ ! #include #else #ifdef __i960__ ! #include #else + #ifdef __alpha__ + #include + #else ! /* Define __gnuc_va_list. */ ! #ifndef __GNUC_VA_LIST ! #define __GNUC_VA_LIST ! #if defined(__svr4__) || defined(_AIX) || defined(_M_UNIX) ! typedef char *__gnuc_va_list; #else ! typedef void *__gnuc_va_list; #endif ! #endif ! ! /* Define the standard macros for the user, ! if this invocation was from the user program. */ ! #ifdef _STDARG_H /* Amount of space required in an argument list for an arg of type TYPE. *************** *** 55,73 **** #define va_start(AP, LASTARG) \ ! (AP = ((char *) __builtin_next_arg ())) ! void va_end (va_list); /* Defined in libgcc.a */ #define va_end(AP) #define va_arg(AP, TYPE) \ ! (AP = ((char *) (AP)) += __va_rounded_size (TYPE), \ ! *((TYPE *) ((char *) (AP) - __va_rounded_size (TYPE)))) #endif /* not i960 */ #endif /* not sparc */ #endif /* not mips */ ! #endif /* not hp9000s800 */ #endif /* not i860 */ #endif /* not m88k */ ! #endif /* __GNUC__ */ #endif /* _STDARG_H */ --- 61,144 ---- #define va_start(AP, LASTARG) \ ! (AP = ((__gnuc_va_list) __builtin_next_arg ())) ! void va_end (__gnuc_va_list); /* Defined in libgcc.a */ #define va_end(AP) + /* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ #define va_arg(AP, TYPE) \ ! (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ ! *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE)))) ! #endif /* _STDARG_H */ + #endif /* not alpha */ #endif /* not i960 */ #endif /* not sparc */ #endif /* not mips */ ! #endif /* not hppa */ #endif /* not i860 */ #endif /* not m88k */ ! ! #ifdef _STDARG_H ! /* Define va_list, if desired, from __gnuc_va_list. */ ! /* We deliberately do not define va_list when called from ! stdio.h, because ANSI C says that stdio.h is not supposed to define ! va_list. stdio.h needs to have access to that data type, ! but must not use that name. It should use the name __gnuc_va_list, ! which is safe because it is reserved for the implementation. */ ! ! #ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ ! #undef _VA_LIST ! #endif ! ! #ifdef _BSD_VA_LIST ! #undef _BSD_VA_LIST ! #endif ! ! #ifdef __SVR4_2__ ! /* SVR4.2 uses _VA_LIST for an internal alias for va_list, ! so we must avoid testing it and setting it here. */ ! #ifndef _VA_LIST_ ! #define _VA_LIST_ ! typedef __gnuc_va_list va_list; ! #endif /* _VA_LIST_ */ ! #else /* not __SVR4_2__ */ ! ! /* On 4.3bsd-net2, make sure ansi.h is included, so we have ! one less case to deal with in the following. */ ! #if defined (__BSD_NET2__) || defined (____386BSD____) ! #include ! #endif ! ! /* In 4.3bsd-net2, machine/ansi.h defines these symbols, which remain ! defined as long as the corresponding type is *not* defined. */ ! #ifdef _ANSI_H_ ! #ifndef _VA_LIST_ ! #define _VA_LIST ! #endif ! #undef _VA_LIST_ ! #endif /* _ANSI_H_ */ ! ! /* The macro _VA_LIST_ is the same thing used by this file in Ultrix. */ ! #ifndef _VA_LIST_ ! /* The macro _VA_LIST is used in SCO Unix 3.2. */ ! #ifndef _VA_LIST ! #define _VA_LIST_ ! #define _VA_LIST ! typedef __gnuc_va_list va_list; ! #endif /* not _VA_LIST */ ! #endif /* not _VA_LIST_ */ ! ! /* On 4.3bsd-net2, leave _VA_LIST_ undef to indicate va_list is defined. */ ! #ifdef _ANSI_H_ ! #undef _VA_LIST_ ! #endif ! ! #endif /* not __SVR4_2__ */ ! #endif /* _STDARG_H */ + + #endif /* __GNUC__ */ + #endif /* not _ANSI_STDARG_H_ */ + #endif /* not _STDARG_H */ diff -rc2N gcc-2.2.2/gstddef.h gcc-2.3.1/gstddef.h *** gcc-2.2.2/gstddef.h Thu Jun 11 15:08:00 1992 --- gcc-2.3.1/gstddef.h Thu Oct 29 16:14:26 1992 *************** *** 1,4 **** --- 1,5 ---- #ifndef _STDDEF_H #ifndef _STDDEF_H_ + #ifndef _ANSI_STDDEF_H /* Any one of these symbols __need_* means that GNU libc *************** *** 9,18 **** #define _STDDEF_H #define _STDDEF_H_ #endif #ifndef __sys_stdtypes_h ! /* This avoids lossage on Sunos but only if stdtypes.h comes first. There's no way to win with the other order! Sun lossage. */ /* In case nobody has defined these types, but we aren't running under GCC 2.00, make sure that __PTRDIFF_TYPE__, __SIZE__TYPE__, and --- 10,44 ---- #define _STDDEF_H #define _STDDEF_H_ + /* snaroff@next.com says the NeXT needs this. */ + #define _ANSI_STDDEF_H #endif #ifndef __sys_stdtypes_h ! /* This avoids lossage on SunOS but only if stdtypes.h comes first. There's no way to win with the other order! Sun lossage. */ + /* On 4.3bsd-net2, make sure ansi.h is included, so we have + one less case to deal with in the following. */ + #if defined (__BSD_NET2__) || defined (____386BSD____) + #include + #endif + + /* In 4.3bsd-net2, machine/ansi.h defines these symbols, which are + defined if the corresponding type is *not* defined. */ + #ifdef _ANSI_H_ + #ifndef _SIZE_T_ + #define _SIZE_T + #endif + #ifndef _PTRDIFF_T_ + #define _PTRDIFF_T + #endif + #ifndef _WCHAR_T_ + #define _WCHAR_T + #endif + #undef _SIZE_T_ + #undef _PTRDIFF_T_ + #undef _WCHAR_T_ + #endif /* _ANSI_H_ */ + /* In case nobody has defined these types, but we aren't running under GCC 2.00, make sure that __PTRDIFF_TYPE__, __SIZE__TYPE__, and *************** *** 23,26 **** --- 49,55 ---- /* Signed type of difference of two pointers. */ + /* Define this type if we are doing the whole job, + or if we want this type in particular. */ + #if defined (_STDDEF_H) || defined (__need_ptrdiff_t) #ifndef _PTRDIFF_T /* in case has defined it. */ #ifndef _T_PTRDIFF_ *************** *** 40,48 **** #define __PTRDIFF_TYPE__ long int #endif - /* Define this type if we are doing the whole job, - or if we want this type in particular. */ - #if defined (_STDDEF_H) || defined (__need_ptrdiff_t) typedef __PTRDIFF_TYPE__ ptrdiff_t; - #endif /* or __need_ptrdiff_t. */ #endif /* _GCC_PTRDIFF_T */ #endif /* ___int_ptrdiff_t_h */ --- 69,73 ---- *************** *** 56,61 **** --- 81,91 ---- #undef __need_ptrdiff_t + #endif /* _STDDEF_H or __need_ptrdiff_t. */ + /* Unsigned type of `sizeof' something. */ + /* Define this type if we are doing the whole job, + or if we want this type in particular. */ + #if defined (_STDDEF_H) || defined (__need_size_t) #ifndef _SIZE_T /* in case has defined it. */ #ifndef _T_SIZE_ *************** *** 77,85 **** #define __SIZE_TYPE__ long unsigned int #endif - /* Define this type if we are doing the whole job, - or if we want this type in particular. */ - #if defined (_STDDEF_H) || defined (__need_size_t) typedef __SIZE_TYPE__ size_t; - #endif /* or __need_size_t. */ #endif /* _SIZET_ */ #endif /* _GCC_SIZE_T */ --- 107,111 ---- *************** *** 91,94 **** --- 117,121 ---- #endif /* _SIZE_T */ #undef __need_size_t + #endif /* _STDDEF_H or __need_size_t. */ *************** *** 98,101 **** --- 125,131 ---- and not (wchar_t) -1, for each defined multibyte character. */ + /* Define this type if we are doing the whole job, + or if we want this type in particular. */ + #if defined (_STDDEF_H) || defined (__need_wchar_t) #ifndef _WCHAR_T #ifndef _T_WCHAR_ *************** *** 115,123 **** #define __WCHAR_TYPE__ int #endif ! /* Define this type if we are doing the whole job, ! or if we want this type in particular. */ ! #if defined (_STDDEF_H) || defined (__need_wchar_t) typedef __WCHAR_TYPE__ wchar_t; - #endif /* or __need_wchar_t. */ #endif #endif --- 145,155 ---- #define __WCHAR_TYPE__ int #endif ! #ifdef __GNUG__ ! /* In C++, wchar_t is a distinct basic type, ! and we can expect __wchar_t to be defined by cc1plus. */ ! typedef __wchar_t wchar_t; ! #else ! /* In C, cpp tells us which type to make an alias for. */ typedef __WCHAR_TYPE__ wchar_t; #endif #endif *************** *** 127,131 **** --- 159,175 ---- #endif #endif + #endif #undef __need_wchar_t + #endif /* _STDDEF_H or __need_wchar_t. */ + + /* In 4.3bsd-net2, leave these undefined to indicate that size_t, etc. + are already defined. We need not worry about the case of wanting just + one of these types, not on 4.3bsd-net2, because only the GNU libc + header files do that. */ + #ifdef _ANSI_H_ + #undef _PTRDIFF_T_ + #undef _SIZE_T_ + #undef _WCHAR_T_ + #endif #endif /* __sys_stdtypes_h */ *************** *** 146,149 **** --- 190,195 ---- #endif /* _STDDEF_H was defined this time */ + + #endif /* _ANSI_STDDEF_H was not defined before */ #endif /* _STDDEF_H_ was not defined before */ #endif /* _STDDEF_H was not defined before */ diff -rc2N gcc-2.2.2/gvarargs.h gcc-2.3.1/gvarargs.h *** gcc-2.2.2/gvarargs.h Tue May 5 13:22:07 1992 --- gcc-2.3.1/gvarargs.h Fri Oct 30 04:33:33 1992 *************** *** 3,7 **** #include #else ! /* Record that varargs.h is defined; this turns off stdarg.h. */ #ifndef _VARARGS_H --- 3,7 ---- #include #else ! /* Record that this is varargs.h; this turns off stdarg.h. */ #ifndef _VARARGS_H *************** *** 9,35 **** #ifdef __sparc__ ! #include "va-sparc.h" #else #ifdef __spur__ ! #include "va-spur.h" #else #ifdef __mips__ ! #include "va-mips.h" #else #ifdef __i860__ ! #include "va-i860.h" #else #ifdef __pyr__ ! #include "va-pyr.h" #else #ifdef __m88k__ ! #include "va-m88k.h" #else ! #ifdef __hp9000s800__ ! #include "va-hp800.h" #else #ifdef __i960__ ! #include "va-i960.h" #else #ifdef __NeXT__ --- 9,38 ---- #ifdef __sparc__ ! #include #else #ifdef __spur__ ! #include #else #ifdef __mips__ ! #include #else #ifdef __i860__ ! #include #else #ifdef __pyr__ ! #include #else #ifdef __m88k__ ! #include #else ! #if defined(__hppa__) || defined(hp800) ! #include #else #ifdef __i960__ ! #include #else + #ifdef __alpha__ + #include + #else #ifdef __NeXT__ *************** *** 37,40 **** --- 40,48 ---- /* On Next, erase any vestiges of stdarg.h. */ + #ifdef _ANSI_STDARG_H_ + #define _VA_LIST_ + #endif + #define _ANSI_STDARG_H_ + #undef va_alist #undef va_dcl *************** *** 62,89 **** #define va_dcl int __builtin_va_alist; __va_ellipsis ! #ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ ! #undef _VA_LIST ! #endif ! /* The macro _VA_LIST_ is the same thing used by this file in Ultrix. */ ! /* But in 4.3bsd-net2, _VA_LIST_ has another meaning. So ignore it. */ ! #if !defined (_VA_LIST_) || defined (_ANSI_H) ! /* The macro _VA_LIST is used in SCO Unix 3.2. */ ! #ifndef _VA_LIST ! #ifndef _VA_LIST_ ! #define _VA_LIST_ #endif - #define _VA_LIST - /* Make this a macro rather than a typedef, so we can undef any other defn. */ - #define va_list __va___list - typedef char * __va___list; - #endif /* _VA_LIST */ - #endif /* !defined (_VA_LIST_) || defined (_ANSI_H) */ - - /* In 4.3bsd-net2, it is said we must #undef this. - I hope this successfully identifies that system. - I don't know why this works--rms. */ - #ifdef _ANSI_H - #undef _VA_LIST_ #endif --- 70,82 ---- #define va_dcl int __builtin_va_alist; __va_ellipsis ! /* Define __gnuc_va_list, just as in gstdarg.h. */ ! #ifndef __GNUC_VA_LIST ! #define __GNUC_VA_LIST ! #if defined(__svr4__) || defined(_AIX) || defined(_M_UNIX) ! typedef char *__gnuc_va_list; ! #else ! typedef void *__gnuc_va_list; #endif #endif *************** *** 99,104 **** *((TYPE *) (AP - __va_rounded_size (TYPE)))) #endif /* not i960 */ ! #endif /* not hp800 */ #endif /* not m88k */ #endif /* not pyr */ --- 92,98 ---- *((TYPE *) (AP - __va_rounded_size (TYPE)))) + #endif /* not alpha */ #endif /* not i960 */ ! #endif /* not hppa */ #endif /* not m88k */ #endif /* not pyr */ *************** *** 108,110 **** --- 102,160 ---- #endif /* not sparc */ #endif /* not _VARARGS_H */ + + /* Define va_list from __gnuc_va_list. */ + + #ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ + #undef _VA_LIST + #endif + + #ifdef __SVR4_2__ + + /* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. */ + #ifndef _VA_LIST_ + #define _VA_LIST_ + typedef __gnuc_va_list va_list; + #endif /* _VA_LIST_ */ + + #else /* not __SVR4_2__ */ + + /* On 4.3bsd-net2, make sure ansi.h is included, so we have + one less case to deal with in the following. */ + #if defined (__BSD_NET2__) || defined (____386BSD____) + #include + #endif + + /* In 4.3bsd-net2, machine/ansi.h defines these symbols, which remain + defined as long as the corresponding type is *not* defined. */ + #ifdef _ANSI_H_ + #ifndef _VA_LIST_ + #define _VA_LIST + #endif + #undef _VA_LIST_ + #endif /* _ANSI_H_ */ + + /* The macro _VA_LIST_ is the same thing used by this file in Ultrix. */ + #ifndef _VA_LIST_ + /* The macro _VA_LIST is used in SCO Unix 3.2. */ + #ifndef _VA_LIST + #define _VA_LIST_ + #define _VA_LIST + typedef __gnuc_va_list va_list; + #endif /* not _VA_LIST */ + #endif /* not _VA_LIST_ */ + + #endif /* not __SVR4_2__ */ + + /* On 4.3bsd-net2, leave _VA_LIST_ undef to indicate va_list is defined. */ + #ifdef _ANSI_H_ + #undef _VA_LIST_ + #endif + + /* The next BSD release (if there is one) wants this symbol to be + undefined instead of _VA_LIST_. */ + #ifdef _BSD_VA_LIST + #undef _BSD_VA_LIST + #endif + #endif /* __GNUC__ */ diff -rc2N gcc-2.2.2/halfpic.c gcc-2.3.1/halfpic.c *** gcc-2.2.2/halfpic.c Thu May 7 02:36:20 1992 --- gcc-2.3.1/halfpic.c Sat Aug 1 23:18:05 1992 *************** *** 35,39 **** #include "rtl.h" #include - #include #include "obstack.h" --- 35,38 ---- *************** *** 210,221 **** return; - /* If this is not an external reference, it can't be half-pic. */ - if (!TREE_EXTERNAL (decl)) - return; - asm_name = DECL_ASSEMBLER_NAME (decl); if (!asm_name) return; ptr = half_pic_hash (IDENTIFIER_POINTER (asm_name), IDENTIFIER_LENGTH (asm_name), --- 209,232 ---- return; asm_name = DECL_ASSEMBLER_NAME (decl); + if (!asm_name) return; + #ifdef HALF_PIC_DEBUG + if (HALF_PIC_DEBUG) + { + if (HALF_PIC_DEBUG) + fprintf (stderr, "\n========== Half_pic_encode %.*s\n", + IDENTIFIER_LENGTH (asm_name), + IDENTIFIER_POINTER (asm_name)); + debug_tree (decl); + } + #endif + + /* If this is not an external reference, it can't be half-pic. */ + if (!DECL_EXTERNAL (decl) && (code != VAR_DECL || !TREE_PUBLIC (decl))) + return; + ptr = half_pic_hash (IDENTIFIER_POINTER (asm_name), IDENTIFIER_LENGTH (asm_name), *************** *** 226,230 **** #ifdef HALF_PIC_DEBUG if (HALF_PIC_DEBUG) ! fprintf (stderr, "\n========== Half_pic_encode %.*s\n", IDENTIFIER_LENGTH (asm_name), IDENTIFIER_POINTER (asm_name)); --- 237,241 ---- #ifdef HALF_PIC_DEBUG if (HALF_PIC_DEBUG) ! fprintf (stderr, "\n%.*s is half-pic\n", IDENTIFIER_LENGTH (asm_name), IDENTIFIER_POINTER (asm_name)); *************** *** 278,282 **** { rtx offset = const0_rtx; ! addr = eliminate_constant_term (addr, &offset); if (GET_CODE (addr) != SYMBOL_REF) return FALSE; --- 289,293 ---- { rtx offset = const0_rtx; ! addr = eliminate_constant_term (XEXP (addr, 0), &offset); if (GET_CODE (addr) != SYMBOL_REF) return FALSE; diff -rc2N gcc-2.2.2/hard-reg-set.h gcc-2.3.1/hard-reg-set.h *** gcc-2.2.2/hard-reg-set.h Tue Dec 24 22:54:19 1991 --- gcc-2.3.1/hard-reg-set.h Sat Aug 1 22:52:57 1992 *************** *** 1,4 **** /* Sets (bit vectors) of hard registers, and operations on them. ! Copyright (C) 1987 Free Software Foundation, Inc. This file is part of GNU CC --- 1,4 ---- /* Sets (bit vectors) of hard registers, and operations on them. ! Copyright (C) 1987, 1992 Free Software Foundation, Inc. This file is part of GNU CC *************** *** 23,55 **** /* If HARD_REG_SET is a macro, its definition is a scalar type that has enough bits for all the target machine's hard registers. ! Otherwise, it is a typedef for a suitable array of longs, ! and HARD_REG_SET_LONGS is how many. */ ! #ifndef HOST_BITS_PER_LONG_LONG ! #define HOST_BITS_PER_LONG_LONG (2 * HOST_BITS_PER_LONG) ! #endif ! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_CHAR ! #define HARD_REG_SET char ! #else ! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_SHORT ! #define HARD_REG_SET short ! #else ! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_INT ! #define HARD_REG_SET int ! #else ! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_LONG ! #define HARD_REG_SET long ! #else ! #if 0 && defined (__GNUC__) && FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_LONGLONG ! #define HARD_REG_SET long long #else #define HARD_REG_SET_LONGS \ ! ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_LONG - 1) / HOST_BITS_PER_LONG) ! typedef long HARD_REG_SET[HARD_REG_SET_LONGS]; ! #endif ! #endif ! #endif ! #endif #endif --- 23,46 ---- /* If HARD_REG_SET is a macro, its definition is a scalar type that has enough bits for all the target machine's hard registers. ! Otherwise, it is a typedef for a suitable array of HOST_WIDE_INTs, ! and HARD_REG_SET_LONGS is how many. ! Note that lots of code assumes that the first part of a regset is ! the same format as a HARD_REG_SET. To help make sure this is true, ! we only try the widest integer mode (HOST_WIDE_INT) instead of all the ! smaller types. This only loses if there are a very few registers and ! then only in the few cases where we have an array of HARD_REG_SETs, ! so it isn't worth making this as complex as it used to be. */ ! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDE_INT ! #define HARD_REG_SET HOST_WIDE_INT ! #else + #define HARD_REG_SET_LONGS \ ! ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDE_INT - 1) \ ! / HOST_BITS_PER_WIDE_INT) ! typedef HOST_WIDE_INT HARD_REG_SET[HARD_REG_SET_LONGS]; ! #endif *************** *** 115,129 **** #else ! #define UHOST_BITS_PER_LONG ((unsigned) HOST_BITS_PER_LONG) ! #define SET_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_LONG] |= 1 << ((BIT) % UHOST_BITS_PER_LONG)) ! #define CLEAR_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_LONG] &= ~(1 << ((BIT) % UHOST_BITS_PER_LONG))) ! #define TEST_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_LONG] & (1 << ((BIT) % UHOST_BITS_PER_LONG))) #define CLEAR_HARD_REG_SET(TO) \ ! do { register long *scan_tp_ = (TO); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 106,125 ---- #else ! #define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDE_INT) ! #define SET_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ ! |= (HOST_WIDE_INT) 1 << ((BIT) % UHOST_BITS_PER_WIDE_INT)) ! ! #define CLEAR_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ ! &= ~((HOST_WIDE_INT) 1 << ((BIT) % UHOST_BITS_PER_WIDE_INT))) ! ! #define TEST_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ ! & ((HOST_WIDE_INT) 1 << ((BIT) % UHOST_BITS_PER_WIDE_INT))) #define CLEAR_HARD_REG_SET(TO) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 131,135 **** #define SET_HARD_REG_SET(TO) \ ! do { register long *scan_tp_ = (TO); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 127,131 ---- #define SET_HARD_REG_SET(TO) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 137,141 **** #define COPY_HARD_REG_SET(TO, FROM) \ ! do { register long *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 133,137 ---- #define COPY_HARD_REG_SET(TO, FROM) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 143,147 **** #define COMPL_HARD_REG_SET(TO, FROM) \ ! do { register long *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 139,143 ---- #define COMPL_HARD_REG_SET(TO, FROM) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 149,153 **** #define AND_HARD_REG_SET(TO, FROM) \ ! do { register long *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 145,149 ---- #define AND_HARD_REG_SET(TO, FROM) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 155,159 **** #define AND_COMPL_HARD_REG_SET(TO, FROM) \ ! do { register long *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 151,155 ---- #define AND_COMPL_HARD_REG_SET(TO, FROM) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 161,165 **** #define IOR_HARD_REG_SET(TO, FROM) \ ! do { register long *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 157,161 ---- #define IOR_HARD_REG_SET(TO, FROM) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 167,171 **** #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ ! do { register long *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 163,167 ---- #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ ! do { register HOST_WIDE_INT *scan_tp_ = (TO), *scan_fp_ = (FROM); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 173,177 **** #define GO_IF_HARD_REG_SUBSET(X,Y,TO) \ ! do { register long *scan_xp_ = (X), *scan_yp_ = (Y); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 169,173 ---- #define GO_IF_HARD_REG_SUBSET(X,Y,TO) \ ! do { register HOST_WIDE_INT *scan_xp_ = (X), *scan_yp_ = (Y); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ *************** *** 180,184 **** #define GO_IF_HARD_REG_EQUAL(X,Y,TO) \ ! do { register long *scan_xp_ = (X), *scan_yp_ = (Y); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ --- 176,180 ---- #define GO_IF_HARD_REG_EQUAL(X,Y,TO) \ ! do { register HOST_WIDE_INT *scan_xp_ = (X), *scan_yp_ = (Y); \ register int i; \ for (i = 0; i < HARD_REG_SET_LONGS; i++) \ diff -rc2N gcc-2.2.2/install.sh gcc-2.3.1/install.sh *** gcc-2.2.2/install.sh Sun Jun 14 18:17:19 1992 --- gcc-2.3.1/install.sh Sun Nov 1 03:44:20 1992 *************** *** 14,29 **** # set DOITPROG to echo to test this script ! doit="${DOITPROG:-}" # put in absolute paths if you don't have them in your path; or use env. vars. ! mvprog="${MVPROG:-mv}" ! cpprog="${CPPROG:-cp}" ! chmodprog="${CHMODPROG:-chmod}" ! chownprog="${CHOWNPROG:-chown}" ! chgrpprog="${CHGRPPROG:-chgrp}" ! stripprog="${STRIPPROG:-strip}" ! rmprog="${RMPROG:-rm}" instcmd="$mvprog" --- 14,30 ---- # set DOITPROG to echo to test this script ! # Don't use :- since 4.3BSD and earlier shells don't like it. ! doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. ! mvprog="${MVPROG-mv}" ! cpprog="${CPPROG-cp}" ! chmodprog="${CHMODPROG-chmod}" ! chownprog="${CHOWNPROG-chown}" ! chgrpprog="${CHGRPPROG-chgrp}" ! stripprog="${STRIPPROG-strip}" ! rmprog="${RMPROG-rm}" instcmd="$mvprog" *************** *** 33,36 **** --- 34,38 ---- stripcmd="" rmcmd="$rmprog -f" + mvcmd="$mvprog" src="" dst="" *************** *** 85,89 **** ! # if destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic --- 87,91 ---- ! # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic *************** *** 93,109 **** fi ! # get rid of the old one and mode the new one in ! $doit $rmcmd $dst ! $doit $instcmd $src $dst # and set any options; do chmod last to preserve setuid bits ! if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; fi ! if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; fi ! if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; fi ! if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; fi exit 0 --- 95,119 ---- fi + # Make a temp file name in the proper directory. ! dstdir=`dirname $dst` ! dsttmp=$dstdir/#inst.$$# ! # Move or copy the file name to the temp name + $doit $instcmd $src $dsttmp # and set any options; do chmod last to preserve setuid bits ! if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi ! if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi ! if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi ! if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi ! ! # Now rename the file to the real destination. ! ! $doit $rmcmd $dst ! $doit $mvcmd $dsttmp $dst ! exit 0 diff -rc2N gcc-2.2.2/install.texi gcc-2.3.1/install.texi *** gcc-2.2.2/install.texi Sun Jun 14 16:14:12 1992 --- gcc-2.3.1/install.texi Sat Oct 31 15:58:36 1992 *************** *** 22,25 **** --- 22,27 ---- * Unos Install:: See below for installation on Unos (from CRDS). * VMS Install:: See below for installation on VMS. + * WE32K Install:: See below for installation on the 3b* aside from the 3b1. + * MIPS Install:: See below for installation on the MIPS Architecture. @end menu @iftex *************** *** 34,38 **** If you have built GNU CC previously in the same directory for a different target machine, do @samp{make distclean} to delete all files ! that might be invalid. @item --- 36,43 ---- If you have built GNU CC previously in the same directory for a different target machine, do @samp{make distclean} to delete all files ! that might be invalid. One of the files this deletes is ! @file{Makefile}; if @samp{make distclean} complains that @file{Makefile} ! does not exist, it probably means that the directory is already suitably ! clean. @item *************** *** 78,85 **** @quotation ! @c gmicro, pyramid, alliant, spur and tahoe omitted since they don't work. ! a29k, arm, c@var{n}, hppa1.0, hppa1.1, i386, ! i860, i960, m68000, m68k, m88k, mips, ! ns32k, romp, rs6000, sparc, vax, we32k. @end quotation --- 83,90 ---- @quotation ! @c gmicro, alliant, spur and tahoe omitted since they don't work. ! a29k, alpha, arm, c@var{n}, elxsi, hppa1.0, hppa1.1, ! i386, i860, i960, m68000, m68k, m88k, mips, ! ns32k, pyramid, romp, rs6000, sparc, vax, we32k. @end quotation *************** *** 89,97 **** @quotation alliant, altos, apollo, att, ! convergent, convex, crds, dec, dg, encore, harris, hp, ibm, mips, motorola, ncr, next, ns, omron, ! sequent, sgi, sony, sun, tti, ! unicom. @end quotation --- 94,101 ---- @quotation alliant, altos, apollo, att, ! cbm, convergent, convex, crds, dec, dg, encore, harris, hp, ibm, mips, motorola, ncr, next, ns, omron, ! sequent, sgi, sony, sun, tti, unicom. @end quotation *************** *** 104,112 **** @quotation ! bsd, sysv, mach, minix, genix, ! ultrix, vms, sco, isc, ! aix, sunos, hpux, unos, ! luna, dgux, newsos, osfrose, osf, ! dynix, aos, ctix. @end quotation --- 108,115 ---- @quotation ! aix, aos, bsd, ctix, dgux, dynix, ! genix, hpux, isc, linux, luna, mach, ! minix, newsos, osf, osfrose, riscos, ! sco, sunos, sysv, ultrix, unos, vms. @end quotation *************** *** 153,159 **** name. ! There are three additional options you can specify independently to describe variant hardware and software configurations. These are ! @samp{--with-gnu-as}, @samp{--with-gnu-ld}, and @samp{--nfp}. @table @samp --- 156,163 ---- name. ! There are four additional options you can specify independently to describe variant hardware and software configurations. These are ! @samp{--with-gnu-as}, @samp{--with-gnu-ld}, @samp{--with-stabs} and ! @samp{--nfp}. @table @samp *************** *** 164,168 **** @file{configure}, if you want to use the GNU tools. (Specify @samp{--with-gnu-ld} as well, since on these systems GAS works only with ! the GNU linker.) The systems were this makes a difference are @samp{i386-@var{anything}-sysv}, @samp{i860-@var{anything}-bsd}, @samp{m68k-hp-hpux}, @samp{m68k-sony-bsd}, @samp{m68k-altos-sysv}, --- 168,172 ---- @file{configure}, if you want to use the GNU tools. (Specify @samp{--with-gnu-ld} as well, since on these systems GAS works only with ! the GNU linker.) The systems where this makes a difference are @samp{i386-@var{anything}-sysv}, @samp{i860-@var{anything}-bsd}, @samp{m68k-hp-hpux}, @samp{m68k-sony-bsd}, @samp{m68k-altos-sysv}, *************** *** 176,179 **** --- 180,198 ---- configurations. + @item --with-stabs + On MIPS based systems, you must specify whether you want GNU CC to + create the normal ECOFF debugging format, or to use BSD-style stabs + passed through the ECOFF symbol table. The normal ECOFF debug format + cannot fully handle languages other than C. BSD stabs format can handle + other languages, but it only works with the GNU debugger GDB. + + Normally, GNU CC uses the ECOFF debugging format by default; if you + prefer BSD stabs, specify @samp{--with-stabs} when you configure GNU + CC. + + No matter which default you choose when you configure GNU CC, the user + can use the @samp{-gcoff} and @samp{-gstabs+} options to specify explicitly + the debug format for a particular compilation. + @item --nfp On certain systems, you must specify whether the machine has a floating *************** *** 197,200 **** --- 216,263 ---- @table @samp + @item alpha-*-osf1 + Systems using processors that implement the DEC Alpha architecture and + are running the OSF/1 operating system. (VMS on the Alpha is not + currently supported by GNU CC.) As of this writing, the only Alpha-based + product currently available from DEC is the 21064 (EV4) processor chip; + no system-level products can be ordered. This port is provided for + those developers who might have early Alpha hardware from DEC or other + vendors and run the OSF/1 operating system. It has not been extensively + tested and both the C++ and Objective-C languages may not work, except + in a cross-compilation environment. + + The @code{ASSEMBLE_FILE_START} macro writes a @code{.verstamp} directive + containing the version of the calling sequence. Currently, we use + @samp{9 0}, which we believe will work until the official release by DEC + of their system, at which point @samp{3 11} is the correct value. If + you get a mismatch error from the assembler on a @code{.verstamp} line, + consult the file @file{/usr/include/stamp.h} for the present value. GNU + C on the Alpha does not support versions of DEC's OSF/1 earlier than + BL9; if you are running an older version, we suggest you ask your DEC + contact for an update. + + Note that since the Alpha is a 64-bit architecture, cross-compilers + from 32-bit machines will not generate as efficient code as that + generated when the compiler is running on a 64-bit machine because many + optimizations that depend on being able to represent a word on the + target in an integral value on the host cannot be performed. + + @item a29k + AMD Am29K-family processors. These are normally used in embedded + applications. There are no standard Unix configurations. + This configuration + corresponds to AMD's standard calling sequence and binary interface + and is compatible with other 29K tools. + + You may need to make a variant of the file @file{a29k.h} for your + particular configuration. + + @item a29k-*-bsd + AMD Am29050 used in a system running a variant of BSD Unix. + + @item elxsi-elxsi-bsd + The Elxsi's C compiler has known limitations that prevent it from + compiling GNU C. Please contact @code{mrs@@cygnus.com} for more details. + @ignore @item fx80 *************** *** 222,227 **** @item i386-*-sco ! Compilation with RCC is recommended, but it produces lots of spurious ! warnings. They do not necessarily indicate that anything is wrong. @item i386-sequent --- 285,292 ---- @item i386-*-sco ! Compilation with RCC is recommended. ! ! @item i386-ibm-aix ! You need a version of GAS that you can get from @code{tranle@@intellicorp.com}. @item i386-sequent *************** *** 261,265 **** @item m88k-svr3 ! Motorola m88k running the AT&T/Unisoft/Motorla V.3 reference port. These systems tend to use the Green Hills C, revision 1.8.5, as the standard C compiler. There are apparently bugs in this compiler that --- 326,330 ---- @item m88k-svr3 ! Motorola m88k running the AT&T/Unisoft/Motorola V.3 reference port. These systems tend to use the Green Hills C, revision 1.8.5, as the standard C compiler. There are apparently bugs in this compiler that *************** *** 312,320 **** @itemx romp-*-mach The only operating systems supported for the IBM RT PC are AOS and ! MACH. GNU CC does not support AIX running on the RT. @item rs6000-*-aix ! Read the file @file{README.RS6000} for information on how to get a fix ! for a problem in the IBM assembler that prevents use of GNU CC. @item vax-dec-ultrix --- 377,393 ---- @itemx romp-*-mach The only operating systems supported for the IBM RT PC are AOS and ! MACH. GNU CC does not support AIX running on the RT. We recommend you ! compile GNU CC with an earlier version of itself; if you compile GNU CC ! with @code{hc}, the Metaware compiler, it will work, but you will get ! mismatches between the stage 2 and stage 3 compilers in various files. ! These errors are minor differences in some floating-point constants and ! can be safely ignored; the stage 3 compiler is correct. @item rs6000-*-aix ! @strong{Read the file @file{README.RS6000} for information on how to get ! a fix for a problem in the IBM assembler that prevents use of GNU CC.} ! You must either obtain the new assembler or avoid using the @samp{-g} ! switch. Note that @file{Makefile.in} uses @samp{-g} by default when ! compiling @file{libgcc2.c}. @item vax-dec-ultrix *************** *** 326,333 **** problem, compile just the GNU C compiler first, and use it to recompile building all the languages that you want to run. - - @item we32k-att-sysv - Don't use @samp{-g} when compiling GNU CC. The system's linker seems to - be unable to handle such a large program with debugging information. @end table --- 399,402 ---- *************** *** 463,467 **** @example ! make CC="stage1/gcc -Bstage1/" CFLAGS="-g -O" @end example --- 532,536 ---- @example ! make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O" @end example *************** *** 488,492 **** @example ! make CC="stage1/gcc -Bstage1/" CFLAGS="-g -O -msoft-float" @end example --- 557,561 ---- @example ! make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O -msoft-float" @end example *************** *** 497,510 **** @example make stage2 ! make CC="stage2/gcc -Bstage2/" CFLAGS="-g -O" @end example @noindent This is called making the stage 3 compiler. Aside from the @samp{-B} ! option, the options should be the same as when you made the stage 2 ! compiler. ! ! The command shown above builds compilers for all the supported ! languages. If you don't want them all, you can specify the languages to build by typing the argument @samp{LANGUAGES="@var{list}"}, as described above. --- 566,578 ---- @example make stage2 ! make CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" @end example @noindent This is called making the stage 3 compiler. Aside from the @samp{-B} ! option, the compiler options should be the same as when you made the ! stage 2 compiler. But the @code{LANGUAGES} option need not be the ! same. The command shown above builds compilers for all the supported ! languages; if you don't want them all, you can specify the languages to build by typing the argument @samp{LANGUAGES="@var{list}"}, as described above. *************** *** 546,550 **** @example ! make CC="stage2/gcc -Bstage2/" CFLAGS="-g -O" install LANGUAGES="@var{list}" @end example --- 614,618 ---- @example ! make install CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" LANGUAGES="@var{list}" @end example *************** *** 584,605 **** @item Correct errors in the header files on your machine. Various system header files often contain constructs which are ! incompatible with ANSI C, and they will not work when you compile ! programs with GNU CC. This behavior consists of substituting for macro ! argument names when they appear inside of character constants. The most ! common offender is @file{ioctl.h}. ! ! You can overcome this problem when you compile by specifying the ! @samp{-traditional} option. ! ! Alternatively, on Sun systems and 4.3BSD at least, you can correct the ! include files by running the shell script @file{fixincludes}. This ! installs modified, corrected copies of the files @file{ioctl.h}, ! @file{ttychars.h} and many others, in a special directory where only ! GNU CC will normally look for them. This script will work on various ! systems because it chooses the files by searching all the system ! headers for the problem cases that we know about. Use the following command to do this: --- 652,680 ---- @item + Install the Objective C library (if you have built the Objective C + compiler). Here is the command to do this: + + @example + make install-libobjc CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" + @end example + + @item Correct errors in the header files on your machine. Various system header files often contain constructs which are ! erroneous, incompatible with ANSI C or otherwise unsuitable, and they ! will not work when you compile programs with GNU CC. ! ! The most common erroneous construct is found in @file{ioctl.h}, where a ! macro expects argument values to be substituted for argument names ! inside of character constants---something not done in ANSI C. This ! particular problem can be prevented by using @samp{-traditional}. Other ! problems are not so easy to work around. ! ! GNU CC comes with shell scripts to fix known header file problems. They ! install corrected copies of various header files in a special directory ! where only GNU CC will normally look for them. The scripts adapt to ! various systems by searching all the system header files for the problem ! cases that we know about. Use the following command to do this: *************** *** 615,620 **** Note that some systems are starting to come with ANSI C system header ! files. On these systems, don't run @file{fixincludes}; it may not work, ! and is certainly not necessary. @end enumerate --- 690,701 ---- Note that some systems are starting to come with ANSI C system header ! files. On these systems, don't run @code{install-fixincludes}; it may ! not work, and is certainly not necessary. One exception: there are is a ! special script for System V release 4, which you should run. ! ! It is not the purpose of @code{install-fixincludes} to add prototypes to ! the system header files. We support headers with ANSI C prototypes in ! the GNU C Library, and we have no time to support adding them to other ! systems' header files. @end enumerate *************** *** 715,719 **** To build GNU CC as a cross-compiler, you start out by running ! @code{configure}. You must specify two different configureations, the host and the target. Use the @samp{--host=@var{host}} option for the host and @samp{--target=@var{target}} to specify the target type. For --- 796,800 ---- To build GNU CC as a cross-compiler, you start out by running ! @code{configure}. You must specify two different configurations, the host and the target. Use the @samp{--host=@var{host}} option for the host and @samp{--target=@var{target}} to specify the target type. For *************** *** 728,732 **** Next you should install the cross-assembler and cross-linker (and @code{ar} and @code{ranlib}). Put them in the directory ! @file{/usr/local/@var{target}}. The installation of GNU CC will find them there and copy or link them to the proper place to find them when you run the cross-compiler later. --- 809,813 ---- Next you should install the cross-assembler and cross-linker (and @code{ar} and @code{ranlib}). Put them in the directory ! @file{/usr/local/@var{target}/bin}. The installation of GNU CC will find them there and copy or link them to the proper place to find them when you run the cross-compiler later. *************** *** 739,758 **** @file{/usr/local/@var{target}/include}. ! Then you can proceed just as for compiling a single-machine compiler ! through the step of building stage 1. ! ! When you are using a cross-compiler configuration, building stage 1 ! does not compile all of GNU CC. This is because one part of building, ! the compilation of @file{libgcc2.c}, requires use of the cross-compiler. ! ! However, when you type @samp{make install} to install the bulk of the ! cross-compiler, that will also compile @file{libgcc2.c} and install the ! resulting @file{libgcc.a}. ! ! You will find it necessary to produce a substitute for @file{libgcc1.a}. ! Normally this file is compiled with the ``native compiler'' for the ! target machine; compiling it with GNU CC does not work. But compiling ! it with the host machine's compiler also doesn't work---that produces a ! file that would run on the host, and you need it to run on the target. We can't give you any automatic way to produce this substitute. For --- 820,828 ---- @file{/usr/local/@var{target}/include}. ! You must now produce a substitute for @file{libgcc1.a}. Normally this ! file is compiled with the ``native compiler'' for the target machine; ! compiling it with GNU CC does not work. But compiling it with the host ! machine's compiler also doesn't work---that produces a file that would ! run on the host, and you need it to run on the target. We can't give you any automatic way to produce this substitute. For *************** *** 764,769 **** macros for the subroutines that you need. If these definitions do not use the C arithmetic operators that they are meant to implement, you ! might be able to compile them with the cross-compiler you have just ! built. Do not try to build stage 2 for a cross-compiler. It doesn't work to --- 834,857 ---- macros for the subroutines that you need. If these definitions do not use the C arithmetic operators that they are meant to implement, you ! might be able to compile them with the cross-compiler you are building. ! To do this, specify @samp{LIBGCC1=libgcc1.a OLDCC=./xgcc} when building ! the compiler. ! ! Now you can proceed just as for compiling a single-machine compiler ! through the step of building stage 1. If you have not provided some ! sort of @file{libgcc1.a}, then compilation will give up at the point ! where it needs that file, printing a suitable error message. If you ! do provide @file{libgcc1.a}, then building the compiler will automatically ! compile and link a test program called @file{cross-test}; if you get ! errors in the linking, it means that not all of the necessary routines ! in @file{libgcc1.a} are available. ! ! When you are using a cross-compiler configuration, building stage 1 ! does not compile all of GNU CC. This is because one part of building, ! the compilation of @file{libgcc2.c}, requires use of the cross-compiler. ! ! However, when you type @samp{make install} to install the bulk of the ! cross-compiler, that will also compile @file{libgcc2.c} and install the ! resulting @file{libgcc.a}. Do not try to build stage 2 for a cross-compiler. It doesn't work to *************** *** 792,800 **** @samp{-g} does not work on HP-UX, since that system uses a peculiar ! debugging format which GNU CC does not know about. There is a ! preliminary version available of some modified GNU tools including the ! GDB debugger which do work with GNU CC for debugging. You can get them ! by anonymous ftp from @code{mancos.cs.utah.edu} in the @samp{dist} ! subdirectory. You would need to install GAS in the file @example --- 880,887 ---- @samp{-g} does not work on HP-UX, since that system uses a peculiar ! debugging format which GNU CC does not know about. There are preliminary ! versions of GAS and GDB for the HP-PA which do work with GNU CC for ! debugging. You can get them by anonymous ftp from @code{jaguar.cs.utah.edu} ! @samp{dist} subdirectory. You would need to install GAS in the file @example *************** *** 805,820 **** where @var{configuration} is the configuration name (perhaps @samp{hp@var{nnn}-hpux}) and @var{gccversion} is the GNU CC version ! number. ! If you do this, delete the line - @example - #undef DBX_DEBUGGING_INFO - @end example - - @noindent - from @file{tm.h} before you build GNU CC, to enable generation of - debugging information. - @node Sun Install @section Installing GNU CC on the Sun --- 892,902 ---- where @var{configuration} is the configuration name (perhaps @samp{hp@var{nnn}-hpux}) and @var{gccversion} is the GNU CC version ! number. Note, if you picked up GAS before October 6, 1992 it is highly ! recommended you get a new one to avoid several bugs which have been ! discovered recently. ! To enable debugging, configure GNU CC with the @samp{--gas} option before ! building. @node Sun Install @section Installing GNU CC on the Sun *************** *** 925,929 **** and linking from that library. ! @node VMS Install, , Unos Install, Installation @section Installing GNU CC on VMS @cindex VMS installation --- 1007,1011 ---- and linking from that library. ! @node VMS Install @section Installing GNU CC on VMS @cindex VMS installation *************** *** 941,946 **** Define the VMS logical names @samp{GNU_CC} and @samp{GNU_CC_INCLUDE} to point to the directories where the GNU CC executables ! (@file{gcc-cpp}, @file{gcc-cc1}, etc.) and the C include files are ! kept. This should be done with the commands:@refill @smallexample --- 1023,1028 ---- Define the VMS logical names @samp{GNU_CC} and @samp{GNU_CC_INCLUDE} to point to the directories where the GNU CC executables ! (@file{gcc-cpp.exe}, @file{gcc-cc1.exe}, etc.) and the C include files are ! kept respectively. This should be done with the commands:@refill @smallexample *************** *** 970,974 **** @smallexample ! $ lib/help sys$library:helplib.hlb gcc.hlp @end smallexample --- 1052,1056 ---- @smallexample ! $ library/help sys$library:helplib.hlb gcc.hlp @end smallexample *************** *** 1008,1012 **** We try to put corresponding binaries and sources on the VMS distribution ! tape. But sometimes the binaries will be from an older version that the sources, because we don't always have time to update them. (Use the @samp{/version} option to determine the version number of the binaries and --- 1090,1094 ---- We try to put corresponding binaries and sources on the VMS distribution ! tape. But sometimes the binaries will be from an older version than the sources, because we don't always have time to update them. (Use the @samp{/version} option to determine the version number of the binaries and *************** *** 1017,1026 **** @enumerate @item ! Copy the file @file{vms.h} to @file{tm.h}, @file{xm-vms.h} to ! @file{config.h}, @file{vax.md} to @file{md.} and @file{vax.c} ! to @file{aux-output.c}. The files to be copied are found in the ! subdirectory named @file{config}; they should be copied to the ! main directory of GNU CC. If you wish, you may use the command file ! @file{config-gcc.com} to perform these steps for you.@refill @item --- 1099,1113 ---- @enumerate @item ! Execute the command procedure @file{vmsconfig.com} to copy files ! @file{vax-vms.h}, @file{xm-vax-vms.h}, @file{vax.c} and @file{vax.md} to ! @file{tm.h}, @file{config.h}, @file{aux-output.c}, and @file{md.} ! respectively, and to create files @file{tconfig.h} and ! @file{hconfig.h}. This procedure also creates several linker option ! files used by @file{make-cc1.com} and a data file used by ! @file{make-l2.com}.@refill ! ! @smallexample ! $ @@vmsconfig.com ! @end smallexample @item *************** *** 1067,1073 **** @smallexample ! $ lib gnu_cc:[000000]gcclib/delete=(new,eprintf) ! $ lib libgcc2/extract=*/output=libgcc2.obj ! $ lib gnu_cc:[000000]gcclib libgcc2.obj @end smallexample --- 1154,1160 ---- @smallexample ! $ library gnu_cc:[000000]gcclib/delete=(new,eprintf) ! $ library libgcc2/extract=*/output=libgcc2.obj ! $ library gnu_cc:[000000]gcclib libgcc2.obj @end smallexample *************** *** 1079,1082 **** --- 1166,1170 ---- library with the above procedure. + @item You may wish to build GCC in such a way that no files are written to the directory where the source files reside. An example would be the when *************** *** 1085,1095 **** @smallexample ! $ assign dua0:[gcc.build_dir.]tran=conc, - ! dua1:[gcc.source_dir.]/tran=conc gcc_build $ set default gcc_build:[000000] @end smallexample ! where @file{dua1:[gcc.source_dir.]} contains the source code, and ! @file{dua0:[gcc.build_dir.]} is meant to contain all of the generated object files and executables. Once you have done this, you can proceed building GCC as described above. (Keep in mind that @file{gcc_build} is a rooted logical --- 1173,1184 ---- @smallexample ! $ assign dua0:[gcc.build_dir.]/translation=concealed, - ! dua1:[gcc.source_dir.]/translation=concealed gcc_build $ set default gcc_build:[000000] @end smallexample ! where @file{dua1:[gcc.source_dir]} ! contains the source code, and ! @file{dua0:[gcc.build_dir]} is meant to contain all of the generated object files and executables. Once you have done this, you can proceed building GCC as described above. (Keep in mind that @file{gcc_build} is a rooted logical *************** *** 1097,1100 **** --- 1186,1190 ---- actual physical device name rather than another rooted logical name). + @item @strong{If you are building GNU CC with a previous version of GNU CC, you also should check to see that you have the newest version of the *************** *** 1112,1142 **** (The older versions had problems supporting @code{inline}.) Once you have a working 1.33 or newer GNU CC, you can change this file back. @end enumerate Under previous versions of GNU CC, the generated code would occasionally ! give strange results when linked to the sharable @file{VAXCRTL} library. Now this should work. ! Even with this version, however, GNU CC itself should not be linked to ! the sharable @file{VAXCRTL}. The @code{qsort} routine supplied with ! @file{VAXCRTL} has a bug which can cause a compiler crash. ! ! Similarly, the preprocessor should not be linked to the sharable ! @file{VAXCRTL}. The @code{strncat} routine supplied with @file{VAXCRTL} ! has a bug which can cause the preprocessor to go into an infinite loop. ! ! If you attempt to link to the sharable @file{VAXCRTL}, the VMS linker ! will strongly resist any effort to force it to use the @code{qsort} and ! @code{strncat} routines from @file{gcclib}. Until the bugs in ! @file{VAXCRTL} have been fixed, linking any of the compiler components ! to the sharable VAXCRTL is not recommended. (These routines can be ! bypassed by placing duplicate copies of @code{qsort} and @code{strncat} ! in @file{gcclib} under different names, and patching the compiler ! sources to use these routines). Both of the bugs in @file{VAXCRTL} are ! still present in VMS version 5.4-1, which is the most recent version as ! of this writing. The executables that are generated by @file{make-cc1.com} and ! @file{make-cccp.com} use the nonshared version of @file{VAXCRTL} (and ! thus use the @code{qsort} and @code{strncat} routines from ! @file{gcclib.olb}). --- 1202,1347 ---- (The older versions had problems supporting @code{inline}.) Once you have a working 1.33 or newer GNU CC, you can change this file back. + + @item + If you want to build GNU CC with the VAX C compiler, you will need to + make minor changes in @file{make-cccp.com} and @file{make-cc1.com} + to choose alternate definitions of @code{CC}, @code{CFLAGS}, and + @code{LIBS}. See comments in those files. However, you must + also have a working version of the GNU assembler (GNU as, aka GAS) as + it is used as the back-end for GNU CC to produce binary object modules + and is not included in the GNU CC sources. GAS is also needed to + compile @file{libgcc2} in order to build @file{gcclib} (see above); + @file{make-l2.com} expects to be able to find it operational in + @file{gnu_cc:[000000]gnu-as.exe}. + + To use GNU CC on VMS, you need the VMS driver programs + @file{gcc.exe}, @file{gcc.com}, and @file{gcc.cld}. They are + distributed with the VMS binaries (@file{gcc-vms}) rather than the + GNU CC sources. GAS is also included in @file{gcc-vms}, as is Bison. + + Once you have successfully built GNU CC with VAX C, you should use the + resulting compiler to rebuild itself. Before doing this, be sure to + restore the @code{CC}, @code{CFLAGS}, and @code{LIBS} definitions in + @file{make-cccp.com} and @file{make-cc1.com}. The second generation + compiler will be able to take advantage of many optimizations that must + be suppressed when building with other compilers. @end enumerate Under previous versions of GNU CC, the generated code would occasionally ! give strange results when linked with the sharable @file{VAXCRTL} library. Now this should work. ! Even with this version, however, GNU CC itself should not be linked with ! the sharable @file{VAXCRTL}. The version of @code{qsort} in ! @file{VAXCRTL} has a bug (known to be present in VMS versions V4.6 ! through V5.5) which causes the compiler to fail. The executables that are generated by @file{make-cc1.com} and ! @file{make-cccp.com} use the object library version of @file{VAXCRTL} in ! order to make use of the @code{qsort} routine in @file{gcclib.olb}. If ! you wish to link the compiler executables with the shareable image ! version of @file{VAXCRTL}, you should edit the file @file{tm.h} (created ! by @file{vmsconfig.com}) to define the macro @code{QSORT_WORKAROUND}. ! ! @code{QSORT_WORKAROUND} is always defined when GNU CC is compiled with ! VAX C, to avoid a problem in case @file{gcclib.olb} is not yet ! available. ! ! ! @node WE32K Install ! @section Installing GNU CC on the WE32K ! ! These computers are also known as the 3b2, 3b5, 3b20 and other similar ! names. (However, the 3b1 is actually a 68000; see @ref{3b1 Install}.) ! ! Don't use @samp{-g} when compiling with the system's compiler. The ! system's linker seems to be unable to handle such a large program with ! debugging information. ! ! The system's compiler runs out of capacity when compiling @file{stmt.c} ! in GNU CC. You can work around this by building @file{cpp} in GNU CC ! first, then use that instead of the system's preprocessor with the ! system's C compiler to compile @file{stmt.c}. Here is how: ! ! @example ! mv /lib/cpp /lib/cpp.att ! cp cpp /lib/cpp.gnu ! echo "/lib/cpp.gnu -traditional $*" > /lib/cpp ! chmod +x /lib/cpp ! @end example ! ! The system's compiler produces bad code for some of the GNU CC ! optimization files. So you must build the stage 2 compiler without ! optimization. Then build a stage 3 compiler with optimization. ! That executable should work. Here are the necessary commands: ! ! @example ! make LANGUAGES=c CC=stage1/xgcc CFLAGS="-Bstage1/ -g" ! make stage2 ! make CC=stage2/xgcc CFLAGS="-Bstage2/ -g -O" ! @end example ! ! You may need to raise the ULIMIT setting to build a C++ compiler, ! as the file @file{cc1plus} is larger than one megabyte. ! ! ! @node MIPS Install ! @section Installing GNU CC on the MIPS ! See @ref{Installation} about whether to use @samp{--with-stabs} or ! not. ! ! The MIPS C compiler needs to be told to increase its table size ! for switch statements with the @samp{-Wf,-XNg1500} option in ! order to compile @file{cp-parse.c}. If you use the @samp{-O2} ! optimization option, you also need to use @samp{-Olimit 3000}. ! Both of these options are automatically generated in the ! @file{Makefile} that the shell script @file{configure} builds. ! If you override the @code{CC} make variable and use the MIPS ! compilers, you may need to add @samp{-Wf,-XNg1500 -Olimit 3000}. ! ! MIPS computers running RISC-OS can support four different ! personalities: default, BSD 4.3, System V.3, and System V.4 ! (older versions of RISC-OS don't support V.4). To configure GCC ! for these platforms use the following configurations: ! ! @table @samp ! @item mips-mips-riscos@code{rev} ! Default configuration for RISC-OS, revision @code{rev}. ! ! @item mips-mips-riscos@code{rev}bsd ! BSD 4.3 configuration for RISC-OS, revision @code{rev}. ! ! @item mips-mips-riscos@code{rev}sysv4 ! System V.4 configuration for RISC-OS, revision @code{rev}. ! ! @item mips-mips-riscos@code{rev}sysv ! System V.3 configuration for RISC-OS, revision @code{rev}. ! @end table ! ! The revision @code{rev} mentioned above is the revision of ! RISC-OS to use. You must reconfigure GCC when going from a ! RISC-OS revision 4 to RISC-OS revision 5. This has the effect of ! avoiding a linker ! @ifclear INSTALLONLY ! bug (see @ref{Installation Problems} for more details). ! @end ifclear ! @ifset INSTALLONLY ! bug. ! @end ifset ! ! DECstations can support three different personalities: Ultrix, ! DEC OSF/1, and OSF/rose. To configure GCC for these platforms ! use the following configurations: ! ! @table @samp ! @item decstation-ultrix ! Ultrix configuration. ! ! @item decstation-osf1 ! Dec's version of OSF/1. ! ! @item decstation-osfrose ! Open Software Foundation reference port of OSF/1 which uses the ! OSF/rose object file format instead of ECOFF. Normally, you ! would not select this configuration. ! @end table diff -rc2N gcc-2.2.2/integrate.c gcc-2.3.1/integrate.c *** gcc-2.2.2/integrate.c Sun Jun 7 15:54:43 1992 --- gcc-2.3.1/integrate.c Tue Oct 20 06:48:15 1992 *************** *** 37,42 **** #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); extern struct obstack *function_maybepermanent_obstack; --- 37,40 ---- *************** *** 69,72 **** --- 67,71 ---- static tree copy_decl_tree (); + static tree copy_decl_list (); /* Return the constant equivalent of a given rtx, or 0 if none. */ *************** *** 115,119 **** /* If its not even close, don't even look. */ ! if (!TREE_INLINE (fndecl) && get_max_uid () > 3 * max_insns) return "function too large to be inline"; --- 114,118 ---- /* If its not even close, don't even look. */ ! if (!DECL_INLINE (fndecl) && get_max_uid () > 3 * max_insns) return "function too large to be inline"; *************** *** 122,126 **** /* Don't inline functions with large stack usage, since they can make other recursive functions burn up stack. */ ! if (!TREE_INLINE (fndecl) && get_frame_size () > 100) return "function stack frame for inlining"; #endif --- 121,125 ---- /* Don't inline functions with large stack usage, since they can make other recursive functions burn up stack. */ ! if (!DECL_INLINE (fndecl) && get_frame_size () > 100) return "function stack frame for inlining"; #endif *************** *** 152,156 **** return "function with varying-size parameter cannot be inline"; ! if (!TREE_INLINE (fndecl) && get_max_uid () > max_insns) { for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns; --- 151,155 ---- return "function with varying-size parameter cannot be inline"; ! if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns) { for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns; *************** *** 308,312 **** and the original DECL_INITIAL. */ ! return gen_inline_header_rtx (NULL, NULL, min_labelno, max_labelno, max_parm_reg, max_reg, current_function_args_size, --- 307,311 ---- and the original DECL_INITIAL. */ ! return gen_inline_header_rtx (NULL_RTX, NULL_RTX, min_labelno, max_labelno, max_parm_reg, max_reg, current_function_args_size, *************** *** 330,336 **** DECL_SAVED_INSNS (fndecl) = head; DECL_FRAME_SIZE (fndecl) = get_frame_size (); ! TREE_INLINE (fndecl) = 1; } /* Make the insns and PARM_DECLs of the current function permanent and record other information in DECL_SAVED_INSNS to allow inlining --- 329,359 ---- DECL_SAVED_INSNS (fndecl) = head; DECL_FRAME_SIZE (fndecl) = get_frame_size (); ! DECL_INLINE (fndecl) = 1; } + /* Adjust the BLOCK_END_NOTE pointers in a given copied DECL tree so that + they all point to the new (copied) rtxs. */ + + static void + adjust_copied_decl_tree (block) + register tree block; + { + register tree subblock; + register rtx original_end; + + original_end = BLOCK_END_NOTE (block); + if (original_end) + { + BLOCK_END_NOTE (block) = (rtx) NOTE_SOURCE_FILE (original_end); + NOTE_SOURCE_FILE (original_end) = 0; + } + + /* Process all subblocks. */ + for (subblock = BLOCK_SUBBLOCKS (block); + subblock; + subblock = TREE_CHAIN (subblock)) + adjust_copied_decl_tree (subblock); + } + /* Make the insns and PARM_DECLs of the current function permanent and record other information in DECL_SAVED_INSNS to allow inlining *************** *** 341,345 **** modified by the compilation process, so we copy all of them to new storage and consider the new insns to be the insn chain to be ! compiled. */ void --- 364,369 ---- modified by the compilation process, so we copy all of them to new storage and consider the new insns to be the insn chain to be ! compiled. Our caller (rest_of_compilation) saves the original ! DECL_INITIAL and DECL_ARGUMENTS; here we copy them. */ void *************** *** 482,485 **** --- 506,510 ---- DECL_INITIAL (fndecl) = copy_decl_tree (DECL_INITIAL (fndecl)); + DECL_ARGUMENTS (fndecl) = copy_decl_list (DECL_ARGUMENTS (fndecl)); /* Now copy each DECL_RTL which is a MEM, *************** *** 487,490 **** --- 512,518 ---- copy_decl_rtls (DECL_INITIAL (fndecl)); + /* The fndecl node acts as its own progenitor, so mark it as such. */ + DECL_ABSTRACT_ORIGIN (fndecl) = fndecl; + /* Now copy the chain of insns. Do this twice. The first copy the insn itself and its body. The second time copy of REG_NOTES. This is because *************** *** 506,511 **** copy = rtx_alloc (NOTE); - NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn); NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn); break; --- 534,545 ---- copy = rtx_alloc (NOTE); NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn); + if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END) + NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn); + else + { + NOTE_SOURCE_FILE (insn) = (char *) copy; + NOTE_SOURCE_FILE (copy) = 0; + } break; *************** *** 539,542 **** --- 573,578 ---- } + adjust_copied_decl_tree (DECL_INITIAL (fndecl)); + /* Now copy the REG_NOTES. */ for (insn = NEXT_INSN (get_insns ()); insn; insn = NEXT_INSN (insn)) *************** *** 553,556 **** --- 589,626 ---- } + /* Return a copy of a chain of nodes, chained through the TREE_CHAIN field. + For example, this can copy a list made of TREE_LIST nodes. While copying, + for each node copied which doesn't already have is DECL_ABSTRACT_ORIGIN + set to some non-zero value, set the DECL_ABSTRACT_ORIGIN of the copy to + point to the corresponding (abstract) original node. */ + + static tree + copy_decl_list (list) + tree list; + { + tree head; + register tree prev, next; + + if (list == 0) + return 0; + + head = prev = copy_node (list); + if (DECL_ABSTRACT_ORIGIN (head) == NULL_TREE) + DECL_ABSTRACT_ORIGIN (head) = list; + next = TREE_CHAIN (list); + while (next) + { + register tree copy; + + copy = copy_node (next); + if (DECL_ABSTRACT_ORIGIN (copy) == NULL_TREE) + DECL_ABSTRACT_ORIGIN (copy) = next; + TREE_CHAIN (prev) = copy; + prev = copy; + next = TREE_CHAIN (next); + } + return head; + } + /* Make a copy of the entire tree of blocks BLOCK, and return it. */ *************** *** 561,565 **** tree t, vars, subblocks; ! vars = copy_list (BLOCK_VARS (block)); subblocks = 0; --- 631,635 ---- tree t, vars, subblocks; ! vars = copy_decl_list (BLOCK_VARS (block)); subblocks = 0; *************** *** 575,578 **** --- 645,653 ---- BLOCK_VARS (t) = vars; BLOCK_SUBBLOCKS (t) = nreverse (subblocks); + /* If the BLOCK being cloned is already marked as having been instantiated + from something else, then leave that `origin' marking alone. Elsewise, + mark the clone as having originated from the BLOCK we are cloning. */ + if (BLOCK_ABSTRACT_ORIGIN (t) == NULL_TREE) + BLOCK_ABSTRACT_ORIGIN (t) = block; return t; } *************** *** 1059,1063 **** rtx structure_value_addr; { ! tree formal, actual; rtx header = DECL_SAVED_INSNS (fndecl); rtx insns = FIRST_FUNCTION_INSN (header); --- 1134,1138 ---- rtx structure_value_addr; { ! tree formal, actual, block; rtx header = DECL_SAVED_INSNS (fndecl); rtx insns = FIRST_FUNCTION_INSN (header); *************** *** 1087,1091 **** /* We expect PARMS to have the right length; don't crash if not. */ if (list_length (parms) != nargs) ! return (rtx)-1; /* Also check that the parms type match. Since the appropriate conversions or default promotions have already been applied, --- 1162,1166 ---- /* We expect PARMS to have the right length; don't crash if not. */ if (list_length (parms) != nargs) ! return (rtx) (HOST_WIDE_INT) -1; /* Also check that the parms type match. Since the appropriate conversions or default promotions have already been applied, *************** *** 1100,1109 **** enum machine_mode mode = TYPE_MODE (DECL_ARG_TYPE (formal)); if (mode != TYPE_MODE (TREE_TYPE (arg))) ! return (rtx)-1; /* If they are block mode, the types should match exactly. They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE, which could happen if the parameter has incomplete type. */ if (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal)) ! return (rtx)-1; } --- 1175,1184 ---- enum machine_mode mode = TYPE_MODE (DECL_ARG_TYPE (formal)); if (mode != TYPE_MODE (TREE_TYPE (arg))) ! return (rtx) (HOST_WIDE_INT) -1; /* If they are block mode, the types should match exactly. They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE, which could happen if the parameter has incomplete type. */ if (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal)) ! return (rtx) (HOST_WIDE_INT) -1; } *************** *** 1150,1155 **** && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER) { ! enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg)); ! rtx stack_slot = assign_stack_temp (mode, int_size_in_bytes (TREE_TYPE (arg)), 1); store_expr (arg, stack_slot, 0); --- 1225,1231 ---- && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER) { ! rtx stack_slot ! = assign_stack_temp (TYPE_MODE (TREE_TYPE (arg)), ! int_size_in_bytes (TREE_TYPE (arg)), 1); store_expr (arg, stack_slot, 0); *************** *** 1158,1162 **** } else if (GET_CODE (loc) != MEM) ! arg_vals[i] = expand_expr (arg, 0, mode, EXPAND_SUM); else arg_vals[i] = 0; --- 1234,1243 ---- } else if (GET_CODE (loc) != MEM) ! /* The mode if LOC and ARG can differ if LOC was a variable ! that had its mode promoted via PROMOTED_MODE. */ ! arg_vals[i] = convert_to_mode (GET_MODE (loc), ! expand_expr (arg, NULL_RTX, mode, ! EXPAND_SUM), ! TREE_UNSIGNED (TREE_TYPE (formal))); else arg_vals[i] = 0; *************** *** 1176,1180 **** || GET_CODE (arg_vals[i]) == MEM) && reg_overlap_mentioned_p (arg_vals[i], target)))) ! arg_vals[i] = copy_to_mode_reg (mode, arg_vals[i]); } --- 1257,1261 ---- || GET_CODE (arg_vals[i]) == MEM) && reg_overlap_mentioned_p (arg_vals[i], target)))) ! arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]); } *************** *** 1323,1327 **** value there. */ temp = copy_rtx_and_substitute (loc, map); ! subst_constants (&temp, 0, map); apply_change_group (); if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0))) --- 1404,1408 ---- value there. */ temp = copy_rtx_and_substitute (loc, map); ! subst_constants (&temp, NULL_RTX, map); apply_change_group (); if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0))) *************** *** 1376,1380 **** { temp = copy_rtx_and_substitute (loc, map); ! subst_constants (&temp, 0, map); apply_change_group (); emit_move_insn (temp, structure_value_addr); --- 1457,1461 ---- { temp = copy_rtx_and_substitute (loc, map); ! subst_constants (&temp, NULL_RTX, map); apply_change_group (); emit_move_insn (temp, structure_value_addr); *************** *** 1618,1629 **** inline_function_decl = fndecl; - integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map, 0); integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector); inline_function_decl = 0; ! /* End the scope containing the copied formal parameter variables. */ expand_end_bindings (getdecls (), 1, 1); ! poplevel (1, 1, 0); poplevel (0, 0, 0); emit_line_note (input_filename, lineno); --- 1699,1712 ---- inline_function_decl = fndecl; integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector); + integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map); inline_function_decl = 0; ! /* End the scope containing the copied formal parameter variables ! and copied LABEL_DECLs. */ expand_end_bindings (getdecls (), 1, 1); ! block = poplevel (1, 1, 0); ! BLOCK_ABSTRACT_ORIGIN (block) = fndecl; poplevel (0, 0, 0); emit_line_note (input_filename, lineno); *************** *** 1657,1661 **** TREE_USED (decl) = 1; /* Prevent warning for shadowing with these. */ ! DECL_FROM_INLINE (decl) = 1; pushdecl (decl); /* Fully instantiate the address with the equivalent form so that the --- 1740,1744 ---- TREE_USED (decl) = 1; /* Prevent warning for shadowing with these. */ ! DECL_ABSTRACT_ORIGIN (decl) = tail; pushdecl (decl); /* Fully instantiate the address with the equivalent form so that the *************** *** 1663,1667 **** virtual register. Do this by not passing an insn to subst_constants. */ ! subst_constants (&new_decl_rtl, 0, map); apply_change_group (); DECL_RTL (decl) = new_decl_rtl; --- 1746,1750 ---- virtual register. Do this by not passing an insn to subst_constants. */ ! subst_constants (&new_decl_rtl, NULL_RTX, map); apply_change_group (); DECL_RTL (decl) = new_decl_rtl; *************** *** 1673,1696 **** LEVEL indicates how far down into the BLOCK tree is the node we are ! currently traversing. It is always zero for the initial call. ! MAP, if nonzero, is a pointer to a inline_remap map which indicates how registers used in the DECL_RTL field should be remapped. If it is zero, ! no mapping is necessary. ! ! FUNCTIONBODY indicates whether the top level block tree corresponds to ! a function body. This is identical in meaning to the functionbody ! argument of poplevel. */ static void ! integrate_decl_tree (let, level, map, functionbody) tree let; int level; struct inline_remap *map; - int functionbody; { tree t, node; ! pushlevel (0); for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) --- 1756,1775 ---- LEVEL indicates how far down into the BLOCK tree is the node we are ! currently traversing. It is always zero except for recursive calls. ! MAP, if nonzero, is a pointer to an inline_remap map which indicates how registers used in the DECL_RTL field should be remapped. If it is zero, ! no mapping is necessary. */ static void ! integrate_decl_tree (let, level, map) tree let; int level; struct inline_remap *map; { tree t, node; ! if (level > 0) ! pushlevel (0); for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) *************** *** 1699,1703 **** DECL_SOURCE_LINE (d) = DECL_SOURCE_LINE (t); DECL_SOURCE_FILE (d) = DECL_SOURCE_FILE (t); ! if (! functionbody && DECL_RTL (t) != 0) { DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t), map); --- 1778,1782 ---- DECL_SOURCE_LINE (d) = DECL_SOURCE_LINE (t); DECL_SOURCE_FILE (d) = DECL_SOURCE_FILE (t); ! if (DECL_RTL (t) != 0) { DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t), map); *************** *** 1706,1715 **** virtual register. Do this by not passing an insn to subst_constants. */ ! subst_constants (&DECL_RTL (d), 0, map); apply_change_group (); } else if (DECL_RTL (t)) DECL_RTL (d) = copy_rtx (DECL_RTL (t)); ! TREE_EXTERNAL (d) = TREE_EXTERNAL (t); TREE_STATIC (d) = TREE_STATIC (t); TREE_PUBLIC (d) = TREE_PUBLIC (t); --- 1785,1794 ---- virtual register. Do this by not passing an insn to subst_constants. */ ! subst_constants (&DECL_RTL (d), NULL_RTX, map); apply_change_group (); } else if (DECL_RTL (t)) DECL_RTL (d) = copy_rtx (DECL_RTL (t)); ! DECL_EXTERNAL (d) = DECL_EXTERNAL (t); TREE_STATIC (d) = TREE_STATIC (t); TREE_PUBLIC (d) = TREE_PUBLIC (t); *************** *** 1721,1734 **** TREE_USED (d) = 1; /* Prevent warning for shadowing with these. */ ! DECL_FROM_INLINE (d) = 1; pushdecl (d); } for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t)) ! integrate_decl_tree (t, level + 1, map, functionbody); ! node = poplevel (level > 0, 0, level == 0 && functionbody); ! if (node) ! TREE_USED (node) = TREE_USED (let); } --- 1800,1819 ---- TREE_USED (d) = 1; /* Prevent warning for shadowing with these. */ ! DECL_ABSTRACT_ORIGIN (d) = t; pushdecl (d); } for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t)) ! integrate_decl_tree (t, level + 1, map); ! if (level > 0) ! { ! node = poplevel (1, 0, 0); ! if (node) ! { ! TREE_USED (node) = TREE_USED (let); ! BLOCK_ABSTRACT_ORIGIN (node) = let; ! } ! } } *************** *** 1802,1806 **** loc = plus_constant (loc, rounded); #endif ! map->reg_map[regno] = temp = force_operand (loc, 0); map->const_equiv_map[REGNO (temp)] = loc; map->const_age_map[REGNO (temp)] = CONST_AGE_PARM; --- 1887,1892 ---- loc = plus_constant (loc, rounded); #endif ! map->reg_map[regno] = temp ! = force_reg (Pmode, force_operand (loc, NULL_RTX)); map->const_equiv_map[REGNO (temp)] = loc; map->const_age_map[REGNO (temp)] = CONST_AGE_PARM; *************** *** 1821,1825 **** loc = assign_stack_temp (BLKmode, size, 1); loc = XEXP (loc, 0); ! map->reg_map[regno] = temp = force_operand (loc, 0); map->const_equiv_map[REGNO (temp)] = loc; map->const_age_map[REGNO (temp)] = CONST_AGE_PARM; --- 1907,1912 ---- loc = assign_stack_temp (BLKmode, size, 1); loc = XEXP (loc, 0); ! map->reg_map[regno] = temp ! = force_reg (Pmode, force_operand (loc, NULL_RTX)); map->const_equiv_map[REGNO (temp)] = loc; map->const_age_map[REGNO (temp)] = CONST_AGE_PARM; *************** *** 2074,2077 **** --- 2161,2168 ---- break; + case 'w': + XWINT (copy, i) = XWINT (orig, i); + break; + case 'i': XINT (copy, i) = XINT (orig, i); *************** *** 2225,2229 **** valid. We handle two cases: extracting a full word in an integral mode and extracting the low part. */ ! subst_constants (&inner, 0, map); if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT --- 2316,2320 ---- valid. We handle two cases: extracting a full word in an integral mode and extracting the low part. */ ! subst_constants (&inner, NULL_RTX, map); if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT *************** *** 2264,2268 **** while (GET_CODE (*dest_loc) == ZERO_EXTRACT ! || GET_CODE (*dest_loc) == SIGN_EXTRACT || GET_CODE (*dest_loc) == SUBREG || GET_CODE (*dest_loc) == STRICT_LOW_PART) --- 2355,2360 ---- while (GET_CODE (*dest_loc) == ZERO_EXTRACT ! /* By convention, we always use ZERO_EXTRACT in the dest. */ ! /* || GET_CODE (*dest_loc) == SIGN_EXTRACT */ || GET_CODE (*dest_loc) == SUBREG || GET_CODE (*dest_loc) == STRICT_LOW_PART) *************** *** 2276,2279 **** --- 2368,2375 ---- } + /* Do substitute in the address of a destination in memory. */ + if (GET_CODE (*dest_loc) == MEM) + subst_constants (&XEXP (*dest_loc, 0), insn, map); + /* Check for the case of DEST a SUBREG, both it and the underlying register are less than one word, and the SUBREG has the wider mode. *************** *** 2336,2339 **** --- 2432,2436 ---- case 'i': case 's': + case 'w': break; *************** *** 2377,2380 **** --- 2474,2482 ---- new = simplify_relational_operation (code, op_mode, XEXP (x, 0), XEXP (x, 1)); + #ifdef FLOAT_STORE_FLAG_VALUE + if (new != 0 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) + new = ((new == const0_rtx) ? CONST0_RTX (GET_MODE (x)) + : immed_real_const_1 (FLOAT_STORE_FLAG_VALUE, GET_MODE (x))); + #endif break; } *************** *** 2486,2489 **** --- 2588,2717 ---- } + /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the + given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so + that it points to the node itself, thus indicating that the node is its + own (abstract) origin. Additionally, if the BLOCK_ABSTRACT_ORIGIN for + the given node is NULL, recursively descend the decl/block tree which + it is the root of, and for each other ..._DECL or BLOCK node contained + therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also + still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN + values to point to themselves. */ + + static void set_decl_origin_self (); + + static void + set_block_origin_self (stmt) + register tree stmt; + { + if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) + { + BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; + + { + register tree local_decl; + + for (local_decl = BLOCK_VARS (stmt); + local_decl != NULL_TREE; + local_decl = TREE_CHAIN (local_decl)) + set_decl_origin_self (local_decl); /* Potential recursion. */ + } + + { + register tree subblock; + + for (subblock = BLOCK_SUBBLOCKS (stmt); + subblock != NULL_TREE; + subblock = BLOCK_CHAIN (subblock)) + set_block_origin_self (subblock); /* Recurse. */ + } + } + } + + /* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for + the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the + node to so that it points to the node itself, thus indicating that the + node represents its own (abstract) origin. Additionally, if the + DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend + the decl/block tree of which the given node is the root of, and for + each other ..._DECL or BLOCK node contained therein whose + DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL, + set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to + point to themselves. */ + + static void + set_decl_origin_self (decl) + register tree decl; + { + if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) + { + DECL_ABSTRACT_ORIGIN (decl) = decl; + if (TREE_CODE (decl) == FUNCTION_DECL) + { + register tree arg; + + for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) + DECL_ABSTRACT_ORIGIN (arg) = arg; + if (DECL_INITIAL (decl) != NULL_TREE) + set_block_origin_self (DECL_INITIAL (decl)); + } + } + } + + /* Given a pointer to some BLOCK node, and a boolean value to set the + "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for + the given block, and for all local decls and all local sub-blocks + (recursively) which are contained therein. */ + + void set_decl_abstract_flags (); + + static void + set_block_abstract_flags (stmt, setting) + register tree stmt; + register int setting; + { + BLOCK_ABSTRACT (stmt) = setting; + + { + register tree local_decl; + + for (local_decl = BLOCK_VARS (stmt); + local_decl != NULL_TREE; + local_decl = TREE_CHAIN (local_decl)) + set_decl_abstract_flags (local_decl, setting); + } + + { + register tree subblock; + + for (subblock = BLOCK_SUBBLOCKS (stmt); + subblock != NULL_TREE; + subblock = BLOCK_CHAIN (subblock)) + set_block_abstract_flags (subblock, setting); + } + } + + /* Given a pointer to some ..._DECL node, and a boolean value to set the + "abstract" flags to, set that value into the DECL_ABSTRACT flag for the + given decl, and (in the case where the decl is a FUNCTION_DECL) also + set the abstract flags for all of the parameters, local vars, local + blocks and sub-blocks (recursively) to the same setting. */ + + void + set_decl_abstract_flags (decl, setting) + register tree decl; + register int setting; + { + DECL_ABSTRACT (decl) = setting; + if (TREE_CODE (decl) == FUNCTION_DECL) + { + register tree arg; + + for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) + DECL_ABSTRACT (arg) = setting; + if (DECL_INITIAL (decl) != NULL_TREE) + set_block_abstract_flags (DECL_INITIAL (decl), setting); + } + } + /* Output the assembly language code for the function FNDECL from its DECL_SAVED_INSNS. Used for inline functions that are output *************** *** 2566,2569 **** --- 2794,2808 ---- set_new_first_and_last_insn (FIRST_PARM_INSN (head), last); set_new_first_and_last_label_num (FIRST_LABELNO (head), LAST_LABELNO (head)); + + /* We must have already output DWARF debugging information for the + original (abstract) inline function declaration/definition, so + we want to make sure that the debugging information we generate + for this special instance of the inline function refers back to + the information we already generated. To make sure that happens, + we simply have to set the DECL_ABSTRACT_ORIGIN for the function + node (and for all of the local ..._DECL nodes which are its children) + so that they all point to themselves. */ + + set_decl_origin_self (fndecl); /* Compile this function all the way down to assembly code. */ diff -rc2N gcc-2.2.2/invoke.texi gcc-2.3.1/invoke.texi *** gcc-2.2.2/invoke.texi Sun May 31 07:27:28 1992 --- gcc-2.3.1/invoke.texi Sat Oct 31 15:54:13 1992 *************** *** 22,38 **** @cindex grouping options @cindex options, grouping ! The GNU C compiler uses a command syntax much like the Unix C compiler. ! The @code{gcc} program accepts options and file names as operands. ! Multiple single-letter options may @emph{not} be grouped: @samp{-dr} is ! very different from @w{@samp{-d -r}}. @cindex order of options @cindex options, order You can mix options and other arguments. For the most part, the order ! you use doesn't matter; @code{gcc} reorders the command-line options so ! that the choices specified by option flags are applied to all input ! files. Order does matter when you use several options of the same kind; ! for example, if you specify @samp{-L} more than once, the directories ! are searched in the order specified. Many options have long names starting with @samp{-f} or with --- 22,36 ---- @cindex grouping options @cindex options, grouping ! The @code{gcc} program accepts options and file names as operands. Many ! options have multiletter names; therefore multiple single-letter options ! may @emph{not} be grouped: @samp{-dr} is very different from @w{@samp{-d ! -r}}. @cindex order of options @cindex options, order You can mix options and other arguments. For the most part, the order ! you use doesn't matter. Order does matter when you use several options ! of the same kind; for example, if you specify @samp{-L} more than once, ! the directories are searched in the order specified. Many options have long names starting with @samp{-f} or with *************** *** 43,46 **** --- 41,71 ---- only one of these two forms, whichever one is not the default. + @menu + * Option Summary:: Brief list of all options, without explanations. + * Overall Options:: Controlling the kind of output: + an executable, object files, assembler files, + or preprocessed source. + * Dialect Options:: Controlling the variant of C language compiled. + * Warning Options:: How picky should the compiler be? + * Debugging Options:: Symbol tables, measurements, and debugging dumps. + * Optimize Options:: How much optimization? + * Preprocessor Options:: Controlling header files and macro definitions. + Also, getting dependency information for Make. + * Assembler Options:: Passing options to the assembler. + * Link Options:: Specifying libraries and so on. + * Directory Options:: Where to find header files and libraries. + Where to find the compiler executable files. + * Target Options:: Running a cross-compiler, or an old version of GNU CC. + * Submodel Options:: Specifying minor hardware or convention variations, + such as 68010 vs 68020. + * Code Gen Options:: Specifying conventions for function calls, data layout + and register usage. + * Environment Variables:: Env vars that affect GNU CC. + * Running Protoize:: Automatically adding or removing function prototypes. + @end menu + + @node Option Summary + @section Option Summary + Here is a summary of all the options, grouped by type. Explanations are in the following sections. *************** *** 56,63 **** @xref{Dialect Options,,Options Controlling Dialect}. @example ! -ansi -fbuiltin -fcond-mismatch -fno-asm -fsigned-bitfields -fsigned-char -funsigned-bitfields -funsigned-char -fwritable-strings -traditional -traditional-cpp -trigraphs @end example --- 81,90 ---- @xref{Dialect Options,,Options Controlling Dialect}. @example ! -ansi -fcond-mismatch -fno-asm -fno-builtin -fsigned-bitfields -fsigned-char -funsigned-bitfields -funsigned-char -fwritable-strings -traditional -traditional-cpp -trigraphs + -fall-virtual -fdollars-in-identifiers -fenum-int-equiv + -fno-strict-prototype -fthis-is-variable @end example *************** *** 68,74 **** -w -W -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wcomment -Wconversion -Werror ! -Wformat -Wid-clash-@var{len} -Wimplicit -Wimport ! -Winline -Wmissing-prototypes ! -Wparentheses -Wpointer-arith -Wreturn-type -Wshadow -Wstrict-prototypes -Wswitch -Wtraditional -Wtrigraphs -Wuninitialized -Wunused -Wwrite-strings -Wchar-subscripts --- 95,101 ---- -w -W -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wcomment -Wconversion -Werror ! -Wformat -Wid-clash-@var{len} -Wenum-clash -Wimplicit -Wimport ! -Winline -Wmissing-prototypes -Wnested-externs -Wparentheses ! -Wpointer-arith -Wredundant-decls -Wreturn-type -Wshadow -Wstrict-prototypes -Wswitch -Wtraditional -Wtrigraphs -Wuninitialized -Wunused -Wwrite-strings -Wchar-subscripts *************** *** 79,84 **** @example -a -d@var{letters} -fpretend-float ! -g -g@var{level} -ggdb -gdwarf ! -gstabs -gstabs+ -gcoff -gxcoff -p -pg -save-temps @end example --- 106,111 ---- @example -a -d@var{letters} -fpretend-float ! -g -g@var{level} -ggdb -gdwarf -gdwarf+ ! -gstabs -gstabs+ -gcoff -gxcoff -gxcoff+ -p -pg -save-temps @end example *************** *** 89,98 **** -fcaller-saves -fcse-follow-jumps -fcse-skip-blocks -fdelayed-branch -fexpensive-optimizations -ffast-math ! -ffloat-store -fforce-addr -fforce-mem -finline ! -finline-functions -fkeep-inline-functions ! -fno-defer-pop -fno-function-cse -fomit-frame-pointer -frerun-cse-after-loop -fschedule-insns -fschedule-insns2 -fstrength-reduce -fthread-jumps -funroll-all-loops -funroll-loops -O -O2 @end example --- 116,126 ---- -fcaller-saves -fcse-follow-jumps -fcse-skip-blocks -fdelayed-branch -fexpensive-optimizations -ffast-math ! -ffloat-store -fforce-addr -fforce-mem ! -finline-functions -fkeep-inline-functions -fno-defer-pop ! -fno-function-cse -fno-inline -fno-peephole -fomit-frame-pointer -frerun-cse-after-loop -fschedule-insns -fschedule-insns2 -fstrength-reduce -fthread-jumps -funroll-all-loops -funroll-loops + -felide-constructors -fmemoize-lookups -fno-default-inline -O -O2 @end example *************** *** 101,105 **** @xref{Preprocessor Options,,Options Controlling the Preprocessor}. @example ! -C -dD -dM -dN -D@var{macro}@r{[}=@var{defn}@r{]} -E -H -include @var{file} -imacros @var{file} --- 129,133 ---- @xref{Preprocessor Options,,Options Controlling the Preprocessor}. @example ! -A@var{assertion} -C -dD -dM -dN -D@var{macro}@r{[}=@var{defn}@r{]} -E -H -include @var{file} -imacros @var{file} *************** *** 107,115 **** @end example @item Linker Options @xref{Link Options,,Options for Linking}. @example @var{object-file-name} ! -l@var{library} -nostdlib -static @end example --- 135,152 ---- @end example + @item Assembler Option + @xref{Assembler Options,,Passing Options to the Assembler}. + @example + -Wa,@var{option} + @end example + @item Linker Options @xref{Link Options,,Options for Linking}. @example @var{object-file-name} ! -l@var{library} -nostdlib ! -static -shared -symbolic ! -Xlinker @var{option} ! -u @var{symbol} @end example *************** *** 130,135 **** @example @emph{M680x0 Options} ! -m68000 -m68020 -m68881 -mbitfield -mc68000 -mc68020 -mfpa ! -mnobitfield -mrtd -mshort -msoft-float @emph{VAX Options} --- 167,172 ---- @example @emph{M680x0 Options} ! -m68000 -m68020 -m68020-40 -m68030 -m68040 -m68881 -mbitfield ! -mc68000 -mc68020 -mfpa -mnobitfield -mrtd -mshort -msoft-float @emph{VAX Options} *************** *** 137,141 **** @emph{SPARC Options} ! -mforce-align -mfpu -mno-epilogue @emph{Convex Options} --- 174,179 ---- @emph{SPARC Options} ! -mforce-align -mno-epilogue ! @c -mfpu turned off below w/@ignore for some reason. @emph{Convex Options} *************** *** 171,175 **** @emph{i386 Options} ! -m486 -msoft-float @end example --- 209,242 ---- @emph{i386 Options} ! -m486 -mno486 -msoft-float -msvr3-shlib -mieee-fp ! -mno-fp-ret-in-387 ! ! @emph{HPPA Options} ! -mno-bss ! -mpa-risc-1-0 ! -mpa-risc-1-1 ! -mkernel ! -mshared-libs ! -mno-shared-libs ! -mlong-calls ! ! @emph{Intel 960 Options} ! -m@var{cpu type} ! -mnumerics -msoft-float ! -mcode-align -mno-code-align ! -mleaf-procedures -mno-leaf-procedures ! -mtail-call -mno-tail-call ! -mcomplex-addr -mno-complex-addr ! -mclean-linkage -mno-clean-linkage ! -mic-compat -mic2.0-compat -mic3.0-compat ! -masm-compat -mintel-asm ! -mstrict-align -mno-strict-align ! -mold-align -mno-old-align ! ! @emph{DEC Alpha Options} ! -mfp-regs -mno-fp-regs -mno-soft-float -msoft-float ! ! @emph{System V Options} ! -G -Qy -Qn -YP,@var{paths} -Ym,@var{dir} @end example *************** *** 178,185 **** @example -fcall-saved-@var{reg} -fcall-used-@var{reg} -ffixed-@var{reg} ! -fno-common -fpcc-struct-return -fpic -fPIC -fshared-data ! -fshort-enums -fshort-double -fvolatile @end example - @end table --- 245,253 ---- @example -fcall-saved-@var{reg} -fcall-used-@var{reg} -ffixed-@var{reg} ! -finhibit-size-directive -fnonnull-objects -fno-common ! -fno-ident -fno-gnu-linker -fpcc-struct-return -fpic -fPIC ! -fshared-data -fshort-enums -fshort-double -fvolatile ! -fverbose-asm @end example @end table *************** *** 194,209 **** * Preprocessor Options:: Controlling header files and macro definitions. Also, getting dependency information for Make. * Link Options:: Specifying libraries and so on. * Directory Options:: Where to find header files and libraries. Where to find the compiler executable files. * Target Options:: Running a cross-compiler, or an old version of GNU CC. - * Submodel Options:: Specifying minor hardware or convention variations, - such as 68010 vs 68020. - * Code Gen Options:: Specifying conventions for function calls, data layout - and register usage. - * Environment Variables:: Env vars that affect GNU CC. @end menu ! @node Overall Options, Dialect Options, Invoking GCC, Invoking GCC @section Options Controlling the Kind of Output --- 262,273 ---- * Preprocessor Options:: Controlling header files and macro definitions. Also, getting dependency information for Make. + * Assembler Options:: Passing options to the assembler. * Link Options:: Specifying libraries and so on. * Directory Options:: Where to find header files and libraries. Where to find the compiler executable files. * Target Options:: Running a cross-compiler, or an old version of GNU CC. @end menu ! @node Overall Options @section Options Controlling the Kind of Output *************** *** 225,230 **** C source code which should not be preprocessed. @item @var{file}.m ! Objective-C source code @item @var{file}.h --- 289,298 ---- C source code which should not be preprocessed. + @item @var{file}.ii + C++ source code which should not be preprocessed. + @item @var{file}.m ! Objective-C source code. Note that you must link with the library ! @file{libobjc.a} to make an Objective-C program work. @item @var{file}.h *************** *** 326,330 **** @end table ! @node Dialect Options, Warning Options, Overall Options, Invoking GCC @section Options Controlling Dialect @cindex dialect options --- 394,398 ---- @end table ! @node Dialect Options @section Options Controlling Dialect @cindex dialect options *************** *** 332,336 **** @cindex options, dialect ! The following options control the dialect of C that the compiler accepts: --- 400,404 ---- @cindex options, dialect ! The following options control the dialect of C or C++ that the compiler accepts: *************** *** 368,371 **** --- 436,467 ---- @code{_exit} are not builtin functions when @samp{-ansi} is used. + @item -fall-virtual + Treat certain member functions as virtual, implicitly (C++ only). This + applies to all member functions declared in the same class with a + ``method-call'' operator method (except for constructor functions and + @code{new} or @code{delete} member operators). In effect, all of these + methods become ``implicitly virtual.'' + + This does not mean that all calls to these methods will be made through + the internal table of virtual functions. There are some circumstances + under which it is obvious that a call to a given virtual function can be + made directly, and in these cases the calls still go direct. + + The effect of making all methods of a class with a declared + @samp{operator->()()} implicitly virtual using @samp{-fall-virtual} + extends also to all non-constructor methods of any class derived from + such a class. + + @item -fdollars-in-identifiers + Permit the use of @samp{$} in identifiers (C++ only). You can also use + @samp{-fno-dollars-in-identifiers} to explicitly prohibit use of + @samp{$}. (GNU C++ allows @samp{$} by default on some target systems + but not others.) + + @item -fenum-int-equiv + Permit implicit conversion of @code{int} to enumeration types (C++ + only). Normally GNU C++ allows conversion of @code{enum} to @code{int}, + but not the other way around. + @item -fno-asm Do not recognize @code{asm}, @code{inline} or @code{typeof} as a *************** *** 376,387 **** @item -fno-builtin Don't recognize built-in functions that do not begin with two leading ! underscores. Currently, the functions affected include @code{alloca}, ! @code{abort}, @code{exit}, @code{_exit}, @code{abs}, @code{fabs}, ! @code{labs}, @code{memcpy}, @code{memcmp}, @code{strcmp}, ! @code{strcpy}, @code{strlen}, and @code{sqrt}. The @samp{-ansi} option prevents @code{alloca} and @code{_exit} from being builtin functions. @item -trigraphs Support ANSI C trigraphs. You don't want to know about this --- 472,497 ---- @item -fno-builtin Don't recognize built-in functions that do not begin with two leading ! underscores. Currently, the functions affected include @code{_exit}, ! @code{abort}, @code{abs}, @code{alloca}, @code{cos}, @code{exit}, ! @code{fabs}, @code{labs}, @code{memcmp}, @code{memcpy}, @code{sin}, ! @code{sqrt}, @code{strcmp}, @code{strcpy}, and @code{strlen}. The @samp{-ansi} option prevents @code{alloca} and @code{_exit} from being builtin functions. + @item -fno-strict-prototype + Treat a function declaration with no arguments, such as @samp{int foo + ();}, as C would treat it---as saying nothing about the number of + arguments or their types (C++ only). Normally, such a declaration in + C++ means that the function @code{foo} takes no arguments. + + @item -fthis-is-variable + Permit assignment to @code{this} (C++ only). The incorporation of + user-defined free store management into C++ has made assignment to + @samp{this} an anachronism. Therefore, by default it is invalid to + assign to @code{this} within a class member function. However, for + backwards compatibility, you can make it valid with + @samp{-fthis-is-variable}. + @item -trigraphs Support ANSI C trigraphs. You don't want to know about this *************** *** 510,514 **** @end table ! @node Warning Options, Debugging Options, Dialect Options, Invoking GCC @section Options to Request or Suppress Warnings @cindex options to control warnings --- 620,624 ---- @end table ! @node Warning Options @section Options to Request or Suppress Warnings @cindex options to control warnings *************** *** 539,543 **** Inhibit all warning messages. ! @item -Wno_import Inhibit warning messages about the use of @samp{#import}. --- 649,653 ---- Inhibit all warning messages. ! @item -Wno-import Inhibit warning messages about the use of @samp{#import}. *************** *** 614,619 **** --- 724,752 ---- @item An unsigned value is compared against zero with @samp{>} or @samp{<=}. + + @item + A comparison like @samp{x<=y<=z} appears; this is equivalent to + @samp{(x<=y ? 1 : 0) <= z}, which is a different interpretation from + that of ordinary mathematical notation. + + @item + Storage-class specifiers like @code{static} are not the first things in + a declaration. According to the C Standard, this usage is obsolescent. + + @item + An aggregate has a partly bracketed initializer. + For example, the following code would evoke such a warning, + because braces are missing around the initializer for @code{x.h}: + + @example + struct s @{ int f, g; @}; + struct t @{ struct s h; int i; @}; + struct t x = @{ 1, 2, 3 @}; + @end example @end itemize + @item -Wenum-clash + Warn about conversion between different enumeration types (C++ only). + @item -Wimplicit Warn whenever a function or parameter is implicitly declared. *************** *** 629,632 **** --- 762,775 ---- a statement computes a result that is explicitly not used. + If you want to prevent a warning for a particular variable, you can use + this macro: + + @example + #define USE(var) \ + static void * use_##var = (&use_##var, (void *) &var) + + USE (string); + @end example + @item -Wswitch Warn whenever a @code{switch} statement has an index of enumeral type *************** *** 817,821 **** @end table ! @node Debugging Options, Optimize Options, Warning Options, Invoking GCC @section Options for Debugging Your Program or GNU CC @cindex options, debugging --- 960,964 ---- @end table ! @node Debugging Options @section Options for Debugging Your Program or GNU CC @cindex options, debugging *************** *** 833,839 **** On most systems that use stabs format, @samp{-g} enables use of extra debugging information that only GDB can use; this extra information ! makes debugging work better in GDB but will probably make DBX crash or refuse to read the program. If you want to control for certain whether ! to generate the extra information, use @samp{-gstabs+} or @samp{-gstabs} (see below). --- 976,984 ---- On most systems that use stabs format, @samp{-g} enables use of extra debugging information that only GDB can use; this extra information ! makes debugging work better in GDB but will probably make other debuggers ! crash or refuse to read the program. If you want to control for certain whether ! to generate the extra information, use @samp{-gstabs+}, @samp{-gstabs}, ! @samp{-gxcoff+}, @samp{-gxcoff}, @samp{-gdwarf+}, or @samp{-gdwarf} (see below). *************** *** 863,880 **** @item -gstabs+ Produce debugging information in stabs format (if that is supported), ! using GDB extensions. The use of these extensions is likely to make DBX ! crash or refuse to read the program. @item -gcoff Produce debugging information in COFF format (if that is supported). ! This is the format used by SDB on COFF systems. @item -gxcoff Produce debugging information in XCOFF format (if that is supported). ! This is the format used on IBM RS/6000 systems. @item -gdwarf Produce debugging information in DWARF format (if that is supported). ! This is the format used by SDB on systems that use DWARF. @item -g@var{level} --- 1008,1039 ---- @item -gstabs+ Produce debugging information in stabs format (if that is supported), ! using GNU extensions understood only by the GNU debugger (GDB). The ! use of these extensions is likely to make other debuggers crash or ! refuse to read the program. @item -gcoff Produce debugging information in COFF format (if that is supported). ! This is the format used by SDB on most System V systems prior to ! System V Release 4. @item -gxcoff Produce debugging information in XCOFF format (if that is supported). ! This is the format used by the DBX debugger on IBM RS/6000 systems. + @item -gxcoff+ + Produce debugging information in XCOFF format (if that is supported), + using GNU extensions understood only by the GNU debugger (GDB). The + use of these extensions is likely to make other debuggers crash or + refuse to read the program. + @item -gdwarf Produce debugging information in DWARF format (if that is supported). ! This is the format used by SDB on most System V Release 4 systems. ! ! @item -gdwarf+ ! Produce debugging information in DWARF format (if that is supported), ! using GNU extensions understood only by the GNU debugger (GDB). The ! use of these extensions is likely to make other debuggers crash or ! refuse to read the program. @item -g@var{level} *************** *** 900,904 **** Generate extra code to write profile information suitable for the analysis program @code{prof}. - @c ??? looks like -p and -pg are now equivalent. Are they? 11dec91 @cindex @code{gprof} --- 1059,1062 ---- *************** *** 956,962 **** @file{@var{file}.sched}. @item l ! Dump after local register allocation, to @file{@var{file}.lreg}. @item g ! Dump after global register allocation, to @file{@var{file}.greg}. @item R Dump after the second instruction scheduling pass, to --- 1114,1122 ---- @file{@var{file}.sched}. @item l ! Dump after local register allocation, to@* ! @file{@var{file}.lreg}. @item g ! Dump after global register allocation, to@* ! @file{@var{file}.greg}. @item R Dump after the second instruction scheduling pass, to *************** *** 992,996 **** @end table ! @node Optimize Options, Preprocessor Options, Debugging Options, Invoking GCC @section Options That Control Optimization @cindex optimize options --- 1152,1156 ---- @end table ! @node Optimize Options @section Options That Control Optimization @cindex optimize options *************** *** 1001,1004 **** --- 1161,1165 ---- @table @code @item -O + @itemx -O1 Optimize. Optimizing compilation takes somewhat more time, and a lot more memory for a large function. *************** *** 1031,1034 **** --- 1192,1201 ---- optimization, except for @samp{-funroll-loops}, @samp{-funroll-all-loops} and @samp{-fomit-frame-pointer}. + + @item -O0 + Do not optimize. + + If you use multiple @samp{-O} options, with or without level numbers, + the last such option is the one that is effective. @end table *************** *** 1042,1053 **** @table @code @item -ffloat-store ! Do not store floating point variables in registers. This ! prevents undesirable excess precision on machines such as the ! 68000 where the floating registers (of the 68881) keep more ! precision than a @code{double} is supposed to have. ! ! For most programs, the excess precision does only good, but a few ! programs rely on the precise definition of IEEE floating point. ! Use @samp{-ffloat-store} for such programs. @item -fno-defer-pop --- 1209,1222 ---- @table @code @item -ffloat-store ! Do not store floating point variables in registers, and inhibit other ! options that might change whether a floating point value is taken from a ! register or memory. ! ! This option prevents undesirable excess precision on machines such as ! the 68000 where the floating registers (of the 68881) keep more ! precision than a @code{double} is supposed to have. For most programs, ! the excess precision does only good, but a few programs rely on the ! precise definition of IEEE floating point. Use @samp{-ffloat-store} for ! such programs. @item -fno-defer-pop *************** *** 1097,1101 **** Don't pay attention to the @code{inline} keyword. Normally this option is used to keep the compiler from expanding any functions inline. ! @item -finline-functions Integrate all simple functions into their callers. The compiler --- 1266,1271 ---- Don't pay attention to the @code{inline} keyword. Normally this option is used to keep the compiler from expanding any functions inline. ! Note that if you are not optimizing, no functions can be expanded inline. ! @item -finline-functions Integrate all simple functions into their callers. The compiler *************** *** 1112,1115 **** --- 1282,1289 ---- callable version of the function. + @item -fno-default-inline + Don't make member functions inline by default merely because they are + defined inside the class scope (C++ only). + @item -fno-function-cse Do not put function addresses in registers; make each instruction that *************** *** 1130,1136 **** an exact implementation of IEEE or ANSI rules/specifications for math functions. ! @end table The following options control specific optimizations. The @samp{-O2} --- 1304,1367 ---- an exact implementation of IEEE or ANSI rules/specifications for math functions. ! ! @item -felide-constructors ! Elide constructors when this seems plausible (C++ only). With this ! option, GNU C++ initializes @code{y} directly from the call to @code{foo} ! without going through a temporary in the following code: ! ! @example ! A foo (); ! A y = foo (); ! @end example ! ! Without this option, GNU C++ first initializes @code{y} by calling the ! appropriate constructor for type @code{A}; then assigns the result of ! @code{foo} to a temporary; and, finally, replaces the initial value of ! @code{y} with the temporary. ! ! The default behavior (@samp{-fno-elide-constructors}) is specified by ! the draft ANSI C++ standard. If your program's constructors have side ! effects, @samp{-felide-constructors} can change your program's behavior, ! since some constructor calls may be omitted. ! ! @item -fmemoize-lookups ! @itemx -fsave-memoized ! Use heuristics to compile faster (C++ only). These heuristics are not ! enabled by default, since they are only effective for certain input ! files. Other input files compile more slowly. ! ! The first time the compiler must build a call to a member function (or ! reference to a data member), it must (1) determine whether the class ! implements member functions of that name; (2) resolve which member ! function to call (which involves figuring out what sorts of type ! conversions need to be made); and (3) check the visibility of the member ! function to the caller. All of this adds up to slower compilation. ! Normally, the second time a call is made to that member function (or ! reference to that data member), it must go through the same lengthy ! process again. This means that code like this + @example + cout << "This " << p << " has " << n << " legs.\n"; + @end example + @noindent + makes six passes through all three steps. By using a software cache, a + ``hit'' significantly reduces this cost. Unfortunately, using the cache + introduces another layer of mechanisms which must be implemented, and so + incurs its own overhead. `-fmemoize-lookups' enables the software + cache. + + Because access privileges (visibility) to members and member functions + may differ from one function context to the next, G++ may need to flush + the cache. With the @samp{-fmemoize-lookups} flag, the cache is flushed + after every function that is compiled. The @samp{-fsave-memoized} flag + enables the same software cache, but when the compiler determines that + the context of the last function compiled would yield the same access + privileges of the next function to compile, it preserves the cache. + This is most helpful when defining many member functions for the same + class: with the exception of member functions which are friends of other + classes, each member function has exactly the same access privileges as + every other, and the cache need not be flushed. + @end table The following options control specific optimizations. The @samp{-O2} *************** *** 1218,1222 **** @end table ! @node Preprocessor Options, Link Options, Optimize Options, Invoking GCC @section Options Controlling the Preprocessor @cindex preprocessor options --- 1449,1453 ---- @end table ! @node Preprocessor Options @section Options Controlling the Preprocessor @cindex preprocessor options *************** *** 1306,1311 **** @item -MD Like @samp{-M} but the dependency information is written to files with ! names made by replacing @samp{.c} with @samp{.d} at the end of the ! input file names. This is in addition to compiling the file as specified---@samp{-MD} does not inhibit ordinary compilation the way @samp{-M} does. --- 1537,1542 ---- @item -MD Like @samp{-M} but the dependency information is written to files with ! names made by replacing @samp{.o} with @samp{.d} at the end of the ! output file names. This is in addition to compiling the input files as specified---@samp{-MD} does not inhibit ordinary compilation the way @samp{-M} does. *************** *** 1323,1326 **** --- 1554,1563 ---- activities. + @item -A@var{question}(@var{answer}) + Assert the answer @var{answer} for @var{question}, in case it is tested + with a preprocessor conditional such as @samp{#if + #@var{question}(@var{answer})}. @samp{-A-} disables the standard + assertions that normally describe the target machine. + @item -D@var{macro} Define macro @var{macro} with the string @samp{1} as its definition. *************** *** 1353,1357 **** @end table ! @node Link Options, Directory Options, Preprocessor Options, Invoking GCC @section Options for Linking @cindex link options --- 1590,1603 ---- @end table ! @node Assembler Options ! @section Passing Options to the Assembler ! ! @table @samp ! @item -Wa,@var{option} ! Pass @var{option} as an option to the assembler. If @var{option} ! contains commas, it is split into multiple options at the commas. ! @end table ! ! @node Link Options @section Options for Linking @cindex link options *************** *** 1404,1407 **** --- 1650,1657 ---- and searches several directories. + @item -lobjc + This special case of the @samp{-l} option is what you need to do when you + link an Objective C program. + @item -nostdlib Don't use the standard system libraries and startup files when linking. *************** *** 1434,1440 **** @samp{-Xlinker "-assert definitions"}, because this passes the entire string as a single argument, which is not what the linker expects. @end table ! @node Directory Options, Target Options, Link Options, Invoking GCC @section Options for Directory Search @cindex directory options --- 1684,1699 ---- @samp{-Xlinker "-assert definitions"}, because this passes the entire string as a single argument, which is not what the linker expects. + + @item -Wl,@var{option} + Pass @var{option} as an option to the linker. If @var{option} contains + commas, it is split into multiple options at the commas. + + @item -u @var{symbol} + Pretend the symbol @var{symbol} is undefined, to force linking of + library modules to define it. You can use @samp{-u} multiple times with + different symbols to force loading of additional library modules. @end table ! @node Directory Options @section Options for Directory Search @cindex directory options *************** *** 1507,1511 **** @end table ! @node Target Options, Submodel Options, Directory Options, Invoking GCC @section Specifying Target Machine and Compiler Version @cindex target options --- 1766,1770 ---- @end table ! @node Target Options @section Specifying Target Machine and Compiler Version @cindex target options *************** *** 1560,1564 **** alternate names (or symbolic links). Thus, if @file{/usr/local/lib/gcc-lib/80386} is a link to ! @file{/usr/local/lib/gcc-lib/i386v}, then @samp{-b 80386} will be an alias for @samp{-b i386v}.@refill --- 1819,1823 ---- alternate names (or symbolic links). Thus, if @file{/usr/local/lib/gcc-lib/80386} is a link to ! @file{/usr/local/lib/gcc-lib/i386v}, then @samp{-b 80386} becomes an alias for @samp{-b i386v}.@refill *************** *** 1589,1593 **** command with the @samp{-V} option. ! @node Submodel Options, Code Gen Options, Target Options, Invoking GCC @section Specifying Hardware Models and Configurations @cindex submodel options --- 1848,1852 ---- command with the @samp{-V} option. ! @node Submodel Options @section Specifying Hardware Models and Configurations @cindex submodel options *************** *** 1607,1610 **** --- 1866,1873 ---- options specified. + Some configurations of the compiler also support additional special + options, usually for compatibility with other compilers on the same + platform. + @ifset INTERNALS These options are defined by the macro @code{TARGET_SWITCHES} in the *************** *** 1624,1630 **** * MIPS Options:: * i386 Options:: @end menu ! @node M680x0 Options, Vax Options, Submodel Options, Submodel Options @subsection M680x0 Options @cindex M680x0 options --- 1887,1897 ---- * MIPS Options:: * i386 Options:: + * HPPA Options:: + * Intel 960 Options:: + * DEC Alpha Options:: + * System V Options:: @end menu ! @node M680x0 Options @subsection M680x0 Options @cindex M680x0 options *************** *** 1636,1649 **** @table @code - @item -m68020 - @itemx -mc68020 - Generate output for a 68020 (rather than a 68000). This is the - default when the compiler is configured for 68020-based systems. - @item -m68000 @itemx -mc68000 ! Generate output for a 68000 (rather than a 68020). This is the default ! when the compiler is configured for a 68000-based systems. @item -m68881 Generate output containing 68881 instructions for floating point. --- 1903,1916 ---- @table @code @item -m68000 @itemx -mc68000 ! Generate output for a 68000. This is the default ! when the compiler is configured for 68000-based systems. + @item -m68020 + @itemx -mc68020 + Generate output for a 68020. This is the default + when the compiler is configured for 68020-based systems. + @item -m68881 Generate output containing 68881 instructions for floating point. *************** *** 1651,1654 **** --- 1918,1934 ---- specified when the compiler was configured. + @item -m68030 + Generate output for a 68030. This is the default + when the compiler is configured for 68030-based systems. + + @item -m68040 + Generate output for a 68040. This is the default + when the compiler is configured for 68040-based systems. + + @item -m68020-40 + Generate output for a 68040, without using any of the new instructions. + This results in code which can run relatively efficiently on either a + 68020/68881 or a 68030 or a 68040. + @item -mfpa Generate output containing Sun FPA instructions for floating point. *************** *** 1698,1702 **** @end table ! @node VAX Options, Sparc Options, M680x0 Options, Submodel Options @subsection VAX Options @cindex VAX options --- 1978,1982 ---- @end table ! @node VAX Options @subsection VAX Options @cindex VAX options *************** *** 1718,1722 **** @end table ! @node Sparc Options, Convex Options, Vax Options, Submodel Options @subsection SPARC Options @cindex SPARC options --- 1998,2002 ---- @end table ! @node Sparc Options @subsection SPARC Options @cindex SPARC options *************** *** 1749,1753 **** @end table ! @node Convex Options, AMD29K Options, SPARC Options, Submodel Options @subsection Convex Options @cindex Convex options --- 2029,2033 ---- @end table ! @node Convex Options @subsection Convex Options @cindex Convex options *************** *** 1775,1779 **** @end table ! @node AMD29K Options, M88K Options, Convex Options, Submodel Options @subsection AMD29K Options @cindex AMD29K options --- 2055,2059 ---- @end table ! @node AMD29K Options @subsection AMD29K Options @cindex AMD29K options *************** *** 1832,1836 **** @end table ! @node M88K Options, RS/6000 Options, AMD29K Options, Submodel Options @subsection M88K Options @cindex M88k options --- 2112,2116 ---- @end table ! @node M88K Options @subsection M88K Options @cindex M88k options *************** *** 1846,1850 **** @item -m88100 @kindex -m88100 - Generate code tha Generate code that works best for the m88100, but that also runs on the m88110. --- 2126,2129 ---- *************** *** 1908,1914 **** @cindex arguments in frame (88k) Control how to store function arguments in stack frames. ! @samp{-moptimize-arg-area} saves space, but was ruled illegal by 88open. ! @samp{-mno-optimize-arg-area} conforms to the 88open standards. By ! default GNU CC does not optimize the argument area. @item -mshort-data-@var{num} --- 2187,2193 ---- @cindex arguments in frame (88k) Control how to store function arguments in stack frames. ! @samp{-moptimize-arg-area} saves space, but conflicts with the 88open ! specifications. @samp{-mno-optimize-arg-area} conforms to the 88open ! standards. By default GNU CC does not optimize the argument area. @item -mshort-data-@var{num} *************** *** 1925,1928 **** --- 2204,2238 ---- than 64K. + @itemx -mserialize-volatile + @kindex -mserialize-volatile + @item -mno-serialize-volatile + @kindex -mno-serialize-volatile + @cindex sequential consistency on 88k + Do, or don't, generate code to guarantee sequential consistency of + volatile memory references. + + GNU CC always guarantees consistency by default, for the preferred + processor submodel. How this is done depends on the submodel. + + The m88100 processor does not reorder memory references and so always + provides sequential consistency. If you use @samp{-m88100}, GNU CC does + not generate any special instructions for sequential consistency. + + The order of memory references made by the m88110 processor does not + always match the order of the instructions requesting those references. + In particular, a load instruction may execute before a preceding store + instruction. Such reordering violates sequential consistency of + volatile memory references, when there are multiple processors. When + you use @samp{-m88000} or @samp{-m88110}, GNU CC generates special + instructions when appropriate, to force execution in the proper order. + + The extra code generated to guarantee consistency may affect the + performance of your application. If you know that you can safely forgo + this guarantee, you may use @samp{-mno-serialize-volatile}. + + If you use @samp{-m88100} but require sequential consistency when + running on the m88110 processor, you should use + @samp{-mserialize-volatile}. + @item -msvr4 @itemx -msvr3 *************** *** 1997,2001 **** @end table ! @node RS/6000 Options, RT Options, M88K Options, Submodel Options @subsection IBM RS/6000 Options @cindex RS/6000 Options --- 2307,2311 ---- @end table ! @node RS/6000 Options @subsection IBM RS/6000 Options @cindex RS/6000 Options *************** *** 2014,2018 **** @end table ! @node RT Options, MIPS Options, RS/6000 Options, Submodel Options @subsection IBM RT Options @cindex RT options --- 2324,2328 ---- @end table ! @node RT Options @subsection IBM RT Options @cindex RT options *************** *** 2063,2067 **** @end table ! @node MIPS Options, i386 Options, RT Options, Submodel Options @subsection MIPS Options @cindex MIPS options --- 2373,2377 ---- @end table ! @node MIPS Options @subsection MIPS Options @cindex MIPS options *************** *** 2210,2214 **** @end ifset ! @node i386 Options, , MIPS Options, Submodel Options @subsection Intel 386 Options @cindex i386 Options --- 2520,2524 ---- @end ifset ! @node i386 Options @subsection Intel 386 Options @cindex i386 Options *************** *** 2231,2240 **** cross-compilation. ! On machines where a function returnings float point results in the 80387 register stack, some floating point opcodes may be emitted even if @samp{-msoft-float} is used. @end table ! @node Code Gen Options, Environment Variables, Submodel Options, Invoking GCC @section Options for Code Generation Conventions @cindex code generation conventions --- 2541,2750 ---- cross-compilation. ! On machines where a function returns floating point results in the 80387 register stack, some floating point opcodes may be emitted even if @samp{-msoft-float} is used. + + @item -mno-fp-ret-in-387 + Don't use the FPU registers for return values of functions. + + The usual calling convention has functions return values of types + @code{float} and @code{double} in an FPU register, even if there + is no FPU. The idea is that the operating system should emulate + an FPU. + + The option @samp{-mno-fp-ret-in-387} causes such values to be returned + in ordinary CPU registers instead. + @end table + + @node HPPA Options + @subsection HPPA Options + @cindex HPPA Options + + This @samp{-m} option is defined for the HPPA family of computers: + + @table @code + @item -mno-bss + Disable the use of the BSS section. This may be necessary with older + versions of pa-gas. It is highly recommended that you pick up a new + version of pa-gas from @code{jaguar.cs.utah.edu}. + + @item -mpa-risc-1-0 + Generate code for a PA 1.0 processor. + + @item -mpa-risc-1-1 + Generate code for a PA 1.1 processor. + + @item -mkernel + Generate code which is suitable for use in kernels. Specifically, avoid + @code{add} instructions in which one of the arguments is the DP register; + generate @code{addil} instructions instead. This avoids a rather serious + bug in the HP-UX linker. + + @item -mshared-libs + Generate code that can be linked against HP-UX shared libraries. This is the + default in HP-UX 8.0. + + @item -mno-shared-libs + Don't generate code that will be linked against shared libraries. This may be + necessary if the emitted object files will be linked on a system older than + HP-UX 8.0. + + @item -mlong-calls + Generate code which allows calls to functions greater than 256K away from + the caller when the caller and callee are in the same source file. Do + not turn this option on unless code refuses to link with "branch out of + range errors" from the linker. + @end table + + @node Intel 960 Options + @subsection Intel 960 Options + + These @samp{-m} options are defined for the Intel 960 implementations: + + @table @code + @item -m@var{cpu type} + Assume the defaults for the machine type @var{cpu type} for some of + the other options, including instruction scheduling, floating point + support, and addressing modes. The choices for @var{cpu type} are + @samp{ka}, @samp{kb}, @samp{mc}, @samp{ca}, @samp{cf}, + @samp{sa}, and @samp{sb}. + The default is + @samp{kb}. + + @item -mnumerics + @itemx -msoft-float + The @samp{-mnumerics} option indicates that the processor does support + floating-point instructions. The @samp{-msoft-float} option indicates + that floating-point support should not be assumed. + + @item -mleaf-procedures + @itemx -mno-leaf-procedures + Do (or do not) attempt to alter leaf procedures to be callable with the + @code{bal} instruction as well as @code{call}. This will result in more + efficient code for explicit calls when the @code{bal} instruction can be + substituted by the assembler or linker, but less efficient code in other + cases, such as calls via function pointers, or using a linker that doesn't + support this optimization. + + @item -mtail-call + @itemx -mno-tail-call + Do (or do not) make additional attempts (beyond those of the + machine-independent portions of the compiler) to optimize tail-recursive + calls into branches. You may not want to do this because the detection of + cases where this is not valid is not totally complete. The default is + @samp{-mno-tail-call}. + + @item -mcomplex-addr + @itemx -mno-complex-addr + Assume (or do not assume) that the use of a complex addressing mode is a + win on this implementation of the i960. Complex addressing modes may not + be worthwhile on the K-series, but they definitely are on the C-series. + The default is currently @samp{-mcomplex-addr} for all processors except + the CB and CC. + + @item -mcode-align + @itemx -mno-code-align + Align code to 8-byte boundaries for faster fetching (or don't bother). + Currently turned on by default for C-series implementations only. + + @ignore + @item -mclean-linkage + @itemx -mno-clean-linkage + These options are not fully implemented. + @end ignore + + @item -mic-compat + @itemx -mic2.0-compat + @itemx -mic3.0-compat + Enable compatibility with iC960 v2.0 or v3.0. + + @item -masm-compat + @itemx -mintel-asm + Enable compatibility with the iC960 assembler. + + @item -mstrict-align + @itemx -mno-strict-align + Do not permit (do permit) unaligned accesses. + + @item -mold-align + Enable structure-alignment compatibility with Intel's gcc release version + 1.3 (based on gcc 1.37). Currently this is buggy in that @samp{#pragma + align 1} is always assumed as well, and cannot be turned off. + @end table + + @node DEC Alpha Options + @subsection DEC Alpha Options + + These @samp{-m} options are defined for the DEC Alpha implementations: + + @table @code + @item -mno-soft-float + @itemx -msoft-float + Use (do not use) the hardware floating-point instructions for + floating-point operations. When @code{-msoft-float} is specified, + functions in @file{libgcc1.c} will be used to perform floating-point + operations. Unless they are replaced by routines that emulate the + floating-point operations, or compiled in such a way as to call such + emulations routines, these routines will issue floating-point + operations. If you are compiling for an Alpha without floating-point + operations, you must ensure that the library is built so as not to call + them. + + Note that Alpha implementations without floating-point operations are + required to have floating-point registers. + + @item -mfp-reg + @itemx -mno-fp-regs + Generate code that uses (does not use) the floating-point register set. + @code{-mno-fp-regs} implies @code{-msoft-float}. If the floating-point + register set is not used, floating point operands are passed in integer + registers as if they were integers and floating-point results are passed + in $0 instead of $f0. This is a non-standard calling sequence, so any + function with a floating-point argument or return value called by code + compiled with @code{-mno-fp-regs} must also be compiled with that + option. + + A typical use of this option is building a kernel that does not use, + and hence need not save and restore, any floating-point registers. + @end table + + @node System V Options + @subsection Options for System V + + These additional options are available on System V Release 4 for + compatibility with other compilers on those systems: + + @table @code + @ignore + This should say *what the option does* and only then say + "For compatibility only..." + @item -G + On SVr4 systems, @code{gcc} accepts the option @samp{-G} (and passes + it to the system linker), for compatibility with other compilers. + However, we suggest you use @samp{-symbolic} or @samp{-shared} as + appropriate, instead of supplying linker options on the @code{gcc} + command line. + @end ignore + + @item -Qy + Identify the versions of each tool used by the compiler, in a + @code{.ident} assembler directive in the output. + + @item -Qn + Refrain from adding @code{.ident} directives to the output file (this is + the default). + + @item -YP,@var{dirs} + Search the directories @var{dirs}, and no others, for libraries + specified with @samp{-l}. + + @item -Ym,@var{dir} + Look in the directory @var{dir} to find the M4 preprocessor. + The assembler uses this option. + @c This is supposed to go with a -Yd for predefined M4 macro files, but + @c the generic assembler that comes with Solaris takes just -Ym. @end table ! @node Code Gen Options @section Options for Code Generation Conventions @cindex code generation conventions *************** *** 2299,2302 **** --- 2809,2830 ---- for anything else. + @item -fnonnull-objects + Assume that objects reached through references are not null + (C++ only). + + Normally, GNU C++ makes conservative assumptions about objects reached + through references. For example, the compiler must check that @code{a} + is not null in code like the following: + + @example + obj &a = g (); + a.f (2); + @end example + + Checking that references of this sort have non-null values requires + extra code, however, and it is unnecessary for many programs. You can + use @samp{-fnonnull-objects} to omit the checks for null, if your + program doesn't require checking. + @item -fverbose-asm Put extra commentary information in the generated assembly code to *************** *** 2310,2315 **** @item -fpic @cindex global offset table ! If supported for the target machines, generate position-independent ! code, suitable for use in a shared library. All addresses will be accessed through a global offset table (GOT). If the GOT size for the linked executable exceeds a machine-specific maximum size, you will get --- 2838,2844 ---- @item -fpic @cindex global offset table ! @cindex PIC ! If supported for the target machine, generate position-independent code ! (PIC) suitable for use in a shared library. All addresses will be accessed through a global offset table (GOT). If the GOT size for the linked executable exceeds a machine-specific maximum size, you will get *************** *** 2320,2324 **** Position-independent code requires special support, and therefore works ! only on certain machines. Code generated for the IBM RS/6000 is always position-independent. --- 2849,2854 ---- Position-independent code requires special support, and therefore works ! only on certain machines. For the 386, GNU CC supports PIC for System V ! but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent. *************** *** 2379,2383 **** @end table ! @node Environment Variables,, Code Gen Options, Invoking GCC @section Environment Variables Affecting GNU CC @cindex environment variables --- 2909,2913 ---- @end table ! @node Environment Variables @section Environment Variables Affecting GNU CC @cindex environment variables *************** *** 2481,2482 **** --- 3011,3165 ---- file @var{file} using @var{target} as the target name. @end table + + @node Running Protoize + @section Running Protoize + + The program @code{protoize} is an optional part of GNU C. You can use + it to add prototypes to a program, thus converting the program to ANSI + C in one respect. The companion program @code{unprotoize} does the + reverse: it removes argument types from any prototypes that are found. + + When you run these programs, you must specify a set of source files as + command line arguments. The conversion programs start out by compiling + these files to see what functions they define. The information gathered + about a file @var{foo} is saved in a file named @file{@var{foo}.X}. + + After scanning comes actual conversion. The specified files are all + eligible to be converted; any files they include (whether sources or + just headers) are eligible as well. + + But not all the eligible files are converted. By default, + @code{protoize} and @code{unprotoize} convert only source and header + files in the current directory. You can specify additional directories + whose files should be converted with the @samp{-d @var{directory}} + option. You can also specify particular files to exclude with the + @samp{-x @var{file}} option. A file is converted if it is eligible, its + directory name matches one of the specified directory names, and its + name within the directory has not been excluded. + + Basic conversion with @code{protoize} consists of rewriting most + function definitions and function declarations to specify the types of + the arguments. The only ones not rewritten are those for varargs + functions. + + @code{protoize} optionally inserts prototype declarations at the + beginning of the source file, to make them available for any calls that + precede the function's definition. Or it can insert prototype + declarations with block scope in the blocks where undeclared functions + are called. + + Basic conversion with @code{unprotoize} consists of rewriting most + function declarations to remove any argument types, and rewriting + function definitions to the old-style pre-ANSI form. + + Both conversion programs print a warning for any function declaration or + definition that they can't convert. You can suppress these warnings + with @samp{-q}. + + The output from @code{protoize} or @code{unprotoize} replaces the + original source file. The original file is renamed to a name ending + with @samp{.save}. If the @samp{.save} file already exists, then + the source file is simply discarded. + + @code{protoize} and @code{unprotoize} both depend on GNU CC itself to + scan the program and collect information about the functions it uses. + So neither of these programs will work until GNU CC is installed. + + Here is a table of the options you can use with @code{protoize} and + @code{unprotoize}. Each option works with both programs unless + otherwise stated. + + @table @samp + @item -B @var{directory} + Look for the file @file{SYSCALLS.c.X} in @var{directory}, instead of the + usual directory (normally @file{/usr/local/lib}). This file contains + prototype information about standard system functions. This option + applies only to @code{protoize}. + + @item -c @var{compilation-options} + Use @var{compilation-options} as the options when running @code{gcc} to + produce the @samp{.X} files. The special option @samp{-aux-info} is + always passed in addition, to tell @code{gcc} to write a @samp{.X} file. + + Note that the compilation options must be given as a single argument to + @code{protoize} or @code{unprotoize}. If you want to specify several + @code{gcc} options, you must quote the entire set of compilation options + to make them a single word in the shell. + + There are certain @code{gcc} arguments that you cannot use, because they + would produce the wrong kind of output. These include @samp{-g}, + @samp{-O}, @samp{-c}, @samp{-S}, and @samp{-o} If you include these in + the @var{compilation-options}, they are ignored. + + @item -C + Rename files to end in @samp{.C} instead of @samp{.c}. + This is convenient if you are converting a C program to C++. + This option applies only to @code{protoize}. + + @item -g + Add explicit global declarations. This means inserting explicit + declarations at the beginning of each source file for each function + that is called in the file and was not declared. These declarations + precede the first function definition that contains a call to an + undeclared function. This option applies only to @code{protoize}. + + @item -i @var{string} + Indent old-style parameter declarations with the string @var{string}. + This option applies only to @code{protoize}. + + @code{unprotoize} converts prototyped function definitions to old-style + function definitions, where the arguments are declared between the + argument list and the initial @samp{@{}. By default, @code{unprotoize} + uses five spaces as the indentation. If you want to indent with just + one space instead, use @samp{-i " "}. + + @item -k + Keep the @samp{.X} files. Normally, they are deleted after conversion + is finished. + + @item -l + Add explicit local declarations. @code{protoize} with @samp{-l} inserts + a prototype declaration for each function in each block which calls the + function without any declaration. This option applies only to + @code{protoize}. + + @item -n + Make no real changes. This mode just prints information about the conversions + that would have been done without @samp{-n}. + + @item -N + Make no @samp{.save} files. The original files are simply deleted. + Use this option with caution. + + @item -p @var{program} + Use the program @var{program} as the compiler. Normally, the name + @file{gcc} is used. + + @item -q + Work quietly. Most warnings are suppressed. + + @item -v + Print the version number, just like @samp{-v} for @code{gcc}. + @end table + + If you need special compiler options to compile one of your program's + source files, then you should generate that file's @samp{.X} file + specially, by running @code{gcc} on that source file with the + appropriate options and the option @samp{-aux-info}. Then run + @code{protoize} on the entire set of files. @code{protoize} will use + the existing @samp{.X} file because it is newer than the source file. + For example: + + @example + gcc -Dfoo=bar file1.c -aux-info + protoize *.c + @end example + + @noindent + You need to include the special files along with the rest in the + @code{protoize} command, even though their @samp{.X} files already + exist, because otherwise they won't get converted. + + @xref{Protoize Caveats}, for more information on how to use + @code{protoize} successfully. + diff -rc2N gcc-2.2.2/jump.c gcc-2.3.1/jump.c *** gcc-2.2.2/jump.c Wed May 20 14:48:17 1992 --- gcc-2.3.1/jump.c Fri Oct 23 07:36:51 1992 *************** *** 1,4 **** /* Optimize jump instructions, for GNU compiler. ! Copyright (C) 1987, 1988, 1989, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Optimize jump instructions, for GNU compiler. ! Copyright (C) 1987, 1988, 1989, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 105,122 **** static int duplicate_loop_exit_test (); - rtx delete_insn (); - int redirect_jump (); - static int redirect_exp (); void redirect_tablejump (); static int delete_labelref_insn (); - int invert_jump (); - static int invert_exp (); - int condjump_p (); - int simplejump_p (); - - extern rtx gen_jump (); - static void mark_jump_label (); void delete_jump (); static void delete_from_jump_chain (); static int tension_vector_labels (); --- 105,113 ---- static int duplicate_loop_exit_test (); void redirect_tablejump (); static int delete_labelref_insn (); static void mark_jump_label (); void delete_jump (); + void delete_computation (); static void delete_from_jump_chain (); static int tension_vector_labels (); *************** *** 124,127 **** --- 115,120 ---- static void do_cross_jump (); static int jump_back_p (); + + extern rtx gen_jump (); /* Delete no-op jumps and optimize jumps to jumps *************** *** 151,155 **** int after_regscan; { ! register rtx insn; int changed; int first = 1; --- 144,148 ---- int after_regscan; { ! register rtx insn, next; int changed; int first = 1; *************** *** 307,311 **** for (insn = f; insn; ) { ! register rtx next = NEXT_INSN (insn); if (GET_CODE (insn) == INSN) --- 300,304 ---- for (insn = f; insn; ) { ! next = NEXT_INSN (insn); if (GET_CODE (insn) == INSN) *************** *** 369,374 **** else XEXP (SET_SRC (PATTERN (stack_adjust_insn)), 1) ! = gen_rtx (CONST_INT, VOIDmode, ! stack_adjust_amount - total_pushed); /* Change the appropriate push insns to ordinary stores. */ --- 362,366 ---- else XEXP (SET_SRC (PATTERN (stack_adjust_insn)), 1) ! = GEN_INT (stack_adjust_amount - total_pushed); /* Change the appropriate push insns to ordinary stores. */ *************** *** 397,401 **** { emit_insn_before (gen_add2_insn (stack_pointer_rtx, ! gen_rtx (CONST_INT, VOIDmode, - total_pushed)), p); break; --- 389,393 ---- { emit_insn_before (gen_add2_insn (stack_pointer_rtx, ! GEN_INT (- total_pushed)), p); break; *************** *** 434,439 **** { rtx trial; ! rtx tem = find_equiv_reg (0, insn, 0, ! sreg, 0, dreg, GET_MODE (SET_SRC (body))); --- 426,431 ---- { rtx trial; ! rtx tem = find_equiv_reg (NULL_RTX, insn, 0, ! sreg, NULL_PTR, dreg, GET_MODE (SET_SRC (body))); *************** *** 464,469 **** } else if (dreg >= 0 && CONSTANT_P (SET_SRC (body)) ! && find_equiv_reg (SET_SRC (body), insn, 0, dreg, 0, ! 0, GET_MODE (SET_DEST (body)))) { /* This handles the case where we have two consecutive --- 456,462 ---- } else if (dreg >= 0 && CONSTANT_P (SET_SRC (body)) ! && find_equiv_reg (SET_SRC (body), insn, 0, dreg, ! NULL_PTR, 0, ! GET_MODE (SET_DEST (body)))) { /* This handles the case where we have two consecutive *************** *** 533,541 **** } /* Now iterate optimizing jumps until nothing changes over one pass. */ changed = 1; while (changed) { - register rtx next; changed = 0; --- 526,553 ---- } + /* If we haven't yet gotten to reload and we have just run regscan, + delete any insn that sets a register that isn't used elsewhere. + This helps some of the optimizations below by having less insns + being jumped around. */ + + if (! reload_completed && after_regscan) + for (insn = f; insn; insn = next) + { + rtx set = single_set (insn); + + next = NEXT_INSN (insn); + + if (set && GET_CODE (SET_DEST (set)) == REG + && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER + && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn) + && regno_last_uid[REGNO (SET_DEST (set))] == INSN_UID (insn) + && ! side_effects_p (SET_SRC (set))) + delete_insn (insn); + } + /* Now iterate optimizing jumps until nothing changes over one pass. */ changed = 1; while (changed) { changed = 0; *************** *** 543,549 **** { rtx reallabelprev; ! rtx temp, temp1, temp2, temp3, temp4, temp5; rtx nlabel; ! int this_is_simplejump, this_is_condjump; #if 0 /* If NOT the first iteration, if this is the last jump pass --- 555,561 ---- { rtx reallabelprev; ! rtx temp, temp1, temp2, temp3, temp4, temp5, temp6; rtx nlabel; ! int this_is_simplejump, this_is_condjump, reversep; #if 0 /* If NOT the first iteration, if this is the last jump pass *************** *** 610,613 **** --- 622,626 ---- break; if (i == len + && dispatch != 0 && GET_CODE (dispatch) == JUMP_INSN && JUMP_LABEL (dispatch) != 0 *************** *** 630,634 **** if (JUMP_LABEL (insn) && next_active_insn (JUMP_LABEL (insn)) == 0) ! changed |= redirect_jump (insn, 0); /* Detect jump to following insn. */ --- 643,647 ---- if (JUMP_LABEL (insn) && next_active_insn (JUMP_LABEL (insn)) == 0) ! changed |= redirect_jump (insn, NULL_RTX); /* Detect jump to following insn. */ *************** *** 657,666 **** if (GET_CODE (temp1) == BARRIER) { ! reorder_insns (temp, temp, temp1); temp1 = NEXT_INSN (temp1); } - else - delete_insn (temp); redirect_jump (insn, get_label_before (temp1)); reallabelprev = prev_real_insn (temp1); --- 670,678 ---- if (GET_CODE (temp1) == BARRIER) { ! emit_insn_after (PATTERN (temp), temp1); temp1 = NEXT_INSN (temp1); } + delete_insn (temp); redirect_jump (insn, get_label_before (temp1)); reallabelprev = prev_real_insn (temp1); *************** *** 693,703 **** TEMP1 to X TEMP2 to the insn that sets "x = b;" ! TEMP3 to the insn that sets "x = a;" */ if (this_is_simplejump && (temp3 = prev_active_insn (insn)) != 0 && GET_CODE (temp3) == INSN ! && GET_CODE (PATTERN (temp3)) == SET ! && GET_CODE (temp1 = SET_DEST (PATTERN (temp3))) == REG #ifdef SMALL_REGISTER_CLASSES && REGNO (temp1) >= FIRST_PSEUDO_REGISTER --- 705,716 ---- TEMP1 to X TEMP2 to the insn that sets "x = b;" ! TEMP3 to the insn that sets "x = a;" ! TEMP4 to the set of "x = b"; */ if (this_is_simplejump && (temp3 = prev_active_insn (insn)) != 0 && GET_CODE (temp3) == INSN ! && (temp4 = single_set (temp3)) != 0 ! && GET_CODE (temp1 = SET_DEST (temp4)) == REG #ifdef SMALL_REGISTER_CLASSES && REGNO (temp1) >= FIRST_PSEUDO_REGISTER *************** *** 705,712 **** && (temp2 = next_active_insn (insn)) != 0 && GET_CODE (temp2) == INSN ! && GET_CODE (PATTERN (temp2)) == SET ! && rtx_equal_p (SET_DEST (PATTERN (temp2)), temp1) ! && (GET_CODE (SET_SRC (PATTERN (temp2))) == REG ! || CONSTANT_P (SET_SRC (PATTERN (temp2)))) && (REG_NOTES (temp2) == 0 || ((REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUAL --- 718,726 ---- && (temp2 = next_active_insn (insn)) != 0 && GET_CODE (temp2) == INSN ! && (temp4 = single_set (temp2)) != 0 ! && rtx_equal_p (SET_DEST (temp4), temp1) ! && (GET_CODE (SET_SRC (temp4)) == REG ! || GET_CODE (SET_SRC (temp4)) == SUBREG ! || CONSTANT_P (SET_SRC (temp4))) && (REG_NOTES (temp2) == 0 || ((REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUAL *************** *** 714,718 **** && XEXP (REG_NOTES (temp2), 1) == 0 && rtx_equal_p (XEXP (REG_NOTES (temp2), 0), ! SET_SRC (PATTERN (temp2))))) && (temp = prev_active_insn (temp3)) != 0 && condjump_p (temp) && ! simplejump_p (temp) --- 728,732 ---- && XEXP (REG_NOTES (temp2), 1) == 0 && rtx_equal_p (XEXP (REG_NOTES (temp2), 0), ! SET_SRC (temp4)))) && (temp = prev_active_insn (temp3)) != 0 && condjump_p (temp) && ! simplejump_p (temp) *************** *** 725,731 **** after TEMP2 must branch to the same place as INSN. */ && (reallabelprev == temp2 ! || ((temp4 = next_active_insn (temp2)) != 0 ! && simplejump_p (temp4) ! && JUMP_LABEL (temp4) == JUMP_LABEL (insn)))) { /* The test expression, X, may be a complicated test with --- 739,745 ---- after TEMP2 must branch to the same place as INSN. */ && (reallabelprev == temp2 ! || ((temp5 = next_active_insn (temp2)) != 0 ! && simplejump_p (temp5) ! && JUMP_LABEL (temp5) == JUMP_LABEL (insn)))) { /* The test expression, X, may be a complicated test with *************** *** 775,783 **** && ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3)) && ! reg_set_between_p (temp1, p, temp3) ! && (GET_CODE (SET_SRC (PATTERN (temp2))) == CONST_INT ! || ! reg_set_between_p (SET_SRC (PATTERN (temp2)), ! p, temp2))) { ! reorder_insns_with_line_notes (temp2, temp2, p); /* Set NEXT to an insn that we know won't go away. */ --- 789,797 ---- && ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3)) && ! reg_set_between_p (temp1, p, temp3) ! && (GET_CODE (SET_SRC (temp4)) == CONST_INT ! || ! reg_set_between_p (SET_SRC (temp4), p, temp2))) { ! emit_insn_after_with_line_notes (PATTERN (temp2), p, temp2); ! delete_insn (temp2); /* Set NEXT to an insn that we know won't go away. */ *************** *** 803,813 **** } ! /* If we have x = a; if (...) x = b; ! and either A or B is zero, or if we have if (...) x = 0; ! and jumps are expensive, try to use a store-flag insn to ! avoid the jump. (If the jump would be faster, the machine ! should not have defined the scc insns!). These cases are often ! made by the previous optimization. INSN here is the jump around the store. We set: --- 817,980 ---- } ! #ifndef HAVE_cc0 ! /* If we have if (...) x = exp; and branches are expensive, ! EXP is a single insn, does not have any side effects, cannot ! trap, and is not too costly, convert this to ! t = exp; if (...) x = t; ! ! Don't do this when we have CC0 because it is unlikely to help ! and we'd need to worry about where to place the new insn and ! the potential for conflicts. We also can't do this when we have ! notes on the insn for the same reason as above. ! ! We set: ! ! TEMP to the "x = exp;" insn. ! TEMP1 to the single set in the "x = exp; insn. ! TEMP2 to "x". */ ! ! if (! reload_completed ! && this_is_condjump && ! this_is_simplejump ! && BRANCH_COST >= 3 ! && (temp = next_nonnote_insn (insn)) != 0 ! && REG_NOTES (temp) == 0 ! && (reallabelprev == temp ! || ((temp2 = next_active_insn (temp)) != 0 ! && simplejump_p (temp2) ! && JUMP_LABEL (temp2) == JUMP_LABEL (insn))) ! && (temp1 = single_set (temp)) != 0 ! && (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG) ! && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT ! #ifdef SMALL_REGISTER_CLASSES ! && REGNO (temp2) >= FIRST_PSEUDO_REGISTER ! #endif ! && GET_CODE (SET_SRC (temp1)) != REG ! && GET_CODE (SET_SRC (temp1)) != SUBREG ! && GET_CODE (SET_SRC (temp1)) != CONST_INT ! && ! side_effects_p (SET_SRC (temp1)) ! && ! may_trap_p (SET_SRC (temp1)) ! && rtx_cost (SET_SRC (temp1)) < 10) ! { ! rtx new = gen_reg_rtx (GET_MODE (temp2)); ! ! if (validate_change (temp, &SET_DEST (temp1), new, 0)) ! { ! next = emit_insn_after (gen_move_insn (temp2, new), insn); ! emit_insn_after_with_line_notes (PATTERN (temp), ! PREV_INSN (insn), temp); ! delete_insn (temp); ! } ! } ! ! /* Similarly, if it takes two insns to compute EXP but they ! have the same destination. Here TEMP3 will be the second ! insn and TEMP4 the SET from that insn. */ ! ! if (! reload_completed ! && this_is_condjump && ! this_is_simplejump ! && BRANCH_COST >= 4 ! && (temp = next_nonnote_insn (insn)) != 0 ! && REG_NOTES (temp) == 0 ! && (temp3 = next_nonnote_insn (temp)) != 0 ! && REG_NOTES (temp3) == 0 ! && (reallabelprev == temp3 ! || ((temp2 = next_active_insn (temp3)) != 0 ! && simplejump_p (temp2) ! && JUMP_LABEL (temp2) == JUMP_LABEL (insn))) ! && (temp1 = single_set (temp)) != 0 ! && (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG) ! && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT ! #ifdef SMALL_REGISTER_CLASSES ! && REGNO (temp2) >= FIRST_PSEUDO_REGISTER ! #endif ! && ! side_effects_p (SET_SRC (temp1)) ! && ! may_trap_p (SET_SRC (temp1)) ! && rtx_cost (SET_SRC (temp1)) < 10 ! && (temp4 = single_set (temp3)) != 0 ! && rtx_equal_p (SET_DEST (temp4), temp2) ! && ! side_effects_p (SET_SRC (temp4)) ! && ! may_trap_p (SET_SRC (temp4)) ! && rtx_cost (SET_SRC (temp4)) < 10) ! { ! rtx new = gen_reg_rtx (GET_MODE (temp2)); ! ! if (validate_change (temp, &SET_DEST (temp1), new, 0)) ! { ! next = emit_insn_after (gen_move_insn (temp2, new), insn); ! emit_insn_after_with_line_notes (PATTERN (temp), ! PREV_INSN (insn), temp); ! emit_insn_after_with_line_notes ! (replace_rtx (PATTERN (temp3), temp2, new), ! PREV_INSN (insn), temp3); ! delete_insn (temp); ! delete_insn (temp3); ! } ! } ! ! /* Finally, handle the case where two insns are used to ! compute EXP but a temporary register is used. Here we must ! ensure that the temporary register is not used anywhere else. */ ! ! if (! reload_completed ! && after_regscan ! && this_is_condjump && ! this_is_simplejump ! && BRANCH_COST >= 4 ! && (temp = next_nonnote_insn (insn)) != 0 ! && REG_NOTES (temp) == 0 ! && (temp3 = next_nonnote_insn (temp)) != 0 ! && REG_NOTES (temp3) == 0 ! && (reallabelprev == temp3 ! || ((temp2 = next_active_insn (temp3)) != 0 ! && simplejump_p (temp2) ! && JUMP_LABEL (temp2) == JUMP_LABEL (insn))) ! && (temp1 = single_set (temp)) != 0 ! && (temp5 = SET_DEST (temp1), GET_CODE (temp5) == REG) ! && REGNO (temp5) >= FIRST_PSEUDO_REGISTER ! && regno_first_uid[REGNO (temp5)] == INSN_UID (temp) ! && regno_last_uid[REGNO (temp5)] == INSN_UID (temp3) ! && ! side_effects_p (SET_SRC (temp1)) ! && ! may_trap_p (SET_SRC (temp1)) ! && rtx_cost (SET_SRC (temp1)) < 10 ! && (temp4 = single_set (temp3)) != 0 ! && (temp2 = SET_DEST (temp4), GET_CODE (temp2) == REG) ! && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT ! #ifdef SMALL_REGISTER_CLASSES ! && REGNO (temp2) >= FIRST_PSEUDO_REGISTER ! #endif ! && rtx_equal_p (SET_DEST (temp4), temp2) ! && ! side_effects_p (SET_SRC (temp4)) ! && ! may_trap_p (SET_SRC (temp4)) ! && rtx_cost (SET_SRC (temp4)) < 10) ! { ! rtx new = gen_reg_rtx (GET_MODE (temp2)); ! ! if (validate_change (temp3, &SET_DEST (temp4), new, 0)) ! { ! next = emit_insn_after (gen_move_insn (temp2, new), insn); ! emit_insn_after_with_line_notes (PATTERN (temp), ! PREV_INSN (insn), temp); ! emit_insn_after_with_line_notes (PATTERN (temp3), ! PREV_INSN (insn), temp3); ! delete_insn (temp); ! delete_insn (temp3); ! } ! } ! #endif /* HAVE_cc0 */ ! ! /* We deal with four cases: + 1) x = a; if (...) x = b; and either A or B is zero, + 2) if (...) x = 0; and jumps are expensive, + 3) x = a; if (...) x = b; and A and B are constants where all the + set bits in A are also set in B and jumps are expensive, and + 4) x = a; if (...) x = b; and A and B non-zero, and jumps are + more expensive. + 5) if (...) x = b; if jumps are even more expensive. + + In each of these try to use a store-flag insn to avoid the jump. + (If the jump would be faster, the machine should not have + defined the scc insns!). These cases are often made by the + previous optimization. + INSN here is the jump around the store. We set: *************** *** 832,847 **** && GET_MODE_CLASS (GET_MODE (temp1)) == MODE_INT && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG || GET_CODE (temp2) == CONST_INT) ! /* Allow either form, but prefer the former if both apply. */ && (((temp3 = reg_set_last (temp1, insn)) != 0 ! && ((GET_CODE (temp3) == REG ! #ifdef SMALL_REGISTER_CLASSES ! && REGNO (temp3) >= FIRST_PSEUDO_REGISTER ! #endif ! ) ! || GET_CODE (temp3) == CONST_INT)) /* Make the latter case look like x = x; if (...) x = 0; */ ! || ((temp3 = temp1, BRANCH_COST > 1) ! && temp2 == const0_rtx)) /* INSN must either branch to the insn after TEMP or the insn after TEMP must branch to the same place as INSN. */ --- 999,1016 ---- && GET_MODE_CLASS (GET_MODE (temp1)) == MODE_INT && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG + || GET_CODE (temp2) == SUBREG || GET_CODE (temp2) == CONST_INT) ! /* Allow either form, but prefer the former if both apply. ! There is no point in using the old value of TEMP1 if ! it is a register, since cse will alias them. It can ! lose if the old value were a hard register since CSE ! won't replace hard registers. */ && (((temp3 = reg_set_last (temp1, insn)) != 0 ! && GET_CODE (temp3) == CONST_INT) /* Make the latter case look like x = x; if (...) x = 0; */ ! || (temp3 = temp1, ! ((BRANCH_COST >= 2 ! && temp2 == const0_rtx) ! || BRANCH_COST >= 3))) /* INSN must either branch to the insn after TEMP or the insn after TEMP must branch to the same place as INSN. */ *************** *** 851,882 **** && JUMP_LABEL (temp4) == JUMP_LABEL (insn))) && (temp4 = get_condition (insn, &temp5)) != 0 ! ! /* If B is zero, OK; if A is zero, can only do this if we ! can reverse the condition. */ ! && (temp2 == const0_rtx || (temp3 == const0_rtx ! && (can_reverse_comparison_p (temp4, insn))))) { enum rtx_code code = GET_CODE (temp4); ! rtx yes = temp3, var = temp1; int normalizep; rtx target; /* If necessary, reverse the condition. */ ! if (temp3 == const0_rtx) ! code = reverse_condition (code), yes = temp2; /* See if we can do this with a store-flag insn. */ start_sequence (); ! /* If YES is the constant 1, it is best to just compute ! the result directly. If YES is constant and STORE_FLAG_VALUE includes all of its bits, it is best to compute the flag ! value unnormalized and `and' it with YES. Otherwise, ! normalize to -1 and `and' with YES. */ ! normalizep = (yes == const1_rtx ? 1 ! : (GET_CODE (yes) == CONST_INT ! && (INTVAL (yes) & ~ STORE_FLAG_VALUE) == 0) ? 0 ! : -1); /* We will be putting the store-flag insn immediately in --- 1020,1080 ---- && JUMP_LABEL (temp4) == JUMP_LABEL (insn))) && (temp4 = get_condition (insn, &temp5)) != 0 ! /* We must be comparing objects whose modes imply the size. ! We could handle BLKmode if (1) emit_store_flag could ! and (2) we could find the size reliably. */ ! && GET_MODE (XEXP (temp4, 0)) != BLKmode ! ! /* If B is zero, OK; if A is zero, can only do (1) if we ! can reverse the condition. See if (3) applies possibly ! by reversing the condition. Prefer reversing to (4) when ! branches are very expensive. */ ! && ((reversep = 0, temp2 == const0_rtx) || (temp3 == const0_rtx ! && (reversep = can_reverse_comparison_p (temp4, insn))) ! || (BRANCH_COST >= 2 ! && GET_CODE (temp2) == CONST_INT ! && GET_CODE (temp3) == CONST_INT ! && ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp2) ! || ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp3) ! && (reversep = can_reverse_comparison_p (temp4, ! insn))))) ! || BRANCH_COST >= 3) ! #ifdef HAVE_cc0 ! /* If the previous insn sets CC0 and something else, we can't ! do this since we are going to delete that insn. */ ! ! && ! ((temp6 = prev_nonnote_insn (insn)) != 0 ! && GET_CODE (temp6) == INSN ! && (sets_cc0_p (PATTERN (temp6)) == -1 ! || (sets_cc0_p (PATTERN (temp6)) == 1 ! && FIND_REG_INC_NOTE (temp6, NULL_RTX)))) ! #endif ! ) { enum rtx_code code = GET_CODE (temp4); ! rtx uval, cval, var = temp1; int normalizep; rtx target; /* If necessary, reverse the condition. */ ! if (reversep) ! code = reverse_condition (code), uval = temp2, cval = temp3; ! else ! uval = temp3, cval = temp2; /* See if we can do this with a store-flag insn. */ start_sequence (); ! /* If CVAL is non-zero, normalize to -1. Otherwise, ! if UVAL is the constant 1, it is best to just compute ! the result directly. If UVAL is constant and STORE_FLAG_VALUE includes all of its bits, it is best to compute the flag ! value unnormalized and `and' it with UVAL. Otherwise, ! normalize to -1 and `and' with UVAL. */ ! normalizep = (cval != const0_rtx ? -1 ! : (uval == const1_rtx ? 1 ! : (GET_CODE (uval) == CONST_INT ! && (INTVAL (uval) & ~STORE_FLAG_VALUE) == 0) ! ? 0 : -1)); /* We will be putting the store-flag insn immediately in *************** *** 898,917 **** if (target) { rtx seq; ! if (normalizep != 1) ! target = expand_and (yes, target, (GET_CODE (target) == REG ! ? target : 0)); ! seq = gen_sequence (); end_sequence (); ! emit_insn_before (seq, temp5); ! emit_insn_after (gen_move_insn (var, target), insn); ! delete_insn (temp); ! next = NEXT_INSN (insn); #ifdef HAVE_cc0 ! delete_insn (prev_nonnote_insn (insn)); #endif ! delete_insn (insn); changed = 1; continue; --- 1096,1171 ---- if (target) { + rtx before = insn; rtx seq; ! /* Put the store-flag insns in front of the first insn ! used to compute the condition to ensure that we ! use the same values of them as the current ! comparison. However, the remainder of the insns we ! generate will be placed directly in front of the ! jump insn, in case any of the pseudos we use ! are modified earlier. */ ! ! seq = get_insns (); ! end_sequence (); ! ! emit_insns_before (seq, temp5); ! ! start_sequence (); ! ! /* Both CVAL and UVAL are non-zero. */ ! if (cval != const0_rtx && uval != const0_rtx) ! { ! rtx tem1, tem2; ! ! tem1 = expand_and (uval, target, NULL_RTX); ! if (GET_CODE (cval) == CONST_INT ! && GET_CODE (uval) == CONST_INT ! && (INTVAL (cval) & INTVAL (uval)) == INTVAL (cval)) ! tem2 = cval; ! else ! { ! tem2 = expand_unop (GET_MODE (var), one_cmpl_optab, ! target, NULL_RTX, 0); ! tem2 = expand_and (cval, tem2, ! (GET_CODE (tem2) == REG ! ? tem2 : 0)); ! } ! ! /* If we usually make new pseudos, do so here. This ! turns out to help machines that have conditional ! move insns. */ ! ! if (flag_expensive_optimizations) ! target = 0; ! ! target = expand_binop (GET_MODE (var), ior_optab, ! tem1, tem2, target, ! 1, OPTAB_WIDEN); ! } ! else if (normalizep != 1) ! target = expand_and (uval, target, (GET_CODE (target) == REG ! && ! preserve_subexpressions_p () ! ? target : NULL_RTX)); ! ! emit_move_insn (var, target); ! seq = get_insns (); end_sequence (); ! #ifdef HAVE_cc0 ! /* If INSN uses CC0, we must not separate it from the ! insn that sets cc0. */ ! ! if (reg_mentioned_p (cc0_rtx, PATTERN (before))) ! before = prev_nonnote_insn (before); #endif ! ! emit_insns_before (seq, before); ! ! delete_insn (temp); ! next = NEXT_INSN (insn); ! ! delete_jump (insn); changed = 1; continue; *************** *** 951,954 **** --- 1205,1212 ---- && JUMP_LABEL (temp3) == JUMP_LABEL (insn))) && (temp3 = get_condition (insn, &temp4)) != 0 + /* We must be comparing objects whose modes imply the size. + We could handle BLKmode if (1) emit_store_flag could + and (2) we could find the size reliably. */ + && GET_MODE (XEXP (temp3, 0)) != BLKmode && can_reverse_comparison_p (temp3, insn)) { *************** *** 1719,1724 **** case INSN: if (++num_insns > 20 ! || find_reg_note (insn, REG_RETVAL, 0) ! || find_reg_note (insn, REG_LIBCALL, 0)) return 0; break; --- 1977,1982 ---- case INSN: if (++num_insns > 20 ! || find_reg_note (insn, REG_RETVAL, NULL_RTX) ! || find_reg_note (insn, REG_LIBCALL, NULL_RTX)) return 0; break; *************** *** 1997,2004 **** if (!lose && GET_CODE (p1) == GET_CODE (p2) ! && ((equiv1 = find_reg_note (i1, REG_EQUAL, 0)) != 0 ! || (equiv1 = find_reg_note (i1, REG_EQUIV, 0)) != 0) ! && ((equiv2 = find_reg_note (i2, REG_EQUAL, 0)) != 0 ! || (equiv2 = find_reg_note (i2, REG_EQUIV, 0)) != 0) /* If the equivalences are not to a constant, they may reference pseudos that no longer exist, so we can't --- 2255,2262 ---- if (!lose && GET_CODE (p1) == GET_CODE (p2) ! && ((equiv1 = find_reg_note (i1, REG_EQUAL, NULL_RTX)) != 0 ! || (equiv1 = find_reg_note (i1, REG_EQUIV, NULL_RTX)) != 0) ! && ((equiv2 = find_reg_note (i2, REG_EQUAL, NULL_RTX)) != 0 ! || (equiv2 = find_reg_note (i2, REG_EQUIV, NULL_RTX)) != 0) /* If the equivalences are not to a constant, they may reference pseudos that no longer exist, so we can't *************** *** 2695,2698 **** --- 2953,2959 ---- if (GET_CODE (label) != CODE_LABEL) abort (); + /* Ignore references to labels of containing functions. */ + if (LABEL_REF_NONLOCAL_P (x)) + break; /* If there are other labels following this one, replace it with the last of the consecutive labels. */ *************** *** 2729,2734 **** && (GET_CODE (PATTERN (next)) == ADDR_VEC || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))) ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, label, ! REG_NOTES (insn)); } } --- 2990,3000 ---- && (GET_CODE (PATTERN (next)) == ADDR_VEC || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))) ! { ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, label, ! REG_NOTES (insn)); ! /* Record in the note whether label is nonlocal. */ ! LABEL_REF_NONLOCAL_P (REG_NOTES (insn)) ! = LABEL_REF_NONLOCAL_P (x); ! } } } *************** *** 2744,2748 **** for (i = 0; i < XVECLEN (x, eltnum); i++) ! mark_jump_label (XVECEXP (x, eltnum, i), 0, cross_jump); return; } --- 3010,3014 ---- for (i = 0; i < XVECLEN (x, eltnum); i++) ! mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, cross_jump); return; } *************** *** 2772,2782 **** { register rtx x = PATTERN (insn); - register rtx prev; if (GET_CODE (x) == SET && GET_CODE (SET_DEST (x)) == PC) { - prev = prev_nonnote_insn (insn); #ifdef HAVE_cc0 /* We assume that at this stage CC's are always set explicitly --- 3038,3047 ---- { register rtx x = PATTERN (insn); if (GET_CODE (x) == SET && GET_CODE (SET_DEST (x)) == PC) { #ifdef HAVE_cc0 + rtx prev = prev_nonnote_insn (insn); /* We assume that at this stage CC's are always set explicitly *************** *** 2789,2793 **** { if (sets_cc0_p (PATTERN (prev)) > 0 ! && !FIND_REG_INC_NOTE (prev, 0)) delete_insn (prev); else --- 3054,3058 ---- { if (sets_cc0_p (PATTERN (prev)) > 0 ! && !FIND_REG_INC_NOTE (prev, NULL_RTX)) delete_insn (prev); else *************** *** 2796,2880 **** cc0_rtx, REG_NOTES (prev)); } ! #else ! { ! rtx note; ! /* If we are running before flow.c, we need do nothing since flow.c ! will delete the set of the condition code if it is dead. We also ! can't know if the register being used as the condition code is ! dead or not at this point. ! ! Otherwise, look at all our REG_DEAD notes. If a previous insn ! does nothing other than set a register that dies in this jump, ! we can delete the insn. */ ! for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) ! { ! rtx our_prev; ! if (REG_NOTE_KIND (note) != REG_DEAD ! /* Verify that the REG_NOTE has a legal value. */ ! || GET_CODE (XEXP (note, 0)) != REG) ! continue; ! for (our_prev = prev_nonnote_insn (insn); ! our_prev && GET_CODE (our_prev) == INSN; ! our_prev = prev_nonnote_insn (our_prev)) ! { ! /* If we reach a SEQUENCE, it is too complex to try to ! do anything with it, so give up. */ ! if (GET_CODE (PATTERN (our_prev)) == SEQUENCE) ! break; ! if (GET_CODE (PATTERN (our_prev)) == USE ! && GET_CODE (XEXP (PATTERN (our_prev), 0)) == INSN) ! /* reorg creates USEs that look like this. We leave them ! alone because reorg needs them for its own purposes. */ ! break; ! if (reg_set_p (XEXP (note, 0), PATTERN (our_prev))) ! { ! if (FIND_REG_INC_NOTE (our_prev, 0)) ! break; ! if (GET_CODE (PATTERN (our_prev)) == PARALLEL) ! { ! /* If we find a SET of something else, we can't ! delete the insn. */ ! int i; ! for (i = 0; i < XVECLEN (PATTERN (our_prev), 0); i++) ! { ! rtx part = XVECEXP (PATTERN (our_prev), 0, i); ! if (GET_CODE (part) == SET ! && SET_DEST (part) != XEXP (note, 0)) ! break; ! } ! if (i == XVECLEN (PATTERN (our_prev), 0)) ! delete_insn (our_prev); ! } ! else if (GET_CODE (PATTERN (our_prev)) == SET ! && SET_DEST (PATTERN (our_prev)) == XEXP (note, 0)) ! delete_insn (our_prev); ! break; ! } ! /* If OUR_PREV references the register that dies here, ! it is an additional use. Hence any prior SET isn't ! dead. */ ! if (reg_overlap_mentioned_p (XEXP (note, 0), ! PATTERN (our_prev))) ! break; ! } ! } ! } ! #endif ! /* Now delete the jump insn itself. */ ! delete_insn (insn); } } --- 3061,3158 ---- cc0_rtx, REG_NOTES (prev)); } ! #endif ! /* Now delete the jump insn itself. */ ! delete_computation (insn); ! } ! } ! /* Delete INSN and recursively delete insns that compute values used only ! by INSN. This uses the REG_DEAD notes computed during flow analysis. ! If we are running before flow.c, we need do nothing since flow.c will ! delete dead code. We also can't know if the registers being used are ! dead or not at this point. ! ! Otherwise, look at all our REG_DEAD notes. If a previous insn does ! nothing other than set a register that dies in this insn, we can delete ! that insn as well. */ ! void ! delete_computation (insn) ! rtx insn; ! { ! #ifndef HAVE_cc0 ! rtx note, next; ! for (note = REG_NOTES (insn); note; note = next) ! { ! rtx our_prev; ! next = XEXP (note, 1); ! if (REG_NOTE_KIND (note) != REG_DEAD ! /* Verify that the REG_NOTE is legitimate. */ ! || GET_CODE (XEXP (note, 0)) != REG) ! continue; ! for (our_prev = prev_nonnote_insn (insn); ! our_prev && GET_CODE (our_prev) == INSN; ! our_prev = prev_nonnote_insn (our_prev)) ! { ! /* If we reach a SEQUENCE, it is too complex to try to ! do anything with it, so give up. */ ! if (GET_CODE (PATTERN (our_prev)) == SEQUENCE) ! break; ! if (GET_CODE (PATTERN (our_prev)) == USE ! && GET_CODE (XEXP (PATTERN (our_prev), 0)) == INSN) ! /* reorg creates USEs that look like this. We leave them ! alone because reorg needs them for its own purposes. */ ! break; ! ! if (reg_set_p (XEXP (note, 0), PATTERN (our_prev))) ! { ! if (FIND_REG_INC_NOTE (our_prev, NULL_RTX)) ! break; ! if (GET_CODE (PATTERN (our_prev)) == PARALLEL) ! { ! /* If we find a SET of something else, we can't ! delete the insn. */ ! int i; ! for (i = 0; i < XVECLEN (PATTERN (our_prev), 0); i++) ! { ! rtx part = XVECEXP (PATTERN (our_prev), 0, i); ! if (GET_CODE (part) == SET ! && SET_DEST (part) != XEXP (note, 0)) ! break; ! } ! if (i == XVECLEN (PATTERN (our_prev), 0)) ! delete_computation (our_prev); ! } ! else if (GET_CODE (PATTERN (our_prev)) == SET ! && SET_DEST (PATTERN (our_prev)) == XEXP (note, 0)) ! delete_computation (our_prev); ! break; ! } ! ! /* If OUR_PREV references the register that dies here, it is an ! additional use. Hence any prior SET isn't dead. However, this ! insn becomes the new place for the REG_DEAD note. */ ! if (reg_overlap_mentioned_p (XEXP (note, 0), ! PATTERN (our_prev))) ! { ! XEXP (note, 1) = REG_NOTES (our_prev); ! REG_NOTES (our_prev) = note; ! break; ! } ! } } + #endif /* Don't HAVE_cc0 */ + delete_insn (insn); } *************** *** 2891,2894 **** --- 3169,3174 ---- register rtx next = NEXT_INSN (insn); register rtx prev = PREV_INSN (insn); + register int was_code_label = (GET_CODE (insn) == CODE_LABEL); + register int dont_really_delete = 0; while (next && INSN_DELETED_P (next)) *************** *** 2899,2905 **** return next; ! /* Mark this insn as deleted. */ ! ! INSN_DELETED_P (insn) = 1; /* If this is an unconditional jump, delete it from the jump chain. */ --- 3179,3195 ---- return next; ! /* Don't delete user-declared labels. Convert them to special NOTEs ! instead. */ ! if (was_code_label && LABEL_NAME (insn) != 0 ! && optimize && ! dont_really_delete) ! { ! PUT_CODE (insn, NOTE); ! NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL; ! NOTE_SOURCE_FILE (insn) = 0; ! dont_really_delete = 1; ! } ! else ! /* Mark this insn as deleted. */ ! INSN_DELETED_P (insn) = 1; /* If this is an unconditional jump, delete it from the jump chain. */ *************** *** 2918,2922 **** /* Patch out INSN (and the barrier if any) */ ! if (optimize) { if (prev) --- 3208,3212 ---- /* Patch out INSN (and the barrier if any) */ ! if (optimize && ! dont_really_delete) { if (prev) *************** *** 2965,2969 **** It isn't useful to fall through into a table. */ ! if (GET_CODE (insn) == CODE_LABEL && NEXT_INSN (insn) != 0 && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN --- 3255,3259 ---- It isn't useful to fall through into a table. */ ! if (was_code_label && NEXT_INSN (insn) != 0 && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN *************** *** 2974,2979 **** /* If INSN was a label, delete insns following it if now unreachable. */ ! if (GET_CODE (insn) == CODE_LABEL && prev ! && GET_CODE (prev) == BARRIER) { register RTX_CODE code; --- 3264,3268 ---- /* If INSN was a label, delete insns following it if now unreachable. */ ! if (was_code_label && prev && GET_CODE (prev) == BARRIER) { register RTX_CODE code; *************** *** 3087,3091 **** matches a pattern. */ ! static int invert_exp (x, insn) rtx x; --- 3376,3380 ---- matches a pattern. */ ! int invert_exp (x, insn) rtx x; *************** *** 3235,3239 **** Otherwise, return 1. */ ! static int redirect_exp (loc, olabel, nlabel, insn) rtx *loc; --- 3524,3528 ---- Otherwise, return 1. */ ! int redirect_exp (loc, olabel, nlabel, insn) rtx *loc; *************** *** 3431,3434 **** --- 3720,3726 ---- case LABEL_REF: + /* We can't assume nonlocal labels have their following insns yet. */ + if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y)) + return XEXP (x, 0) == XEXP (y, 0); /* Two label-refs are equivalent if they point at labels in the same position in the instruction stream. */ *************** *** 3454,3457 **** --- 3746,3754 ---- switch (fmt[i]) { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + case 'i': if (XINT (x, i) != XINT (y, i)) *************** *** 3866,3869 **** --- 4163,4171 ---- switch (fmt[i]) { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + case 'n': case 'i': diff -rc2N gcc-2.2.2/libgcc2.c gcc-2.3.1/libgcc2.c *** gcc-2.2.2/libgcc2.c Mon May 4 21:46:51 1992 --- gcc-2.3.1/libgcc2.c Thu Oct 29 16:33:10 1992 *************** *** 29,33 **** do not apply. */ ! #include "tm.h" #ifndef L_trampoline #include "gstddef.h" --- 29,34 ---- do not apply. */ ! #include "tconfig.h" ! #include "machmode.h" #ifndef L_trampoline #include "gstddef.h" *************** *** 39,73 **** #endif ! /* Need to undef this because LONG_TYPE_SIZE may rely upon GCC's ! internal `target_flags' variable. */ ! #undef LONG_TYPE_SIZE ! #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT) ! #ifndef SItype ! #define SItype long int ! #endif ! ! /* long long ints are pairs of long ints in the order determined by WORDS_BIG_ENDIAN. */ #if WORDS_BIG_ENDIAN ! struct longlong {long high, low;}; #else ! struct longlong {long low, high;}; #endif ! /* We need this union to unpack/pack longlongs, since we don't have ! any arithmetic yet. Incoming long long parameters are stored ! into the `ll' field, and the unpacked result is read from the struct ! longlong. */ typedef union { ! struct longlong s; ! long long ll; ! } long_long; ! #if defined (L_udivmoddi4) || defined (L_muldi3) #include "longlong.h" --- 40,102 ---- #endif ! /* In the first part of this file, we are interfacing to calls generated ! by the compiler itself. These calls pass values into these routines ! which have very specific modes (rather than very specific types), and ! these compiler-generated calls also expect any return values to have ! very specific modes (rather than very specific types). Thus, we need ! to avoid using regular C language type names in this part of the file ! because the sizes for those types can be configured to be anything. ! Instead we use the following special type names. */ ! ! typedef unsigned int UQItype __attribute__ ((mode (QI))); ! typedef int SItype __attribute__ ((mode (SI))); ! typedef unsigned int USItype __attribute__ ((mode (SI))); ! typedef int DItype __attribute__ ((mode (DI))); ! typedef unsigned int UDItype __attribute__ ((mode (DI))); ! typedef float SFtype __attribute__ ((mode (SF))); ! typedef float DFtype __attribute__ ((mode (DF))); ! #if 0 ! typedef float XFtype __attribute__ ((mode (XF))); ! #endif ! #if LONG_DOUBLE_TYPE_SIZE == 128 ! typedef float TFtype __attribute__ ((mode (TF))); ! #endif ! ! /* Make sure that we don't accidentaly use any normal C language built-in ! type names in the first part of this file. Instead we want to use *only* ! the type names defined above. The following macro definitions insure ! that if we *do* accidently use soem normal C language built-in type name, ! we will get a syntax error. */ ! ! #define char bogus_type ! #define short bogus_type ! #define int bogus_type ! #define long bogus_type ! #define unsigned bogus_type ! #define float bogus_type ! #define double bogus_type ! #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT) ! /* DIstructs are pairs of SItype values in the order determined by WORDS_BIG_ENDIAN. */ #if WORDS_BIG_ENDIAN ! struct DIstruct {SItype high, low;}; #else ! struct DIstruct {SItype low, high;}; #endif ! /* We need this union to unpack/pack DImode values, since we don't have ! any arithmetic yet. Incoming DImode parameters are stored into the ! `ll' field, and the unpacked result is read from the struct `s'. */ typedef union { ! struct DIstruct s; ! DItype ll; ! } DIunion; ! #if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv) #include "longlong.h" *************** *** 75,80 **** #endif /* udiv or mul */ ! extern long long __fixunssfdi (float a); ! extern long long __fixunsdfdi (double a); #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) --- 104,109 ---- #endif /* udiv or mul */ ! extern DItype __fixunssfdi (SFtype a); ! extern DItype __fixunsdfdi (DFtype a); #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) *************** *** 82,96 **** static inline #endif ! long long __negdi2 (u) ! long long u; { ! long_long w; ! long_long uu; uu.ll = u; w.s.low = -uu.s.low; ! w.s.high = -uu.s.high - ((unsigned long) w.s.low > 0); return w.ll; --- 111,125 ---- static inline #endif ! DItype __negdi2 (u) ! DItype u; { ! DIunion w; ! DIunion uu; uu.ll = u; w.s.low = -uu.s.low; ! w.s.high = -uu.s.high - ((USItype) w.s.low > 0); return w.ll; *************** *** 99,110 **** #ifdef L_lshldi3 ! long long __lshldi3 (u, b) ! long long u; ! int b; { ! long_long w; ! long bm; ! long_long uu; if (b == 0) --- 128,139 ---- #ifdef L_lshldi3 ! DItype __lshldi3 (u, b) ! DItype u; ! SItype b; { ! DIunion w; ! SItype bm; ! DIunion uu; if (b == 0) *************** *** 113,127 **** uu.ll = u; ! bm = (sizeof (long) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.low = 0; ! w.s.high = (unsigned long)uu.s.low << -bm; } else { ! unsigned long carries = (unsigned long)uu.s.low >> bm; ! w.s.low = (unsigned long)uu.s.low << b; ! w.s.high = ((unsigned long)uu.s.high << b) | carries; } --- 142,156 ---- uu.ll = u; ! bm = (sizeof (SItype) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.low = 0; ! w.s.high = (USItype)uu.s.low << -bm; } else { ! USItype carries = (USItype)uu.s.low >> bm; ! w.s.low = (USItype)uu.s.low << b; ! w.s.high = ((USItype)uu.s.high << b) | carries; } *************** *** 131,142 **** #ifdef L_lshrdi3 ! long long __lshrdi3 (u, b) ! long long u; ! int b; { ! long_long w; ! long bm; ! long_long uu; if (b == 0) --- 160,171 ---- #ifdef L_lshrdi3 ! DItype __lshrdi3 (u, b) ! DItype u; ! SItype b; { ! DIunion w; ! SItype bm; ! DIunion uu; if (b == 0) *************** *** 145,159 **** uu.ll = u; ! bm = (sizeof (long) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.high = 0; ! w.s.low = (unsigned long)uu.s.high >> -bm; } else { ! unsigned long carries = (unsigned long)uu.s.high << bm; ! w.s.high = (unsigned long)uu.s.high >> b; ! w.s.low = ((unsigned long)uu.s.low >> b) | carries; } --- 174,188 ---- uu.ll = u; ! bm = (sizeof (SItype) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.high = 0; ! w.s.low = (USItype)uu.s.high >> -bm; } else { ! USItype carries = (USItype)uu.s.high << bm; ! w.s.high = (USItype)uu.s.high >> b; ! w.s.low = ((USItype)uu.s.low >> b) | carries; } *************** *** 163,174 **** #ifdef L_ashldi3 ! long long __ashldi3 (u, b) ! long long u; ! int b; { ! long_long w; ! long bm; ! long_long uu; if (b == 0) --- 192,203 ---- #ifdef L_ashldi3 ! DItype __ashldi3 (u, b) ! DItype u; ! SItype b; { ! DIunion w; ! SItype bm; ! DIunion uu; if (b == 0) *************** *** 177,191 **** uu.ll = u; ! bm = (sizeof (long) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.low = 0; ! w.s.high = (unsigned long)uu.s.low << -bm; } else { ! unsigned long carries = (unsigned long)uu.s.low >> bm; ! w.s.low = (unsigned long)uu.s.low << b; ! w.s.high = ((unsigned long)uu.s.high << b) | carries; } --- 206,220 ---- uu.ll = u; ! bm = (sizeof (SItype) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.low = 0; ! w.s.high = (USItype)uu.s.low << -bm; } else { ! USItype carries = (USItype)uu.s.low >> bm; ! w.s.low = (USItype)uu.s.low << b; ! w.s.high = ((USItype)uu.s.high << b) | carries; } *************** *** 195,206 **** #ifdef L_ashrdi3 ! long long __ashrdi3 (u, b) ! long long u; ! int b; { ! long_long w; ! long bm; ! long_long uu; if (b == 0) --- 224,235 ---- #ifdef L_ashrdi3 ! DItype __ashrdi3 (u, b) ! DItype u; ! SItype b; { ! DIunion w; ! SItype bm; ! DIunion uu; if (b == 0) *************** *** 209,224 **** uu.ll = u; ! bm = (sizeof (long) * BITS_PER_UNIT) - b; if (bm <= 0) { /* w.s.high = 1..1 or 0..0 */ ! w.s.high = uu.s.high >> (sizeof (long) * BITS_PER_UNIT - 1); w.s.low = uu.s.high >> -bm; } else { ! unsigned long carries = (unsigned long)uu.s.high << bm; w.s.high = uu.s.high >> b; ! w.s.low = ((unsigned long)uu.s.low >> b) | carries; } --- 238,253 ---- uu.ll = u; ! bm = (sizeof (SItype) * BITS_PER_UNIT) - b; if (bm <= 0) { /* w.s.high = 1..1 or 0..0 */ ! w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); w.s.low = uu.s.high >> -bm; } else { ! USItype carries = (USItype)uu.s.high << bm; w.s.high = uu.s.high >> b; ! w.s.low = ((USItype)uu.s.low >> b) | carries; } *************** *** 228,237 **** #ifdef L_muldi3 ! long long __muldi3 (u, v) ! long long u, v; { ! long_long w; ! long_long uu, vv; uu.ll = u, --- 257,266 ---- #ifdef L_muldi3 ! DItype __muldi3 (u, v) ! DItype u, v; { ! DIunion w; ! DIunion uu, vv; uu.ll = u, *************** *** 239,244 **** w.ll = __umulsidi3 (uu.s.low, vv.s.low); ! w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high ! + (unsigned long) uu.s.high * (unsigned long) vv.s.low); return w.ll; --- 268,273 ---- w.ll = __umulsidi3 (uu.s.low, vv.s.low); ! w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high ! + (USItype) uu.s.high * (USItype) vv.s.low); return w.ll; *************** *** 246,251 **** #endif #ifdef L_udivmoddi4 ! static const unsigned char __clz_tab[] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, --- 275,380 ---- #endif + #ifdef L_udiv_w_sdiv + USItype + __udiv_w_sdiv (rp, a1, a0, d) + USItype *rp, a1, a0, d; + { + USItype q, r; + USItype c0, c1, b1; + + if ((SItype) d >= 0) + { + if (a1 < d - a1 - (a0 >> 31)) + { + /* dividend, divisor, and quotient are nonnegative */ + sdiv_qrnnd (q, r, a1, a0, d); + } + else + { + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + sub_ddmmss (c1, c0, a1, a0, d >> 1, d << 31); + /* Divide (c1*2^32 + c0) by d */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient */ + q += 1 << 31; + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << 31) + (a0 >> 1); + + if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ + { + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ + { + c1 = (b1 - 1) - c1; + c0 = ~c0; /* logical NOT */ + + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + q = ~q; /* (A/2)/b1 */ + r = (b1 - 1) - r; + + r = 2*r + (a0 & 1); /* A/(2*b1) */ + + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else /* Implies c1 = b1 */ + { /* Hence a1 = d - 1 = 2*b1 - 1 */ + if (a0 >= -d) + { + q = -1; + r = a0 + d; + } + else + { + q = -2; + r = a0 + 2*d; + } + } + } + + *rp = r; + return q; + } + #endif + #ifdef L_udivmoddi4 ! static const UQItype __clz_tab[] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, *************** *** 259,273 **** }; ! unsigned long long __udivmoddi4 (n, d, rp) ! unsigned long long n, d; ! unsigned long long int *rp; { ! long_long ww; ! long_long nn, dd; ! long_long rr; ! unsigned long d0, d1, n0, n1, n2; ! unsigned long q0, q1; ! unsigned b, bm; nn.ll = n; --- 388,402 ---- }; ! UDItype __udivmoddi4 (n, d, rp) ! UDItype n, d; ! UDItype *rp; { ! DIunion ww; ! DIunion nn, dd; ! DIunion rr; ! USItype d0, d1, n0, n1, n2; ! USItype q0, q1; ! USItype b, bm; nn.ll = n; *************** *** 328,332 **** d0 = d0 << bm; ! n1 = (n1 << bm) | (n0 >> (LONG_TYPE_SIZE - bm)); n0 = n0 << bm; } --- 457,461 ---- d0 = d0 << bm; ! n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm)); n0 = n0 << bm; } *************** *** 353,357 **** This special case is necessary, not an optimization. ! (Shifts counts of LONG_TYPE_SIZE are undefined.) */ n1 -= d0; --- 482,486 ---- This special case is necessary, not an optimization. ! (Shifts counts of SI_TYPE_SIZE are undefined.) */ n1 -= d0; *************** *** 362,366 **** /* Normalize. */ ! b = LONG_TYPE_SIZE - bm; d0 = d0 << bm; --- 491,495 ---- /* Normalize. */ ! b = SI_TYPE_SIZE - bm; d0 = d0 << bm; *************** *** 439,446 **** else { ! unsigned long m1, m0; /* Normalize. */ ! b = LONG_TYPE_SIZE - bm; d1 = (d1 << bm) | (d0 >> b); --- 568,575 ---- else { ! USItype m1, m0; /* Normalize. */ ! b = SI_TYPE_SIZE - bm; d1 = (d1 << bm) | (d0 >> b); *************** *** 480,491 **** #ifdef L_divdi3 ! unsigned long long __udivmoddi4 (); ! long long __divdi3 (u, v) ! long long u, v; { ! int c = 0; ! long_long uu, vv; ! long long w; uu.ll = u; --- 609,620 ---- #ifdef L_divdi3 ! UDItype __udivmoddi4 (); ! DItype __divdi3 (u, v) ! DItype u, v; { ! SItype c = 0; ! DIunion uu, vv; ! DItype w; uu.ll = u; *************** *** 499,503 **** vv.ll = __negdi2 (vv.ll); ! w = __udivmoddi4 (uu.ll, vv.ll, (unsigned long long *) 0); if (c) w = __negdi2 (w); --- 628,632 ---- vv.ll = __negdi2 (vv.ll); ! w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0); if (c) w = __negdi2 (w); *************** *** 508,519 **** #ifdef L_moddi3 ! unsigned long long __udivmoddi4 (); ! long long __moddi3 (u, v) ! long long u, v; { ! int c = 0; ! long_long uu, vv; ! long long w; uu.ll = u; --- 637,648 ---- #ifdef L_moddi3 ! UDItype __udivmoddi4 (); ! DItype __moddi3 (u, v) ! DItype u, v; { ! SItype c = 0; ! DIunion uu, vv; ! DItype w; uu.ll = u; *************** *** 535,544 **** #ifdef L_umoddi3 ! unsigned long long __udivmoddi4 (); ! unsigned long long __umoddi3 (u, v) ! unsigned long long u, v; { ! long long w; (void) __udivmoddi4 (u, v, &w); --- 664,673 ---- #ifdef L_umoddi3 ! UDItype __udivmoddi4 (); ! UDItype __umoddi3 (u, v) ! UDItype u, v; { ! DItype w; (void) __udivmoddi4 (u, v, &w); *************** *** 549,558 **** #ifdef L_udivdi3 ! unsigned long long __udivmoddi4 (); ! unsigned long long __udivdi3 (n, d) ! unsigned long long n, d; { ! return __udivmoddi4 (n, d, (unsigned long long *) 0); } #endif --- 678,687 ---- #ifdef L_udivdi3 ! UDItype __udivmoddi4 (); ! UDItype __udivdi3 (n, d) ! UDItype n, d; { ! return __udivmoddi4 (n, d, (UDItype *) 0); } #endif *************** *** 561,567 **** SItype __cmpdi2 (a, b) ! long long a, b; { ! long_long au, bu; au.ll = a, bu.ll = b; --- 690,696 ---- SItype __cmpdi2 (a, b) ! DItype a, b; { ! DIunion au, bu; au.ll = a, bu.ll = b; *************** *** 571,577 **** else if (au.s.high > bu.s.high) return 2; ! if ((unsigned long) au.s.low < (unsigned long) bu.s.low) return 0; ! else if ((unsigned long) au.s.low > (unsigned long) bu.s.low) return 2; return 1; --- 700,706 ---- else if (au.s.high > bu.s.high) return 2; ! if ((USItype) au.s.low < (USItype) bu.s.low) return 0; ! else if ((USItype) au.s.low > (USItype) bu.s.low) return 2; return 1; *************** *** 582,598 **** SItype __ucmpdi2 (a, b) ! long long a, b; { ! long_long au, bu; au.ll = a, bu.ll = b; ! if ((unsigned long) au.s.high < (unsigned long) bu.s.high) return 0; ! else if ((unsigned long) au.s.high > (unsigned long) bu.s.high) return 2; ! if ((unsigned long) au.s.low < (unsigned long) bu.s.low) return 0; ! else if ((unsigned long) au.s.low > (unsigned long) bu.s.low) return 2; return 1; --- 711,727 ---- SItype __ucmpdi2 (a, b) ! DItype a, b; { ! DIunion au, bu; au.ll = a, bu.ll = b; ! if ((USItype) au.s.high < (USItype) bu.s.high) return 0; ! else if ((USItype) au.s.high > (USItype) bu.s.high) return 2; ! if ((USItype) au.s.low < (USItype) bu.s.low) return 0; ! else if ((USItype) au.s.low > (USItype) bu.s.low) return 2; return 1; *************** *** 600,613 **** #endif #ifdef L_fixunsdfdi ! #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! long long __fixunsdfdi (a) ! double a; { ! double b; ! unsigned long long v; if (a < 0) --- 729,786 ---- #endif + #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128) + #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) + #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) + + DItype + __fixunstfdi (a) + TFtype a; + { + TFtype b; + UDItype v; + + if (a < 0) + return 0; + + /* Compute high word of result, as a flonum. */ + b = (a / HIGH_WORD_COEFF); + /* Convert that to fixed (but not to DItype!), + and shift it into the high word. */ + v = (USItype) b; + v <<= WORD_SIZE; + /* Remove high part from the TFtype, leaving the low part as flonum. */ + a -= (TFtype)v; + /* Convert that to fixed (but not to DItype!) and add it in. + Sometimes A comes out negative. This is significant, since + A has more bits than a long int does. */ + if (a < 0) + v -= (USItype) (- a); + else + v += (USItype) a; + return v; + } + #endif + + #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128) + DItype + __fixtfdi (a) + TFtype a; + { + if (a < 0) + return - __fixunstfdi (-a); + return __fixunstfdi (a); + } + #endif + #ifdef L_fixunsdfdi ! #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) ! #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) ! DItype __fixunsdfdi (a) ! DFtype a; { ! DFtype b; ! UDItype v; if (a < 0) *************** *** 616,632 **** /* Compute high word of result, as a flonum. */ b = (a / HIGH_WORD_COEFF); ! /* Convert that to fixed (but not to long long!), and shift it into the high word. */ ! v = (unsigned long int) b; v <<= WORD_SIZE; ! /* Remove high part from the double, leaving the low part as flonum. */ ! a -= (double)v; ! /* Convert that to fixed (but not to long long!) and add it in. Sometimes A comes out negative. This is significant, since A has more bits than a long int does. */ if (a < 0) ! v -= (unsigned long int) (- a); else ! v += (unsigned long int) a; return v; } --- 789,805 ---- /* Compute high word of result, as a flonum. */ b = (a / HIGH_WORD_COEFF); ! /* Convert that to fixed (but not to DItype!), and shift it into the high word. */ ! v = (USItype) b; v <<= WORD_SIZE; ! /* Remove high part from the DFtype, leaving the low part as flonum. */ ! a -= (DFtype)v; ! /* Convert that to fixed (but not to DItype!) and add it in. Sometimes A comes out negative. This is significant, since A has more bits than a long int does. */ if (a < 0) ! v -= (USItype) (- a); else ! v += (USItype) a; return v; } *************** *** 634,640 **** #ifdef L_fixdfdi ! long long __fixdfdi (a) ! double a; { if (a < 0) --- 807,813 ---- #ifdef L_fixdfdi ! DItype __fixdfdi (a) ! DFtype a; { if (a < 0) *************** *** 645,660 **** #ifdef L_fixunssfdi ! #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! long long ! __fixunssfdi (float original_a) { ! /* Convert the float to a double, because that is surely not going to lose any bits. Some day someone else can write a faster version ! that avoids converting to double, and verify it really works right. */ ! double a = original_a; ! double b; ! unsigned long long v; if (a < 0) --- 818,833 ---- #ifdef L_fixunssfdi ! #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) ! #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) ! DItype ! __fixunssfdi (SFtype original_a) { ! /* Convert the SFtype to a DFtype, because that is surely not going to lose any bits. Some day someone else can write a faster version ! that avoids converting to DFtype, and verify it really works right. */ ! DFtype a = original_a; ! DFtype b; ! UDItype v; if (a < 0) *************** *** 663,679 **** /* Compute high word of result, as a flonum. */ b = (a / HIGH_WORD_COEFF); ! /* Convert that to fixed (but not to long long!), and shift it into the high word. */ ! v = (unsigned long int) b; v <<= WORD_SIZE; ! /* Remove high part from the double, leaving the low part as flonum. */ ! a -= (double)v; ! /* Convert that to fixed (but not to long long!) and add it in. Sometimes A comes out negative. This is significant, since A has more bits than a long int does. */ if (a < 0) ! v -= (unsigned long int) (- a); else ! v += (unsigned long int) a; return v; } --- 836,852 ---- /* Compute high word of result, as a flonum. */ b = (a / HIGH_WORD_COEFF); ! /* Convert that to fixed (but not to DItype!), and shift it into the high word. */ ! v = (USItype) b; v <<= WORD_SIZE; ! /* Remove high part from the DFtype, leaving the low part as flonum. */ ! a -= (DFtype)v; ! /* Convert that to fixed (but not to DItype!) and add it in. Sometimes A comes out negative. This is significant, since A has more bits than a long int does. */ if (a < 0) ! v -= (USItype) (- a); else ! v += (USItype) a; return v; } *************** *** 681,686 **** #ifdef L_fixsfdi ! long long ! __fixsfdi (float a) { if (a < 0) --- 854,859 ---- #ifdef L_fixsfdi ! DItype ! __fixsfdi (SFtype a) { if (a < 0) *************** *** 690,712 **** #endif #ifdef L_floatdidf ! #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2)) ! #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! double __floatdidf (u) ! long long u; { ! double d; ! int negate = 0; if (u < 0) u = -u, negate = 1; ! d = (unsigned int) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; ! d += (unsigned int) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -d : d); --- 863,909 ---- #endif + #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128) + #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) + #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) + #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) + + TFtype + __floatditf (u) + DItype u; + { + TFtype d; + SItype negate = 0; + + if (u < 0) + u = -u, negate = 1; + + d = (USItype) (u >> WORD_SIZE); + d *= HIGH_HALFWORD_COEFF; + d *= HIGH_HALFWORD_COEFF; + d += (USItype) (u & (HIGH_WORD_COEFF - 1)); + + return (negate ? -d : d); + } + #endif + #ifdef L_floatdidf ! #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) ! #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) ! #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) ! DFtype __floatdidf (u) ! DItype u; { ! DFtype d; ! SItype negate = 0; if (u < 0) u = -u, negate = 1; ! d = (USItype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; ! d += (USItype) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -d : d); *************** *** 715,736 **** #ifdef L_floatdisf ! #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT) ! #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2)) ! #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE) ! float __floatdisf (u) ! long long u; { ! float f; ! int negate = 0; if (u < 0) u = -u, negate = 1; ! f = (unsigned int) (u >> WORD_SIZE); f *= HIGH_HALFWORD_COEFF; f *= HIGH_HALFWORD_COEFF; ! f += (unsigned int) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -f : f); --- 912,933 ---- #ifdef L_floatdisf ! #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) ! #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2)) ! #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) ! SFtype __floatdisf (u) ! DItype u; { ! SFtype f; ! SItype negate = 0; if (u < 0) u = -u, negate = 1; ! f = (USItype) (u >> WORD_SIZE); f *= HIGH_HALFWORD_COEFF; f *= HIGH_HALFWORD_COEFF; ! f += (USItype) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -f : f); *************** *** 739,749 **** #ifdef L_fixunsdfsi ! #include "limits.h" ! unsigned SItype __fixunsdfsi (a) ! double a; { ! if (a >= - (double) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; --- 936,946 ---- #ifdef L_fixunsdfsi ! #include "glimits.h" ! USItype __fixunsdfsi (a) ! DFtype a; { ! if (a >= - (DFtype) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; *************** *** 752,761 **** #ifdef L_fixunssfsi ! #include "limits.h" ! unsigned SItype ! __fixunssfsi (float a) { ! if (a >= - (float) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; --- 949,958 ---- #ifdef L_fixunssfsi ! #include "glimits.h" ! USItype ! __fixunssfsi (SFtype a) { ! if (a >= - (SFtype) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; *************** *** 763,775 **** #endif #ifdef L_varargs #ifdef __i860__ ! #ifdef SVR4 asm (" .text"); asm (" .align 4"); asm (".globl __builtin_saveregs"); asm ("__builtin_saveregs:"); ! asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */ asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save area and also for a new va_list --- 960,1016 ---- #endif + /* From here on down, the routines use normal data types. */ + + #define SItype bogus_type + #define USItype bogus_type + #define DItype bogus_type + #define UDItype bogus_type + #define SFtype bogus_type + #define DFtype bogus_type + + #undef char + #undef short + #undef int + #undef long + #undef unsigned + #undef float + #undef double + + #ifdef L__gcc_bcmp + + /* Like bcmp except the sign is meaningful. + Reult is negative if S1 is less than S2, + positive if S1 is greater, 0 if S1 and S2 are equal. */ + + int + __gcc_bcmp (s1, s2, size) + unsigned char *s1, *s2; + size_t size; + { + while (size > 0) + { + unsigned char c1 = *s1++, c2 = *s2++; + if (c1 != c2) + return c1 - c2; + size--; + } + return 0; + } + + #endif + #ifdef L_varargs #ifdef __i860__ ! #if defined(__svr4__) || defined(__alliant__) asm (" .text"); asm (" .align 4"); + /* The Alliant needs the added underscore. */ asm (".globl __builtin_saveregs"); asm ("__builtin_saveregs:"); ! asm (".globl ___builtin_saveregs"); ! asm ("___builtin_saveregs:"); ! ! asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */ asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save area and also for a new va_list *************** *** 826,830 **** asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */ ! #else /* not SVR4 */ asm (" .text"); asm (" .align 4"); --- 1067,1071 ---- asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */ ! #else /* not __SVR4__ */ asm (" .text"); asm (" .align 4"); *************** *** 864,868 **** /* recover stack and pass address to start of data. */ ! #endif /* not SVR4 */ #else /* not __i860__ */ #ifdef __sparc__ --- 1105,1109 ---- /* recover stack and pass address to start of data. */ ! #endif /* not __SVR4__ */ #else /* not __i860__ */ #ifdef __sparc__ *************** *** 909,912 **** --- 1150,1155 ---- #ifdef L_eprintf + #ifndef inhibit_eprintf + #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ #include *************** *** 923,926 **** --- 1166,1171 ---- abort (); } + + #endif #endif *************** *** 962,966 **** extern vfp __new_handler; - extern void *malloc (); void * --- 1207,1210 ---- *************** *** 970,974 **** void *p; ! p = malloc (sz); if (p == 0) (*__new_handler) (); --- 1214,1221 ---- void *p; ! /* malloc (0) is unpredictable; avoid it. */ ! if (sz == 0) ! sz = 1; ! p = (void *) malloc (sz); if (p == 0) (*__new_handler) (); *************** *** 977,981 **** #endif ! #ifdef L_builtin_New typedef void (*vfp)(void); --- 1224,1239 ---- #endif ! #ifdef L_caps_New ! ! /* This gets us __GNU_LIBRARY__. */ ! #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ ! #include ! ! #ifdef __GNU_LIBRARY__ ! /* Avoid forcing the library's meaning of `write' on the user program ! by using the "internal" name (for use within the library) */ ! #define write(fd, buf, n) __write((fd), (buf), (n)) ! #endif ! typedef void (*vfp)(void); *************** *** 1243,1246 **** --- 1501,1505 ---- #ifdef __pyr__ + #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ #include #include *************** *** 1279,1283 **** DO_GLOBAL_DTORS_BODY; #else ! unsigned nptrs = (unsigned) __DTOR_LIST__[0]; unsigned i; --- 1538,1542 ---- DO_GLOBAL_DTORS_BODY; #else ! unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0]; unsigned i; *************** *** 1343,1347 **** #endif /* L__main */ ! #ifdef L_exit #include "gbl-ctors.h" --- 1602,1606 ---- #endif /* L__main */ ! #ifdef L_ctors #include "gbl-ctors.h" *************** *** 1355,1361 **** --- 1614,1631 ---- so that they are valid empty lists if no other definition is loaded. */ #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY) + #ifdef __NeXT__ + /* After 2.3, try this definition on all systems. */ + func_ptr __CTOR_LIST__[2] = {0, 0}; + func_ptr __DTOR_LIST__[2] = {0, 0}; + #else func_ptr __CTOR_LIST__[2]; func_ptr __DTOR_LIST__[2]; + #endif #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ + #endif /* L_ctors */ + + #ifdef L_exit + + #include "gbl-ctors.h" #ifndef ON_EXIT *************** *** 1367,1371 **** extern void __do_global_dtors (); extern void _cleanup (); ! extern void _exit (); void --- 1637,1641 ---- extern void __do_global_dtors (); extern void _cleanup (); ! extern volatile void _exit (); void diff -rc2N gcc-2.2.2/limitx.h gcc-2.3.1/limitx.h *** gcc-2.2.2/limitx.h Mon Jan 6 22:53:27 1992 --- gcc-2.3.1/limitx.h Tue Sep 29 17:29:04 1992 *************** *** 2,5 **** if the system has its own version of limits.h. */ ! #include_next --- 2,10 ---- if the system has its own version of limits.h. */ ! #ifndef _LIMITS_H_ /* Terminated in limity.h. */ ! #define _LIMITS_H_ + #ifndef _LIBC_LIMITS_H_ + /* Use <...> so that we find syslimits.h only in system include dirs. */ + #include + #endif diff -rc2N gcc-2.2.2/limity.h gcc-2.3.1/limity.h *** gcc-2.2.2/limity.h --- gcc-2.3.1/limity.h Sat Aug 1 22:53:10 1992 *************** *** 0 **** --- 1,4 ---- + /* This administrivia gets added to the end of limits.h + if the system has its own version of limits.h. */ + + #endif /* not _LIMITS_H_ */ diff -rc2N gcc-2.2.2/local-alloc.c gcc-2.3.1/local-alloc.c *** gcc-2.2.2/local-alloc.c Thu May 7 02:36:34 1992 --- gcc-2.3.1/local-alloc.c Fri Oct 9 07:25:42 1992 *************** *** 146,152 **** static int *qty_n_calls_crossed; ! /* Nonzero means don't allocate qty Q if we can't get its preferred class. */ ! static char *qty_preferred_or_nothing; /* Element Q is the SCRATCH expression for which this quantity is being --- 146,153 ---- static int *qty_n_calls_crossed; ! /* Register class within which we allocate qty Q if we can't get ! its preferred class. */ ! static enum reg_class *qty_alternate_class; /* Element Q is the SCRATCH expression for which this quantity is being *************** *** 259,263 **** qty_n_calls_crossed[qty] = reg_n_calls_crossed[regno]; qty_min_class[qty] = reg_preferred_class (regno); ! qty_preferred_or_nothing[qty] = reg_preferred_or_nothing (regno); qty_n_refs[qty] = reg_n_refs[regno]; } --- 260,264 ---- qty_n_calls_crossed[qty] = reg_n_calls_crossed[regno]; qty_min_class[qty] = reg_preferred_class (regno); ! qty_alternate_class[qty] = reg_alternate_class (regno); qty_n_refs[qty] = reg_n_refs[regno]; } *************** *** 279,282 **** --- 280,284 ---- int i; + #ifdef REGISTER_CONSTRAINTS /* If we haven't yet computed which alternative will be used, do so now. Then set P to the constraints for that alternative. */ *************** *** 335,338 **** --- 337,346 ---- return; + #else /* REGISTER_CONSTRAINTS */ + + class = GENERAL_REGS; + #endif + + qty = next_qty++; *************** *** 345,349 **** qty_n_calls_crossed[qty] = 0; qty_min_class[qty] = class; ! qty_preferred_or_nothing[qty] = 1; qty_n_refs[qty] = 1; } --- 353,357 ---- qty_n_calls_crossed[qty] = 0; qty_min_class[qty] = class; ! qty_alternate_class[qty] = NO_REGS; qty_n_refs[qty] = 1; } *************** *** 390,394 **** qty_n_calls_crossed = (int *) alloca (max_qty * sizeof (int)); qty_min_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class)); ! qty_preferred_or_nothing = (char *) alloca (max_qty); qty_n_refs = (short *) alloca (max_qty * sizeof (short)); --- 398,402 ---- qty_n_calls_crossed = (int *) alloca (max_qty * sizeof (int)); qty_min_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class)); ! qty_alternate_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class)); qty_n_refs = (short *) alloca (max_qty * sizeof (short)); *************** *** 414,418 **** { if (reg_basic_block[i] >= 0 && reg_n_deaths[i] == 1 ! && (reg_preferred_or_nothing (i) || reg_class_size[(int) reg_preferred_class (i)] > 1)) reg_qty[i] = -2; --- 422,426 ---- { if (reg_basic_block[i] >= 0 && reg_n_deaths[i] == 1 ! && (reg_alternate_class (i) == NO_REGS || reg_class_size[(int) reg_preferred_class (i)] > 1)) reg_qty[i] = -2; *************** *** 679,687 **** break; ! if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0) { int failed = 0; int length = 0; int n_calls = 0; /* We can do the optimization. Scan forward from INSN again, --- 687,700 ---- break; ! /* See if all of SRC dies in P. This test is slightly more ! conservative than it needs to be. */ ! if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0 ! && GET_MODE (XEXP (note, 0)) == GET_MODE (src)) { int failed = 0; int length = 0; + int d_length = 0; int n_calls = 0; + int d_n_calls = 0; /* We can do the optimization. Scan forward from INSN again, *************** *** 695,701 **** q = next_real_insn (q)) { ! if (reg_mentioned_p (src, PATTERN (q))) { ! if (validate_replace_rtx (src, dest, q)) { /* We assume that a register is used exactly once per --- 708,728 ---- q = next_real_insn (q)) { ! if (reg_overlap_mentioned_p (src, PATTERN (q))) { ! /* If SRC is a hard register, we might miss some ! overlapping registers with validate_replace_rtx, ! so we would have to undo it. We can't if DEST is ! present in the insn, so fail in that combination ! of cases. */ ! if (sregno < FIRST_PSEUDO_REGISTER ! && reg_mentioned_p (dest, PATTERN (q))) ! failed = 1; ! ! /* Replace all uses and make sure that the register ! isn't still present. */ ! else if (validate_replace_rtx (src, dest, q) ! && (sregno >= FIRST_PSEUDO_REGISTER ! || ! reg_overlap_mentioned_p (src, ! PATTERN (q)))) { /* We assume that a register is used exactly once per *************** *** 708,712 **** } else ! failed = 1; } --- 735,742 ---- } else ! { ! validate_replace_rtx (dest, src, q); ! failed = 1; ! } } *************** *** 715,719 **** length++; if (dest_death) ! reg_live_length[dregno]++; if (GET_CODE (q) == CALL_INSN) --- 745,749 ---- length++; if (dest_death) ! d_length++; if (GET_CODE (q) == CALL_INSN) *************** *** 721,731 **** n_calls++; if (dest_death) ! reg_n_calls_crossed[dregno]++; } /* If DEST dies here, remove the death note and save it for ! later. */ if (dest_death == 0 ! && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0) remove_note (q, dest_death); } --- 751,763 ---- n_calls++; if (dest_death) ! d_n_calls++; } /* If DEST dies here, remove the death note and save it for ! later. Make sure ALL of DEST dies here; again, this is ! overly conservative. */ if (dest_death == 0 ! && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0 ! && GET_MODE (XEXP (dest_death, 0)) == GET_MODE (dest)) remove_note (q, dest_death); } *************** *** 739,742 **** --- 771,780 ---- } + if (dregno >= FIRST_PSEUDO_REGISTER) + { + reg_live_length[dregno] += d_length; + reg_n_calls_crossed[dregno] += d_n_calls; + } + /* Move death note of SRC from P to INSN. */ remove_note (p, note); *************** *** 754,757 **** --- 792,801 ---- return; } + + /* If SRC is a hard register which is set or killed in some other + way, we can't do this optimization. */ + else if (sregno < FIRST_PSEUDO_REGISTER + && dead_or_set_p (p, src)) + break; } } *************** *** 922,926 **** continue; ! note = find_reg_note (insn, REG_EQUAL, 0); /* Record this insn as initializing this register. */ --- 966,970 ---- continue; ! note = find_reg_note (insn, REG_EQUAL, NULL_RTX); /* Record this insn as initializing this register. */ *************** *** 947,951 **** note. */ ! note = find_reg_note (insn, REG_EQUIV, 0); if (note == 0 && reg_basic_block[regno] >= 0 --- 991,995 ---- note. */ ! note = find_reg_note (insn, REG_EQUIV, NULL_RTX); if (note == 0 && reg_basic_block[regno] >= 0 *************** *** 1099,1105 **** if (insn_code_number >= 0 && insn_n_operands[insn_code_number] > 1 && insn_operand_constraint[insn_code_number][0][0] == '=' ! && insn_operand_constraint[insn_code_number][0][1] != '&') { r0 = recog_operand[0]; --- 1143,1155 ---- if (insn_code_number >= 0 + #ifdef REGISTER_CONSTRAINTS && insn_n_operands[insn_code_number] > 1 && insn_operand_constraint[insn_code_number][0][0] == '=' ! && insn_operand_constraint[insn_code_number][0][1] != '&' ! #else ! && GET_CODE (PATTERN (insn)) == SET ! && rtx_equal_p (SET_DEST (PATTERN (insn)), recog_operand[0]) ! #endif ! ) { r0 = recog_operand[0]; *************** *** 1109,1113 **** There may be more than one register, but we only try one of them. */ ! if (insn_operand_constraint[insn_code_number][1][0] == 'p') while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT) r1 = XEXP (r1, 0); --- 1159,1169 ---- There may be more than one register, but we only try one of them. */ ! if ( ! #ifdef REGISTER_CONSTRAINTS ! insn_operand_constraint[insn_code_number][1][0] == 'p' ! #else ! insn_operand_address_p[insn_code_number][1] ! #endif ! ) while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT) r1 = XEXP (r1, 0); *************** *** 1119,1126 **** --- 1175,1186 ---- only be in the same register as the output, give priority to an equivalence found from that insn. */ + #ifdef REGISTER_CONSTRAINTS int may_save_copy = ((SET_DEST (body) == r0 && SET_SRC (body) == r1) || (r1 == recog_operand[1] && (requires_inout_p (insn_operand_constraint[insn_code_number][1])))); + #else + int may_save_copy = 0; + #endif if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG) *************** *** 1130,1134 **** --- 1190,1202 ---- if (win == 0 && insn_n_operands[insn_code_number] > 2 + #ifdef REGISTER_CONSTRAINTS && insn_operand_constraint[insn_code_number][1][0] == '%' + #else + && GET_CODE (PATTERN (insn)) == SET + && (GET_RTX_CLASS (GET_CODE (SET_SRC (PATTERN (insn)))) + == 'c') + && rtx_equal_p (recog_operand[2], + XEXP (SET_SRC (PATTERN (insn)), 0)) + #endif && (r1 = recog_operand[2], GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)) *************** *** 1155,1163 **** && (r0 = XEXP (PATTERN (insn), 0), GET_CODE (r0) == REG) ! && (link = find_reg_note (insn, REG_LIBCALL, 0)) != 0 && GET_CODE (XEXP (link, 0)) == INSN && (set = single_set (XEXP (link, 0))) != 0 && SET_DEST (set) == r0 && SET_SRC (set) == r0 ! && (note = find_reg_note (XEXP (link, 0), REG_EQUAL, 0)) != 0) { if (r1 = XEXP (note, 0), GET_CODE (r1) == REG --- 1223,1232 ---- && (r0 = XEXP (PATTERN (insn), 0), GET_CODE (r0) == REG) ! && (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0 && GET_CODE (XEXP (link, 0)) == INSN && (set = single_set (XEXP (link, 0))) != 0 && SET_DEST (set) == r0 && SET_SRC (set) == r0 ! && (note = find_reg_note (XEXP (link, 0), REG_EQUAL, ! NULL_RTX)) != 0) { if (r1 = XEXP (note, 0), GET_CODE (r1) == REG *************** *** 1245,1249 **** CLOBBER insn, we have reached the end of a REG_NO_CONFLICT block, so clear any register number that combined within it. */ ! if ((note = find_reg_note (insn, REG_RETVAL, 0)) != 0 && GET_CODE (XEXP (note, 0)) == INSN && GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER) --- 1314,1318 ---- CLOBBER insn, we have reached the end of a REG_NO_CONFLICT block, so clear any register number that combined within it. */ ! if ((note = find_reg_note (insn, REG_RETVAL, NULL_RTX)) != 0 && GET_CODE (XEXP (note, 0)) == INSN && GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER) *************** *** 1337,1342 **** } ! if (!qty_preferred_or_nothing[q]) ! qty_phys_reg[q] = find_free_reg (ALL_REGS, qty_mode[q], q, 0, 0, qty_birth[q], qty_death[q]); --- 1406,1411 ---- } ! if (qty_alternate_class[q] != NO_REGS) ! qty_phys_reg[q] = find_free_reg (qty_alternate_class[q], qty_mode[q], q, 0, 0, qty_birth[q], qty_death[q]); *************** *** 1597,1602 **** qty_n_calls_crossed[sqty] += reg_n_calls_crossed[sreg]; qty_n_refs[sqty] += reg_n_refs[sreg]; - if (! reg_preferred_or_nothing (sreg)) - qty_preferred_or_nothing[sqty] = 0; if (usize < ssize) { --- 1666,1669 ---- *************** *** 1663,1666 **** --- 1730,1737 ---- if (reg_class_subset_p (rclass, qty_min_class[qty])) qty_min_class[qty] = rclass; + + rclass = reg_alternate_class (reg); + if (reg_class_subset_p (rclass, qty_alternate_class[qty])) + qty_alternate_class[qty] = rclass; } *************** *** 1986,1990 **** { int ok = 0; ! rtx note = find_reg_note (insn, REG_LIBCALL, 0); rtx p, last; --- 2057,2061 ---- { int ok = 0; ! rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); rtx p, last; *************** *** 2014,2017 **** --- 2085,2090 ---- } + #ifdef REGISTER_CONSTRAINTS + /* Return 1 if the constraint string P indicates that the a the operand must be equal to operand 0 and that no register is acceptable. */ *************** *** 2056,2059 **** --- 2129,2133 ---- return found_zero; } + #endif /* REGISTER_CONSTRAINTS */ void diff -rc2N gcc-2.2.2/longlong.h gcc-2.3.1/longlong.h *** gcc-2.2.2/longlong.h Wed Jun 3 17:51:17 1992 --- gcc-2.3.1/longlong.h Wed Oct 28 14:26:19 1992 *************** *** 16,37 **** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ! #ifndef LONG_TYPE_SIZE ! #define LONG_TYPE_SIZE 32 #endif ! #define __BITS4 (LONG_TYPE_SIZE / 4) ! #define __ll_B (1L << (LONG_TYPE_SIZE / 2)) ! #define __ll_lowpart(t) ((unsigned long int) (t) % __ll_B) ! #define __ll_highpart(t) ((unsigned long int) (t) / __ll_B) /* Define auxiliary asm macros. 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) ! multiplies two unsigned long integers MULTIPLER and MULTIPLICAND, ! and generates a two unsigned word product in HIGH_PROD and LOW_PROD. ! 2) __umulsidi3(a,b) multiplies two unsigned long integers A and B, ! and returns a long long product. This is just a variant of umul_ppmm. 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, --- 16,37 ---- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ! #ifndef SI_TYPE_SIZE ! #define SI_TYPE_SIZE 32 #endif ! #define __BITS4 (SI_TYPE_SIZE / 4) ! #define __ll_B (1L << (SI_TYPE_SIZE / 2)) ! #define __ll_lowpart(t) ((USItype) (t) % __ll_B) ! #define __ll_highpart(t) ((USItype) (t) / __ll_B) /* Define auxiliary asm macros. 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) ! multiplies two USItype integers MULTIPLER and MULTIPLICAND, ! and generates a two-part USItype product in HIGH_PROD and LOW_PROD. ! 2) __umulsidi3(a,b) multiplies two USItype integers A and B, ! and returns a UDItype product. This is just a variant of umul_ppmm. 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, *************** *** 43,51 **** then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1. ! 4) count_leading_zeros(count, x) counts the number of zero-bits from the msb to the first non-zero bit. This is the number of steps X needs to be shifted left to set the msb. Undefined for X == 0. ! 5) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, high_addend_2, low_addend_2) adds two two-word unsigned integers, composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and --- 43,55 ---- then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1. ! 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, ! denominator). Like udiv_qrnnd but the numbers are signed. The ! quotient is rounded towards 0. ! ! 5) count_leading_zeros(count, x) counts the number of zero-bits from the msb to the first non-zero bit. This is the number of steps X needs to be shifted left to set the msb. Undefined for X == 0. ! 6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, high_addend_2, low_addend_2) adds two two-word unsigned integers, composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and *************** *** 54,58 **** lost. ! 6) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, high_subtrahend, low_subtrahend) subtracts two two-word unsigned integers, composed by HIGH_MINUEND_1 and --- 58,62 ---- lost. ! 7) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, high_subtrahend, low_subtrahend) subtracts two two-word unsigned integers, composed by HIGH_MINUEND_1 and *************** *** 87,114 **** __asm__ ("add %1,%4,%5 addc %0,%2,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%r" ((unsigned long int)(ah)), \ ! "rI" ((unsigned long int)(bh)), \ ! "%r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %1,%4,%5 subc %0,%2,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "r" ((unsigned long int)(ah)), \ ! "rI" ((unsigned long int)(bh)), \ ! "r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl))) #define umul_ppmm(xh, xl, m0, m1) \ do { \ ! unsigned long int __m0 = (m0), __m1 = (m1); \ __asm__ ("multiplu %0,%1,%2" \ ! : "=r" ((unsigned long int)(xl)) \ : "r" (__m0), \ "r" (__m1)); \ __asm__ ("multmu %0,%1,%2" \ ! : "=r" ((unsigned long int)(xh)) \ : "r" (__m0), \ "r" (__m1)); \ --- 91,118 ---- __asm__ ("add %1,%4,%5 addc %0,%2,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%r" ((USItype)(ah)), \ ! "rI" ((USItype)(bh)), \ ! "%r" ((USItype)(al)), \ ! "rI" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %1,%4,%5 subc %0,%2,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "r" ((USItype)(ah)), \ ! "rI" ((USItype)(bh)), \ ! "r" ((USItype)(al)), \ ! "rI" ((USItype)(bl))) #define umul_ppmm(xh, xl, m0, m1) \ do { \ ! USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("multiplu %0,%1,%2" \ ! : "=r" ((USItype)(xl)) \ : "r" (__m0), \ "r" (__m1)); \ __asm__ ("multmu %0,%1,%2" \ ! : "=r" ((USItype)(xh)) \ : "r" (__m0), \ "r" (__m1)); \ *************** *** 116,128 **** #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("dividu %0,%3,%4" \ ! : "=r" ((unsigned long int)(q)), \ ! "=q" ((unsigned long int)(r)) \ ! : "1" ((unsigned long int)(n1)), \ ! "r" ((unsigned long int)(n0)), \ ! "r" ((unsigned long int)(d))) #define count_leading_zeros(count, x) \ __asm__ ("clz %0,%1" \ ! : "=r" ((unsigned long int)(count)) \ ! : "r" ((unsigned long int)(x))) #endif /* __a29k__ */ --- 120,132 ---- #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("dividu %0,%3,%4" \ ! : "=r" ((USItype)(q)), \ ! "=q" ((USItype)(r)) \ ! : "1" ((USItype)(n1)), \ ! "r" ((USItype)(n0)), \ ! "r" ((USItype)(d))) #define count_leading_zeros(count, x) \ __asm__ ("clz %0,%1" \ ! : "=r" ((USItype)(count)) \ ! : "r" ((USItype)(x))) #endif /* __a29k__ */ *************** *** 131,149 **** __asm__ ("adds %1,%4,%5 adc %0,%2,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%r" ((unsigned long int)(ah)), \ ! "rI" ((unsigned long int)(bh)), \ ! "%r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subs %1,%4,%5 sbc %0,%2,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "r" ((unsigned long int)(ah)), \ ! "rI" ((unsigned long int)(bh)), \ ! "r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl))) #endif /* __arm__ */ --- 135,153 ---- __asm__ ("adds %1,%4,%5 adc %0,%2,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%r" ((USItype)(ah)), \ ! "rI" ((USItype)(bh)), \ ! "%r" ((USItype)(al)), \ ! "rI" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subs %1,%4,%5 sbc %0,%2,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "r" ((USItype)(ah)), \ ! "rI" ((USItype)(bh)), \ ! "r" ((USItype)(al)), \ ! "rI" ((USItype)(bl))) #endif /* __arm__ */ *************** *** 152,188 **** __asm__ ("add.w %5,%1 addx %3,%0" \ ! : "=g" ((unsigned long int)(sh)), \ ! "=&g" ((unsigned long int)(sl)) \ ! : "%0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "%1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub.w %5,%1 subx %3,%0" \ ! : "=g" ((unsigned long int)(sh)), \ ! "=&g" ((unsigned long int)(sl)) \ ! : "0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define umul_ppmm(ph, pl, m0, m1) \ __asm__ ("mulx %3,%0,%1" \ ! : "=g" ((unsigned long int)(ph)), \ ! "=r" ((unsigned long int)(pl)) \ ! : "%0" ((unsigned long int)(m0)), \ ! "g" ((unsigned long int)(m1))) #define udiv_qrnnd(q, r, nh, nl, d) \ __asm__ ("divx %4,%0,%1" \ ! : "=g" ((unsigned long int)(q)), \ ! "=r" ((unsigned long int)(r)) \ ! : "1" ((unsigned long int)(nh)), \ ! "0" ((unsigned long int)(nl)), \ ! "g" ((unsigned long int)(d))) #define count_leading_zeros(count, x) \ __asm__ ("bsch/1 %1,%0" \ : "=g" (count) \ ! : "g" ((unsigned long int)(x)), \ ! "0" (0UL)) #endif --- 156,192 ---- __asm__ ("add.w %5,%1 addx %3,%0" \ ! : "=g" ((USItype)(sh)), \ ! "=&g" ((USItype)(sl)) \ ! : "%0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "%1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub.w %5,%1 subx %3,%0" \ ! : "=g" ((USItype)(sh)), \ ! "=&g" ((USItype)(sl)) \ ! : "0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define umul_ppmm(ph, pl, m0, m1) \ __asm__ ("mulx %3,%0,%1" \ ! : "=g" ((USItype)(ph)), \ ! "=r" ((USItype)(pl)) \ ! : "%0" ((USItype)(m0)), \ ! "g" ((USItype)(m1))) #define udiv_qrnnd(q, r, nh, nl, d) \ __asm__ ("divx %4,%0,%1" \ ! : "=g" ((USItype)(q)), \ ! "=r" ((USItype)(r)) \ ! : "1" ((USItype)(nh)), \ ! "0" ((USItype)(nl)), \ ! "g" ((USItype)(d))) #define count_leading_zeros(count, x) \ __asm__ ("bsch/1 %1,%0" \ : "=g" (count) \ ! : "g" ((USItype)(x)), \ ! "0" ((USItype)0)) #endif *************** *** 191,209 **** __asm__ ("add %4,%5,%1 addc %2,%3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%rM" ((unsigned long int)(ah)), \ ! "rM" ((unsigned long int)(bh)), \ ! "%rM" ((unsigned long int)(al)), \ ! "rM" ((unsigned long int)(bl))) ! #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ ! __asm__ ("sub %5,%4,%1 ! subb %3,%2,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "rM" ((unsigned long int)(ah)), \ ! "rM" ((unsigned long int)(bh)), \ ! "rM" ((unsigned long int)(al)), \ ! "rM" ((unsigned long int)(bl))) #if defined (_PA_RISC1_1) #define umul_ppmm(w1, w0, u, v) \ --- 195,213 ---- __asm__ ("add %4,%5,%1 addc %2,%3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%rM" ((USItype)(ah)), \ ! "rM" ((USItype)(bh)), \ ! "%rM" ((USItype)(al)), \ ! "rM" ((USItype)(bl))) ! #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ ! __asm__ ("sub %4,%5,%1 ! subb %2,%3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "rM" ((USItype)(ah)), \ ! "rM" ((USItype)(bh)), \ ! "rM" ((USItype)(al)), \ ! "rM" ((USItype)(bl))) #if defined (_PA_RISC1_1) #define umul_ppmm(w1, w0, u, v) \ *************** *** 211,221 **** union \ { \ ! long long __f; \ ! struct {unsigned long int __w1, __w0;} __w1w0; \ } __t; \ __asm__ ("xmpyu %1,%2,%0" \ : "=x" (__t.__f) \ ! : "x" ((u)), \ ! "x" ((v))); \ (w1) = __t.__w1w0.__w1; \ (w0) = __t.__w1w0.__w0; \ --- 215,225 ---- union \ { \ ! UDItype __f; \ ! struct {USItype __w1, __w0;} __w1w0; \ } __t; \ __asm__ ("xmpyu %1,%2,%0" \ : "=x" (__t.__f) \ ! : "x" ((USItype)(u)), \ ! "x" ((USItype)(v))); \ (w1) = __t.__w1w0.__w1; \ (w0) = __t.__w1w0.__w0; \ *************** *** 232,268 **** __asm__ ("addl %5,%1 adcl %3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "%1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%1 sbbl %3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mull %3" \ ! : "=a" ((unsigned long int)(w0)), \ ! "=d" ((unsigned long int)(w1)) \ ! : "%0" ((unsigned long int)(u)), \ ! "rm" ((unsigned long int)(v))) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divl %4" \ ! : "=a" ((unsigned long int)(q)), \ ! "=d" ((unsigned long int)(r)) \ ! : "0" ((unsigned long int)(n0)), \ ! "1" ((unsigned long int)(n1)), \ ! "rm" ((unsigned long int)(d))) #define count_leading_zeros(count, x) \ do { \ ! unsigned long int __cbtmp; \ __asm__ ("bsrl %1,%0" \ ! : "=r" (__cbtmp) : "rm" ((unsigned long int)(x))); \ (count) = __cbtmp ^ 31; \ } while (0) --- 236,272 ---- __asm__ ("addl %5,%1 adcl %3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "%1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl %5,%1 sbbl %3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mull %3" \ ! : "=a" ((USItype)(w0)), \ ! "=d" ((USItype)(w1)) \ ! : "%0" ((USItype)(u)), \ ! "rm" ((USItype)(v))) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divl %4" \ ! : "=a" ((USItype)(q)), \ ! "=d" ((USItype)(r)) \ ! : "0" ((USItype)(n0)), \ ! "1" ((USItype)(n1)), \ ! "rm" ((USItype)(d))) #define count_leading_zeros(count, x) \ do { \ ! USItype __cbtmp; \ __asm__ ("bsrl %1,%0" \ ! : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ (count) = __cbtmp ^ 31; \ } while (0) *************** *** 279,291 **** union \ { \ ! long long int ll; \ ! struct {unsigned long int l, h;} i; \ } __a, __b, __s; \ ! __a.i.l = (al); __a.i.h = (ah); \ ! __b.i.l = (bl); __b.i.h = (bh); \ __asm__ ("fiadd.dd %1,%2,%0" \ ! : "=f" (__s.ll) \ ! : "%f" (__a.ll), "f" (__b.ll)); \ ! (sh) = __s.i.h; (sl) = __s.i.l; \ } while (0) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ --- 283,298 ---- union \ { \ ! DItype __ll; \ ! struct {USItype __l, __h;} __i; \ } __a, __b, __s; \ ! __a.__i.__l = (al); \ ! __a.__i.__h = (ah); \ ! __b.__i.__l = (bl); \ ! __b.__i.__h = (bh); \ __asm__ ("fiadd.dd %1,%2,%0" \ ! : "=f" (__s.__ll) \ ! : "%f" (__a.__ll), "f" (__b.__ll)); \ ! (sh) = __s.__i.__h; \ ! (sl) = __s.__i.__l; \ } while (0) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ *************** *** 293,305 **** union \ { \ ! long long int ll; \ ! struct {unsigned long int l, h;} i; \ } __a, __b, __s; \ ! __a.i.l = (al); __a.i.h = (ah); \ ! __b.i.l = (bl); __b.i.h = (bh); \ __asm__ ("fisub.dd %1,%2,%0" \ ! : "=f" (__s.ll) \ ! : "%f" (__a.ll), "f" (__b.ll)); \ ! (sh) = __s.i.h; (sl) = __s.i.l; \ } while (0) #endif --- 300,315 ---- union \ { \ ! DItype __ll; \ ! struct {USItype __l, __h;} __i; \ } __a, __b, __s; \ ! __a.__i.__l = (al); \ ! __a.__i.__h = (ah); \ ! __b.__i.__l = (bl); \ ! __b.__i.__h = (bh); \ __asm__ ("fisub.dd %1,%2,%0" \ ! : "=f" (__s.__ll) \ ! : "%f" (__a.__ll), "f" (__b.__ll)); \ ! (sh) = __s.__i.__h; \ ! (sl) = __s.__i.__l; \ } while (0) #endif *************** *** 310,356 **** __asm__ ("a%I5 %1,%4,%5 ae %0,%2,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%r" ((unsigned long int)(ah)), \ ! "r" ((unsigned long int)(bh)), \ ! "%r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sf%I4 %1,%5,%4 sfe %0,%3,%2" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "r" ((unsigned long int)(ah)), \ ! "r" ((unsigned long int)(bh)), \ ! "rI" ((unsigned long int)(al)), \ ! "r" ((unsigned long int)(bl))) #define umul_ppmm(xh, xl, m0, m1) \ do { \ ! unsigned long int __m0 = (m0), __m1 = (m1); \ __asm__ ("mul %0,%2,%3" \ ! : "=r" ((unsigned long int)(xh)), \ ! "=q" ((unsigned long int)(xl)) \ : "r" (__m0), \ "r" (__m1)); \ ! (xh) += ((((signed long int) __m0 >> 31) & __m1) \ ! + (((signed long int) __m1 >> 31) & __m0)); \ } while (0) #define smul_ppmm(xh, xl, m0, m1) \ __asm__ ("mul %0,%2,%3" \ ! : "=r" ((unsigned long int)(xh)), \ ! "=q" ((unsigned long int)(xl)) \ ! : "r" (m0), \ ! "r" (m1)) #define UMUL_TIME 8 #define sdiv_qrnnd(q, r, nh, nl, d) \ __asm__ ("div %0,%2,%4" \ ! : "=r" (q), "=q" (r) \ ! : "r" (nh), "1" (nl), "r" (d)) #define UDIV_TIME 40 #define UDIV_NEEDS_NORMALIZATION 1 #define count_leading_zeros(count, x) \ __asm__ ("cntlz %0,%1" \ ! : "=r" ((unsigned long int)(count)) \ ! : "r" ((unsigned long int)(x))) #endif /* ___IBMR2__ */ --- 320,366 ---- __asm__ ("a%I5 %1,%4,%5 ae %0,%2,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%r" ((USItype)(ah)), \ ! "r" ((USItype)(bh)), \ ! "%r" ((USItype)(al)), \ ! "rI" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sf%I4 %1,%5,%4 sfe %0,%3,%2" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "r" ((USItype)(ah)), \ ! "r" ((USItype)(bh)), \ ! "rI" ((USItype)(al)), \ ! "r" ((USItype)(bl))) #define umul_ppmm(xh, xl, m0, m1) \ do { \ ! USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("mul %0,%2,%3" \ ! : "=r" ((USItype)(xh)), \ ! "=q" ((USItype)(xl)) \ : "r" (__m0), \ "r" (__m1)); \ ! (xh) += ((((SItype) __m0 >> 31) & __m1) \ ! + (((SItype) __m1 >> 31) & __m0)); \ } while (0) #define smul_ppmm(xh, xl, m0, m1) \ __asm__ ("mul %0,%2,%3" \ ! : "=r" ((USItype)(xh)), \ ! "=q" ((USItype)(xl)) \ ! : "r" ((USItype)(m0)), \ ! "r" ((USItype)(m1))) #define UMUL_TIME 8 #define sdiv_qrnnd(q, r, nh, nl, d) \ __asm__ ("div %0,%2,%4" \ ! : "=r" ((USItype)(q)), "=q" ((USItype)(r)) \ ! : "r" ((USItype)(nh)), "1" ((USItype)(nl)), "r" ((USItype)(d))) #define UDIV_TIME 40 #define UDIV_NEEDS_NORMALIZATION 1 #define count_leading_zeros(count, x) \ __asm__ ("cntlz %0,%1" \ ! : "=r" ((USItype)(count)) \ ! : "r" ((USItype)(x))) #endif /* ___IBMR2__ */ *************** *** 359,404 **** __asm__ ("add%.l %5,%1 addx%.l %3,%0" \ ! : "=d" ((unsigned long int)(sh)), \ ! "=&d" ((unsigned long int)(sl)) \ ! : "%0" ((unsigned long int)(ah)), \ ! "d" ((unsigned long int)(bh)), \ ! "%1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub%.l %5,%1 subx%.l %3,%0" \ ! : "=d" ((unsigned long int)(sh)), \ ! "=&d" ((unsigned long int)(sl)) \ ! : "0" ((unsigned long int)(ah)), \ ! "d" ((unsigned long int)(bh)), \ ! "1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #if defined (__mc68020__) || defined (__NeXT__) || defined(mc68020) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mulu%.l %3,%1:%0" \ ! : "=d" ((unsigned long int)(w0)), \ ! "=d" ((unsigned long int)(w1)) \ ! : "%0" ((unsigned long int)(u)), \ ! "dmi" ((unsigned long int)(v))) #define UMUL_TIME 45 #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divu%.l %4,%1:%0" \ ! : "=d" ((unsigned long int)(q)), \ ! "=d" ((unsigned long int)(r)) \ ! : "0" ((unsigned long int)(n0)), \ ! "1" ((unsigned long int)(n1)), \ ! "dmi" ((unsigned long int)(d))) #define UDIV_TIME 90 #define sdiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divs%.l %4,%1:%0" \ ! : "=d" ((unsigned long int)(q)), \ ! "=d" ((unsigned long int)(r)) \ ! : "0" ((unsigned long int)(n0)), \ ! "1" ((unsigned long int)(n1)), \ ! "dmi" ((unsigned long int)(d))) #define count_leading_zeros(count, x) \ __asm__ ("bfffo %1{%b2:%b2},%0" \ ! : "=d" ((unsigned long int)(count)) \ ! : "od" ((unsigned long int)(x)), "n" (0)) #else /* not mc68020 */ #define umul_ppmm(xh, xl, a, b) \ --- 369,414 ---- __asm__ ("add%.l %5,%1 addx%.l %3,%0" \ ! : "=d" ((USItype)(sh)), \ ! "=&d" ((USItype)(sl)) \ ! : "%0" ((USItype)(ah)), \ ! "d" ((USItype)(bh)), \ ! "%1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub%.l %5,%1 subx%.l %3,%0" \ ! : "=d" ((USItype)(sh)), \ ! "=&d" ((USItype)(sl)) \ ! : "0" ((USItype)(ah)), \ ! "d" ((USItype)(bh)), \ ! "1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #if defined (__mc68020__) || defined (__NeXT__) || defined(mc68020) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mulu%.l %3,%1:%0" \ ! : "=d" ((USItype)(w0)), \ ! "=d" ((USItype)(w1)) \ ! : "%0" ((USItype)(u)), \ ! "dmi" ((USItype)(v))) #define UMUL_TIME 45 #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divu%.l %4,%1:%0" \ ! : "=d" ((USItype)(q)), \ ! "=d" ((USItype)(r)) \ ! : "0" ((USItype)(n0)), \ ! "1" ((USItype)(n1)), \ ! "dmi" ((USItype)(d))) #define UDIV_TIME 90 #define sdiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("divs%.l %4,%1:%0" \ ! : "=d" ((USItype)(q)), \ ! "=d" ((USItype)(r)) \ ! : "0" ((USItype)(n0)), \ ! "1" ((USItype)(n1)), \ ! "dmi" ((USItype)(d))) #define count_leading_zeros(count, x) \ __asm__ ("bfffo %1{%b2:%b2},%0" \ ! : "=d" ((USItype)(count)) \ ! : "od" ((USItype)(x)), "n" (0)) #else /* not mc68020 */ #define umul_ppmm(xh, xl, a, b) \ *************** *** 429,436 **** addl d1,d0 movel d0,%0" \ ! : "=g" ((unsigned long int)(xh)), \ ! "=g" ((unsigned long int)(xl)) \ ! : "g" ((unsigned long int)(a)), \ ! "g" ((unsigned long int)(b)) \ : "d0", "d1", "d2", "d3", "d4") #define UMUL_TIME 100 --- 439,446 ---- addl d1,d0 movel d0,%0" \ ! : "=g" ((USItype)(xh)), \ ! "=g" ((USItype)(xl)) \ ! : "g" ((USItype)(a)), \ ! "g" ((USItype)(b)) \ : "d0", "d1", "d2", "d3", "d4") #define UMUL_TIME 100 *************** *** 443,469 **** __asm__ ("addu.co %1,%r4,%r5 addu.ci %0,%r2,%r3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%rJ" ((unsigned long int)(ah)), \ ! "rJ" ((unsigned long int)(bh)), \ ! "%rJ" ((unsigned long int)(al)), \ ! "rJ" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subu.co %1,%r4,%r5 subu.ci %0,%r2,%r3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "rJ" ((unsigned long int)(ah)), \ ! "rJ" ((unsigned long int)(bh)), \ ! "rJ" ((unsigned long int)(al)), \ ! "rJ" ((unsigned long int)(bl))) #define UMUL_TIME 17 #define UDIV_TIME 150 #define count_leading_zeros(count, x) \ do { \ ! unsigned long int __cbtmp; \ __asm__ ("ff1 %0,%1" \ : "=r" (__cbtmp) \ ! : "r" ((unsigned long int)(x))); \ (count) = __cbtmp ^ 31; \ } while (0) --- 453,479 ---- __asm__ ("addu.co %1,%r4,%r5 addu.ci %0,%r2,%r3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%rJ" ((USItype)(ah)), \ ! "rJ" ((USItype)(bh)), \ ! "%rJ" ((USItype)(al)), \ ! "rJ" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subu.co %1,%r4,%r5 subu.ci %0,%r2,%r3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "rJ" ((USItype)(ah)), \ ! "rJ" ((USItype)(bh)), \ ! "rJ" ((USItype)(al)), \ ! "rJ" ((USItype)(bl))) #define UMUL_TIME 17 #define UDIV_TIME 150 #define count_leading_zeros(count, x) \ do { \ ! USItype __cbtmp; \ __asm__ ("ff1 %0,%1" \ : "=r" (__cbtmp) \ ! : "r" ((USItype)(x))); \ (count) = __cbtmp ^ 31; \ } while (0) *************** *** 475,480 **** : "=r" (w1), \ "=r" (w0) \ ! : "r" (u), \ ! "r" (v) \ : "r10", "r11") #define udiv_qrnnd(q, r, n1, n0, d) \ --- 485,490 ---- : "=r" (w1), \ "=r" (w0) \ ! : "r" ((USItype)(u)), \ ! "r" ((USItype)(v)) \ : "r10", "r11") #define udiv_qrnnd(q, r, n1, n0, d) \ *************** *** 487,493 **** : "=r" (q), \ "=&r" (r) \ ! : "r" (n1), \ ! "r" (n0), \ ! "r" (d) \ : "r10", "r11") #endif --- 497,503 ---- : "=r" (q), \ "=&r" (r) \ ! : "r" ((USItype)(n1)), \ ! "r" ((USItype)(n0)), \ ! "r" ((USItype)(d)) \ : "r10", "r11") #endif *************** *** 499,506 **** mflo %0 mfhi %1" \ ! : "=d" ((unsigned long int)(w0)), \ ! "=d" ((unsigned long int)(w1)) \ ! : "d" ((unsigned long int)(u)), \ ! "d" ((unsigned long int)(v))) #define UMUL_TIME 5 #define UDIV_TIME 100 --- 509,516 ---- mflo %0 mfhi %1" \ ! : "=d" ((USItype)(w0)), \ ! "=d" ((USItype)(w1)) \ ! : "d" ((USItype)(u)), \ ! "d" ((USItype)(v))) #define UMUL_TIME 5 #define UDIV_TIME 100 *************** *** 509,517 **** #if defined (__ns32000__) #define __umulsidi3(u, v) \ ! ({long long int __w; \ __asm__ ("meid %2,%0" \ : "=g" (__w) \ ! : "%0" ((unsigned long int)(u)), \ ! "g" ((unsigned long int)(v))); \ __w; }) #define div_qrnnd(q, r, n1, n0, d) \ --- 519,527 ---- #if defined (__ns32000__) #define __umulsidi3(u, v) \ ! ({UDItype __w; \ __asm__ ("meid %2,%0" \ : "=g" (__w) \ ! : "%0" ((USItype)(u)), \ ! "g" ((USItype)(v))); \ __w; }) #define div_qrnnd(q, r, n1, n0, d) \ *************** *** 521,529 **** movd r1,%0 movd r0,%1" \ ! : "=g" ((unsigned long int)(q)), \ ! "=g" ((unsigned long int)(r)) \ ! : "g" ((unsigned long int)(n0)), \ ! "g" ((unsigned long int)(n1)), \ ! "g" ((unsigned long int)(d)) \ : "r0", "r1") #endif /* __ns32000__ */ --- 531,539 ---- movd r1,%0 movd r0,%1" \ ! : "=g" ((USItype)(q)), \ ! "=g" ((USItype)(r)) \ ! : "g" ((USItype)(n0)), \ ! "g" ((USItype)(n1)), \ ! "g" ((USItype)(d)) \ : "r0", "r1") #endif /* __ns32000__ */ *************** *** 533,561 **** __asm__ ("addw %5,%1 addwc %3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "%1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subw %5,%1 subwb %3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) /* This insn doesn't work on ancient pyramids. */ #define umul_ppmm(w1, w0, u, v) \ ! ({union {long long int ll;struct {unsigned long int h, l;} i;} __xx; \ ! __xx.i.l = u; \ __asm__ ("uemul %3,%0" \ ! : "=r" (__xx.i.h), \ ! "=r" (__xx.i.l) \ ! : "1" (__xx.i.l), \ ! "g" (v)); \ ! (w1) = __xx.i.h; (w0) = __xx.i.l;}) #endif /* __pyr__ */ --- 543,575 ---- __asm__ ("addw %5,%1 addwc %3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "%1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subw %5,%1 subwb %3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) /* This insn doesn't work on ancient pyramids. */ #define umul_ppmm(w1, w0, u, v) \ ! ({union { \ ! UDItype __ll; \ ! struct {USItype __h, __l;} __i; \ ! } __xx; \ ! __xx.__i.__l = u; \ __asm__ ("uemul %3,%0" \ ! : "=r" (__xx.__i.__h), \ ! "=r" (__xx.__i.__l) \ ! : "1" (__xx.__i.__l), \ ! "g" ((UDItype)(v))); \ ! (w1) = __xx.__i.__h; \ ! (w0) = __xx.__i.__l;}) #endif /* __pyr__ */ *************** *** 564,585 **** __asm__ ("a %1,%5 ae %0,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%0" ((unsigned long int)(ah)), \ ! "r" ((unsigned long int)(bh)), \ ! "%1" ((unsigned long int)(al)), \ ! "r" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("s %1,%5 se %0,%3" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "0" ((unsigned long int)(ah)), \ ! "r" ((unsigned long int)(bh)), \ ! "1" ((unsigned long int)(al)), \ ! "r" ((unsigned long int)(bl))) #define umul_ppmm(ph, pl, m0, m1) \ do { \ ! unsigned long int __m0 = (m0), __m1 = (m1); \ __asm__ ( \ "s r2,r2 --- 578,599 ---- __asm__ ("a %1,%5 ae %0,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%0" ((USItype)(ah)), \ ! "r" ((USItype)(bh)), \ ! "%1" ((USItype)(al)), \ ! "r" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("s %1,%5 se %0,%3" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "0" ((USItype)(ah)), \ ! "r" ((USItype)(bh)), \ ! "1" ((USItype)(al)), \ ! "r" ((USItype)(bl))) #define umul_ppmm(ph, pl, m0, m1) \ do { \ ! USItype __m0 = (m0), __m1 = (m1); \ __asm__ ( \ "s r2,r2 *************** *** 603,613 **** cas %0,r2,r0 mfs r10,%1" \ ! : "=r" ((unsigned long int)(ph)), \ ! "=r" ((unsigned long int)(pl)) \ : "%r" (__m0), \ "r" (__m1) \ : "r2"); \ ! (ph) += ((((signed long int) __m0 >> 31) & __m1) \ ! + (((signed long int) __m1 >> 31) & __m0)); \ } while (0) #define UMUL_TIME 20 --- 617,627 ---- cas %0,r2,r0 mfs r10,%1" \ ! : "=r" ((USItype)(ph)), \ ! "=r" ((USItype)(pl)) \ : "%r" (__m0), \ "r" (__m1) \ : "r2"); \ ! (ph) += ((((SItype) __m0 >> 31) & __m1) \ ! + (((SItype) __m1 >> 31) & __m0)); \ } while (0) #define UMUL_TIME 20 *************** *** 617,627 **** if ((x) >= 0x10000) \ __asm__ ("clz %0,%1" \ ! : "=r" ((unsigned long int)(count)) \ ! : "r" ((unsigned long int)(x) >> 16)); \ else \ { \ __asm__ ("clz %0,%1" \ ! : "=r" ((unsigned long int)(count)) \ ! : "r" ((unsigned long int)(x))); \ (count) += 16; \ } \ --- 631,641 ---- if ((x) >= 0x10000) \ __asm__ ("clz %0,%1" \ ! : "=r" ((USItype)(count)) \ ! : "r" ((USItype)(x) >> 16)); \ else \ { \ __asm__ ("clz %0,%1" \ ! : "=r" ((USItype)(count)) \ ! : "r" ((USItype)(x))); \ (count) += 16; \ } \ *************** *** 633,667 **** __asm__ ("addcc %4,%5,%1 addx %2,%3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "%r" ((unsigned long int)(ah)), \ ! "rI" ((unsigned long int)(bh)), \ ! "%r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl)) \ __CLOBBER_CC) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subcc %4,%5,%1 subx %2,%3,%0" \ ! : "=r" ((unsigned long int)(sh)), \ ! "=&r" ((unsigned long int)(sl)) \ ! : "r" ((unsigned long int)(ah)), \ ! "rI" ((unsigned long int)(bh)), \ ! "r" ((unsigned long int)(al)), \ ! "rI" ((unsigned long int)(bl)) \ __CLOBBER_CC) ! #if defined (__sparcv8__) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("umul %2,%3,%1;rd %%y,%0" \ ! : "=r" ((unsigned long int)(w1)), \ ! "=r" ((unsigned long int)(w0)) \ ! : "r" ((unsigned long int)(u)), \ ! "r" ((unsigned long int)(v))) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ ! : "=&r" ((unsigned long int)(q)), \ ! "=&r" ((unsigned long int)(r)) \ ! : "r" ((unsigned long int)(n1)), \ ! "r" ((unsigned long int)(n0)), \ ! "r" ((unsigned long int)(d))) #else /* SPARC without integer multiplication and divide instructions. --- 647,742 ---- __asm__ ("addcc %4,%5,%1 addx %2,%3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "%r" ((USItype)(ah)), \ ! "rI" ((USItype)(bh)), \ ! "%r" ((USItype)(al)), \ ! "rI" ((USItype)(bl)) \ __CLOBBER_CC) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subcc %4,%5,%1 subx %2,%3,%0" \ ! : "=r" ((USItype)(sh)), \ ! "=&r" ((USItype)(sl)) \ ! : "r" ((USItype)(ah)), \ ! "rI" ((USItype)(bh)), \ ! "r" ((USItype)(al)), \ ! "rI" ((USItype)(bl)) \ __CLOBBER_CC) ! #if defined (__sparc_v8__) #define umul_ppmm(w1, w0, u, v) \ __asm__ ("umul %2,%3,%1;rd %%y,%0" \ ! : "=r" ((USItype)(w1)), \ ! "=r" ((USItype)(w0)) \ ! : "r" ((USItype)(u)), \ ! "r" ((USItype)(v))) #define udiv_qrnnd(q, r, n1, n0, d) \ __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ ! : "=&r" ((USItype)(q)), \ ! "=&r" ((USItype)(r)) \ ! : "r" ((USItype)(n1)), \ ! "r" ((USItype)(n0)), \ ! "r" ((USItype)(d))) ! #else ! #if defined (__sparclite__) ! /* This has hardware multiply but not divide. It also has two additional ! instructions scan (ffs from high bit) and divscc. */ ! #define umul_ppmm(w1, w0, u, v) \ ! __asm__ ("umul %2,%3,%1;rd %%y,%0" \ ! : "=r" ((USItype)(w1)), \ ! "=r" ((USItype)(w0)) \ ! : "r" ((USItype)(u)), \ ! "r" ((USItype)(v))) ! #define udiv_qrnnd(q, r, n1, n0, d) \ ! __asm__ ("! Inlined udiv_qrnnd ! wr %%g0,%2,%%y ! Not a delayed write for sparclite ! tst %%g0 ! divscc %3,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%%g1 ! divscc %%g1,%4,%0 ! rd %%y,%1 ! bl,a 1f ! add %1,%4,%1 ! 1: ! End of inline udiv_qrnnd" \ ! : "=r" ((USItype)(q)), \ ! "=r" ((USItype)(r)) \ ! : "r" ((USItype)(n1)), \ ! "r" ((USItype)(n0)), \ ! "rI" ((USItype)(d)) \ ! : "%g1" __AND_CLOBBER_CC) ! #define UDIV_TIME 37 ! #define count_leading_zeros(count, x) \ ! __asm__ ("scan %1,0,%0" \ ! : "=r" ((USItype)(x)) \ ! : "r" ((USItype)(count))) #else /* SPARC without integer multiplication and divide instructions. *************** *** 708,715 **** add %%g1,%%g2,%0 rd %%y,%1" \ ! : "=r" ((unsigned long int)(w1)), \ ! "=r" ((unsigned long int)(w0)) \ ! : "%rI" ((unsigned long int)(u)), \ ! "r" ((unsigned long int)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) #define UMUL_TIME 39 /* 39 instructions */ --- 783,790 ---- add %%g1,%%g2,%0 rd %%y,%1" \ ! : "=r" ((USItype)(w1)), \ ! "=r" ((USItype)(w0)) \ ! : "%rI" ((USItype)(u)), \ ! "r" ((USItype)(v)) \ : "%g1", "%g2" __AND_CLOBBER_CC) #define UMUL_TIME 39 /* 39 instructions */ *************** *** 741,751 **** 3: xnor %0,0,%0 ! End of inline udiv_qrnnd" \ ! : "=&r" ((unsigned long int)(q)), \ ! "=&r" ((unsigned long int)(r)) \ ! : "r" ((unsigned long int)(d)), \ ! "1" ((unsigned long int)(n1)), \ ! "0" ((unsigned long int)(n0)) : "%g1" __AND_CLOBBER_CC) #define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ ! #endif /* __sparc8__ */ #endif /* __sparc__ */ --- 816,827 ---- 3: xnor %0,0,%0 ! End of inline udiv_qrnnd" \ ! : "=&r" ((USItype)(q)), \ ! "=&r" ((USItype)(r)) \ ! : "r" ((USItype)(d)), \ ! "1" ((USItype)(n1)), \ ! "0" ((USItype)(n0)) : "%g1" __AND_CLOBBER_CC) #define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ ! #endif /* __sparclite__ */ ! #endif /* __sparc_v8__ */ #endif /* __sparc__ */ *************** *** 754,783 **** __asm__ ("addl2 %5,%1 adwc %3,%0" \ ! : "=g" ((unsigned long int)(sh)), \ ! "=&g" ((unsigned long int)(sl)) \ ! : "%0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "%1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl2 %5,%1 sbwc %3,%0" \ ! : "=g" ((unsigned long int)(sh)), \ ! "=&g" ((unsigned long int)(sl)) \ ! : "0" ((unsigned long int)(ah)), \ ! "g" ((unsigned long int)(bh)), \ ! "1" ((unsigned long int)(al)), \ ! "g" ((unsigned long int)(bl))) #define umul_ppmm(xh, xl, m0, m1) \ do { \ ! union {long long int ll;struct {unsigned long int l, h;} i;} __xx; \ ! unsigned long int __m0 = (m0), __m1 = (m1); \ __asm__ ("emul %1,%2,$0,%0" \ ! : "=r" (__xx.ll) \ : "g" (__m0), \ "g" (__m1)); \ ! (xh) = __xx.i.h; (xl) = __xx.i.l; \ ! (xh) += ((((signed long int) __m0 >> 31) & __m1) \ ! + (((signed long int) __m1 >> 31) & __m0)); \ } while (0) #endif /* __vax__ */ --- 830,863 ---- __asm__ ("addl2 %5,%1 adwc %3,%0" \ ! : "=g" ((USItype)(sh)), \ ! "=&g" ((USItype)(sl)) \ ! : "%0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "%1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subl2 %5,%1 sbwc %3,%0" \ ! : "=g" ((USItype)(sh)), \ ! "=&g" ((USItype)(sl)) \ ! : "0" ((USItype)(ah)), \ ! "g" ((USItype)(bh)), \ ! "1" ((USItype)(al)), \ ! "g" ((USItype)(bl))) #define umul_ppmm(xh, xl, m0, m1) \ do { \ ! union { \ ! UDItype __ll; \ ! struct {USItype __l, __h;} __i; \ ! } __xx; \ ! USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("emul %1,%2,$0,%0" \ ! : "=r" (__xx.__ll) \ : "g" (__m0), \ "g" (__m1)); \ ! (xh) = __xx.__i.__h; \ ! (xl) = __xx.__i.__l; \ ! (xh) += ((((SItype) __m0 >> 31) & __m1) \ ! + (((SItype) __m1 >> 31) & __m0)); \ } while (0) #endif /* __vax__ */ *************** *** 790,794 **** #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ do { \ ! unsigned long int __x; \ __x = (al) + (bl); \ (sh) = (ah) + (bh) + (__x < (al)); \ --- 870,874 ---- #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ do { \ ! USItype __x; \ __x = (al) + (bl); \ (sh) = (ah) + (bh) + (__x < (al)); \ *************** *** 800,804 **** #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ ! unsigned long int __x; \ __x = (al) - (bl); \ (sh) = (ah) - (bh) - (__x > (al)); \ --- 880,884 ---- #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ do { \ ! USItype __x; \ __x = (al) - (bl); \ (sh) = (ah) - (bh) - (__x > (al)); \ *************** *** 810,815 **** #define umul_ppmm(w1, w0, u, v) \ do { \ ! unsigned long int __x0, __x1, __x2, __x3; \ ! unsigned int __ul, __vl, __uh, __vh; \ \ __ul = __ll_lowpart (u); \ --- 890,895 ---- #define umul_ppmm(w1, w0, u, v) \ do { \ ! USItype __x0, __x1, __x2, __x3; \ ! USItype __ul, __vl, __uh, __vh; \ \ __ul = __ll_lowpart (u); \ *************** *** 818,825 **** __vh = __ll_highpart (v); \ \ ! __x0 = (unsigned long int) __ul * __vl; \ ! __x1 = (unsigned long int) __ul * __vh; \ ! __x2 = (unsigned long int) __uh * __vl; \ ! __x3 = (unsigned long int) __uh * __vh; \ \ __x1 += __ll_highpart (__x0);/* this can't give carry */ \ --- 898,905 ---- __vh = __ll_highpart (v); \ \ ! __x0 = (USItype) __ul * __vl; \ ! __x1 = (USItype) __ul * __vh; \ ! __x2 = (USItype) __uh * __vl; \ ! __x3 = (USItype) __uh * __vh; \ \ __x1 += __ll_highpart (__x0);/* this can't give carry */ \ *************** *** 835,839 **** #if !defined (__umulsidi3) #define __umulsidi3(u, v) \ ! ({long_long __w; \ umul_ppmm (__w.s.high, __w.s.low, u, v); \ __w.ll; }) --- 915,919 ---- #if !defined (__umulsidi3) #define __umulsidi3(u, v) \ ! ({DIunion __w; \ umul_ppmm (__w.s.high, __w.s.low, u, v); \ __w.ll; }) *************** *** 843,848 **** #define __udiv_qrnnd_c(q, r, n1, n0, d) \ do { \ ! unsigned int __d1, __d0, __q1, __q0; \ ! unsigned long int __r1, __r0, __m; \ __d1 = __ll_highpart (d); \ __d0 = __ll_lowpart (d); \ --- 923,928 ---- #define __udiv_qrnnd_c(q, r, n1, n0, d) \ do { \ ! USItype __d1, __d0, __q1, __q0; \ ! USItype __r1, __r0, __m; \ __d1 = __ll_highpart (d); \ __d0 = __ll_lowpart (d); \ *************** *** 850,854 **** __r1 = (n1) % __d1; \ __q1 = (n1) / __d1; \ ! __m = (unsigned long int) __q1 * __d0; \ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ if (__r1 < __m) \ --- 930,934 ---- __r1 = (n1) % __d1; \ __q1 = (n1) / __d1; \ ! __m = (USItype) __q1 * __d0; \ __r1 = __r1 * __ll_B | __ll_highpart (n0); \ if (__r1 < __m) \ *************** *** 863,867 **** __r0 = __r1 % __d1; \ __q0 = __r1 / __d1; \ ! __m = (unsigned long int) __q0 * __d0; \ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ if (__r0 < __m) \ --- 943,947 ---- __r0 = __r1 % __d1; \ __q0 = __r1 / __d1; \ ! __m = (USItype) __q0 * __d0; \ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ if (__r0 < __m) \ *************** *** 874,880 **** __r0 -= __m; \ \ ! (q) = (unsigned long int) __q1 * __ll_B | __q0; \ (r) = __r0; \ } while (0) /* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ #if !defined (udiv_qrnnd) --- 954,972 ---- __r0 -= __m; \ \ ! (q) = (USItype) __q1 * __ll_B | __q0; \ (r) = __r0; \ } while (0) + + /* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ + #if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) + #define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) + #endif + /* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ #if !defined (udiv_qrnnd) *************** *** 884,894 **** #if !defined (count_leading_zeros) ! extern const unsigned char __clz_tab[]; #define count_leading_zeros(count, x) \ do { \ ! unsigned long int __xr = (x); \ ! unsigned int __a; \ \ ! if (LONG_TYPE_SIZE <= 32) \ { \ __a = __xr < (1<<2*__BITS4) \ --- 976,986 ---- #if !defined (count_leading_zeros) ! extern const UQItype __clz_tab[]; #define count_leading_zeros(count, x) \ do { \ ! USItype __xr = (x); \ ! USItype __a; \ \ ! if (SI_TYPE_SIZE <= 32) \ { \ __a = __xr < (1<<2*__BITS4) \ *************** *** 898,907 **** else \ { \ ! for (__a = LONG_TYPE_SIZE - 8; __a > 0; __a -= 8) \ if (((__xr >> __a) & 0xff) != 0) \ break; \ } \ \ ! (count) = LONG_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ } while (0) #endif --- 990,999 ---- else \ { \ ! for (__a = SI_TYPE_SIZE - 8; __a > 0; __a -= 8) \ if (((__xr >> __a) & 0xff) != 0) \ break; \ } \ \ ! (count) = SI_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ } while (0) #endif diff -rc2N gcc-2.2.2/loop.c gcc-2.3.1/loop.c *** gcc-2.2.2/loop.c Tue May 26 04:59:15 1992 --- gcc-2.3.1/loop.c Fri Oct 23 02:01:59 1992 *************** *** 1,4 **** /* Move constant computations out of loops. ! Copyright (C) 1987, 1988, 1989, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Move constant computations out of loops. ! Copyright (C) 1987, 1988, 1989, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 34,37 **** --- 34,38 ---- while to do these things. */ + #include #include "config.h" #include "rtl.h" *************** *** 45,49 **** #include "flags.h" #include "real.h" - #include #include "loop.h" --- 46,49 ---- *************** *** 98,107 **** /* Holds the number of loop iterations. It is zero if the number could not be ! calculated. Must be unsigned long since the number of iterations can ! be as high as 2^31-1. For loops with a DImode iterator, this number will ! will be zero if the number of loop iterations is too large for an ! unsigned long to hold. */ ! unsigned long loop_n_iterations; /* Nonzero if there is a subroutine call in the current loop. --- 98,107 ---- /* Holds the number of loop iterations. It is zero if the number could not be ! calculated. Must be unsigned since the number of iterations can ! be as high as 2^wordsize-1. For loops with a wider iterator, this number ! will will be zero if the number of loop iterations is too large for an ! unsigned integer to hold. */ ! unsigned HOST_WIDE_INT loop_n_iterations; /* Nonzero if there is a subroutine call in the current loop. *************** *** 194,199 **** extern char *oballoc (); - extern int xmalloc (); - extern void free (); /* During the analysis of a loop, a chain of `struct movable's --- 194,197 ---- *************** *** 300,318 **** { char *free_point = (char *) oballoc (1); ! rtx reg = gen_rtx (REG, SImode, 0); ! rtx pow2 = gen_rtx (CONST_INT, VOIDmode, 32); rtx lea; int i; ! add_cost = rtx_cost (gen_rtx (PLUS, SImode, reg, reg), SET); /* We multiply by 2 to reconcile the difference in scale between these two ways of computing costs. Otherwise the cost of a copy will be far less than the cost of an add. */ ! #ifdef REGISTER_MOVE_COST ! copy_cost = REGISTER_MOVE_COST (GENERAL_REGS, GENERAL_REGS) * 2; ! #else copy_cost = 2 * 2; - #endif /* Free the objects we just allocated. */ --- 298,313 ---- { char *free_point = (char *) oballoc (1); ! rtx reg = gen_rtx (REG, word_mode, 0); ! rtx pow2 = GEN_INT (32); rtx lea; int i; ! add_cost = rtx_cost (gen_rtx (PLUS, word_mode, reg, reg), SET); /* We multiply by 2 to reconcile the difference in scale between these two ways of computing costs. Otherwise the cost of a copy will be far less than the cost of an add. */ ! copy_cost = 2 * 2; /* Free the objects we just allocated. */ *************** *** 367,371 **** /* Get size to use for tables indexed by uids. Leave some space for labels allocated by find_and_verify_loops. */ ! max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 4; uid_luid = (int *) alloca (max_uid_for_loop * sizeof (int)); --- 362,366 ---- /* Get size to use for tables indexed by uids. Leave some space for labels allocated by find_and_verify_loops. */ ! max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 32; uid_luid = (int *) alloca (max_uid_for_loop * sizeof (int)); *************** *** 383,397 **** loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx)); - if (flag_unroll_loops && write_symbols != NO_DEBUG) - { - loop_number_first_block - = (union tree_node **) alloca (max_loop_num - * sizeof (union tree_node *)); - loop_number_last_block - = (union tree_node **) alloca (max_loop_num - * sizeof (union tree_node *)); - loop_number_block_level = (int *) alloca (max_loop_num * sizeof (int)); - } - /* Find and process each loop. First, find them, and record them in order of their beginnings. */ --- 378,381 ---- *************** *** 403,406 **** --- 387,394 ---- reg_scan (f, max_reg_num (), 1); + /* See if we went too far. */ + if (get_max_uid () > max_uid_for_loop) + abort (); + /* Compute the mapping from uids to luids. LUIDs are numbers assigned to insns, like uids, *************** *** 439,443 **** /* Create a mapping from loops to BLOCK tree nodes. */ if (flag_unroll_loops && write_symbols != NO_DEBUG) ! find_loop_tree_blocks (f); /* Now scan the loops, last ones first, since this means inner ones are done --- 427,431 ---- /* Create a mapping from loops to BLOCK tree nodes. */ if (flag_unroll_loops && write_symbols != NO_DEBUG) ! find_loop_tree_blocks (); /* Now scan the loops, last ones first, since this means inner ones are done *************** *** 447,450 **** --- 435,444 ---- scan_loop (loop_number_loop_starts[i], loop_number_loop_ends[i], max_reg_num ()); + + /* If debugging and unrolling loops, we must replicate the tree nodes + corresponding to the blocks inside the loop, so that the original one + to one mapping will remain. */ + if (flag_unroll_loops && write_symbols != NO_DEBUG) + unroll_block_trees (); } *************** *** 640,647 **** if (GET_RTX_CLASS (GET_CODE (p)) == 'i' ! && find_reg_note (p, REG_LIBCALL, 0)) in_libcall = 1; else if (GET_RTX_CLASS (GET_CODE (p)) == 'i' ! && find_reg_note (p, REG_RETVAL, 0)) in_libcall = 0; --- 634,641 ---- if (GET_RTX_CLASS (GET_CODE (p)) == 'i' ! && find_reg_note (p, REG_LIBCALL, NULL_RTX)) in_libcall = 1; else if (GET_RTX_CLASS (GET_CODE (p)) == 'i' ! && find_reg_note (p, REG_RETVAL, NULL_RTX)) in_libcall = 0; *************** *** 665,677 **** Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note is present. */ ! temp = find_reg_note (p, REG_EQUIV, 0); if (temp) src = XEXP (temp, 0), move_insn = 1; else { ! temp = find_reg_note (p, REG_EQUAL, 0); if (temp && CONSTANT_P (XEXP (temp, 0))) src = XEXP (temp, 0), move_insn = 1; ! if (temp && find_reg_note (p, REG_RETVAL, 0)) { src = XEXP (temp, 0); --- 659,671 ---- Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note is present. */ ! temp = find_reg_note (p, REG_EQUIV, NULL_RTX); if (temp) src = XEXP (temp, 0), move_insn = 1; else { ! temp = find_reg_note (p, REG_EQUAL, NULL_RTX); if (temp && CONSTANT_P (XEXP (temp, 0))) src = XEXP (temp, 0), move_insn = 1; ! if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX)) { src = XEXP (temp, 0); *************** *** 739,743 **** && n_times_set[REGNO (SET_DEST (set))] == 1 && ! side_effects_p (SET_SRC (set)) ! && ! find_reg_note (p, REG_RETVAL, 0) #ifdef SMALL_REGISTER_CLASSES && ! (GET_CODE (SET_SRC (set)) == REG --- 733,737 ---- && n_times_set[REGNO (SET_DEST (set))] == 1 && ! side_effects_p (SET_SRC (set)) ! && ! find_reg_note (p, REG_RETVAL, NULL_RTX) #ifdef SMALL_REGISTER_CLASSES && ! (GET_CODE (SET_SRC (set)) == REG *************** *** 776,780 **** m->partial = 0; m->move_insn = move_insn; ! m->is_equiv = (find_reg_note (p, REG_EQUIV, 0) != 0); m->savemode = VOIDmode; m->regno = regno; --- 770,774 ---- m->partial = 0; m->move_insn = move_insn; ! m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); m->savemode = VOIDmode; m->regno = regno; *************** *** 788,792 **** - uid_luid[regno_first_uid[regno]]); m->savings = n_times_used[regno]; ! if (find_reg_note (p, REG_RETVAL, 0)) m->savings += libcall_benefit (p); n_times_set[regno] = move_insn ? -2 : -1; --- 782,786 ---- - uid_luid[regno_first_uid[regno]]); m->savings = n_times_used[regno]; ! if (find_reg_note (p, REG_RETVAL, NULL_RTX)) m->savings += libcall_benefit (p); n_times_set[regno] = move_insn ? -2 : -1; *************** *** 810,819 **** m->set_src to correspond to the effects of all the insns. */ ! temp = find_reg_note (p, REG_EQUIV, 0); if (temp) m->set_src = XEXP (temp, 0), m->move_insn = 1; else { ! temp = find_reg_note (p, REG_EQUAL, 0); if (temp && CONSTANT_P (XEXP (temp, 0))) m->set_src = XEXP (temp, 0), m->move_insn = 1; --- 804,813 ---- m->set_src to correspond to the effects of all the insns. */ ! temp = find_reg_note (p, REG_EQUIV, NULL_RTX); if (temp) m->set_src = XEXP (temp, 0), m->move_insn = 1; else { ! temp = find_reg_note (p, REG_EQUAL, NULL_RTX); if (temp && CONSTANT_P (XEXP (temp, 0))) m->set_src = XEXP (temp, 0), m->move_insn = 1; *************** *** 822,826 **** } ! m->is_equiv = (find_reg_note (p, REG_EQUIV, 0) != 0); } } --- 816,820 ---- } ! m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0); } } *************** *** 1028,1032 **** rtx insn, equiv; { ! rtx note = find_reg_note (insn, REG_RETVAL, 0); rtx p = XEXP (note, 0); rtx output = 0; --- 1022,1026 ---- rtx insn, equiv; { ! rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX); rtx p = XEXP (note, 0); rtx output = 0; *************** *** 1103,1107 **** int benefit = 0; ! for (insn = XEXP (find_reg_note (last, REG_RETVAL, 0), 0); insn != last; insn = NEXT_INSN (insn)) { --- 1097,1101 ---- int benefit = 0; ! for (insn = XEXP (find_reg_note (last, REG_RETVAL, NULL_RTX), 0); insn != last; insn = NEXT_INSN (insn)) { *************** *** 1133,1137 **** be an insn here. */ if (GET_CODE (insn) != NOTE ! && (temp = find_reg_note (insn, REG_LIBCALL, 0))) insn = XEXP (temp, 0); --- 1127,1131 ---- be an insn here. */ if (GET_CODE (insn) != NOTE ! && (temp = find_reg_note (insn, REG_LIBCALL, NULL_RTX))) insn = XEXP (temp, 0); *************** *** 1157,1161 **** { /* Is this a movable for the value of a libcall? */ ! rtx note = find_reg_note (m->insn, REG_RETVAL, 0); if (note) { --- 1151,1155 ---- { /* Is this a movable for the value of a libcall? */ ! rtx note = find_reg_note (m->insn, REG_RETVAL, NULL_RTX); if (note) { *************** *** 1421,1424 **** --- 1415,1423 ---- switch (fmt[i]) { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + case 'i': if (XINT (x, i) != XINT (y, i)) *************** *** 1477,1481 **** rtx insn; ! if (code == LABEL_REF) { for (insn = insns; insn; insn = NEXT_INSN (insn)) --- 1476,1480 ---- rtx insn; ! if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x)) { for (insn = insns; insn; insn = NEXT_INSN (insn)) *************** *** 1655,1659 **** skip to the end. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_LIBCALL, 0))) p = XEXP (temp, 0); --- 1654,1658 ---- skip to the end. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) p = XEXP (temp, 0); *************** *** 1662,1666 **** The last insn is handled in the normal manner. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_RETVAL, 0))) { temp = XEXP (temp, 0); --- 1661,1665 ---- The last insn is handled in the normal manner. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX))) { temp = XEXP (temp, 0); *************** *** 1680,1684 **** i1 = emit_insns_before (temp, loop_start); ! if (! find_reg_note (i1, REG_EQUAL, 0)) REG_NOTES (i1) = gen_rtx (EXPR_LIST, --- 1679,1683 ---- i1 = emit_insns_before (temp, loop_start); ! if (! find_reg_note (i1, REG_EQUAL, NULL_RTX)) REG_NOTES (i1) = gen_rtx (EXPR_LIST, *************** *** 1702,1706 **** be an insn here. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_LIBCALL, 0))) p = XEXP (temp, 0); --- 1701,1705 ---- be an insn here. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) p = XEXP (temp, 0); *************** *** 1709,1713 **** insn is handled in the normal manner. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_RETVAL, 0))) { rtx fn_address = 0; --- 1708,1712 ---- insn is handled in the normal manner. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX))) { rtx fn_address = 0; *************** *** 1751,1755 **** && GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == REG ! && (n = find_reg_note (temp, REG_EQUAL, 0))) { fn_reg = SET_SRC (body); --- 1750,1755 ---- && GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == REG ! && (n = find_reg_note (temp, REG_EQUAL, ! NULL_RTX))) { fn_reg = SET_SRC (body); *************** *** 1764,1768 **** if (GET_CODE (temp) == CALL_INSN && fn_address != 0 ! && reg_mentioned_p (fn_reg, body)) emit_insn_after (gen_move_insn (fn_reg, fn_address), --- 1764,1768 ---- if (GET_CODE (temp) == CALL_INSN && fn_address != 0 ! && reg_referenced_p (fn_reg, body)) emit_insn_after (gen_move_insn (fn_reg, fn_address), *************** *** 1793,1798 **** tem = expand_binop (GET_MODE (reg), and_optab, reg, ! gen_rtx (CONST_INT, VOIDmode, ! ((1 << GET_MODE_BITSIZE (m->savemode))) - 1), reg, 1, OPTAB_LIB_WIDEN); --- 1793,1798 ---- tem = expand_binop (GET_MODE (reg), and_optab, reg, ! GEN_INT ((((HOST_WIDE_INT) 1 ! << GET_MODE_BITSIZE (m->savemode))) - 1), reg, 1, OPTAB_LIB_WIDEN); *************** *** 1835,1842 **** insn pointers, namely REG_LIBCALL on FIRST and REG_RETVAL on I1. */ ! if (temp = find_reg_note (i1, REG_RETVAL, 0)) { XEXP (temp, 0) = first; ! temp = find_reg_note (first, REG_LIBCALL, 0); XEXP (temp, 0) = i1; } --- 1835,1842 ---- insn pointers, namely REG_LIBCALL on FIRST and REG_RETVAL on I1. */ ! if (temp = find_reg_note (i1, REG_RETVAL, NULL_RTX)) { XEXP (temp, 0) = first; ! temp = find_reg_note (first, REG_LIBCALL, NULL_RTX); XEXP (temp, 0) = i1; } *************** *** 1901,1905 **** /* if library call, delete all insn except last, which is deleted below */ ! if (temp = find_reg_note (m1->insn, REG_RETVAL, 0)) { for (temp = XEXP (temp, 0); temp != m1->insn; --- 1901,1906 ---- /* if library call, delete all insn except last, which is deleted below */ ! if (temp = find_reg_note (m1->insn, REG_RETVAL, ! NULL_RTX)) { for (temp = XEXP (temp, 0); temp != m1->insn; *************** *** 2244,2248 **** || (simplejump_p (insn) && (uid_loop_num[INSN_UID (JUMP_LABEL (insn))] ! != this_loop_num)))) { rtx p; --- 2245,2250 ---- || (simplejump_p (insn) && (uid_loop_num[INSN_UID (JUMP_LABEL (insn))] ! != this_loop_num))) ! && get_max_uid () < max_uid_for_loop) { rtx p; *************** *** 2269,2276 **** if (GET_CODE (p) == JUMP_INSN ! && JUMP_LABEL (p) != 0 ! && condjump_p (p) ! && ! simplejump_p (p) ! && next_real_insn (JUMP_LABEL (p)) == our_next) { rtx target --- 2271,2281 ---- if (GET_CODE (p) == JUMP_INSN ! && JUMP_LABEL (p) != 0 ! /* Just ignore jumps to labels that were never emitted. ! These always indicate compilation errors. */ ! && INSN_UID (JUMP_LABEL (p)) != 0 ! && condjump_p (p) ! && ! simplejump_p (p) ! && next_real_insn (JUMP_LABEL (p)) == our_next) { rtx target *************** *** 2300,2305 **** /* Verify that uid_loop_num is large enough and that we can invert P. */ ! if (INSN_UID (new_label) < max_uid_for_loop ! && invert_jump (p, new_label)) { rtx q, r; --- 2305,2309 ---- /* Verify that uid_loop_num is large enough and that we can invert P. */ ! if (invert_jump (p, new_label)) { rtx q, r; *************** *** 2665,2671 **** rtx other; rtx base; ! int size; { ! int start = 0, end; if (GET_CODE (base) == CONST) --- 2669,2675 ---- rtx other; rtx base; ! HOST_WIDE_INT size; { ! HOST_WIDE_INT start = 0, end; if (GET_CODE (base) == CONST) *************** *** 2721,2725 **** /* If library call, skip to end of of it. */ ! if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, 0))) p = XEXP (temp, 0); --- 2725,2729 ---- /* If library call, skip to end of of it. */ ! if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) p = XEXP (temp, 0); *************** *** 2733,2737 **** if (this != 0) value |= this; ! else if (temp = find_reg_note (p, REG_EQUAL, 0)) { this = invariant_p (XEXP (temp, 0)); --- 2737,2741 ---- if (this != 0) value |= this; ! else if (temp = find_reg_note (p, REG_EQUAL, NULL_RTX)) { this = invariant_p (XEXP (temp, 0)); *************** *** 3152,3156 **** && reg_iv_type[REGNO (dest_reg)] != NOT_BASIC_INDUCT) { ! if (basic_induction_var (SET_SRC (set), dest_reg, &inc_val, &mult_val)) { --- 3156,3160 ---- && reg_iv_type[REGNO (dest_reg)] != NOT_BASIC_INDUCT) { ! if (basic_induction_var (SET_SRC (set), dest_reg, p, &inc_val, &mult_val)) { *************** *** 3419,3423 **** &mult_val)) /* Equivalent expression is a giv. */ ! || ((regnote = find_reg_note (p, REG_EQUAL, 0)) && (benefit = general_induction_var (XEXP (regnote, 0), &src_reg, --- 3423,3427 ---- &mult_val)) /* Equivalent expression is a giv. */ ! || ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX)) && (benefit = general_induction_var (XEXP (regnote, 0), &src_reg, *************** *** 3441,3445 **** /* If this is a library call, increase benefit. */ ! if (find_reg_note (p, REG_RETVAL, 0)) benefit += libcall_benefit (p); --- 3445,3449 ---- /* If this is a library call, increase benefit. */ ! if (find_reg_note (p, REG_RETVAL, NULL_RTX)) benefit += libcall_benefit (p); *************** *** 3452,3456 **** be an insn here. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_LIBCALL, 0))) p = XEXP (temp, 0); --- 3456,3460 ---- be an insn here. */ if (GET_CODE (p) != NOTE ! && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) p = XEXP (temp, 0); *************** *** 3460,3464 **** record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit, ! DEST_REG, not_every_iteration, 0, loop_start, loop_end); --- 3464,3468 ---- record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit, ! DEST_REG, not_every_iteration, NULL_PTR, loop_start, loop_end); *************** *** 4119,4122 **** --- 4123,4127 ---- bl->nonneg = 0; bl->reversed = 0; + bl->total_benefit = 0; /* Add this class to loop_iv_list. */ *************** *** 4638,4647 **** /* Check whether an insn is an increment legitimate for a basic induction var. ! X is the source of the insn. DEST_REG is the putative biv, also the destination of the insn. We accept patterns of these forms: ! REG = REG + INVARIANT REG = INVARIANT + REG - REG = REG - CONSTANT If X is suitable, we return 1, set *MULT_VAL to CONST1_RTX, --- 4643,4651 ---- /* Check whether an insn is an increment legitimate for a basic induction var. ! X is the source of insn P. DEST_REG is the putative biv, also the destination of the insn. We accept patterns of these forms: ! REG = REG + INVARIANT (includes REG = REG - CONSTANT) REG = INVARIANT + REG If X is suitable, we return 1, set *MULT_VAL to CONST1_RTX, *************** *** 4651,4659 **** *MULT_VAL to CONST0_RTX, and store the invariant into *INC_VAL. ! Otherwise we return 0. */ static int ! basic_induction_var (x, dest_reg, inc_val, mult_val) register rtx x; rtx dest_reg; rtx *inc_val; --- 4655,4683 ---- *MULT_VAL to CONST0_RTX, and store the invariant into *INC_VAL. ! We also want to detect a BIV when it corresponds to a variable ! whose mode was promoted via PROMOTED_MODE. In that case, an increment ! of the variable may be a PLUS that adds a SUBREG of that variable to ! an invariant and then sign- or zero-extends the result of the PLUS ! into the variable. ! ! Most GIVs in such cases will be in the promoted mode, since that is the ! probably the natural computation mode (and almost certainly the mode ! used for addresses) on the machine. So we view the pseudo-reg containing ! the variable as the BIV, as if it were simply incremented. ! ! Note that treating the entire pseudo as a BIV will result in making ! simple increments to any GIVs based on it. However, if the variable ! overflows in its declared mode but not its promoted mode, the result will ! be incorrect. This is acceptable if the variable is signed, since ! overflows in such cases are undefined, but not if it is unsigned, since ! those overflows are defined. So we only check for SIGN_EXTEND and ! not ZERO_EXTEND. ! ! If we cannot find a biv, we return 0. */ static int ! basic_induction_var (x, dest_reg, p, inc_val, mult_val) register rtx x; + rtx p; rtx dest_reg; rtx *inc_val; *************** *** 4662,4665 **** --- 4686,4690 ---- register enum rtx_code code; rtx arg; + rtx insn, set = 0; code = GET_CODE (x); *************** *** 4667,4673 **** { case PLUS: ! if (XEXP (x, 0) == dest_reg) arg = XEXP (x, 1); ! else if (XEXP (x, 1) == dest_reg) arg = XEXP (x, 0); else --- 4692,4704 ---- { case PLUS: ! if (XEXP (x, 0) == dest_reg ! || (GET_CODE (XEXP (x, 0)) == SUBREG ! && SUBREG_PROMOTED_VAR_P (XEXP (x, 0)) ! && SUBREG_REG (XEXP (x, 0)) == dest_reg)) arg = XEXP (x, 1); ! else if (XEXP (x, 1) == dest_reg ! || (GET_CODE (XEXP (x, 1)) == SUBREG ! && SUBREG_PROMOTED_VAR_P (XEXP (x, 1)) ! && SUBREG_REG (XEXP (x, 1)) == dest_reg)) arg = XEXP (x, 0); else *************** *** 4677,4695 **** return 0; ! *inc_val = arg; *mult_val = const1_rtx; return 1; ! case MINUS: ! if (XEXP (x, 0) == dest_reg ! && GET_CODE (XEXP (x, 1)) == CONST_INT) ! *inc_val = gen_rtx (CONST_INT, VOIDmode, ! - INTVAL (XEXP (x, 1))); ! else ! return 0; ! *mult_val = const1_rtx; ! return 1; /* Can accept constant setting of biv only when inside inner most loop. Otherwise, a biv of an inner loop may be incorrectly recognized --- 4708,4740 ---- return 0; ! *inc_val = convert_to_mode (GET_MODE (dest_reg), arg, 0);; *mult_val = const1_rtx; return 1; ! case SUBREG: ! /* If this is a SUBREG for a promoted variable, check the inner ! value. */ ! if (SUBREG_PROMOTED_VAR_P (x)) ! return basic_induction_var (SUBREG_REG (x), dest_reg, p, ! inc_val, mult_val); ! case REG: ! /* If this register is assigned in the previous insn, look at its ! source, but don't go outside the loop or past a label. */ + for (insn = PREV_INSN (p); + (insn && GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG); + insn = PREV_INSN (insn)) + ; + + if (insn) + set = single_set (insn); + + if (set != 0 && SET_DEST (set) == x) + return basic_induction_var (SET_SRC (set), dest_reg, insn, + inc_val, mult_val); + /* ... fall through ... */ + /* Can accept constant setting of biv only when inside inner most loop. Otherwise, a biv of an inner loop may be incorrectly recognized *************** *** 4697,4701 **** causing code to be moved INTO the inner loop. */ case MEM: - case REG: if (invariant_p (x) != 1) return 0; --- 4742,4745 ---- *************** *** 4705,4709 **** if (loops_enclosed == 1) { ! *inc_val = x; *mult_val = const0_rtx; return 1; --- 4749,4753 ---- if (loops_enclosed == 1) { ! *inc_val = convert_to_mode (GET_MODE (dest_reg), x, 0);; *mult_val = const0_rtx; return 1; *************** *** 4712,4715 **** --- 4756,4782 ---- return 0; + case SIGN_EXTEND: + return basic_induction_var (XEXP (x, 0), dest_reg, p, + inc_val, mult_val); + case ASHIFTRT: + /* Similar, since this can be a sign extension. */ + for (insn = PREV_INSN (p); + (insn && GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG); + insn = PREV_INSN (insn)) + ; + + if (insn) + set = single_set (insn); + + if (set && SET_DEST (set) == XEXP (x, 0) + && GET_CODE (XEXP (x, 1)) == CONST_INT + && INTVAL (XEXP (x, 1)) >= 0 + && GET_CODE (SET_SRC (set)) == ASHIFT + && XEXP (x, 1) == XEXP (SET_SRC (set), 1)) + return basic_induction_var (XEXP (SET_SRC (set), 0), dest_reg, insn, + inc_val, mult_val); + return 0; + default: return 0; *************** *** 4850,4854 **** if (mode != VOIDmode && (GET_MODE_CLASS (mode) != MODE_INT ! || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_INT)) return 0; --- 4917,4921 ---- if (mode != VOIDmode && (GET_MODE_CLASS (mode) != MODE_INT ! || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)) return 0; *************** *** 4946,4952 **** XEXP (x, 0), gen_rtx (MULT, mode, ! XEXP (x, 1), ! gen_rtx (CONST_INT, ! VOIDmode, -1))), benefit); --- 5013,5017 ---- XEXP (x, 0), gen_rtx (MULT, mode, ! XEXP (x, 1), constm1_rtx)), benefit); *************** *** 4981,4985 **** case CONST_INT: /* Product of two constants. */ ! return gen_rtx (CONST_INT, mode, INTVAL (arg0) * INTVAL (arg1)); case USE: --- 5046,5050 ---- case CONST_INT: /* Product of two constants. */ ! return GEN_INT (INTVAL (arg0) * INTVAL (arg1)); case USE: *************** *** 5016,5028 **** return simplify_giv_expr (gen_rtx (MULT, mode, XEXP (x, 0), ! gen_rtx (CONST_INT, VOIDmode, ! 1 << INTVAL (XEXP (x, 1)))), benefit); case NEG: /* "-a" is "a * (-1)" */ ! return simplify_giv_expr (gen_rtx (MULT, mode, ! XEXP (x, 0), ! gen_rtx (CONST_INT, VOIDmode, -1)), benefit); --- 5081,5091 ---- return simplify_giv_expr (gen_rtx (MULT, mode, XEXP (x, 0), ! GEN_INT ((HOST_WIDE_INT) 1 ! << INTVAL (XEXP (x, 1)))), benefit); case NEG: /* "-a" is "a * (-1)" */ ! return simplify_giv_expr (gen_rtx (MULT, mode, XEXP (x, 0), constm1_rtx), benefit); *************** *** 5148,5152 **** /* If libcall, skip to end of call sequence. */ ! if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, 0))) p = XEXP (temp, 0); --- 5211,5215 ---- /* If libcall, skip to end of call sequence. */ ! if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX))) p = XEXP (temp, 0); *************** *** 5158,5167 **** add_val, mult_val)) /* Giv created by equivalent expression. */ ! || ((temp = find_reg_note (p, REG_EQUAL, 0)) && (benefit = general_induction_var (XEXP (temp, 0), &src_reg, add_val, mult_val)))) && src_reg == v->src_reg) { ! if (find_reg_note (p, REG_RETVAL, 0)) benefit += libcall_benefit (p); --- 5221,5230 ---- add_val, mult_val)) /* Giv created by equivalent expression. */ ! || ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX)) && (benefit = general_induction_var (XEXP (temp, 0), &src_reg, add_val, mult_val)))) && src_reg == v->src_reg) { ! if (find_reg_note (p, REG_RETVAL, NULL_RTX)) benefit += libcall_benefit (p); *************** *** 5218,5223 **** return 0; ! mult = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (g2->mult_val) / INTVAL (g1->mult_val)); add = plus_constant (g2->add_val, - INTVAL (g1->add_val) * INTVAL (mult)); --- 5281,5285 ---- return 0; ! mult = GEN_INT (INTVAL (g2->mult_val) / INTVAL (g1->mult_val)); add = plus_constant (g2->add_val, - INTVAL (g1->add_val) * INTVAL (mult)); *************** *** 5381,5385 **** rtl_obstack = &temp_obstack; start_sequence (); ! expand_mult (GET_MODE (a), a, b, 0, 0); tmp = gen_sequence (); end_sequence (); --- 5443,5447 ---- rtl_obstack = &temp_obstack; start_sequence (); ! expand_mult (GET_MODE (a), a, b, NULL_RTX, 0); tmp = gen_sequence (); end_sequence (); *************** *** 5503,5507 **** /* register always nonnegative, add REG_NOTE to branch */ REG_NOTES (PREV_INSN (loop_end)) ! = gen_rtx (EXPR_LIST, REG_NONNEG, 0, REG_NOTES (PREV_INSN (loop_end))); bl->nonneg = 1; --- 5565,5569 ---- /* register always nonnegative, add REG_NOTE to branch */ REG_NOTES (PREV_INSN (loop_end)) ! = gen_rtx (EXPR_LIST, REG_NONNEG, NULL_RTX, REG_NOTES (PREV_INSN (loop_end))); bl->nonneg = 1; *************** *** 5528,5532 **** { REG_NOTES (PREV_INSN (loop_end)) ! = gen_rtx (EXPR_LIST, REG_NONNEG, 0, REG_NOTES (PREV_INSN (loop_end))); bl->nonneg = 1; --- 5590,5594 ---- { REG_NOTES (PREV_INSN (loop_end)) ! = gen_rtx (EXPR_LIST, REG_NONNEG, NULL_RTX, REG_NOTES (PREV_INSN (loop_end))); bl->nonneg = 1; *************** *** 5626,5636 **** reg = bl->biv->dest_reg; jump_label = XEXP (SET_SRC (PATTERN (PREV_INSN (loop_end))), 1); ! new_add_val = gen_rtx (CONST_INT, VOIDmode, ! - INTVAL (bl->biv->add_val)); final_value = XEXP (comparison, 1); ! start_value = gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (XEXP (comparison, 1)) ! - INTVAL (bl->biv->add_val))); /* Initialize biv to start_value before loop start. --- 5688,5696 ---- reg = bl->biv->dest_reg; jump_label = XEXP (SET_SRC (PATTERN (PREV_INSN (loop_end))), 1); ! new_add_val = GEN_INT (- INTVAL (bl->biv->add_val)); final_value = XEXP (comparison, 1); ! start_value = GEN_INT (INTVAL (XEXP (comparison, 1)) ! - INTVAL (bl->biv->add_val)); /* Initialize biv to start_value before loop start. *************** *** 5669,5673 **** /* Add new compare/branch insn at end of loop. */ start_sequence (); ! emit_cmp_insn (reg, const0_rtx, GE, 0, GET_MODE (reg), 0, 0); emit_jump_insn (gen_bge (XEXP (jump_label, 0))); tem = gen_sequence (); --- 5729,5734 ---- /* Add new compare/branch insn at end of loop. */ start_sequence (); ! emit_cmp_insn (reg, const0_rtx, GE, NULL_RTX, ! GET_MODE (reg), 0, 0); emit_jump_insn (gen_bge (XEXP (jump_label, 0))); tem = gen_sequence (); *************** *** 5685,5689 **** /* Register is now always nonnegative, so add REG_NONNEG note to the branch. */ ! REG_NOTES (tem) = gen_rtx (EXPR_LIST, REG_NONNEG, 0, REG_NOTES (tem)); } --- 5746,5750 ---- /* Register is now always nonnegative, so add REG_NONNEG note to the branch. */ ! REG_NOTES (tem) = gen_rtx (EXPR_LIST, REG_NONNEG, NULL_RTX, REG_NOTES (tem)); } *************** *** 5916,5923 **** && GET_CODE (v->add_val) == CONST_INT && validate_change (insn, &XEXP (x, arg_operand), ! gen_rtx (CONST_INT, VOIDmode, ! (INTVAL (arg) ! * INTVAL (v->mult_val) ! + INTVAL (v->add_val))), 0)) return 1; --- 5977,5983 ---- && GET_CODE (v->add_val) == CONST_INT && validate_change (insn, &XEXP (x, arg_operand), ! GEN_INT (INTVAL (arg) ! * INTVAL (v->mult_val) ! + INTVAL (v->add_val)), 0)) return 1; *************** *** 6197,6201 **** /* If this branches to JUMP_LABEL when the condition is false, reverse the condition. */ ! if (XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump)) code = reverse_condition (code), did_reverse_condition ^= 1; --- 6257,6262 ---- /* If this branches to JUMP_LABEL when the condition is false, reverse the condition. */ ! if (GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF ! && XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump)) code = reverse_condition (code), did_reverse_condition ^= 1; *************** *** 6255,6270 **** if ((GET_CODE (SET_SRC (set)) == COMPARE ! || ((code == NE ! || (code == LT ! && GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_INT ! && (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (inner_mode) - 1))))) && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))) x = SET_SRC (set); ! else if ((code == EQ ! || (code == GE ! && GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_INT ! && (STORE_FLAG_VALUE ! & (1 << (GET_MODE_BITSIZE (inner_mode) - 1))))) && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<') { --- 6316,6349 ---- if ((GET_CODE (SET_SRC (set)) == COMPARE ! || (((code == NE ! || (code == LT ! && GET_MODE_CLASS (inner_mode) == MODE_INT ! && (GET_MODE_BITSIZE (inner_mode) ! <= HOST_BITS_PER_WIDE_INT) ! && (STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (inner_mode) - 1)))) ! #ifdef FLOAT_STORE_FLAG_VALUE ! || (code == LT ! && GET_MODE_CLASS (inner_mode) == MODE_FLOAT ! && FLOAT_STORE_FLAG_VALUE < 0) ! #endif ! )) && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))) x = SET_SRC (set); ! else if (((code == EQ ! || (code == GE ! && (GET_MODE_BITSIZE (inner_mode) ! <= HOST_BITS_PER_WIDE_INT) ! && GET_MODE_CLASS (inner_mode) == MODE_INT ! && (STORE_FLAG_VALUE ! & ((HOST_WIDE_INT) 1 ! << (GET_MODE_BITSIZE (inner_mode) - 1)))) ! #ifdef FLOAT_STORE_FLAG_VALUE ! || (code == GE ! && GET_MODE_CLASS (inner_mode) == MODE_FLOAT ! && FLOAT_STORE_FLAG_VALUE < 0) ! #endif ! )) && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<') { *************** *** 6311,6316 **** if (GET_CODE (op1) == CONST_INT) { ! int const_val = INTVAL (op1); ! unsigned uconst_val = (unsigned) const_val; switch (code) --- 6390,6395 ---- if (GET_CODE (op1) == CONST_INT) { ! HOST_WIDE_INT const_val = INTVAL (op1); ! unsigned HOST_WIDE_INT uconst_val = const_val; switch (code) *************** *** 6318,6337 **** case LE: code = LT; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_val + 1); break; case GE: code = GT; ! op1 = gen_rtx (CONST_INT, VOIDmode, const_val - 1); break; case LEU: code = LTU; ! op1 = gen_rtx (CONST_INT, VOIDmode, uconst_val + 1); break; case GEU: code = GTU; ! op1 = gen_rtx (CONST_INT, VOIDmode, uconst_val - 1); break; } --- 6397,6416 ---- case LE: code = LT; ! op1 = GEN_INT (const_val + 1); break; case GE: code = GT; ! op1 = GEN_INT (const_val - 1); break; case LEU: code = LTU; ! op1 = GEN_INT (uconst_val + 1); break; case GEU: code = GTU; ! op1 = GEN_INT (uconst_val - 1); break; } *************** *** 6361,6365 **** rtx x; { ! rtx comparison = get_condition (x, 0); if (comparison == 0 --- 6440,6444 ---- rtx x; { ! rtx comparison = get_condition (x, NULL_PTR); if (comparison == 0 diff -rc2N gcc-2.2.2/loop.h gcc-2.3.1/loop.h *** gcc-2.2.2/loop.h Thu May 7 02:36:44 1992 --- gcc-2.3.1/loop.h Tue Aug 11 15:47:36 1992 *************** *** 101,105 **** giv, this points to the base giv. The base giv will have COMBINED_WITH non-zero. */ ! int const_adjust; /* Used by loop unrolling, when an address giv is split, and a constant is eliminated from the address, the -constant is stored here --- 101,105 ---- giv, this points to the base giv. The base giv will have COMBINED_WITH non-zero. */ ! HOST_WIDE_INT const_adjust; /* Used by loop unrolling, when an address giv is split, and a constant is eliminated from the address, the -constant is stored here *************** *** 142,146 **** extern int *loop_outer_loop; extern rtx *loop_number_exit_labels; ! extern unsigned long loop_n_iterations; extern int max_reg_before_loop; --- 142,146 ---- extern int *loop_outer_loop; extern rtx *loop_number_exit_labels; ! extern unsigned HOST_WIDE_INT loop_n_iterations; extern int max_reg_before_loop; *************** *** 158,167 **** void emit_iv_add_mult (); - /* Variables declared in stmt.c but also needed in loop.c. */ - - extern union tree_node **loop_number_first_block; - extern union tree_node **loop_number_last_block; - extern int *loop_number_block_level; - /* Forward declarations for non-static functions declared in stmt.c. */ void find_loop_tree_blocks (); --- 158,161 ---- *************** *** 170,174 **** void unroll_loop (); rtx biv_total_increment (); ! unsigned long loop_iterations (); rtx final_biv_value (); rtx final_giv_value (); --- 164,168 ---- void unroll_loop (); rtx biv_total_increment (); ! unsigned HOST_WIDE_INT loop_iterations (); rtx final_biv_value (); rtx final_giv_value (); diff -rc2N gcc-2.2.2/machmode.h gcc-2.3.1/machmode.h *** gcc-2.2.2/machmode.h Tue Mar 10 17:11:09 1992 --- gcc-2.3.1/machmode.h Sat Aug 1 22:59:22 1992 *************** *** 34,37 **** --- 34,65 ---- #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) + /* Find the largest host integer type and set its size and type. */ + + #ifndef HOST_BITS_PER_WIDE_INT + + #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT + #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG + #define HOST_WIDE_INT long + #else + #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT + #define HOST_WIDE_INT int + #endif + + #endif + + /* Define the number of entries in an 8-bit `shorts' array needed to represent + the largest supported constant, which is twice the width of the largest + host integer type. */ + + #ifndef MAX_SHORTS + #define MAX_SHORTS (HOST_BITS_PER_WIDE_INT * 2 / 8) + #endif + + /* Provide a default way to print an address in hex via printf. */ + + #ifndef HOST_PTR_PRINTF + #define HOST_PTR_PRINTF sizeof (int) == sizeof (char *) ? "%x" : "%lx" + #endif + /* Make an enum class that gives all the machine modes. */ *************** *** 81,85 **** #define GET_MODE_NUNITS(MODE) \ ! (GET_MODE_SIZE ((MODE)) / GET_MODE_UNIT_SIZE ((MODE))) /* Get the size in bits of an object of mode MODE. */ --- 109,114 ---- #define GET_MODE_NUNITS(MODE) \ ! ((GET_MODE_UNIT_SIZE ((MODE)) == 0) ? 0 \ ! : (GET_MODE_SIZE ((MODE)) / GET_MODE_UNIT_SIZE ((MODE)))) /* Get the size in bits of an object of mode MODE. */ *************** *** 91,96 **** #define GET_MODE_MASK(MODE) \ ! ((GET_MODE_BITSIZE (MODE) >= HOST_BITS_PER_INT) \ ! ? -1 : ((1 << GET_MODE_BITSIZE (MODE)) - 1)) /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */ --- 120,125 ---- #define GET_MODE_MASK(MODE) \ ! ((GET_MODE_BITSIZE (MODE) >= HOST_BITS_PER_WIDE_INT) \ ! ?(HOST_WIDE_INT) ~0 : (((HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (MODE)) - 1)) /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */ diff -rc2N gcc-2.2.2/make-cc1.com gcc-2.3.1/make-cc1.com *** gcc-2.2.2/make-cc1.com Mon Apr 20 15:15:22 1992 --- gcc-2.3.1/make-cc1.com Fri Oct 16 23:43:50 1992 *************** *** 11,14 **** --- 11,19 ---- $! Build the GNU "C" compiler on VMS $! + $! Note: to build with DEC's VAX C compiler, uncomment the 2nd CC, CFLAGS, + $! and LIBS alternatives, and also execute the following command: + $! DEFINE SYS SYS$LIBRARY: + $! After a successful build, restore those items and rebuild with gcc. + $ $! C compiler $! *************** *** 18,21 **** --- 23,27 ---- $ RENAME := rename/new_vers $ LINK := link + $ EDIT := edit $! $! Compiler options *************** *** 176,179 **** --- 182,245 ---- $! $compile_cc1: + $if (DO_CC1 + DO_CC1OBJ) .ne.0 + $ then + $if (f$search("C-PARSE.Y") .eqs. "") then goto yes_yfiles + $if (f$cvtime(f$file_attributes("C-PARSE.IN","RDT")).gts. - + f$cvtime(f$file_attributes("C-PARSE.Y","RDT"))) - + then goto yes_yfiles + $if (f$search("OBJC-PARSE.Y") .eqs. "") then goto yes_yfiles + $if (f$cvtime(f$file_attributes("C-PARSE.IN","RDT")).gts. - + f$cvtime(f$file_attributes("OBJC-PARSE.Y","RDT"))) - + then goto yes_yfiles + $GOTO no_yfiles + $yes_yfiles: + $echo "Now processing c-parse.in to generate c-parse.y and objc-parse.y." + $ edit/tpu/nojournal/nosection/nodisplay/command=sys$input + ! + ! Read c-parse.in, write c-parse.y and objc-parse.y, depending on + ! paired lines of "ifc" & "end ifc" and "ifobjc" & "end ifobjc" to + ! control what goes into each file. Most lines will be common to + ! both (hence not bracketed by either control pair). Mismatched + ! pairs aren't detected--garbage in, garbage out... + ! + + PROCEDURE do_output() + IF NOT objc_only THEN POSITION(END_OF(c)); COPY_TEXT(input_line); ENDIF; + IF NOT c_only THEN POSITION(END_OF(objc)); COPY_TEXT(input_line); ENDIF; + POSITION(input_file); !reset + ENDPROCEDURE; + + input_file := CREATE_BUFFER("input", "c-parse.in"); !load data + SET(NO_WRITE, input_file); + c := CREATE_BUFFER("c_output"); !1st output file + objc := CREATE_BUFFER("objc_output"); !2nd output file + + POSITION(BEGINNING_OF(input_file)); + c_only := 0; + objc_only := 0; + + LOOP + EXITIF MARK(NONE) = END_OF(input_file); !are we done yet? + + input_line := CURRENT_LINE; !access current_line just once + CASE EDIT(input_line, TRIM_TRAILING, OFF, NOT_IN_PLACE) + ["ifc"] : c_only := 1; + ["end ifc"] : c_only := 0; + ["ifobjc"] : objc_only := 1; + ["end ifobjc"] : objc_only := 0; + ! default -- add non-control line to either or both output files + [INRANGE] : do_output(); !between "end" and "if" + [OUTRANGE] : do_output(); !before "end" or after "if" + ENDCASE; + + MOVE_VERTICAL(1); !go to next line + ENDLOOP; + + WRITE_FILE(c, "c-parse.y"); + WRITE_FILE(objc, "objc-parse.y"); + QUIT + $ endif + $no_yfiles: + $! $open cfile$ compilers.list $cloop:read cfile$ compilername/end=cdone *************** *** 237,240 **** --- 303,312 ---- $ 'RENAME' 'flnm'_tab.c 'flnm'.c $ 'RENAME' 'flnm'_tab.h 'flnm'.h + $ if flnm.eqs."cp-parse" + $ then ! fgrep '#define YYEMPTY' cp-parse.c >>cp-parse.h + $ open/append jfile$ cp-parse.h + $ search/exact/output=jfile$ cp-parse.c "#define YYEMPTY" + $ close jfile$ + $ endif $!'f$verify(0) $no_bison: diff -rc2N gcc-2.2.2/make-cccp.com gcc-2.3.1/make-cccp.com *** gcc-2.2.2/make-cccp.com Thu Feb 13 17:08:28 1992 --- gcc-2.3.1/make-cccp.com Fri Aug 21 02:24:35 1992 *************** *** 5,8 **** --- 5,11 ---- $! Build the GNU "C" pre-processor on VMS $! + $! Note: to build with DEC's VAX C compiler, uncomment the 2nd CC, CFLAGS, + $! and LIBS alternatives, and also execute the following command: + $! DEFINE SYS SYS$LIBRARY: $ $! *************** *** 10,13 **** --- 13,17 ---- $! $ CC := gcc + $! CC := cc !uncomment for VAXC $ BISON := bison $ RENAME := rename *************** *** 16,20 **** $! Compiler options $! ! $ CFLAGS = "/debug/inc=([],[.config])" $! $! Link options --- 20,25 ---- $! Compiler options $! ! $ CFLAGS = "/debug/incl=([],[.config])" ! $! CFLAGS = "/noopt/incl=([],[.config])" !uncomment for VAXC $! $! Link options *************** *** 24,28 **** $! Link libraries $! ! $ LIBS := gnu_cc:[000000]gcclib/libr,sys$share:vaxcrtl/libr $ if "''p1'" .eqs. "LINK" then goto Link $ 'CC 'CFLAGS cccp.c --- 29,35 ---- $! Link libraries $! ! $ LIBS := gnu_cc:[000000]gcclib.olb/libr,sys$library:vaxcrtl.olb/libr ! $! LIBS := alloca.obj,sys$library:vaxcrtl.olb/libr !uncomment for VAXC ! $ $ if "''p1'" .eqs. "LINK" then goto Link $ 'CC 'CFLAGS cccp.c *************** *** 39,49 **** $ 20$: $! $ 'CC 'CFLAGS cexp.c $ 'CC 'CFLAGS version.c $ Link: $ link 'LDFLAGS /exe=gcc-cpp cccp,cexp,version,version.opt/opt,'LIBS' - $! - $! CAUTION: If you want to link gcc-cpp to the sharable image library - $! VAXCRTL, see the notes in gcc.texinfo (or INSTALL) first. $! $! Done --- 46,56 ---- $ 20$: $! + $ if f$locate("alloca.obj",f$edit(LIBS,"lowercase")).lt.f$length(LIBS) then - + 'CC 'CFLAGS /define="STACK_DIRECTION=(-1)" alloca.c + $! $ 'CC 'CFLAGS cexp.c $ 'CC 'CFLAGS version.c $ Link: $ link 'LDFLAGS /exe=gcc-cpp cccp,cexp,version,version.opt/opt,'LIBS' $! $! Done diff -rc2N gcc-2.2.2/make-l2.com gcc-2.3.1/make-l2.com *** gcc-2.2.2/make-l2.com Mon Apr 20 15:15:26 1992 --- gcc-2.3.1/make-l2.com Sun Aug 9 21:36:34 1992 *************** *** 61,65 **** $flnm = "L"+flnm $if flnm.eqs."L_exit" then goto loop1 ! $write sys$output "$ gcc/debug/define=''flnm' LIBGCC2.C" $! $objname = flnm --- 61,65 ---- $flnm = "L"+flnm $if flnm.eqs."L_exit" then goto loop1 ! $write sys$output "$ gcc/debug/define=""''flnm'"" LIBGCC2.C" $! $objname = flnm *************** *** 74,81 **** $ delete/nolog 'cpp_file'; $ gcc_as "-vGNU CC V''Version'" 's_file' -o 'objname'.OBJ $ delete/nolog 's_file'; $! ! $lib libgcc2.olb 'objname'.obj ! $del 'objname'.obj;/nolog $! $goto loop1 --- 74,83 ---- $ delete/nolog 'cpp_file'; $ gcc_as "-vGNU CC V''Version'" 's_file' -o 'objname'.OBJ + $! Assemble again, preserving lowercase symbol names this time. + $ gcc_as "-vGNU CC V''Version'" -h3 's_file' -o 'objname'-c.OBJ $ delete/nolog 's_file'; $! ! $ library libgcc2.olb 'objname'.obj,'objname'-c.obj ! $ delete/nolog 'objname'.obj;,'objname'-c.obj; $! $goto loop1 diff -rc2N gcc-2.2.2/md.texi gcc-2.3.1/md.texi *** gcc-2.2.2/md.texi Mon Jun 8 18:38:52 1992 --- gcc-2.3.1/md.texi Tue Oct 13 21:24:22 1992 *************** *** 330,333 **** --- 330,343 ---- their own. + @findex match_op_dup + @item (match_op_dup:@var{m} @var{n}[@var{operands}@dots{}]) + Like @code{match_dup}, except that it applies to operators instead of + operands. When constructing an insn, operand number @var{n} will be + substituted at this point. But in matching, @code{match_op_dup} behaves + differently. It assumes that operand number @var{n} has already been + determined by a @code{match_operator} appearing earlier in the + recognition template, and it matches only an identical-looking + expression. + @findex match_parallel @item (match_parallel @var{n} @var{predicate} [@var{subpat}@dots{}]) *************** *** 353,360 **** (define_insn "" [(match_parallel 0 "load_multiple_operation" ! [(set (match_operand:SI 1 "gen_reg_operand" "=r") ! (match_operand:SI 2 "memory_operand" "m")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "" "loadm 0,0,%1,%2") --- 363,370 ---- (define_insn "" [(match_parallel 0 "load_multiple_operation" ! [(set (match_operand:SI 1 "gpc_reg_operand" "=r") ! (match_operand:SI 2 "memory_operand" "m")) ! (use (reg:SI 179)) ! (clobber (reg:SI 179))])] "" "loadm 0,0,%1,%2") *************** *** 371,380 **** @example (parallel [(set (reg:SI 20) (mem:SI (reg:SI 100))) ! (use (reg:SI 179)) ! (clobber (reg:SI 179)) ! (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 100) (const_int 4)))) ! (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 100) (const_int 8))))]) @end example @findex address @item (address (match_operand:@var{m} @var{n} "address_operand" "")) --- 381,395 ---- @example (parallel [(set (reg:SI 20) (mem:SI (reg:SI 100))) ! (use (reg:SI 179)) ! (clobber (reg:SI 179)) ! (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 100) (const_int 4)))) ! (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 100) (const_int 8))))]) @end example + @findex match_par_dup + @item (match_par_dup @var{n} [@var{subpat}@dots{}]) + Like @code{match_op_dup}, but for @code{match_parallel} instead of + @code{match_operator}. + @findex address @item (address (match_operand:@var{m} @var{n} "address_operand" "")) *************** *** 440,443 **** --- 455,463 ---- instruction. + @samp{%=} outputs a number which is unique to each instruction in the + entire compilation. This is useful for making local labels to be + referred to more than once in a single template that generates multiple + assembler instructions. + @samp{%} followed by a punctuation character specifies a substitution that does not use an operand. Only one case is standard: @samp{%%} outputs a *************** *** 497,502 **** "" "@@ ! addr %1,%0 ! addm %1,%0") @end example --- 517,522 ---- "" "@@ ! addr %2,%0 ! addm %2,%0") @end example *************** *** 1529,1533 **** simply store the operands away and generate all the required insns in a @code{define_expand} (@pxref{Expander Definitions}) for the conditional ! branch operations. All calls to expand @samp{v@var{cond}} patterns are immediately preceded by calls to expand either a @samp{cmp@var{m}} pattern or a @samp{tst@var{m}} pattern. --- 1549,1553 ---- simply store the operands away and generate all the required insns in a @code{define_expand} (@pxref{Expander Definitions}) for the conditional ! branch operations. All calls to expand @samp{b@var{cond}} patterns are immediately preceded by calls to expand either a @samp{cmp@var{m}} pattern or a @samp{tst@var{m}} pattern. *************** *** 1608,1615 **** (define_insn "" [(set (pc) ! (if_then_else (match_operator 0 "comparison_operator" ! [(cc0) (const_int 0)]) ! (return) ! (pc)))] "@var{condition}" "@dots{}") --- 1628,1635 ---- (define_insn "" [(set (pc) ! (if_then_else (match_operator 0 "comparison_operator" ! [(cc0) (const_int 0)]) ! (return) ! (pc)))] "@var{condition}" "@dots{}") *************** *** 1814,1820 **** [(set (pc) (if_then_else (match_operator 0 "comparison_operator" ! [(cc0) (const_int 0)]) ! (pc) ! (label_ref (match_operand 1 "" ""))))] "@var{condition}" "@dots{}") --- 1834,1840 ---- [(set (pc) (if_then_else (match_operator 0 "comparison_operator" ! [(cc0) (const_int 0)]) ! (pc) ! (label_ref (match_operand 1 "" ""))))] "@var{condition}" "@dots{}") *************** *** 1961,1967 **** (define_insn "" [(set (reg:CC_NOOV 0) ! (compare:CC_NOOV (plus:SI (match_operand:SI 0 "register_operand" "%r") ! (match_operand:SI 1 "arith_operand" "rI")) ! (const_int 0)))] "" "@dots{}") --- 1981,1987 ---- (define_insn "" [(set (reg:CC_NOOV 0) ! (compare:CC_NOOV (plus:SI (match_operand:SI 0 "register_operand" "%r") ! (match_operand:SI 1 "arith_operand" "rI")) ! (const_int 0)))] "" "@dots{}") *************** *** 2038,2043 **** (define_insn "" [(set (match_operand:@var{m} 0 @dots{}) ! (and:@var{m} (not:@var{m} (match_operand:@var{m} 1 @dots{})) ! (match_operand:@var{m} 2 @dots{})))] "@dots{}" "@dots{}") --- 2058,2063 ---- (define_insn "" [(set (match_operand:@var{m} 0 @dots{}) ! (and:@var{m} (not:@var{m} (match_operand:@var{m} 1 @dots{})) ! (match_operand:@var{m} 2 @dots{})))] "@dots{}" "@dots{}") *************** *** 2050,2055 **** (define_insn "" [(set (match_operand:@var{m} 0 @dots{}) ! (ior:@var{m} (not:@var{m} (match_operand:@var{m} 1 @dots{})) ! (not:@var{m} (match_operand:@var{m} 2 @dots{}))))] "@dots{}" "@dots{}") --- 2070,2075 ---- (define_insn "" [(set (match_operand:@var{m} 0 @dots{}) ! (ior:@var{m} (not:@var{m} (match_operand:@var{m} 1 @dots{})) ! (not:@var{m} (match_operand:@var{m} 2 @dots{}))))] "@dots{}" "@dots{}") *************** *** 2519,2523 **** @code{define_expand} (@pxref{Expander Definitions}) and are executed before the new RTL is generated to prepare for the generated code ! or emit some insns whose pattern is not fixed. Patterns are matched against @var{insn-pattern} in two different --- 2539,2546 ---- @code{define_expand} (@pxref{Expander Definitions}) and are executed before the new RTL is generated to prepare for the generated code ! or emit some insns whose pattern is not fixed. Unlike those in ! @code{define_expand}, however, these statements must not generate ! any new pseudo-registers. Once reload has completed, they also ! must not allocate any space in the stack frame. Patterns are matched against @var{insn-pattern} in two different *************** *** 2538,2549 **** (define_split [(set (match_operand:SI 0 "gen_reg_operand" "") ! (sign_extend:SI (match_operand:HI 1 "gen_reg_operand" "")))] "" [(set (match_dup 0) ! (ashift:SI (match_dup 1) ! (const_int 16))) (set (match_dup 0) ! (ashiftrt:SI (match_dup 0) ! (const_int 16)))] " @{ operands[1] = gen_lowpart (SImode, operands[1]); @}") --- 2561,2572 ---- (define_split [(set (match_operand:SI 0 "gen_reg_operand" "") ! (sign_extend:SI (match_operand:HI 1 "gen_reg_operand" "")))] "" [(set (match_dup 0) ! (ashift:SI (match_dup 1) ! (const_int 16))) (set (match_dup 0) ! (ashiftrt:SI (match_dup 0) ! (const_int 16)))] " @{ operands[1] = gen_lowpart (SImode, operands[1]); @}") *************** *** 2567,2572 **** (define_split [(set (match_operand:SI 0 "gen_reg_operand" "") ! (plus:SI (match_operand:SI 1 "gen_reg_operand" "") ! (match_operand:SI 2 "non_add_cint_operand" "")))] "" [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) --- 2590,2595 ---- (define_split [(set (match_operand:SI 0 "gen_reg_operand" "") ! (plus:SI (match_operand:SI 1 "gen_reg_operand" "") ! (match_operand:SI 2 "non_add_cint_operand" "")))] "" [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) *************** *** 2596,2601 **** (define_split [(set (match_operand:CC 0 "cc_reg_operand" "") ! (compare:CC (match_operand:SI 1 "gen_reg_operand" "") ! (match_operand:SI 2 "non_short_cint_operand" ""))) (clobber (match_operand:SI 3 "gen_reg_operand" ""))] "find_single_use (operands[0], insn, 0) --- 2619,2624 ---- (define_split [(set (match_operand:CC 0 "cc_reg_operand" "") ! (compare:CC (match_operand:SI 1 "gen_reg_operand" "") ! (match_operand:SI 2 "non_short_cint_operand" ""))) (clobber (match_operand:SI 3 "gen_reg_operand" ""))] "find_single_use (operands[0], insn, 0) *************** *** 2704,2708 **** #define HAVE_ATTR_type enum attr_type @{TYPE_BRANCH, TYPE_FP, TYPE_LOAD, ! TYPE_STORE, TYPE_ARITH@}; extern enum attr_type get_attr_type (); @end example --- 2727,2731 ---- #define HAVE_ATTR_type enum attr_type @{TYPE_BRANCH, TYPE_FP, TYPE_LOAD, ! TYPE_STORE, TYPE_ARITH@}; extern enum attr_type get_attr_type (); @end example *************** *** 2903,2907 **** When the attribute value depends on the @samp{alternative} attribute (i.e., which is the applicable alternative in the constraint of the ! insn), the @code{set_attr_alternative} expression can can be used. It allows the specification of a vector of attribute expressions, one for each alternative. --- 2926,2930 ---- When the attribute value depends on the @samp{alternative} attribute (i.e., which is the applicable alternative in the constraint of the ! insn), the @code{set_attr_alternative} expression can be used. It allows the specification of a vector of attribute expressions, one for each alternative. *************** *** 3138,3149 **** (const (cond [(symbol_ref "TARGET_88100") (const_string "m88100") ! (symbol_ref "TARGET_88110") (const_string "m88110")] ! (const_string "m88000")))) (define_attr "memory" "fast,slow" (const (if_then_else (symbol_ref "TARGET_FAST_MEM") ! (const_string "fast") ! (const_string "slow")))) @end example --- 3161,3172 ---- (const (cond [(symbol_ref "TARGET_88100") (const_string "m88100") ! (symbol_ref "TARGET_88110") (const_string "m88110")] ! (const_string "m88000")))) (define_attr "memory" "fast,slow" (const (if_then_else (symbol_ref "TARGET_FAST_MEM") ! (const_string "fast") ! (const_string "slow")))) @end example *************** *** 3247,3257 **** For the purposes of the specifications in this section, a machine is divided into @dfn{function units}, each of which execute a specific ! class of instructions. Function units that accept one instruction each ! cycle and allow a result to be used in the succeeding instruction ! (usually via forwarding) need not be specified. Classic RISC ! microprocessors will normally have a single function unit, which we can ! call @samp{memory}. The newer ``superscalar'' processors will often ! have function units for floating point operations, usually at least ! a floating point adder and multiplier. @findex define_function_unit --- 3270,3280 ---- For the purposes of the specifications in this section, a machine is divided into @dfn{function units}, each of which execute a specific ! class of instructions in first-in-first-out order. Function units that ! accept one instruction each cycle and allow a result to be used in the ! succeeding instruction (usually via forwarding) need not be specified. ! Classic RISC microprocessors will normally have a single function unit, ! which we can call @samp{memory}. The newer ``superscalar'' processors ! will often have function units for floating point operations, usually at ! least a floating point adder and multiplier. @findex define_function_unit *************** *** 3261,3266 **** @example (define_function_unit @var{name} @var{multiplicity} @var{simultaneity} ! @var{test} @var{ready-delay} @var{busy-delay} ! [@var{conflict-list}]) @end example --- 3284,3289 ---- @example (define_function_unit @var{name} @var{multiplicity} @var{simultaneity} ! @var{test} @var{ready-delay} @var{issue-delay} ! [@var{conflict-list}]) @end example *************** *** 3292,3310 **** introducing any stalls. ! @var{busy-delay} is an integer that represents the default cost if an ! insn is scheduled for this unit while the unit is active with another ! insn. If @var{simultaneity} is zero, this specification is ignored. ! Otherwise, a zero value indicates that these insns execute on @var{name} ! in a fully pipelined fashion, even if @var{simultaneity} is non-zero. A ! non-zero value indicates that scheduling a new insn on this unit while ! another is active will incur a cost. A cost of two indicates a single ! cycle delay. For a normal non-pipelined function unit, @var{busy-delay} ! will be twice @var{ready-delay}. @var{conflict-list} is an optional list giving detailed conflict costs for this unit. If specified, it is a list of condition test expressions which are applied to insns already executing in @var{name}. For each ! insn that is in the list, @var{busy-delay} will be used for the conflict ! cost, while a value of zero will be used for insns not in the list. Typical uses of this vector are where a floating point function unit can --- 3315,3335 ---- introducing any stalls. ! @var{issue-delay} is an integer that specifies the number of cycles ! after the instruction matching the @var{test} expression begins using ! this unit until a subsequent instruction can begin. A cost of @var{N} ! indicates an @var{N-1} cycle delay. A subsequent instruction may also ! be delayed if an earlier instruction has a longer @var{ready-delay} ! value. This blocking effect is computed using the @var{simultaneity}, ! @var{ready-delay}, @var{issue-delay}, and @var{conflict-list} terms. ! For a normal non-pipelined function unit, @var{simultaneity} will be ! one, the unit will block for the @var{ready-delay} cycles of the ! executing insn, and smaller values of @var{issue-delay} will be ignored. @var{conflict-list} is an optional list giving detailed conflict costs for this unit. If specified, it is a list of condition test expressions which are applied to insns already executing in @var{name}. For each ! insn that is in the list, @var{issue-delay} will be used for the conflict ! cost, while a value of zero will be used for insns not in the list. If ! not specified, it defaults to all instructions that use the function unit. Typical uses of this vector are where a floating point function unit can *************** *** 3318,3322 **** @example ! (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 4) @end example --- 3343,3347 ---- @example ! (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) @end example *************** *** 3326,3345 **** @example (define_function_unit ! "fp" 1 1 (eq_attr "type" "sp_fp") 4 8 (eq_attr "type" "dp_fp")] (define_function_unit ! "fp" 1 1 (eq_attr "type" "dp_fp") 4 8 (eq_attr "type" "sp_fp")] @end example ! @strong{Note:} No code currently exists to avoid function unit ! conflicts, only data conflicts. Hence @var{multiplicity}, ! @var{simultaneity}, @var{busy-cost}, and @var{conflict-list} are ! currently ignored. When such code is written, it is possible that the ! specifications for these values may be changed. It has recently come to ! our attention that these specifications may not allow modeling of some ! of the newer ``superscalar'' processors that have insns using multiple ! pipelined units. These insns will cause a potential conflict for the ! second unit used during their execution and there is no way of ! representing that conflict. We welcome any examples of how function ! unit conflicts work in such processors and suggestions for their ! representation. @end ifset --- 3351,3367 ---- @example (define_function_unit ! "fp" 1 0 (eq_attr "type" "sp_fp") 4 4 (eq_attr "type" "dp_fp")] (define_function_unit ! "fp" 1 0 (eq_attr "type" "dp_fp") 4 4 (eq_attr "type" "sp_fp")] @end example ! @strong{Note:} The scheduler attempts to avoid function unit conflicts ! and uses all the specifications in the @code{define_function_unit} ! expression. It has recently come to our attention that these ! specifications may not allow modeling of some of the newer ! ``superscalar'' processors that have insns using multiple pipelined ! units. These insns will cause a potential conflict for the second unit ! used during their execution and there is no way of representing that ! conflict. We welcome any examples of how function unit conflicts work ! in such processors and suggestions for their representation. @end ifset diff -rc2N gcc-2.2.2/mips-tdump.c gcc-2.3.1/mips-tdump.c *** gcc-2.2.2/mips-tdump.c Thu May 7 02:36:49 1992 --- gcc-2.3.1/mips-tdump.c Thu Oct 29 14:32:39 1992 *************** *** 25,31 **** #include #include - #include #include "config.h" #ifdef __STDC__ typedef void *PTR_T; --- 25,40 ---- #include #include #include "config.h" + #ifndef CROSS_COMPILE + #include + #else + #include "symconst.h" + #define LANGUAGE_C + #include "sym.h" + #include "filehdr.h" + #define ST_RFDESCAPE 0xfff + #endif + #ifdef __STDC__ typedef void *PTR_T; *************** *** 51,54 **** --- 60,69 ---- #define uint unsigned int #define ulong unsigned long + + #ifdef index + #undef index + #undef rindex + #endif + /* Do to size_t being defined in sys/types.h and different diff -rc2N gcc-2.2.2/mips-tfile.c gcc-2.3.1/mips-tfile.c *** gcc-2.2.2/mips-tfile.c Thu May 7 02:36:56 1992 --- gcc-2.3.1/mips-tfile.c Thu Oct 29 14:32:38 1992 *************** *** 599,605 **** - #include #include "gvarargs.h" #include "config.h" #ifndef __SABER__ --- 599,605 ---- #include "gvarargs.h" #include "config.h" + #include #ifndef __SABER__ *************** *** 638,642 **** --- 638,646 ---- instead of the standard one it's not worth it to fix it. */ + #if defined(__OSF1__) || defined(__OSF__) || defined(__osf__) + #define Size_t long unsigned int + #else #define Size_t unsigned int + #endif #define Ptrdiff_t int *************** *** 675,681 **** #else /* MIPS_DEBUGGING defined */ #include - #include #include #include --- 679,689 ---- #else /* MIPS_DEBUGGING defined */ + /* The local and global symbols have a field index, so undo any defines + of index -> strchr and rindex -> strrchr. */ + + #undef rindex + #undef index #include #include #include *************** *** 685,688 **** --- 693,706 ---- #include + #ifndef CROSS_COMPILE + #include + #else + #include "symconst.h" + #define LANGUAGE_C + #include "sym.h" + #include "filehdr.h" + #define ST_RFDESCAPE 0xfff + #endif + #if defined (USG) || defined (NO_STAB_H) #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */ *************** *** 1022,1026 **** bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */ symint_t ifd; /* file # tag defined in */ ! symint_t index; /* index within file's local symbols */ } tag_t; --- 1040,1044 ---- bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */ symint_t ifd; /* file # tag defined in */ ! symint_t indx; /* index within file's local symbols */ } tag_t; *************** *** 1056,1060 **** char *string; /* string we are hashing */ symint_t len; /* string length */ ! symint_t index; /* index within string table */ EXTR *esym_ptr; /* global symbol pointer */ SYMR *sym_ptr; /* local symbol pointer */ --- 1074,1078 ---- char *string; /* string we are hashing */ symint_t len; /* string length */ ! symint_t indx; /* index within string table */ EXTR *esym_ptr; /* global symbol pointer */ SYMR *sym_ptr; /* local symbol pointer */ *************** *** 1077,1081 **** struct thash *next; /* next hash value */ AUXU type; /* type we are hashing */ ! symint_t index; /* index within string table */ } thash_t; --- 1095,1099 ---- struct thash *next; /* next hash value */ AUXU type; /* type we are hashing */ ! symint_t indx; /* index within string table */ } thash_t; *************** *** 1556,1570 **** (((unsigned long)num > (unsigned long)max) ? out_of_bounds (num, max, str, __LINE__) : 0) ! #define ORIG_LINENUM(index) (CHECK ((index), orig_sym_hdr.cbLine, "line#"), (index) + orig_linenum) ! #define ORIG_DENSE(index) (CHECK ((index), orig_sym_hdr.idnMax, "dense"), (index) + orig_dense) ! #define ORIG_PROCS(index) (CHECK ((index), orig_sym_hdr.ipdMax, "procs"), (index) + orig_procs) ! #define ORIG_FILES(index) (CHECK ((index), orig_sym_hdr.ifdMax, "funcs"), (index) + orig_files) ! #define ORIG_LSYMS(index) (CHECK ((index), orig_sym_hdr.isymMax, "lsyms"), (index) + orig_local_syms) ! #define ORIG_LSTRS(index) (CHECK ((index), orig_sym_hdr.issMax, "lstrs"), (index) + orig_local_strs) ! #define ORIG_ESYMS(index) (CHECK ((index), orig_sym_hdr.iextMax, "esyms"), (index) + orig_ext_syms) ! #define ORIG_ESTRS(index) (CHECK ((index), orig_sym_hdr.issExtMax, "estrs"), (index) + orig_ext_strs) ! #define ORIG_OPT(index) (CHECK ((index), orig_sym_hdr.ioptMax, "opt"), (index) + orig_opt_syms) ! #define ORIG_AUX(index) (CHECK ((index), orig_sym_hdr.iauxMax, "aux"), (index) + orig_aux_syms) ! #define ORIG_RFDS(index) (CHECK ((index), orig_sym_hdr.crfd, "rfds"), (index) + orig_rfds) /* Various other statics. */ --- 1574,1588 ---- (((unsigned long)num > (unsigned long)max) ? out_of_bounds (num, max, str, __LINE__) : 0) ! #define ORIG_LINENUM(indx) (CHECK ((indx), orig_sym_hdr.cbLine, "line#"), (indx) + orig_linenum) ! #define ORIG_DENSE(indx) (CHECK ((indx), orig_sym_hdr.idnMax, "dense"), (indx) + orig_dense) ! #define ORIG_PROCS(indx) (CHECK ((indx), orig_sym_hdr.ipdMax, "procs"), (indx) + orig_procs) ! #define ORIG_FILES(indx) (CHECK ((indx), orig_sym_hdr.ifdMax, "funcs"), (indx) + orig_files) ! #define ORIG_LSYMS(indx) (CHECK ((indx), orig_sym_hdr.isymMax, "lsyms"), (indx) + orig_local_syms) ! #define ORIG_LSTRS(indx) (CHECK ((indx), orig_sym_hdr.issMax, "lstrs"), (indx) + orig_local_strs) ! #define ORIG_ESYMS(indx) (CHECK ((indx), orig_sym_hdr.iextMax, "esyms"), (indx) + orig_ext_syms) ! #define ORIG_ESTRS(indx) (CHECK ((indx), orig_sym_hdr.issExtMax, "estrs"), (indx) + orig_ext_strs) ! #define ORIG_OPT(indx) (CHECK ((indx), orig_sym_hdr.ioptMax, "opt"), (indx) + orig_opt_syms) ! #define ORIG_AUX(indx) (CHECK ((indx), orig_sym_hdr.iauxMax, "aux"), (indx) + orig_aux_syms) ! #define ORIG_RFDS(indx) (CHECK ((indx), orig_sym_hdr.crfd, "rfds"), (indx) + orig_rfds) /* Various other statics. */ *************** *** 1718,1721 **** --- 1736,1742 ---- STATIC void free_thead __proto((thead_t *)); + STATIC char *local_index __proto((const char *, int)); + STATIC char *local_rindex __proto((const char *, int)); + extern char *sbrk __proto((int)); extern PTR_T malloc __proto((Size_t)); *************** *** 1869,1875 **** hash_ptr->len = len; ! hash_ptr->index = vp->num_allocated; ! hash_ptr->string = p = ! & vp->last->datum->byte[ vp->objects_last_page ]; vp->objects_last_page += len+1; --- 1890,1895 ---- hash_ptr->len = len; ! hash_ptr->indx = vp->num_allocated; ! hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ]; vp->objects_last_page += len+1; *************** *** 1885,1889 **** *ret_hash = hash_ptr; ! return hash_ptr->index; } --- 1905,1909 ---- *ret_hash = hash_ptr; ! return hash_ptr->indx; } *************** *** 2012,2016 **** if (begin_type == st_File || begin_type == st_Block) ! pscope->lsym->index = ret+1; /* block begin gets next sym # */ /* Functions push two or more aux words as follows: --- 2032,2036 ---- if (begin_type == st_File || begin_type == st_Block) ! pscope->lsym->index = ret+1; /* block begin gets next sym # */ /* Functions push two or more aux words as follows: *************** *** 2228,2232 **** if (hash_ptr != (thash_t *)0 && state == hash_yes) ! return hash_ptr->index; if (hash_ptr == (thash_t *)0) --- 2248,2252 ---- if (hash_ptr != (thash_t *)0 && state == hash_yes) ! return hash_ptr->indx; if (hash_ptr == (thash_t *)0) *************** *** 2235,2239 **** hash_ptr->next = hash_tbl[hi]; hash_ptr->type = aux; ! hash_ptr->index = vp->num_allocated; hash_tbl[hi] = hash_ptr; } --- 2255,2259 ---- hash_ptr->next = hash_tbl[hi]; hash_ptr->type = aux; ! hash_ptr->indx = vp->num_allocated; hash_tbl[hi] = hash_ptr; } *************** *** 2271,2275 **** { register symint_t file_index = t->tag_ptr->ifd; ! register symint_t sym_index = t->tag_ptr->index; if (t->unknown_tag) --- 2291,2295 ---- { register symint_t file_index = t->tag_ptr->ifd; ! register symint_t sym_index = t->tag_ptr->indx; if (t->unknown_tag) *************** *** 2325,2332 **** STATIC tag_t * ! get_tag (tag_start, tag_end_p1, index, basic_type) const char *tag_start; /* 1st byte of tag name */ const char *tag_end_p1; /* 1st byte after tag name */ ! symint_t index; /* index of tag start block */ bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */ { --- 2345,2352 ---- STATIC tag_t * ! get_tag (tag_start, tag_end_p1, indx, basic_type) const char *tag_start; /* 1st byte of tag name */ const char *tag_end_p1; /* 1st byte after tag name */ ! symint_t indx; /* index of tag start block */ bt_t basic_type; /* bt_Struct, bt_Union, or bt_Enum */ { *************** *** 2342,2350 **** { tag_ptr = hash_ptr->tag_ptr; ! if (index != indexNil) { tag_ptr->basic_type = basic_type; tag_ptr->ifd = cur_file_ptr->file_index; ! tag_ptr->index = index; } return tag_ptr; --- 2362,2370 ---- { tag_ptr = hash_ptr->tag_ptr; ! if (indx != indexNil) { tag_ptr->basic_type = basic_type; tag_ptr->ifd = cur_file_ptr->file_index; ! tag_ptr->indx = indx; } return tag_ptr; *************** *** 2362,2367 **** tag_ptr->same_name = hash_ptr->tag_ptr; tag_ptr->basic_type = basic_type; ! tag_ptr->index = index; ! tag_ptr->ifd = (index == indexNil) ? -1 : cur_file_ptr->file_index; tag_ptr->same_block = cur_tag_head->first_tag; --- 2382,2387 ---- tag_ptr->same_name = hash_ptr->tag_ptr; tag_ptr->basic_type = basic_type; ! tag_ptr->indx = indx; ! tag_ptr->ifd = (indx == indexNil) ? -1 : cur_file_ptr->file_index; tag_ptr->same_block = cur_tag_head->first_tag; *************** *** 2692,2696 **** /* Read a line from standard input, and return the start of the buffer (which is grows if the line is too big). We split lines at the ! semi-colon, and return each logical line indpendently. */ STATIC char * --- 2712,2716 ---- /* Read a line from standard input, and return the start of the buffer (which is grows if the line is too big). We split lines at the ! semi-colon, and return each logical line independently. */ STATIC char * *************** *** 2748,2752 **** comment_p++; ! else if (ch == ';') { line_split_p = 1; --- 2768,2772 ---- comment_p++; ! else if (ch == ';' && !string_p) { line_split_p = 1; *************** *** 2895,2899 **** int is_function = 0; /* != 0 if function */ symint_t value = 0; ! symint_t index = cur_file_ptr->void_type; int error_line = 0; symint_t arg_number; --- 2915,2919 ---- int is_function = 0; /* != 0 if function */ symint_t value = 0; ! symint_t indx = cur_file_ptr->void_type; int error_line = 0; symint_t arg_number; *************** *** 2911,2922 **** /* Search for the end of the name being defined. */ ! for (name_end_p1 = name_start; (ch = *name_end_p1) != ';'; name_end_p1++) { ! if (ch == '\0' || isspace (ch)) ! { ! error_line = __LINE__; ! saber_stop (); ! goto bomb_out; ! } } --- 2931,2947 ---- /* Search for the end of the name being defined. */ ! /* Allow spaces and such in names for G++ templates, which produce stabs ! that look like: ! ! #.def SMANIP; .scl 10; .type 0x8; .size 8; .endef */ ! ! for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++) ! ; ! ! if (ch == '\0') { ! error_line = __LINE__; ! saber_stop (); ! goto bomb_out; } *************** *** 2977,2990 **** if (!arg_was_number) ! for (arg_end_p1 = arg_start+1; (ch = *arg_end_p1) != ';'; arg_end_p1++) ! { ! if (ch == '\0' || isspace (ch)) ! { ! error_line = __LINE__; ! saber_stop (); ! goto bomb_out; ! } ! } /* Classify the directives now. */ --- 3002,3019 ---- if (!arg_was_number) ! { ! /* Allow spaces and such in names for G++ templates. */ ! for (arg_end_p1 = arg_start+1; ! (ch = *arg_end_p1) != ';' && ch != '\0'; ! arg_end_p1++) ! ; + if (ch == '\0') + { + error_line = __LINE__; + saber_stop (); + goto bomb_out; + } + } /* Classify the directives now. */ *************** *** 3285,3292 **** if (symbol_type == st_Block || symbol_type == st_End) ! index = 0; else if (inside_enumeration) ! index = cur_file_ptr->void_type; else --- 3314,3321 ---- if (symbol_type == st_Block || symbol_type == st_End) ! indx = 0; else if (inside_enumeration) ! indx = cur_file_ptr->void_type; else *************** *** 3315,3321 **** } ! index = add_aux_sym_tir (&t, ! hash_yes, ! &cur_file_ptr->thash_head[0]); } --- 3344,3350 ---- } ! indx = add_aux_sym_tir (&t, ! hash_yes, ! &cur_file_ptr->thash_head[0]); } *************** *** 3328,3332 **** { eptr->ifd = cur_file_ptr->file_index; ! eptr->asym.index = index; } --- 3357,3361 ---- { eptr->ifd = cur_file_ptr->file_index; ! eptr->asym.index = indx; } *************** *** 3370,3374 **** to adjust the value from a byte offset to a bit offset. Members of enumerations do not have the value adjusted, and ! can be distinguished by index == indexNil. For enumerations, update the maximum enumeration value. */ --- 3399,3403 ---- to adjust the value from a byte offset to a bit offset. Members of enumerations do not have the value adjusted, and ! can be distinguished by indx == indexNil. For enumerations, update the maximum enumeration value. */ *************** *** 3391,3395 **** symbol_type, storage_class, value, ! index); /* deal with struct, union, and enum tags. */ --- 3420,3424 ---- symbol_type, storage_class, value, ! indx); /* deal with struct, union, and enum tags. */ *************** *** 3549,3554 **** (void) strtol (start, &p, 0); if (start == p ! || (start_name = strchr (p, '"')) == (char *)0 ! || (end_name_p1 = strrchr (++start_name, '"')) == (char *)0) { error ("Illegal .file directive"); --- 3578,3583 ---- (void) strtol (start, &p, 0); if (start == p ! || (start_name = local_index (p, '"')) == (char *)0 ! || (end_name_p1 = local_rindex (++start_name, '"')) == (char *)0) { error ("Illegal .file directive"); *************** *** 3647,3651 **** if (code == (int)N_SLINE) { ! SYMR *sym_ptr; shash_t *shash_ptr; --- 3676,3680 ---- if (code == (int)N_SLINE) { ! SYMR *sym_ptr, dummy_symr; shash_t *shash_ptr; *************** *** 3659,3663 **** code = strtol (p+3, &p, 0); ch = *++p; ! if (code <= 0 || p[-1] != ',' || isdigit (ch) || !IS_ASM_IDENT (ch)) { error ("Illegal line number .stabs/.stabn directive"); --- 3688,3692 ---- code = strtol (p+3, &p, 0); ch = *++p; ! if (p[-1] != ',' || isdigit (ch) || !IS_ASM_IDENT (ch)) { error ("Illegal line number .stabs/.stabn directive"); *************** *** 3665,3668 **** --- 3694,3706 ---- } + dummy_symr.index = code; + if (dummy_symr.index != code) + { + error ("Line number (%d) for .stabs/.stabn directive cannot fit in index field (20 bits)", + code); + + return; + } + shash_ptr = hash_string (p, strlen (p) - 1, *************** *** 3723,3736 **** { SYMR *sym_ptr; ! shash_t *shash_ptr = hash_string (p, ! strlen (p) - 1, ! &orig_str_hash[0], ! (symint_t *)0); if (shash_ptr == (shash_t *)0 || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0) { ! error ("Illegal .stabs/.stabn directive, value not found"); ! return; } --- 3761,3795 ---- { SYMR *sym_ptr; ! shash_t *shash_ptr; ! const char *start, *end_p1; + start = p; + if ((end_p1 = strchr (start, '+')) == (char *)0) + { + if ((end_p1 = strchr (start, '-')) == (char *)0) + end_p1 = start + strlen(start) - 1; + } + + shash_ptr = hash_string (start, + end_p1 - start, + &orig_str_hash[0], + (symint_t *)0); + if (shash_ptr == (shash_t *)0 || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0) { ! shash_ptr = hash_string (start, ! end_p1 - start, ! &ext_str_hash[0], ! (symint_t *)0); ! ! if (shash_ptr == (shash_t *)0 ! || shash_ptr->esym_ptr == (EXTR *)0) ! { ! error ("Illegal .stabs/.stabn directive, value not found"); ! return; ! } ! else ! sym_ptr = &(shash_ptr->esym_ptr->asym); } *************** *** 3747,3750 **** --- 3806,3830 ---- } value = sym_ptr->value; + + ch = *end_p1++; + if (ch != '\n') + { + if (((!isdigit (*end_p1)) && (*end_p1 != '-')) + || ((ch != '+') && (ch != '-'))) + { + error ("Illegal .stabs/.stabn directive, badly formed value"); + return; + } + if (ch == '+') + value += strtol (end_p1, &p, 0); + else if (ch == '-') + value -= strtol (end_p1, &p, 0); + + if (*p != '\n') + { + error ("Illegal .stabs/.stabn directive, stuff after numeric value"); + return; + } + } } code = MIPS_MARK_STAB(code); *************** *** 3761,3765 **** const char *start; /* start of directive */ { ! const char *end = strchr (start+1, '"'); if (*start != '"' || end == (const char *)0 || end[1] != ',') --- 3841,3845 ---- const char *start; /* start of directive */ { ! const char *end = local_index (start+1, '"'); if (*start != '"' || end == (const char *)0 || end[1] != ',') *************** *** 4459,4463 **** { char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss); ! char *suffix = strrchr (filename, '.'); if (suffix != (char *)0 && strcmp (suffix, ".s") == 0) --- 4539,4543 ---- { char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss); ! char *suffix = local_rindex (filename, '.'); if (suffix != (char *)0 && strcmp (suffix, ".s") == 0) *************** *** 4583,4587 **** shash_ptr->len = len; ! shash_ptr->index = indexNil; shash_ptr->string = str; shash_ptr->sym_ptr = sym; --- 4663,4667 ---- shash_ptr->len = len; ! shash_ptr->indx = indexNil; shash_ptr->string = str; shash_ptr->sym_ptr = sym; *************** *** 4693,4697 **** { int iflag = 0; ! char *p = strrchr (argv[0], '/'); char *num_end; int option; --- 4773,4777 ---- { int iflag = 0; ! char *p = local_rindex (argv[0], '/'); char *num_end; int option; *************** *** 4942,4956 **** static int ! out_of_bounds (index, max, str, prog_line) ! symint_t index; /* index that is out of bounds */ symint_t max; /* maximum index */ const char *str; /* string to print out */ int prog_line; /* line number within mips-tfile.c */ { ! if (index < max) /* just in case */ return 0; fprintf (stderr, "%s, %s:%ld index %u is out of bounds for %s, max is %u, mips-tfile.c line# %d\n", ! progname, input_name, line_number, index, str, max, prog_line); exit (1); --- 5022,5036 ---- static int ! out_of_bounds (indx, max, str, prog_line) ! symint_t indx; /* index that is out of bounds */ symint_t max; /* maximum index */ const char *str; /* string to print out */ int prog_line; /* line number within mips-tfile.c */ { ! if (indx < max) /* just in case */ return 0; fprintf (stderr, "%s, %s:%ld index %u is out of bounds for %s, max is %u, mips-tfile.c line# %d\n", ! progname, input_name, line_number, indx, str, max, prog_line); exit (1); *************** *** 5429,5433 **** } ! #endif /* MIPS_DEBUGGING_INFO *? --- 5509,5513 ---- } ! #endif /* MIPS_DEBUGGING_INFO */ *************** *** 5564,5566 **** --- 5644,5683 ---- free (ptr); + } + + + /* Define our own index/rindex, since the local and global symbol + structures as defined by MIPS has an 'index' field. */ + + STATIC char * + local_index (str, sentinel) + const char *str; + int sentinel; + { + int ch; + + for ( ; (ch = *str) != sentinel; str++) + { + if (ch == '\0') + return (char *)0; + } + + return (char *)str; + } + + STATIC char * + local_rindex (str, sentinel) + const char *str; + int sentinel; + { + int ch; + const char *ret = (const char *)0; + + for ( ; (ch = *str) != '\0'; str++) + { + if (ch == sentinel) + ret = str; + } + + return (char *)ret; } diff -rc2N gcc-2.2.2/move-if-change gcc-2.3.1/move-if-change *** gcc-2.2.2/move-if-change Sun Jul 28 16:41:51 1991 --- gcc-2.3.1/move-if-change Fri Sep 4 03:54:04 1992 *************** *** 1,3 **** --- 1,5 ---- #!/bin/sh + # Like mv $1 $2, but if the files are the same, just delete $1. + # Status is 0 if $2 is changed, 1 otherwise. if test -r $2 diff -rc2N gcc-2.2.2/objc/Makefile gcc-2.3.1/objc/Makefile *** gcc-2.2.2/objc/Makefile --- gcc-2.3.1/objc/Makefile Sun Oct 18 20:59:28 1992 *************** *** 0 **** --- 1,50 ---- + # 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)" + # Two targets are used by ../Makefile: `all' and `mostlyclean'. + + .SUFFIXES: .m + + VPATH = $(srcdir)/objc + + AR = ar + AR_FLAGS = rc + + # Always search these dirs when compiling. + SUBDIR_INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/config + + .c.o: + $(GCC_FOR_TARGET) -c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $< + + .m.o: + $(GCC_FOR_TARGET) -c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $< + + # If we were not invoked from the parent dir, + # invoke make in the parent dir and have reinvoke this makefile. + # That's necessary to get the right values for srcdir, etc. + all: + cd ..; $(MAKE) sublibobjc.a + + libobjc.a: core.o hash.o object.o + -rm -f libobjc.a + $(AR) rc libobjc.a object.o core.o hash.o + # ranlib is run in the parent directory's makefile. + + OBJC_H = objc.h objc-proto.h record.h ../assert.h ../gstdarg.h + HASH_H = hash.h mutex.h + + core.o: core.c $(OBJC_H) $(HASH_H) ../gstddef.h + hash.o: hash.c $(OBJC_H) $(HASH_H) ../gstddef.h + object.o: object.m object.h $(OBJC_H) + $(GCC_FOR_TARGET) -c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $< + + mostlyclean: + -rm -f core.o hash.o object.o libobjc.a + clean: mostlyclean + distclean: mostlyclean + extraclean: mostlyclean diff -rc2N gcc-2.2.2/objc/Object.h gcc-2.3.1/objc/Object.h *** gcc-2.2.2/objc/Object.h --- gcc-2.3.1/objc/Object.h Fri Oct 16 21:08:59 1992 *************** *** 0 **** --- 1,116 ---- + /* Declare the class Object for Objective C programs. + Copyright (C) 1992 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. */ + + /* 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 __object_INCLUDE_GNU + #define __object_INCLUDE_GNU + + #include "objc.h" + #include "stdio.h" + + + /* + * All classes are derived from Object. As such this is the + * overhead tacked onto those objects. + */ + @interface Object { + Class_t isa; /* A pointer to the instance's + class structure. + + This structure is the one + generated by the compiler + and located in the TEXT + segment. The run-time uses + its address as a key to + run-time information. */ + } + + /* Creating, copying, and freeing instances */ + + + new; + + free; + - free; + - copy; + - shallowCopy; + - deepCopy; + + /* Identifying classes */ + + + ( Class_t )class; + + ( Class_t )superClass; + - ( Class_t )class; + - ( Class_t )superClass; + - ( const char* )name; + + /* Identifying and comparing instances */ + + - self; + - ( unsigned int )hash; + - ( BOOL )isEqual:anObject; + + /* Testing inheritance relationships */ + + - ( BOOL )isKindOf:( Class_t )aClassObject; + - ( BOOL )isMemberOf:( Class_t )aClassObject; + - ( BOOL )isKindOfGivenName:( const char* )aClassName; + - ( BOOL )isMemberOfGivenName:( const char* )aClassName; + + /* Testing class functionality */ + + + ( BOOL )instancesRespondTo:( SEL )aSel; + - ( BOOL )respondsTo:( SEL )aSel; + + /* Sending messages determined at run time */ + + - perform:( SEL )aSel; + - perform:( SEL )aSel with:aObject; + + /* Posing */ + + + poseAs:( Class_t )aClassObject; + + /* Enforcing intentions */ + + - subclassResponsibility:( SEL )aSel; + - notImplemented:( SEL )aSel; + + /* Error handling */ + + - doesNotRecognize:(SEL)aSelector; + - error:( const char* )aString, ...; + + error:( const char* )aString, ...; + + /* Archiving */ + + - storeOn:( int )aFd; + + readFrom:( int )aFd; + - readFrom:( int )aFd; + + ( int )version; + + setVersion:( int )aVersion; + + @end + + + #endif + diff -rc2N gcc-2.2.2/objc/core.c gcc-2.3.1/objc/core.c *** gcc-2.2.2/objc/core.c --- gcc-2.3.1/objc/core.c Wed Oct 28 16:50:37 1992 *************** *** 0 **** --- 1,1360 ---- + /* Method dispatcher and class-object creator for Objective C. + Copyright (C) 1992 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. */ + + /* 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 "tconfig.h" + #include "assert.h" + #include + #include "gstdarg.h" + #include + #include "gstddef.h" + + #include "hash.h" + #include "objc.h" + #include "objc-proto.h" + + + #define MODULE_HASH_SIZE 32 /* Initial module hash table size. + Value doesn't really matter. */ + + #define CLASS_HASH_SIZE 32 /* Initial number of buckets size of + class hash table. Value doesn't + really matter. */ + + + /* Forward declare some functions. */ + id objc_object_create (Class_t), + objc_object_dispose (id), + objc_object_realloc (id, unsigned int), + objc_object_copy (id); + void objc_error (id object, const char *fmt, va_list ap); + static id nil_method (id, SEL, ...); + static id return_error_static (id, SEL, ...); + static IMP handle_runtime_error (id, SEL); + static void initialize_dispatch_tables (void); + static SEL record_selector (const char*); + static void record_methods_from_class (Class_t); + static void record_methods_from_list (MethodList_t); + static void initialize_class (const char*); + /* + * This is a hash table of Class_t structures. + * + * At initialization the executable is searched for all Class_t structures. + * Since these structures are created by the compiler they are therefore + * located in the TEXT segment. + * + * A identical structure is allocated from the free store and initialized from + * its TEXT counterpart and placed in the hash table using the TEXT part as + * its key. + * + * Since the free store structure is now writable, additional initialization + * takes place such as its "info" variable, method cache allocation, and + * linking of all of its method and ivar lists from multiple implementations. + */ + cache_ptr class_hash_table = NULL; + + /* + * This variable is a flag used within the messaging routines. If a + * application sets it to !0 then the messager will print messages sent to + * objects. + */ + BOOL objc_trace = NO; + + /* This mutex provides a course lock for method dispatch. */ + MUTEX runtimeMutex; + + /* + * This hash table is used by the initialization routines. When the + * constructor function (__objc_execClass) is called it is passed a pointer + * to a module structure. That pointer is stored in this table and its + * contents are processed in __objcInit. + */ + cache_ptr module_hash_table = NULL; + + /* + * This hash table is used in the constructor subroutine to hold pointers + * to categories that have not been attached to a class. Constructors are + * received in a random order. Files may contain category implementation + * of objects whose constructor hasn't been executed yet. Therefore, + * there is no object to attach the categories. + * + * This hash table holds pointers to categories that haven't been + * attached to objects. As objects are processed the category hash + * table is searched for attachments. If a category is found for the + * object it is attached to the object and deleted from the hash table. + */ + cache_ptr unclaimed_category_hash_table = NULL; + + /* + * This flag is used by the messager routines to determine if the run-time + * has been initialized. If the run-time isn't initialized then a + * initialization clean up routine is called. + */ + static int initialized = 0; + + /* + * Records that hold pointers to arrays of records. The terminal records are + * method implementations. + * + * The size of the first record is the number of unique classes in the + * executable. The second is the number of selectors. + * + * The second record conatins methods that are visible to the class -- that is, + * methods that are not overriden from the classt to the root object. + * + * The cache pointers of class and meta class structures point to one of these + * records. + */ + static struct record *instance_method_record = NULL; + static struct record *factory_method_record = NULL; + + /* + * This structure is used to translate between selectors and their ASCII + * representation. A NULL terminated array of char*, + * OBJC_SELECTOR_REFERENCES, is passed to the constructor routine: + * __objc_execClass. That routine places entries from that array into this + * structure. The location within OBJC_SELECTOR_REFERENCES where the string + * was taken from is replaced with a small integer, the index into the array + * inside selectorTranslateTable. That integer then becomes the selector. + * + * Selectors begin at 1 to numEntries. A selector outside of that range is + * considered an error. The selector integers are used as the first index + * into the instance_method_record and factory_method_record arrays. + */ + static struct record *selector_record = NULL; + + /* + * This data structure is used in the special case where usual fatal error + * functions are called but have been overridden in a class. The value + * returned by that function is returned to the calling object. error_static + * holds the returned value until it is retrieved by return_error_static + * which returns it to the calling function. + */ + static id error_static; + + + /* Given a class and selector, return the selector's implementation. */ + static inline IMP + get_imp (Class_t class, SEL sel) + { + IMP imp = NULL; + imp = record_get (getClassNumber (class), + record_get ((unsigned int)sel, *class->cache)); + + return imp; + } + + + static void + error (msg, arg1, arg2) + char *msg, *arg1, *arg2; + { + #if 0 /* There is no portable way to get the program name. Too bad. */ + fprintf (stderr, "%s: ", programname); + #endif + fprintf (stderr, msg, arg1, arg2); + fprintf (stderr, "\n"); + } + + static void + fatal (msg, arg1, arg2) + char *msg, *arg1, *arg2; + { + error (msg, arg1, arg2); + exit (1); + } + + static void * + xmalloc (unsigned int size) + { + void *ptr = (void *) malloc (size); + if (ptr == 0) + fatal ("virtual memory exceeded"); + return ptr; + } + + static void * + xcalloc (unsigned int size, unsigned int units) + { + void *ptr = (void *) calloc (size, units); + if (ptr == 0) + fatal ("virtual memory exceeded"); + return ptr; + } + + void * + __objc_xmalloc (unsigned int size) + { + void *ptr = (void *) malloc (size); + if (ptr == 0) + fatal ("virtual memory exceeded"); + return ptr; + } + + void * + __objc_xrealloc (void *optr, unsigned int size) + { + void *ptr = (void *) realloc (optr, size); + if (ptr == 0) + fatal ("virtual memory exceeded"); + return ptr; + } + + void * + __objc_xcalloc (unsigned int size, unsigned int units) + { + void *ptr = (void *) calloc (size, units); + if (ptr == 0) + fatal ("virtual memory exceeded"); + return ptr; + } + + static inline char * + my_strdup (const char *str) + { + char *new = (char *) xmalloc (strlen (str) + 1); + strcpy (new, str); + + return new; + } + + + /* + * This function is called by constructor functions generated for each module + * compiled. + * + * The purpose of this function is to gather the module pointers so that they + * may be processed by the initialization clean up routine. + */ + void + __objc_execClass (Module_t module) + { + /* Has we processed any constructors previously? + Flag used to indicate that some global data structures + need to be built. */ + static BOOL previous_constructors = 0; + + Symtab_t symtab = module->symtab; + Class_t object_class; + node_ptr node; + SEL *(*selectors)[] = (SEL *(*)[])symtab->refs; + int i; + BOOL incomplete = 0; + + + assert (module->size == sizeof (Module)); + DEBUG_PRINTF ("received load module: %s\n",module->name); + + /* Header file data structure hack test. */ + assert (sizeof (Class) == sizeof (MetaClass)); + + /* On the first call of this routine, initialize + some data structures. */ + if (!previous_constructors) { + + /* Enable malloc debugging. This'll slow'er down! */ + #if defined (DEBUG) && defined (NeXT) + malloc_debug (62); + #endif + + /* Allocate and initialize the mutex. */ + MUTEX_ALLOC (&runtimeMutex); + MUTEX_INIT (runtimeMutex); + + /* Allocate the module hash table. */ + module_hash_table + = hash_new (MODULE_HASH_SIZE, (hash_func_type)hash_ptr, + (compare_func_type)compare_ptrs); + + /* Allocate a table for unclaimed categories. */ + unclaimed_category_hash_table + = hash_new (16, (hash_func_type)hash_ptr, + (compare_func_type)compare_ptrs); + + /* Allocate a master selector table if it doesn't exist. */ + selector_record = record_new (); + + previous_constructors = 1; + } + + /* Save the module pointer for later processing. */ + hash_add (&module_hash_table, module, module); + + /* Parse the classes in the load module and gather selector information. */ + DEBUG_PRINTF ("gathering selectors from module: %s\n",module->name); + for (i = 0; i < symtab->cls_def_cnt; ++i) { + Class_t class = (Class_t)symtab->defs[i]; + + /* Make sure we have what we think. */ + assert (class->info & CLS_CLASS); + assert (class->class_pointer->info & CLS_META); + DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name); + + /* Store the class in the class table and assign class numbers. */ + addClassToHash (class); + + /* Store all of the selectors in the class and meta class. */ + record_methods_from_class (class); + record_methods_from_class ((Class_t)class->class_pointer); + + /* Initialize the cache pointers. */ + class->cache = &instance_method_record; + class->class_pointer->cache = &factory_method_record; + } + + /* Replace referenced selectors. */ + for (i=0; i < symtab->sel_ref_cnt; ++i) + (*selectors)[i] = record_selector ((const char*)(*selectors)[i]); + + /* Try to build the class hierarchy and initialize the data structures. */ + object_class = objc_getClass ("Object"); + if (object_class) { + + /* Make sure we have what we think we have. */ + assert (object_class->class_pointer->info & CLS_META); + assert (object_class->info & CLS_CLASS); + + /* Connect the classes together (at least as much as we can). */ + for (node = hash_next (class_hash_table, NULL); node; + node = hash_next (class_hash_table, node)) { + Class_t class1 = node->value; + + /* Make sure we have what we think we have. */ + assert (class1->info & CLS_CLASS); + assert (class1->class_pointer->info & CLS_META); + + /* The class_pointer of all meta classes point to Object's meta class. */ + class1->class_pointer->class_pointer = object_class->class_pointer; + + /* Assign super class pointers */ + if (class1->super_class) { + Class_t aSuperClass = objc_getClass ((char*)class1->super_class); + + if (aSuperClass) { + + DEBUG_PRINTF ("making class connections for: %s\n", + class1->name); + + class1->super_class = aSuperClass; + if (class1->class_pointer->super_class) + class1->class_pointer->super_class = class1->super_class->class_pointer; + + /* Mark the class as initialized. */ + class1->info |= CLS_RTI; + } else + /* Couldn't find the class's super class. */ + incomplete = 1; + } + } + } else + /* Couldn't find class Object. */ + incomplete = 1; + + /* Process category information from the module. */ + for (i = 0; i < symtab->cat_def_cnt; ++i) { + Category_t category = symtab->defs[i + symtab->cls_def_cnt]; + Class_t class = objc_getClass (category->class_name); + + /* If the class for the category exists then append its + methods. */ + if (class) { + + DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n", + module->name, + class_getClassName (class)); + + /* Do instance methods. */ + if (category->instance_methods) + addMethodsToClass (class, category->instance_methods); + + /* Do class methods. */ + if (category->class_methods) + addMethodsToClass ((Class_t)class->class_pointer, category->class_methods); + } else { + /* The object to which the category methods belong can't + be found. Save the information. */ + hash_add (&unclaimed_category_hash_table, category, category); + + incomplete = 1; + } + } + + /* Scan the unclaimed category hash. + Attempt to attach any unclaimed categories to objects. */ + for (node = hash_next (unclaimed_category_hash_table, NULL); node; + node = hash_next (unclaimed_category_hash_table, node)) { + Category_t category = node->value; + Class_t class = objc_getClass (category->class_name); + + if (class) { + + DEBUG_PRINTF ("attaching stored categories to object: %s\n", + class_getClassName (class)); + + /* Delete this class from the hash table. */ + hash_remove (unclaimed_category_hash_table, category); + node = NULL; + + if (category->instance_methods) + addMethodsToClass (class, category->instance_methods); + + if (category->class_methods) + addMethodsToClass ((Class_t)class->class_pointer, + category->class_methods); + } else + incomplete = 1; + } + + /* Can we finish the run time initialization? */ + if (!incomplete) { + + initialize_dispatch_tables (); + + /* Debug run time test. + We're initialized! */ + initialized = 1; + + /* Print out class tables if debugging. */ + DEBUG_PRINTF ("dump of class tables from objcInit\n"); + debug_dump_classes (); + } + + } + + + IMP + objc_msgSend (id receiver, SEL sel) + { + /* + * A method is always called by the compiler. If a method wasn't + * found then supply a default. + */ + IMP imp = nil_method; + + + /* The run time must be initialized at this point. + Otherwise we get a message sent to a object with a bogus selector. */ + assert (initialized); + + /* Objective-C allows messages to be sent to a nil object. */ + if (receiver) { + + /* Check for common programmer error. */ + if (!receiver->class_pointer) { + fprintf (stderr, "method %s sent to deallocated object %#x\n", + sel_getName (sel), receiver); + abort (); + } + + /* Initialize the class if need be. */ + if (!(receiver->class_pointer->info & CLS_INITIALIZED)) + initialize_class (receiver->class_pointer->name); + + /* + * If we're passed a object then its class_pointer is a Class. If + * we're passed a Class then its class_pointer is a MetaClass. + * Therefore, searching for a instance or class method + * requires no special decision making here. + * + * Look for the method. + */ + imp = get_imp (receiver->class_pointer, sel); + + /* If the method cannot be found then perform error handling. */ + if (!imp) + imp = handle_runtime_error (receiver, sel); + } + + /* Nice debugging messages if enabled. */ + if (objc_trace) { + printf ("trace: objc_msgSend , obj=%#x, class=%s, method=%s\n", + receiver, + receiver->class_pointer->name, + sel_getName (sel)); + fflush (stdout); + } + + return imp; + } + + + IMP + objc_msgSendSuper (Super_t super, SEL sel) + { + IMP imp; + + + assert (initialized); + + if (!(super->class->info & CLS_INITIALIZED)) + initialize_class (super->class->name); + if (!(super->receiver->class_pointer->info & CLS_INITIALIZED)) + initialize_class (super->receiver->class_pointer->name); + + imp = get_imp (super->class, sel); + + if (!imp) + imp = handle_runtime_error (super->receiver, sel); + + if (objc_trace) { + printf ("trace: objc_msgSendSuper , obj=%#x, class=%s, method=%s\n", + super->receiver, + super->receiver->class_pointer->name, + sel_getName (sel)); + fflush (stdout); + } + + return imp; + } + + + /* + * This function is called by objc_msgSend or objc_msgSendSuper when a + * message is sent to a object which it does not recognize. + */ + static IMP + handle_runtime_error (id object, SEL sel) + { + IMP imp; + + + /* + * If the object recognizes the doesNotRecognize: method then we're + * going to send it. + */ + imp = get_imp (object->class_pointer, sel_getUid ("doesNotRecognize:")); + if (imp) + error_static = (*imp)(object, sel_getUid ("doesNotRecognize:"), sel); + else { + /* + * The object doesn't recognize the method. Check for + * responding to error:. If it does then sent it. + */ + char msg[256 + strlen (sel_getName (sel)) + + strlen (object->class_pointer->name)]; + + sprintf (msg, "%s does not recognize %s", + object->class_pointer->name, sel_getName (sel)); + + imp = get_imp (object->class_pointer, sel_getUid ("error:")); + if (imp) + error_static = (*imp)(object, sel_getUid ("error:"), msg); + else { + /* + * The object doesn't respond to doesNotRecognize: or + * error:; Therefore, a default action is taken. + */ + fprintf (stderr, "%s\n", msg); + abort (); + } + } + + /* + * Either doesNotRecognize: or error: has been overridden. We have + * to return that value as the default action. + */ + return return_error_static; + } + + + /* + * This function is used by the run-time to provide a method where nil + * objects can receive messages. + * + * This method simply returns self. + */ + static id + nil_method (id object, SEL sel, ...) + { + return object; + } + + + /* + * This function is used by the run-time to provide a method where nil + * objects can receive messages. + * + * This method simply returns self. + * + * Note: multiple thread problem area. + */ + static id + return_error_static (id object, SEL sel, ...) + { + return error_static; + } + + + /* + * These variables provide a way for the defalut methods of object + * allocation, destruction, and reallocation to be overridden. + */ + id (*_alloc)(Class_t) = objc_object_create; + id (*_dealloc)(id) = objc_object_dispose; + id (*_realloc)(id, unsigned int) = objc_object_realloc; + id (*_copy)(id) = objc_object_copy; + void (*_error)(id, const char*, va_list) = objc_error; + + + id + objc_object_create (Class_t class) + { + id object; + + + assert (class); + + /* + * Allocate memory for the object, initialize the memory to 0, and + * set the object's class_pointer. + * + * The object's class_pointer is the class's TEXT image. It is used by + * the messager as the key to the class hash for methods. + * + * No need to initialize the class. That was done in objcInit. + */ + object = (id) xcalloc (1, class->instance_size); + object->class_pointer = class; + + return object; + } + + + id + objc_object_dispose (id object) + { + object->class_pointer = NULL; + free (object); + + return nil; + } + + + id + objc_object_realloc (id object, unsigned int length) + { + id obj; + /* Can't resize a object smaller than its instance size. */ + /* Don't use assert here; + checks for user errors shouldn't depend on NDEBUG. */ + if (length < object->class_pointer->instance_size) + abort (); + + obj = (id) realloc (object, length); + bzero ((char*)obj + object->class_pointer->instance_size, + length - object->class_pointer->instance_size); + + return obj; + } + + + id + objc_object_copy (id object) + { + id obj; + obj = class_createInstance (object->class_pointer); + bcopy (object, obj, objc_classSize (object)); + + return obj; + } + + + void + objc_error (id object, const char *fmt, va_list ap) + { + vfprintf (stderr, fmt, ap); + abort (); + } + + + /* Silly function to skip past a sequence of digits in a string. */ + static inline const char * + skip_digits (const char *str) + { + while (isdigit (*str)) + ++str; + + return str; + } + + + unsigned int + method_getNumberOfArguments (Method_t method) + { + unsigned int num = 0; + const char *args = &method->method_types[1]; + + + while (*args) { + + /* Skip past size info. */ + args = skip_digits (args); + + /* Argument type next. */ + assert (*args); + ++num; + + /* Step to next arg. */ + ++args; + } + + assert (num >= 2); + return num; + } + + + unsigned int + method_getArgumentInfo (Method_t method, int indx, const char **type, + int *offset) + { + const char *args = skip_digits (&method->method_types[1]); + int i; + + + assert (method_getNumberOfArguments (method) >= indx); + + /* Step to arg. */ + for (i = 0; i < indx; ++i) { + ++args; + args = skip_digits (args); + } + + /* Return arg data. */ + *type = args++; + *offset = atoi (args); + + return indx; + } + + + /* This function is not thread safe. */ + Ivar_t + object_getIvarAddress (id object, const char *name) + { + Class_t class = object->class_pointer; /* Here is the thread safe problem. */ + Ivar_t ivar = NULL; + + + do { + IvarList_t ivars = class->ivars; + int i; + + /* Look at all of the ivar names. */ + for (i = 0; i < ivars->ivar_count; ++i) + if (!strcmp (name, ivars->ivar_list[i].ivar_name)) + ivar = &ivars->ivar_list[i]; + + /* + * If the ivar wasn't found then lets look to the + * super class. + * + * If the class is Object then the super class is NULL + * and we're done. + */ + class = class->super_class; + + } while (!ivar && class); + + return ivar; + } + + + /* + * Search for a method starting from the current class up its hierarchy. + * + * Return a pointer to the method's method structure if found. NULL otherwise. + */ + Method_t + searchForMethodInHierarchy (Class_t class, SEL sel) + { + Method_t method = NULL; + const char* name = sel_getName (sel); + + + /* + * Scan the method list of the class. If the method isn't found in + * the list then step to its super class. + */ + do { + + method = searchForMethodInList (class->methods, name); + class = class->super_class; + + } while (!method && class); + + return method; + } + + + /* + * Given a linked list of method and a method's name. Search for the named + * method's method structure. + * + * Return a pointer to the method's method structure if found. NULL otherwise. + */ + Method_t + searchForMethodInList (MethodList_t list, const char *name) + { + MethodList_t method_list = list; + + + /* Check for bumbling. */ + /* ??? Who generates the name? Is it the user, or part of this file? + If we crash here, whose fault is it? */ + assert (name); + + /* If not found then we'll search the list. */ + while (method_list) { + int i; + + /* Search the method list. */ + for (i = 0; i < method_list->method_count; ++i) { + Method_t method = &method_list->method_list[i]; + + if (method->method_name) + if (!strcmp (method->method_name, name)) + return method; + } + + /* The method wasn't found. Follow the link to the next list of + methods. */ + method_list = method_list->method_next; + } + + return NULL; + } + + + /* + * This function adds a method list to a class. + * + * This function is typically called by another function specific to the + * run-time. As such this function does not worry about thread safe issued. + */ + void + addMethodsToClass (Class_t class, MethodList_t list) + { + int i; + + + /* Passing of a linked list is not allowed. Do multiple calls. */ + assert (!list->method_next); + + /* Check for duplicates. */ + for (i = 0; i < list->method_count; ++i) { + Method_t method = &list->method_list[i]; + + if (method->method_name) /* Sometimes these are NULL */ + if (searchForMethodInList (class->methods, method->method_name)) { + /* + * Duplication. Print a error message an change the + * method name to NULL. + */ + fprintf (stderr, "attempt to add a existing method: %s\n", + method->method_name); + method->method_name = NULL; + } + } + + /* Add the methods to the class's method list. */ + list->method_next = class->methods; + class->methods = list; + } + + + /* + * This function removes the instance and factory methods in the passed list + * from a class. + * + * Methods are removed from a class by replacing the method's name with NULL. + * + * + * This function is typically called by another function specific to the + * run-time. As such this function does not worry about thread safe issued. + */ + void + class_removeMethods (Class_t class, MethodList_t method_list) + { + int i; + + + /* Passing of a linked list is not allowed. Do multiple calls. */ + assert (!method_list->method_next); + + /* + * For each method in the list search the method lists erasing any + * entries found. + */ + for (i = 0; i < method_list->method_count; ++i) { + Method_t kill_method = &method_list->method_list[i]; + Method_t method; + + /* Remove any instance method found. */ + method = searchForMethodInList (class->methods, + kill_method->method_name); + if (method) + method->method_name = NULL; + + /* Remove any factory method found. */ + method = searchForMethodInList (class->class_pointer->methods, + kill_method->method_name); + if (method) + method->method_name = NULL; + } + } + + + /* + * This is a incomplete implementation of posing. This function does the + * bulk of the work but does not initialize the class method caches. That is + * a run-time specific operation. + * + * I implement posing by hiding SUPER_CLASS, creating new class and meta + * class structures, initializing it with IMPOSTOR, and changing it such + * that it is identified as SUPER_CLASS. SUPER_CLASS remains in the + * hierarchy but is inaccessible by the means. The class hierarchy is then re + * arranged such that all of the subclasses of SUPER_CLASS now inherit from + * the new class structures -- except the impostor itself. The only dramatic + * effect on the application is that subclasses of SUPER_CLASS cannot do a + * [ .... superClass ] and expect their real super class. + */ + Class_t + class_poseAs (Class_t impostor, Class_t super_class) + { + Class_t new_class = (Class_t) calloc (1, sizeof (Class)); + MetaClass_t new_meta_class = (MetaClass_t) calloc (1, sizeof (MetaClass)); + node_ptr node; + char *new_name = (char *) malloc (strlen (super_class->name) + 12); + + + assert (new_class); + assert (new_meta_class); + assert (new_name); + + /* No dispatching while the the posing class is being built. + The dispatch tables will be hacked on. */ + MUTEX_LOCK (runtimeMutex); + + assert (impostor->info & CLS_CLASS); + assert (super_class->info & CLS_CLASS); + + assert (impostor->instance_size == super_class->instance_size); + + /* Create the impostor class. */ + new_class->class_pointer = new_meta_class; + new_class->super_class = super_class; + new_class->name = super_class->name; + new_class->version = super_class->version; + new_class->info = super_class->info; + new_class->instance_size = super_class->instance_size; + new_class->ivars = super_class->ivars; + new_class->methods = impostor->methods; + new_class->cache = &instance_method_record; + + /* Create the impostor meta class. */ + new_meta_class->class_pointer = super_class->class_pointer->class_pointer; + new_meta_class->super_class = super_class->class_pointer->super_class; + new_meta_class->name = super_class->class_pointer->name; + new_meta_class->version = super_class->class_pointer->version; + new_meta_class->info = super_class->class_pointer->info; + new_meta_class->instance_size = super_class->class_pointer->instance_size; + new_meta_class->ivars = super_class->class_pointer->ivars; + new_meta_class->methods = impostor->class_pointer->methods; + new_meta_class->cache = &factory_method_record; + + /* + * Delete the class from the hash table, change its name so that it + * can no longer be found, then place it back into the hash table + * using its new name. + * + * Don't worry about the class number. It is already assigned. + * + * Don't worry about dangling pointers. Life's a bitch. (A little bit + * of memory is lost with the hash key.) + */ + hash_remove (class_hash_table, super_class->name); + sprintf (new_name, "%s*", super_class->name); + super_class->name = new_name; + super_class->class_pointer->name = new_name; + hash_add (&class_hash_table, super_class->name, super_class); + + /* + * Now change all of the classes derived from super_class to be + * derived from a impostor (except the impostor's impostor. + */ + for (node = hash_next (class_hash_table, NULL); node; + node = hash_next (class_hash_table, node)) { + + Class_t class1 = node->value; + + if (class1->super_class == super_class) + if (class1 != impostor) + class1->super_class = new_class; + } + + /* Place the impostor class in class hash table + and assign it a class number. */ + addClassToHash (new_class); + + /* Reinitialize the dispatch tables. */ + initialize_dispatch_tables (); + + MUTEX_UNLOCK (runtimeMutex); + + /* Print out class tables if debugging. */ + DEBUG_PRINTF ("dump of class tables class_poseAs\n"); + debug_dump_classes (); + + return new_class; + } + + + /* + * This routine is given a class and records all of the methods in its class + * structure in the record table. + */ + static void + record_methods_from_class (Class_t class) + { + MethodList_t method_list; + + + method_list = class->methods; + while (method_list) { + record_methods_from_list (method_list); + method_list = method_list->method_next; + } + } + + + /* + * This routine is given a list of methods and records each of the methods in + * the record table. This is the routine that does the actual recording + * work. + */ + static void + record_methods_from_list (MethodList_t method_list) + { + int i; + + + for (i = 0; i < method_list->method_count; ++i) { + Method_t method = &method_list->method_list[i]; + + record_selector (method->method_name); + } + } + + + SEL + sel_getUid (const STR name) + { + int i; + + + for (i = 1; i <= record_entries (selector_record); ++i) + if (!strcmp (name, record_get (i, selector_record))) + return (SEL)i; + + /* Unable to locate selector. Return error value. */ + return (SEL)0; + } + + + STR + sel_getName (SEL selector) + { + return record_get ((unsigned int)selector, selector_record); + } + + + /* + * Store the passed selector name in the selector record and return its + * selector value (value returned by sel_getUid). + */ + static SEL + record_selector (const char *sel) + { + int j; + + + /* Find either the selector in the table or an empty slot. */ + for (j = 1; j <= record_entries (selector_record); ++j) + if (!strcmp (sel, record_get (j, selector_record))) + return (SEL)j; + + /* Save the selector name. */ + record_store (my_strdup (sel), selector_record); + DEBUG_PRINTF ("Record: %s as: %#x\n", sel, j); + + return (SEL)j; + } + + + /* + * Initialize the dispatch tables. This requires the initialization of the + * instance_method_record and factory_method_record arrays and the arrays they + * point to. + * + * The first array is indexed by a class number. Therefore its size is the + * number of classes in the executable. The second array is indexed by a + * selector id. Therefore its size is the number of unique selectors in the + * application. + * + * When a method is sent to a object its class number is extracted from the + * class structure and used in the first array. The selector id is used in + * the second. The result value is a method implementation. + */ + static void + initialize_dispatch_tables (void) + { + int i; + + + /* Check to make sure things are in place. */ + assert (selector_record); + + /* Blow away the instance and factory method records. */ + if (factory_method_record) { + for (i = 1; i <= record_entries (factory_method_record); ++i) + record_delete (record_get (i, factory_method_record)); + record_delete (factory_method_record); + } + if (instance_method_record) { + for (i = 1; i <= record_entries (instance_method_record); ++i) + record_delete (record_get (i, instance_method_record)); + record_delete (instance_method_record); + } + + /* Reallocate the instance and factory method records. */ + factory_method_record = record_new (); + instance_method_record = record_new (); + for (i = 1; i <= record_entries (selector_record); ++i) { + record_store (record_new (), factory_method_record); + record_store (record_new (), instance_method_record); + } + + /* Fool all of the secondary records into thinking they have data. */ + for (i = 1; i <= record_entries (selector_record); ++i) { + struct record *record; + node_ptr node; + + record = record_get (i, factory_method_record); + for (node = hash_next (module_hash_table, NULL); node; + node = hash_next (module_hash_table, node)) + record_store (NULL, record); + + record = record_get (i, instance_method_record); + for (node = hash_next (module_hash_table, NULL); node; + node = hash_next (module_hash_table, node)) + record_store (NULL, record); + } + + /* For all classes fill in the methods implemented by the class and visiable + from the class in the hierarchy. Those methods are assigned to the + class. */ + for (i = 1; i <= record_entries (selector_record); ++i) { /* i is a sel */ + node_ptr node; + + for (node = hash_next (class_hash_table, NULL); node; + node = hash_next (class_hash_table, node)) { + Class_t class = node->value; + MetaClass_t meta_class = class->class_pointer; + int class_number = getClassNumber (class); + Method_t method; + + /* DEBUG_PRINTF ("Assignment of sel=%s, class=%s (%#x, %#x)\n", + sel_getName ((SEL)i), class->name, + searchForMethodInHierarchy (class, (SEL)i), + searchForMethodInHierarchy ((Class_t)meta_class, (SEL)i)); */ + + method = searchForMethodInHierarchy (class, (SEL)i); + if (method) + record_store_at (class_number, method->method_imp, + record_get (i, instance_method_record)); + + assert (class_number == getClassNumber ((Class_t)class->class_pointer)); + method = searchForMethodInHierarchy ((Class_t)meta_class, (SEL)i); + if (method) + record_store_at (class_number, method->method_imp, + record_get (i, factory_method_record)); + } + } + } + + + /* + * This method is called by the dispatch routines when a class has not been + * initialized. This method is responsible for initializing the class. This + * is accomplished by first testing the class itself for responding to the + * +initialize method. If such a method is implemented then it is called. + * Before exit, irregardless if the class implements +initialize, the class + * is marked as initialized. + */ + static void + initialize_class (const char *name) + { + Method_t method = NULL; + Class_t class = objc_getClass (name); + SEL sel = sel_getUid ("initialize"); + + + /* The class should not be initialized at this point. */ + assert (!(class->info & CLS_INITIALIZED)); + assert (!(class->class_pointer->info & CLS_INITIALIZED)); + + /* Search for the +initialize method. + Call it if it exists. */ + method + = searchForMethodInList (class->class_pointer->methods, sel_getName (sel)); + if (method) { + IMP imp; + + DEBUG_PRINTF ("Class: %s sending +%s\n", + name, sel_getName (sel)); + imp = get_imp ((Class_t)class->class_pointer, sel); + assert (imp); + (*imp)((id)class, sel); + } + + /* Mark the class as initialized. */ + class->info |= CLS_INITIALIZED; + class->class_pointer->info |= CLS_INITIALIZED; + } + + + /* + * Silly little function that checks to make sure the class hash table is + * initialized. If it isn't initialized then do it. + */ + static inline void + class_hash_init (void) + { + static unsigned int init = 0; + + + if (!init) + class_hash_table = hash_new (CLASS_HASH_SIZE, + (hash_func_type)hash_string, + (compare_func_type)compare_strings); + init = 1; + } + + + Class_t + objc_getClass (const char *name) + { + Class_t class; + + + /* Make sure the class hash table exists. */ + class_hash_init (); + + class = hash_value_for_key (class_hash_table, name); + + return class; + } + + + MetaClass_t + objc_getMetaClass (const char *name) + { + /* Meta classes are pointed to by the class's class_pointer. + Just get the class and return its class_pointer. */ + return (objc_getClass (name))->class_pointer; + } + + + void + addClassToHash (Class_t class) + { + Class_t hClass; + + + class_hash_init (); + + /* Check to see if the class is already in the hash table. */ + hClass = hash_value_for_key (class_hash_table, class->name); + if (!hClass) { + + /* The class isn't in the hash table. Add the class and + assign a class number. */ + static unsigned int class_number = 1; + + setClassNumber (class, class_number); + setClassNumber ((Class_t)class->class_pointer, class_number); + ++class_number; + + hash_add (&class_hash_table, class->name, class); + } + } + + + void + debug_dump_classes (void) + { + node_ptr node; + int i; + + + DEBUG_PRINTF ("class tables\n"); + i = 0; + for (node = hash_next (class_hash_table, NULL); node; + node = hash_next (class_hash_table, node)) { + + Class_t class = node->value; + + DEBUG_PRINTF ("Class { /*%#x*/\n", class); + DEBUG_PRINTF (" MetaClass_t class_pointer = %#x\n", class->class_pointer); + DEBUG_PRINTF (" Class_t super_class = %#x\n", class->super_class); + DEBUG_PRINTF (" char *name = %s\n", class->name); + DEBUG_PRINTF (" long version = %ld\n", class->version); + DEBUG_PRINTF (" long info = %#x\n", class->info); + DEBUG_PRINTF (" long instance_size = %ld\n", class->instance_size); + DEBUG_PRINTF (" IvarList_t ivars = %#x\n", class->ivars); + DEBUG_PRINTF (" MethodList_t methods = %#x\n", class->methods); + DEBUG_PRINTF (" cache_ptr cache = %#x\n", class->cache); + DEBUG_PRINTF ("}[%d];\n", i++); + } + + i = 0; + for (node = hash_next (class_hash_table, NULL); node; + node = hash_next (class_hash_table, node)) { + + Class_t class = (Class_t)((Class_t)(node->value))->class_pointer; + + DEBUG_PRINTF ("MetaClass { /*%#x*/\n", class); + DEBUG_PRINTF (" MetaClass_t class_pointer = %#x\n", class->class_pointer); + DEBUG_PRINTF (" MetaClass_t super_class = %#x\n", class->super_class); + DEBUG_PRINTF (" char *name = %s\n", class->name); + DEBUG_PRINTF (" long version = %ld\n", class->version); + DEBUG_PRINTF (" long info = %#x\n", class->info); + DEBUG_PRINTF (" long instance_size = %ld\n", class->instance_size); + DEBUG_PRINTF (" IvarList_t ivars = %#x\n", class->ivars); + DEBUG_PRINTF (" MethodList_t methods = %#x\n", class->methods); + DEBUG_PRINTF (" cache_ptr cache = %#x\n", class->cache); + DEBUG_PRINTF ("}[%d];\n", i++); + } + } + diff -rc2N gcc-2.2.2/objc/hash.c gcc-2.3.1/objc/hash.c *** gcc-2.2.2/objc/hash.c --- gcc-2.3.1/objc/hash.c Wed Oct 28 16:50:40 1992 *************** *** 0 **** --- 1,254 ---- + /* Hash tables for Objective C method dispatch. + Copyright (C) 1992 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. */ + + /* 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 "tconfig.h" + #include "gstddef.h" + #include "gstdarg.h" + #include "assert.h" + + #include "hash.h" + #include "objc.h" + #include "objc-proto.h" + + + /* These two macros determine when a hash table is full and + by how much it should be expanded respectively. + + These equations are percentages. */ + #define FULLNESS(cache) \ + ((((cache)->size * 75) / 100) <= (cache)->used) + #define EXPANSION(cache) \ + ((cache)->size * 2) + + cache_ptr + hash_new (unsigned int size, hash_func_type hash_func, + compare_func_type compare_func) + { + cache_ptr cache; + + + /* Pass me a value greater than 0 and a power of 2. */ + assert (size); + assert (!(size & (size - 1))); + + /* Allocate the cache structure. calloc insures + its initialization for default values. */ + cache = (cache_ptr) calloc (1, sizeof (struct cache)); + assert (cache); + + /* Allocate the array of buckets for the cache. + calloc initializes all of the pointers to NULL. */ + cache->node_table + = (node_ptr *) calloc (size, sizeof (node_ptr)); + assert (cache->node_table); + + cache->size = size; + + /* This should work for all processor architectures? */ + cache->mask = (size - 1); + + /* Store the hashing function so that codes can be computed. */ + cache->hash_func = hash_func; + + /* Store the function that compares hash keys to + determine if they are equal. */ + cache->compare_func = compare_func; + + return cache; + } + + + void + hash_delete (cache_ptr cache) + { + node_ptr node; + + + /* Purge all key/value pairs from the table. */ + while (node = hash_next (cache, NULL)) + hash_remove (cache, node->key); + + /* Release the array of nodes and the cache itself. */ + free (cache->node_table); + free (cache); + } + + + void + hash_add (cache_ptr *cachep, const void *key, void *value) + { + size_t indx = (*(*cachep)->hash_func)(*cachep, key); + node_ptr node = (node_ptr) calloc (1, sizeof (struct cache_node)); + + + assert (node); + + /* Initialize the new node. */ + node->key = key; + node->value = value; + node->next = (*cachep)->node_table[indx]; + + /* Debugging. + Check the list for another key. */ + #ifdef DEBUG + { node_ptr node1 = (*cachep)->node_table[indx]; + + while (node1) { + + assert (node1->key != key); + node1 = node1->next; + } + } + #endif + + /* Install the node as the first element on the list. */ + (*cachep)->node_table[indx] = node; + + /* Bump the number of entries in the cache. */ + ++(*cachep)->used; + + /* Check the hash table's fullness. We're going + to expand if it is above the fullness level. */ + if (FULLNESS (*cachep)) { + + /* The hash table has reached its fullness level. Time to + expand it. + + I'm using a slow method here but is built on other + primitive functions thereby increasing its + correctness. */ + node_ptr node1 = NULL; + cache_ptr new = hash_new (EXPANSION (*cachep), + (*cachep)->hash_func, + (*cachep)->compare_func); + + DEBUG_PRINTF ("Expanding cache %#x from %d to %d\n", + *cachep, (*cachep)->size, new->size); + + /* Copy the nodes from the first hash table to the new one. */ + while (node1 = hash_next (*cachep, node1)) + hash_add (&new, node1->key, node1->value); + + /* Trash the old cache. */ + hash_delete (*cachep); + + /* Return a pointer to the new hash table. */ + *cachep = new; + } + } + + + void + hash_remove (cache_ptr cache, const void *key) + { + size_t indx = (*cache->hash_func)(cache, key); + node_ptr node = cache->node_table[indx]; + + + /* We assume there is an entry in the table. Error if it is not. */ + assert (node); + + /* Special case. First element is the key/value pair to be removed. */ + if ((*cache->compare_func)(node->key, key)) { + cache->node_table[indx] = node->next; + free (node); + } else { + + /* Otherwise, find the hash entry. */ + node_ptr prev = node; + BOOL removed = NO; + + do { + + if ((*cache->compare_func)(node->key, key)) { + prev->next = node->next, removed = YES; + free (node); + } else + prev = node, node = node->next; + } while (!removed && node); + assert (removed); + } + + /* Decrement the number of entries in the hash table. */ + --cache->used; + } + + + node_ptr + hash_next (cache_ptr cache, node_ptr node) + { + /* If the scan is being started then reset the last node + visitied pointer and bucket index. */ + if (!node) + cache->last_bucket = 0; + + /* If there is a node visited last then check for another + entry in the same bucket; Otherwise step to the next bucket. */ + if (node) { + if (node->next) + /* There is a node which follows the last node + returned. Step to that node and retun it. */ + return node->next; + else + ++cache->last_bucket; + } + + /* If the list isn't exhausted then search the buckets for + other nodes. */ + if (cache->last_bucket < cache->size) { + /* Scan the remainder of the buckets looking for an entry + at the head of the list. Return the first item found. */ + while (cache->last_bucket < cache->size) + if (cache->node_table[cache->last_bucket]) + return cache->node_table[cache->last_bucket]; + else + ++cache->last_bucket; + + /* No further nodes were found in the hash table. */ + return NULL; + } else + return NULL; + } + + + /* Given KEY, return corresponding value for it in CACHE. + Return NULL if the KEY is not recorded. */ + + void * + hash_value_for_key (cache_ptr cache, const void *key) + { + node_ptr node = cache->node_table[(*cache->hash_func)(cache, key)]; + void *retval = NULL; + + if (node) + do { + if ((*cache->compare_func)(node->key, key)) + retval = node->value; + else + node = node->next; + } while (!retval && node); + + return retval; + } diff -rc2N gcc-2.2.2/objc/hash.h gcc-2.3.1/objc/hash.h *** gcc-2.2.2/objc/hash.h --- gcc-2.3.1/objc/hash.h Mon Oct 26 03:15:43 1992 *************** *** 0 **** --- 1,197 ---- + /* Hash tables for Objective C method dispatch. + Copyright (C) 1992 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. */ + + /* 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 __hash_INCLUDE_GNU + #define __hash_INCLUDE_GNU + + #include "mutex.h" + + + /* + * This data structure is used to hold items + * stored in a hash table. Each node holds + * a key/value pair. + * + * Items in the cache are really of type void *. + */ + typedef struct cache_node + { + struct cache_node *next; /* Pointer to next entry on the list. + NULL indicates end of list. */ + const void *key; /* Key used to locate the value. Used + to locate value when more than one + key computes the same hash + value. */ + void *value; /* Value stored for the key. */ + } *node_ptr; + + + /* + * This data type is the function that computes a hash code given a key. + * Therefore, the key can be a pointer to anything and the function specific + * to the key type. + * + * Unfortunately there is a mutual data structure reference problem with this + * typedef. Therefore, to remove compiler warnings the functions passed to + * hash_new will have to be casted to this type. + */ + typedef unsigned int (*hash_func_type)(void *, const void *); + + /* + * This data type is the function that compares two hash keys and returns an + * integer greater than, equal to, or less than 0, according as the first + * parameter is lexico-graphically greater than, equal to, or less than the + * second. + */ + + typedef int (*compare_func_type)(const void *, const void *); + + + /* + * This data structure is the cache. + * + * It must be passed to all of the hashing routines + * (except for new). + */ + typedef struct cache + { + /* Variables used to implement the hash itself. */ + node_ptr *node_table; /* Pointer to an array of hash nodes. */ + /* Variables used to track the size of the hash table so to determine + when to resize it. */ + unsigned int size; /* Number of buckets allocated for the hash table + (number of array entries allocated for + "node_table"). Must be a power of two. */ + unsigned int used; /* Current number of entries in the hash table. */ + unsigned int mask; /* Precomputed mask. */ + + /* Variables used to implement indexing through the hash table. */ + + unsigned int last_bucket; /* Tracks which entry in the array where + the last value was returned. */ + /* Function used to compute a hash code given a key. + This function is specified when the hash table is created. */ + hash_func_type hash_func; + /* Function used to compare two hash keys to see if they are equal. */ + compare_func_type compare_func; + } *cache_ptr; + + + /* Two important hash tables. */ + extern cache_ptr module_hash_table, class_hash_table; + + /* Allocate and initialize a hash table. */ + + cache_ptr hash_new (unsigned int size, + hash_func_type hash_func, + compare_func_type compare_func); + + /* Deallocate all of the hash nodes and the cache itself. */ + + void hash_delete (cache_ptr cache); + + /* Add the key/value pair to the hash table. If the + hash table reaches a level of fullnes then it will be resized. + + assert if the key is already in the hash. */ + + void hash_add (cache_ptr *cachep, const void *key, void *value); + + /* Remove the key/value pair from the hash table. + assert if the key isn't in the table. */ + + void hash_remove (cache_ptr cache, const void *key); + + /* Used to index through the hash table. Start with NULL + to get the first entry. + + Successive calls pass the value returned previously. + ** Don't modify the hash during this operation *** + + Cache nodes are returned such that key or value can + be extracted. */ + + node_ptr hash_next (cache_ptr cache, node_ptr node); + + /* Used to return a value from a hash table using a given key. */ + + void *hash_value_for_key (cache_ptr cache, const void *key); + + + /************************************************ + + Useful hashing functions. + + Declared inline for your pleaseure. + + ************************************************/ + + /* Calculate a hash code by performing some + manipulation of the key pointer. (Use the lowest bits + except for those likely to be 0 due to alignment.) */ + + static inline unsigned int + hash_ptr (cache_ptr cache, const void *key) + { + return ((unsigned int)key / sizeof (void *)) & cache->mask; + } + + + /* Calculate a hash code by iterating over a NULL + terminate string. */ + static inline unsigned int + hash_string (cache_ptr cache, const void *key) + { + unsigned int ret = 0; + unsigned int ctr = 0; + + + while (*(char*)key) { + ret ^= *(char*)key++ << ctr; + ctr = (ctr + 1) % sizeof (void *); + } + + return ret & cache->mask; + } + + + /* Compare two pointers for equality. */ + static inline int + compare_ptrs (const void *k1, const void *k2) + { + return !(k1 - k2); + } + + + /* Compare two strings. */ + static inline int + compare_strings (const void *k1, const void *k2) + { + return !strcmp (k1, k2); + } + + + #endif /* not __hash_INCLUDE_GNU */ diff -rc2N gcc-2.2.2/objc/mutex.h gcc-2.3.1/objc/mutex.h *** gcc-2.2.2/objc/mutex.h --- gcc-2.3.1/objc/mutex.h Wed Oct 14 04:57:51 1992 *************** *** 0 **** --- 1,110 ---- + /* Copyright (C) 1992 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. */ + + /* 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 _MUTEX_H + #define _MUTEX_H + + #ifdef WANT_MUTEX + #if defined (NeXT) + #include + #define MUTEX mutex_t + #define MUTEX_ALLOC(mutex) { *mutex = mutex_alloc (); } + #define MUTEX_INIT(mutex) mutex_init (mutex) + #define MUTEX_FREE(mutex) mutex_free (mutex) + #define MUTEX_LOCK(mutex) mutex_lock (mutex) + #define MUTEX_UNLOCK(mutex) mutex_unlock (mutex) + #define MUTEX_ISLOCK(mutex) mutex->lock /* Gak */ + + #elif defined (OSF) + + #elif defined (mach) + + #elif defined (sun) + /* + * Sun lwp uses monitors. + * + * Untested. 8-Dec-91, dennisg. + */ + #include + #include + + #define MUTEX (mon_t) + + inline MUTEX + MUTEX_ALLOC (mutex) + { + MUTEX mon; + + mon_create (&mon); + return mon; + } + + #define MUTEX_INIT(mutex) + #define MUTEX_FREE(mutex) mon_destroy (mutex) + + inline void + MUTEX_LOCK (mutex) + { + int level = mon_enter (mutex); + assert (level); + } + + #define MUTEX_UNLOCK(mutex) mon_exit (mutex) + + inline int + MUTEX_ISLOCK (mutex) + { + thread_t thread; + + /* Won't work? */ + return mon_waiters (mutex, &thread, NULL, 0); + } + + #elif defined (COROUTINES) + /* + * A environment where threads are implemented as a + * set of coroutines. + */ + + #endif + #endif + + #ifndef MUTEX + /* + * These are default mutex handler routines. + * There is no mutex support. + * + * Let the optimizer get rid of mutexes. + */ + + #define MUTEX void * + #define MUTEX_ALLOC(mutex) (MUTEX)-1 + #define MUTEX_INIT(mutex) (mutex) + #define MUTEX_FREE(mutex) (mutex) + #define MUTEX_LOCK(mutex) (mutex) + #define MUTEX_UNLOCK(mutex) (mutex) + #define MUTEX_ISLOCK(mutex) 1 + #endif + + #endif /* not _MUTEX_H */ diff -rc2N gcc-2.2.2/objc/objc-proto.h gcc-2.3.1/objc/objc-proto.h *** gcc-2.2.2/objc/objc-proto.h --- gcc-2.3.1/objc/objc-proto.h Wed Oct 28 16:50:47 1992 *************** *** 0 **** --- 1,421 ---- + /* Declare functions used within Objective C runtime support. + Copyright (C) 1992 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. */ + + /* 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 __objc_proto_INCLUDE_GNU + #define __objc_proto_INCLUDE_GNU + + /* This used to be #ifndef __OBJC__, but it turns out that + object.m needs these declarations. I don't understand why one + might want to avoid them in object.m. */ + + #if 1 + /* + * objc_getClass returns the id of the class + * object for the aClassName class. The class + * object holds information used by instances of + * the class. + * + * Print a message to the standard error stream if + * aClassName isn't part of the executable image. + */ + Class_t objc_getClass (const char *); + + /* + * objc_getMetaClass returns the id of the + * meta class object for the aClassName class. + * The meta class object holds information used + * by the class object, just as the class + * object holds information used by instances + * of the class. + * + * Print a message to the standard error stream + * if aClassName isn't part of the executable image. + */ + MetaClass_t objc_getMetaClass (const char *); + + /* + * The compiler converts every message expression into a + * call on one of these two functions. Messages to + * super are converted to calls on objc_msgSendSuper; + * all others are converted to calls on objc_msgSend. + * + * These functions return the address of the method + * implementation. The compiler then generates calls + * to those methods passing the full argument array. + * + * Calls to objc_msgSend and objc_msgSendSuper + * should be generated only by the compiler. You shouldn't + * call them directly in the Objective-C code you write. + */ + IMP objc_msgSend (id, SEL); + + IMP objc_msgSendSuper (Super_t, SEL); + #endif + + /* + * Given the name of a variable within a class's + * definition, return a pointer to a structure that + * describes it. + */ + Ivar_t object_getIvarAddress (id obj, const char *variableName); + + /* + * Given a class and a selector, return a pointer to the method's method + * structure. Return NULL if not found. + * + * This is a method internal to the run-time. + */ + Method_t searchForMethodInHierarchy (Class_t, SEL); + + + /* + * The first function, sel_getUid, returns a selector that's + * used at run time to identify the aName method. Whenever + * possible, you should use the @selector directive to + * ask the compiler, rather than the run-time system, + * to provide the selector for a method. This function + * should be used only if the name isn't known at compile + * time. + * + * The second function, sel_getName, is the inverse + * of the first. It returns the name that was mapped to + * aSelector. + */ + SEL sel_getUid (const STR); + + const STR sel_getName (SEL); + + /* + * This function returns the number of arguments that METHOD + * the takes. This will be at least two, since it + * includes the ªhiddenº arguments, self and _cmd, + * which are the first two arguments passed to every + * method implementation. + */ + unsigned int method_getNumberOfArguments (Method_t method); + + /* This functiontakes an index into METHOD's argument + * list and returns, by reference, the type of the argument + * and the offset to the location of that argument in the + * list. Indices begin with 0. The ªhiddenº arguments + * self and _cmd are indexed at 0 and 1; method-specific + * arguments begin at index 2. The offset is measured in + * bytes and depends on the size of arguments preceding the + * indexed argument in the argument list. The type is + * encoded according to the conventions of the @encode + * compiler directive. + */ + unsigned int method_getArgumentInfo (Method_t, int indx, + const char **type, int *offset); + + /* + * This function is used to support archiving when a unknown class is to read + * from a archive. This function returns a instantiated object. To further + * dearchive the object it should be sent: -readFrom:. + * + * This function positions the file pointer just past class Object's class + * data. + */ + id objc_objectFromFile (int fd); + + /* + * class_getInstanceMethod returns a pointer + * to the data structure that describes the method. + * + * The selector must identify an + * instance method. + * + * Return a NULL pointer if SEL doesn't + * identify a method defined in or inherited + * by CLASS. + */ + static inline Method_t + class_getInstanceMethod (Class_t class, SEL sel) + { + return searchForMethodInHierarchy (class, sel); + } + + /* + * class_getClassMethod returns a pointer to + * the data structure that describes the method. + * + * The selector must identify a class (factory) method. + * + * Return a NULL pointer if SEL doesn't + * identify a method defined in or inherited by CLASS. + */ + static inline Method_t + class_getClassMethod (MetaClass_t class, SEL sel) + { + return searchForMethodInHierarchy ((Class_t)class, sel); + } + + /* + * This function returns the name of OBJ's + * class. anObject should be an instance + * object, not a class object. + */ + static inline const char * + object_getClassName (id obj) + { + return obj->class_pointer->name; + } + + /* + * This function returns the name of the + * class. + */ + static inline const char * + class_getClassName (Class_t class) + { + return class->name; + } + + /* + * Add a class to the class hash table and assign it a class number. + */ + void addClassToHash (Class_t class); + + /* + * This function takes a list of methods and adds them to the method list of + * a class. The method list must remain intact during the lifetime of the + * class. + */ + void addMethodsToClass (Class_t, MethodList_t); + + /* + * This function creates a new instance of CLASS, initializes its class_pointer + * instance variable to point to the class, and return the new instance. + * + * All other instance variables are initialized to 0. + */ + static inline id + class_createInstance (Class_t class) + { + return (*_alloc)(class); + } + + /* + * object_dispose frees the memory occupied by OBJ after setting its + * class_pointer instance variable to nil, and returns nil. The function it calls to + * do this work can be changed by reassigning the _dealloc variable. + */ + static inline id + object_dispose (id obj) + { + return (*_dealloc)(obj); + } + + /* + * object_copy creates a new object that's an exact copy of anObject and + * return the new object. The second argument, indexedIvarBytes, specifies + * the number of additional bytes that should be allocated for the copy to + * accommodate indexed instance variables; it serves the same purpose as the + * second argument to class_createInstance. The function that + * object_copy calls to do this work can be changed by reassigning the + * _copy variable. + */ + static inline id + object_copy (id obj) + { + return (*_copy)(obj); + } + + /* + * object_realloc reallocates storage for anObject, adding numBytes if + * possible. The memory previously occupied by anObject is freed if it can't + * be reused, and a pointer to the new location of anObject is returned. The + * function that object_realloc calls to do this work can be changed by + * reassigning the _realloc variable. + */ + static inline id + object_realloc (id obj, unsigned int size) + { + return (*_realloc)(obj, size); + } + + /* + * This function causes one class to pose as its super class. Messages sent + * to the super class will actually be sent to the posing class. + * + * Instance variables should not be declared in the posing class. The posing + * class can add new methods to the class or override existing methods in the + * super class. + */ + Class_t class_poseAs (Class_t, Class_t); + + + /* These functions set and return the class version number. */ + static inline void + class_setVersion (Class_t class, long version) + { + class->version = version ; + class->class_pointer->version = version ; + } + + static inline long + class_getVersion (Class_t class) + { + return class->version ; + } + + + /* + * Class numbers are stored in the class's info variable. This is temporary. + * Eventually we will allocate a member to the class so that some efficiency + * can be gained by not shifting. + */ + #define CLASS_LOCATION_SHIFT (HOST_BITS_PER_LONG / 2) + + static inline void + setClassNumber (Class_t class, unsigned long number) + { + class->info |= number << CLASS_LOCATION_SHIFT; + } + + static inline unsigned long + getClassNumber (Class_t class) + { + return class->info >> CLASS_LOCATION_SHIFT; + } + + /* + * class_addInstanceMethods adds methods that can be + * used by instances of the class and class_addClassMethods + * adds methods used by the class object. Before adding a + * method, both functions check for duplicates. A warning + * is sent to the standard error stream if any ambiguities exist. + * + * The passed structure and its contents must exist for the the + * duration of the program. These functions don't support + * linked structures. + */ + static inline void + class_addInstanceMethods (Class_t class, MethodList_t method_list) + { + addMethodsToClass (class, method_list); + } + + static inline void + class_addClassMethods (Class_t class, MethodList_t method_list) + { + addMethodsToClass ((Class_t)class->class_pointer, method_list); + } + + /* + * This function returns the number of bytes that all of METHOD's + * arguments, taken together, would occupy on the stack. + */ + static inline unsigned int + method_getSizeOfArguments (Method_t method) + { + return atoi (&method->method_types[1]); + } + + /* + * This function returns the size in bytes of a + * instance of OBJ. + */ + static inline long + objc_classSize (id obj) + { + return obj->class_pointer->instance_size; + } + + /* Some functions that I've been told are useful by Henry Flurry */ + + /* Returns a C string representing the ASCII rep of the selector. */ + static inline const char * + SELNAME (SEL sel) + { + return sel_getName (sel); + } + + /* + * Converts a C string to a SEL that can be used in perform: methods, + * objc_msgSend, etc. + */ + static inline SEL + SELUID (const STR str) + { + return sel_getUid (str); + } + + /* + * Returns the class name of the object (or meta class name of a class + * object), or some _nilName if obj is nil. + */ + static inline const char * + NAMEOF (id obj) + { + const char *name = 0; + + if (obj) + { + if (obj->class_pointer->info & CLS_CLASS) + name = object_getClassName (obj); + else if (((Class_t)obj)->class_pointer->info & CLS_META) + name = class_getClassName ((Class_t)obj); + } + + return name; + } + + /* + * These functions add and remove methods in a list from a class. These + * functions perform the actual work required for those functions. + * + * The appropriate run-time is to provide the user callable functions to + * perform these functions. Typically those functions perform something + * specific to their run-time type and call these functions to perform the + * actual work. + */ + void class_removeMethods (Class_t class, MethodList_t method_list); + + /* + * Find the named method in a linked list of methods. + */ + Method_t searchForMethodInList (MethodList_t list, const char *name); + + /* + * printf is used if we're debugging. If DEBUG isn't defined then this + * def isn't defined thereby causing the compiler to eliminate the parameter + * decl. + */ + #ifdef DEBUG + #define DEBUG_PRINTF printf + #else + #define DEBUG_PRINTF + #endif + + + /* + * Function that dumps information about all of the classes to stdout. + */ + void debug_dump_classes (void); + + #endif /* not __objc_proto_INCLUDE_GNU */ + diff -rc2N gcc-2.2.2/objc/objc.h gcc-2.3.1/objc/objc.h *** gcc-2.2.2/objc/objc.h --- gcc-2.3.1/objc/objc.h Wed Oct 28 16:50:43 1992 *************** *** 0 **** --- 1,354 ---- + /* Basic data types for Objective C. + Copyright (C) 1992 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. */ + + /* 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 __objc_INCLUDE_GNU + #define __objc_INCLUDE_GNU + + /* If someone is using a c++ compiler then adjust the types in the + file back to C. */ + #ifdef __cplusplus + extern "C" { + #endif + + #include "record.h" + + + #define nil (id)0 /* id of Nil instance */ + #define Nil (Class_t)0 /* id of Nil class */ + typedef char* STR; /* String alias */ + + /* Boolean typedefs */ + typedef char BOOL; + #define YES (BOOL)1 + #define NO (BOOL)0 + + /* Definition of a selector. Selectors are really of type char*. The + run-time hashes the string's address to locate the method. If the + method isn't in the hash table then a search is made through the + class hierarchy using strcmp to locate the method. */ + #if 0 + typedef struct objc_selector* SEL; + #else + typedef void* SEL; + #endif + + /* ObjC uses this typedef for untyped instances. */ + + typedef struct objc_object { + struct objc_class* class_pointer; + } *id; + + /* Prototype for method functions. */ + typedef id (*IMP)(id, SEL, ...); + + /* Filer types used to describe Ivars and Methods. */ + #define _C_ID '@' + #define _C_CLASS '#' + #define _C_SEL ':' + #define _C_CHR 'c' + #define _C_UCHR 'C' + #define _C_SHT 's' + #define _C_USHT 'S' + #define _C_INT 'i' + #define _C_UINT 'I' + #define _C_LNG 'l' + #define _C_ULNG 'L' + #define _C_FLT 'f' + #define _C_DBL 'd' + #define _C_BFLD 'b' + #define _C_VOID 'v' + #define _C_UNDEF '?' + #define _C_PTR '^' + #define _C_CHARPTR '*' + #define _C_ARY_B '[' + #define _C_ARY_E ']' + #define _C_UNION_B '(' + #define _C_UNION_E ')' + #define _C_STRUCT_B '{' + #define _C_STRUCT_E '}' + + /* These definitions are masks used with the "info" member variable in + the lass and meta class structures. */ + #define CLS_CLASS 0x1L /* The structure is of type + class (Class_t). */ + #define CLS_META 0x2L /* The structure is of type + meta class (MetaClass_t). */ + #define CLS_INITIALIZED 0x4L /* Class is initialized. A + +initialize method is the + first message sent to a + class. It isn't guaranteed + to be sent only once. */ + #define CLS_RTI 0x8L /* The class has been initialized + within the run time library. */ + + /* Set this variable nonzero to print a line describing each + message that is sent. */ + extern BOOL objc_trace; + + + /* + * Whereas a Module (defined further down) is the root (typically) of a file, + * a Symtab is the root of the class and category definitions within the + * module. + * + * A Symtab contains a variable length array of pointers to classes and + * categories defined in the module. + */ + typedef struct objc_symtab { + unsigned long sel_ref_cnt; /* Unknown. */ + SEL *refs; /* Unknown. */ + unsigned short cls_def_cnt; /* Number of classes compiled + (defined) in the module. */ + unsigned short cat_def_cnt; /* Number of categories + compiled (defined) in the + module. */ + void *defs[1]; /* Variable array of pointers. + cls_def_cnt of type Class_t + followed by cat_def_cnt of + type Category_t. */ + } Symtab, *Symtab_t; + + + /* + * The compiler generates one of these structures for each module that + * composes the executable (eg main.m). + * + * This data structure is the root of the definition tree for the module. + * + * A collect program runs between ld stages and creates a ObjC ctor array. + * That array holds a pointer to each module structure of the executable. + */ + typedef struct objc_module { + unsigned long version; /* Compiler revision. */ + unsigned long size; /* sizeof(Module). */ + const char* name; /* Name of the file where the + module was generated. The + name includes the path. */ + Symtab_t symtab; /* Pointer to the Symtab of + the module. The Symtab + holds an array of pointers to + the classes and categories + defined in the module. */ + } Module, *Module_t; + + + /* + * The compiler generates one of these structures for a class that has + * instance variables defined in its specification. + */ + typedef struct objc_ivar* Ivar_t; + typedef struct objc_ivar_list { + int ivar_count; /* Number of structures (Ivar) + contained in the list. One + structure per instance + variable defined in the + class. */ + struct objc_ivar { + const char* ivar_name; /* Name of the instance + variable as entered in the + class definition. */ + const char* ivar_type; /* Description of the Ivar's + type. Useful for + debuggers. */ + int ivar_offset; /* Byte offset from the base + address of the instance + structure to the variable. */ + + } ivar_list[1]; /* Variable length + structure. */ + } IvarList, *IvarList_t; + + + /* + * The compiler generates one (or more) of these structures for a class that + * has methods defined in its specification. + * + * The implementation of a class can be broken into separate pieces in a file + * and categories can break them across modules. To handle this problem is a + * singly linked list of methods. + */ + typedef struct objc_method Method; + typedef Method* Method_t; + typedef struct objc_method_list { + struct objc_method_list* method_next; /* This variable is used to link + a method list to another. It + is a singly linked list. */ + int method_count; /* Number of methods defined in + this structure. */ + struct objc_method { + SEL method_name; /* This variable is the method's + name. It is a char*. + The unique integer passed to + objc_msgSend is a char* too. + It is compared against + method_name using strcmp. */ + const char* method_types; /* Description of the method's + parameter list. Useful for + debuggers. */ + IMP method_imp; /* Address of the method in the + executable. */ + } method_list[1]; /* Variable length + structure. */ + } MethodList, *MethodList_t; + + + /* + * The compiler generates one of these structures for each class. + * + * This structure is the definition for meta classes. By definition a meta + * class is the class's class. Its most relevant contribution is that its + * method list contain the class's factory methods. + * + * This structure is generated by the compiler in the executable and used by + * the run-time during normal messaging operations. Therefore some members + * change type. The compiler generates "char* const" and places a string in + * the following member variables: class_pointer and super_class. + */ + typedef struct objc_metaClass { + struct objc_metaClass* class_pointer; /* Pointer to Object meta class. */ + struct objc_metaClass* super_class; /* Pointer to meta class's + super class. NULL for + Object. */ + const char* name; /* Name of the meta class. */ + long version; /* Unknown. */ + long info; /* Bit mask. See class masks + defined above. */ + long instance_size; /* Always 0 except for Object. + Should be ignored. */ + IvarList_t ivars; /* Always NULL except for + Object. Should be ignored. */ + MethodList_t methods; /* Linked List of factory methods + for the class. */ + struct record ** cache; /* Pointer to factory method dispatch table. */ + } MetaClass, *MetaClass_t; + + + /* + * The compiler generates one of these structures for each class. + * + * This structure is the definition for classes. + * + * This structure is generated by the compiler in the executable and used by + * the run-time during normal messaging operations. Therefore some members + * change type. The compiler generates "char* const" and places a string in + * the following member variables: super_class. + */ + typedef struct objc_class { + MetaClass_t class_pointer; /* Pointer to the class's + meta class. */ + struct objc_class* super_class; /* Pointer to the super + class. NULL for class + Object. */ + const char* name; /* Name of the class. */ + long version; /* Unknown. */ + long info; /* Bit mask. See class masks + defined above. */ + long instance_size; /* Size in bytes of the class. + The sum of the class definition + and all super class + definitions. */ + IvarList_t ivars; /* Pointer to a structure that + describes the instance + variables in the class + definition. NULL indicates + no instance variables. Does + not include super class + variables. */ + MethodList_t methods; /* Linked list of instance + methods defined for the + class. */ + struct record ** cache; /* Pointer to instance method dispatch table. */ + } Class, *Class_t; + + + /* + * The compiler generates one of these structures for each category. A class + * may have many categories and contain both instance and factory methods. + */ + typedef struct objc_category { + const char* category_name; /* Name of the category. Name + contained in the () of the + category definition. */ + const char* class_name; /* Name of the class to which + the category belongs. */ + MethodList_t instance_methods; /* Linked list of instance + methods defined in the + category. NULL indicates no + instance methods defined. */ + MethodList_t class_methods; /* Linked list of factory + methods defined in the + category. NULL indicates no + class methods defined. */ + } Category, *Category_t; + + + /* + * Structure used when a message is send to a class's super class. The + * compiler generates one of these structures and passes it to + * objc_msgSuper. + */ + typedef struct objc_super { + id receiver; /* Id of the object sending + the message. */ + Class_t class; /* Object's super class. */ + } Super, *Super_t; + + /* + * _alloc points to the function, called through class_createInstance, used + * to allocate memory for new instances. + */ + extern id (*_alloc)(Class_t); + /* + * _dealloc points to the function, called through object_dispose, used to + * free instances. + */ + extern id (*_dealloc)(id); + /* + * _realloc points to the function, called through object_realloc, used to + * reallocate memory for an object + */ + extern id (*_realloc)(id, unsigned int); + + /* + * _copy points to the function, called through object_copy, used to create + * an exact copy of an object. + */ + extern id (*_copy)(id); + + /* + * _error points to the function that the run-time system calls in response + * to an error. By default, it prints formatted error messages to the + * standard error stream and calls abort to produce a core file. + */ + extern void (*_error)(id object, const char *fmt, va_list ap); + + + #ifdef __cplusplus + } + #endif + + + #endif /* not __objc_INCLUDE_GNU */ diff -rc2N gcc-2.2.2/objc/object.h gcc-2.3.1/objc/object.h *** gcc-2.2.2/objc/object.h --- gcc-2.3.1/objc/object.h Fri Oct 16 21:08:59 1992 *************** *** 0 **** --- 1,116 ---- + /* Declare the class Object for Objective C programs. + Copyright (C) 1992 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. */ + + /* 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 __object_INCLUDE_GNU + #define __object_INCLUDE_GNU + + #include "objc.h" + #include "stdio.h" + + + /* + * All classes are derived from Object. As such this is the + * overhead tacked onto those objects. + */ + @interface Object { + Class_t isa; /* A pointer to the instance's + class structure. + + This structure is the one + generated by the compiler + and located in the TEXT + segment. The run-time uses + its address as a key to + run-time information. */ + } + + /* Creating, copying, and freeing instances */ + + + new; + + free; + - free; + - copy; + - shallowCopy; + - deepCopy; + + /* Identifying classes */ + + + ( Class_t )class; + + ( Class_t )superClass; + - ( Class_t )class; + - ( Class_t )superClass; + - ( const char* )name; + + /* Identifying and comparing instances */ + + - self; + - ( unsigned int )hash; + - ( BOOL )isEqual:anObject; + + /* Testing inheritance relationships */ + + - ( BOOL )isKindOf:( Class_t )aClassObject; + - ( BOOL )isMemberOf:( Class_t )aClassObject; + - ( BOOL )isKindOfGivenName:( const char* )aClassName; + - ( BOOL )isMemberOfGivenName:( const char* )aClassName; + + /* Testing class functionality */ + + + ( BOOL )instancesRespondTo:( SEL )aSel; + - ( BOOL )respondsTo:( SEL )aSel; + + /* Sending messages determined at run time */ + + - perform:( SEL )aSel; + - perform:( SEL )aSel with:aObject; + + /* Posing */ + + + poseAs:( Class_t )aClassObject; + + /* Enforcing intentions */ + + - subclassResponsibility:( SEL )aSel; + - notImplemented:( SEL )aSel; + + /* Error handling */ + + - doesNotRecognize:(SEL)aSelector; + - error:( const char* )aString, ...; + + error:( const char* )aString, ...; + + /* Archiving */ + + - storeOn:( int )aFd; + + readFrom:( int )aFd; + - readFrom:( int )aFd; + + ( int )version; + + setVersion:( int )aVersion; + + @end + + + #endif + diff -rc2N gcc-2.2.2/objc/object.m gcc-2.3.1/objc/object.m *** gcc-2.2.2/objc/object.m --- gcc-2.3.1/objc/object.m Wed Oct 28 16:50:50 1992 *************** *** 0 **** --- 1,286 ---- + /* This file contains the implementation of class Object. + Copyright (C) 1992 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. */ + + + #include "tconfig.h" + #include "gstdarg.h" + #include "object.h" + #include "objc-proto.h" + + #include + #ifndef errno + extern int errno; + #endif + + #define CLASS(class) ((Class_t)class) + + + @implementation Object + + + + new + { + return class_createInstance (CLASS (self)); + } + + + + free { return nil; } + - free { return object_dispose (self); } + + + - copy { return [self shallowCopy]; } + + + - shallowCopy + { + return object_copy (self); + } + + + - deepCopy + { + return class_createInstance ([self class]); + } + + + + (Class_t)class { return CLASS (self); } + + (Class_t)superClass { return CLASS (self)->super_class; } + - (Class_t)class { return isa; } + - (Class_t)superClass { return isa->super_class; } + - (const char *)name { return object_getClassName (self); } + - self { return self; } + + + - (unsigned int)hash + { + return (unsigned int)self; /* gak! Not portable. */ + } + + + - (BOOL)isEqual:anObject + { + return self == anObject ; + } + + + - (BOOL)isKindOf:(Class_t)aClassObject + { + Class_t class; + + for (class = isa; class; class = class->super_class) + if (class == aClassObject) + return YES; + + return NO; + } + + + - (BOOL)isMemberOf:(Class_t)aClassObject + { + return isa == aClassObject ; + } + + + - (BOOL)isKindOfGivenName:(const char*)aClassName + { + Class_t class; + + for (class = isa; class; class = class->super_class) + if (!strcmp (class_getClassName (class), aClassName)) + return YES; + + return NO; + } + + + - (BOOL)isMemberOfGivenName:(const char*)aClassName + { + return !strcmp ([self name], aClassName); + } + + + + (BOOL)instancesRespondTo:(SEL)aSel + { + if (class_getInstanceMethod (CLASS (self), aSel)) + return YES; + + return NO; + } + + + - (BOOL)respondsTo:(SEL)aSel + { + if (class_getInstanceMethod (isa, aSel)) + return YES; + + return NO; + } + + + - perform:(SEL)aSel + { + return (*((IMP)objc_msgSend (self, aSel)))(self, aSel); + } + + + - perform:(SEL)aSel with:aObject + { + return (*((IMP)objc_msgSend (self, aSel)))(self, aSel, aObject); + } + + + + poseAs:(Class_t)aClassObject + { + return class_poseAs (self, aClassObject); + } + + + - subclassResponsibility:(SEL)aSel + { + return [self error:"subclass should override %s", aSel]; + } + + + - notImplemented:(SEL)aSel + { + return [self error:"method %s not implemented", aSel]; + } + + + - doesNotRecognize:(SEL)aSel + { + return [self error:"%s does not recognize %s", [self name], aSel]; + } + + - error:(const char*)aString, ... + { + #define FMT "error: %s (instance)\n%s\n" + + char fmt[strlen (FMT) + + strlen (isa->name) + + strlen (aString) + 8]; + va_list ap; + + sprintf (fmt, FMT, isa->name, aString); + va_start (ap, aString); + (*_error)(self, fmt, ap); + va_end (ap); + + #undef FMT + return self; + } + + + + error:(const char*)aString, ... + { + #define FMT "error: %s (class)\n%s\n" + + char fmt[strlen (FMT) + + strlen (isa->name) + + strlen (aString) + 8]; + va_list ap; + + sprintf (fmt, FMT, isa->name, aString); + va_start (ap, aString); + (*_error)(self, fmt, ap); + va_end (ap); + + #undef FMT + return self; + } + + + - storeOn:(int)aFd + { + int len; + long version = [[self class] version]; + + if ((len = write (aFd, "#", strlen ("#"))) != -1) + if ((len = write (aFd, [self name], strlen ([self name]) + 1)) != -1) + len = write (aFd, &version, sizeof (version)); + + if (len == -1) + [self error:"error passivating object, errno=%d", errno]; + + return self; + } + + + + readFrom:(int)aFd + { + id aObj = nil; + char objName[256]; + int len; + + + if ((len = read (aFd, &objName, strlen ("#"))) != -1) + if (objName[0] == '#') { + long version; + int i = 0; + + /* Read the object's class. */ + do { + len = read (aFd, &objName[i], sizeof (char)); + } while (objName[i++] && (len != -1)); + + /* Get its version. */ + if (len != -1) + len = read (aFd, &version, sizeof (version)); + + /* No errors??? + Then create a object. */ + if (len != -1) { + aObj = class_createInstance (objc_getClass (objName)); + + /* If the object was + successfully created then + tell it to dearchive + itself. */ + if (aObj) + [aObj readFrom:aFd]; + } + } + + if (len == -1) + [self error:"error activating object, errno=%d", errno]; + + return aObj; + } + + + - readFrom:(int)aFd { return self; } + + + + (int)version + { + return class_getVersion (CLASS (self)); + } + + + + setVersion:(int)aVersion + { + class_setVersion (CLASS (self), aVersion); + + return self; + } + + + @end + + diff -rc2N gcc-2.2.2/objc/record.h gcc-2.3.1/objc/record.h *** gcc-2.2.2/objc/record.h --- gcc-2.3.1/objc/record.h Wed Oct 14 05:34:49 1992 *************** *** 0 **** --- 1,129 ---- + /* Implement a vector type that indicates its used size and allocated size. + Copyright (C) 1992 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. */ + + /* 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 __record_INCLUDE_GNU + #define __record_INCLUDE_GNU + + #include "assert.h" + + + /* Structure to hold records. */ + struct record + { + unsigned int capacity; + unsigned int used; + void **records; + }; + + + extern void *__objc_xmalloc (unsigned int); + extern void *__objc_xcalloc (unsigned int, unsigned int); + extern void *__objc_xrealloc (void *, unsigned int); + + /* Allocate, initialize and return a new record structure. */ + + static inline struct record * + record_new () + { + struct record *record; + + record = (struct record *) __objc_xcalloc (1, sizeof (struct record)); + record->capacity = 8; + record ->records + = (void **) __objc_xcalloc (record->capacity, sizeof (void *)); + + return record; + } + + + /* Delete the record. */ + static inline void + record_delete (struct record *record) + { + free (record->records); + free (record); + } + + + /* Return the number of entries in the record. */ + + static inline unsigned int + record_entries (struct record *record) + { + return record->used; + } + + + /* Return the capacity of the record. */ + + static inline unsigned int + record_capacity (struct record *record) + { + return record->capacity; + } + + + /* Store an entry at the specified record location. */ + + static inline void + record_store_at (unsigned int i, void *value, struct record *record) + { + assert (i); + assert (i <= record_entries (record)); + + record->records[i] = value; + } + + + /* Make a record entry. Expand the record's size if full. */ + + static inline void + record_store (void *value, struct record *record) + { + ++record->used; + if (record_entries (record) == record_capacity (record)) + { + record->capacity *= 2; + record->records + = (void **) __objc_xrealloc (record->records, + record_capacity (record) * sizeof (void *)); + } + record_store_at (record_entries (record), value, record); + } + + + /* Get a value from the record. */ + + static inline void * + record_get (unsigned int i, struct record *record) + { + assert (i); + assert (i <= record_entries (record)); + return record->records[i]; + } + + #endif /* not __record_INCLUDE_GNU */ + diff -rc2N gcc-2.2.2/objc/todo gcc-2.3.1/objc/todo *** gcc-2.2.2/objc/todo --- gcc-2.3.1/objc/todo Wed Oct 14 05:55:49 1992 *************** *** 0 **** --- 1,52 ---- + Must eliminate use of stdio.h; that loses when using GNU libc. + (It is ok to include stdio.h only when debugging, + for the sake of DEBUG_PRINTF.) + Can this be done? If not, how do we make this work? + + Eliminate the asserts in record.h. + + Rename the global functions in core.c to GNU-style names; + fix object.m at same time. + + + It is undesirable to use statics variables such as errorStatic in + handleRuntimeError--as dennisg noted. Do programs depend on error + handling to be compatible with what it is on the NeXT? + + For example, would it be ok for DoesNotRecognize to return + a method to be called, rather than a value to be returned? + + If that is not ok, I have other ideas, but they are harder to + implement. + + + + Why does dennisg say that object_getIvarAddress is not thread-safe? + + + + objc_msgSend can be faster. + 1. Delete the statement if (!theReceiver->isa). + Instead, set the isa field of a deallocated object + to point to a dummy class called "deallocated". + This class should have a vector of operations + at least as long as any class has had during this execution. + Every element of this vector should point to `abort'. + Don't bother to print a fancy message; that is a waste of effort. + For something impossible, abort is *exactly* the right thing to do. + 2. Is it really necessary to call initializeClass here? + Can't it be done in __objc_execClass, as soon as the class + is complete? If you can avoid doing this here, that is + one fewer statement to execute. + 3. Get rid of objc_trace. + 4. Don't check wether getIMP returns null. + There should never be a null in the method vector. + If the method is not defined, store in the vector + a fake method that will print the appropriate error. + With these changes, all you need is this: + if (theReceiver) + return getIMP (theReceiver->isa, aSel); + else + return nilMethodIMP; + which is something that could plausibly be open-coded in the future. + diff -rc2N gcc-2.2.2/objc-actions.c gcc-2.3.1/objc-actions.c *** gcc-2.2.2/objc-actions.c Wed Jun 10 00:52:37 1992 --- gcc-2.3.1/objc-actions.c Sat Oct 31 15:41:21 1992 *************** *** 48,51 **** --- 48,57 ---- #include "objc-actions.h" #include "input.h" + + /* The GNU run time requires the selectors in a vector + so it can store the operation numbers in them. */ + #ifndef NEXT_OBJC_RUNTIME + #define OBJC_SELECTORS_WITHOUT_LABELS + #endif /* Define the special tree codes that we use. */ *************** *** 92,98 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - /* This obstack is used to accumulate the encoding of a data type. */ static struct obstack util_obstack; --- 98,101 ---- *************** *** 500,505 **** if (code == VAR_DECL) { ! TREE_EXTERNAL (decl) = 1; ! TREE_PUBLIC (decl) = 1; make_decl_rtl (decl, 0, 1); pushdecl (decl); --- 503,507 ---- if (code == VAR_DECL) { ! TREE_STATIC (decl) = 1; make_decl_rtl (decl, 0, 1); pushdecl (decl); *************** *** 886,891 **** finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT); ! /* Mark the decl as used to avoid "defined but not used" warning. */ ! TREE_USED (_OBJC_MODULES_decl) = 1; /* Generate a constructor call for the module descriptor. --- 888,893 ---- finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT); ! /* Mark the decl to avoid "defined but not used" warning. */ ! DECL_IN_SYSTEM_HEADER (_OBJC_MODULES_decl) = 1; /* Generate a constructor call for the module descriptor. *************** *** 907,911 **** /* Find the name of some global object defined in this file. */ for (t = getdecls (); t; t = TREE_CHAIN (t)) ! if (TREE_PUBLIC (t) && !TREE_EXTERNAL (t) && DECL_INITIAL (t) != 0) { global_object_name = IDENTIFIER_POINTER (DECL_NAME (t)); --- 909,913 ---- /* Find the name of some global object defined in this file. */ for (t = getdecls (); t; t = TREE_CHAIN (t)) ! if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0) { global_object_name = IDENTIFIER_POINTER (DECL_NAME (t)); *************** *** 949,953 **** get_identifier ("__objc_execClass"), function_type); ! TREE_EXTERNAL (function_decl) = 1; TREE_PUBLIC (function_decl) = 1; pushdecl (function_decl); --- 951,955 ---- get_identifier ("__objc_execClass"), function_type); ! DECL_EXTERNAL (function_decl) = 1; TREE_PUBLIC (function_decl) = 1; pushdecl (function_decl); *************** *** 1087,1091 **** { decl = build_decl (VAR_DECL, ident, selector_type); ! TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; TREE_USED (decl) = 1; --- 1089,1093 ---- { decl = build_decl (VAR_DECL, ident, selector_type); ! DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; TREE_USED (decl) = 1; *************** *** 1158,1161 **** --- 1160,1168 ---- #ifdef OBJC_SELECTORS_WITHOUT_LABELS + /* Cause the variable and its initial value to be actually output. */ + DECL_EXTERNAL (_OBJC_SELECTOR_REFERENCES_decl) = 0; + TREE_STATIC (_OBJC_SELECTOR_REFERENCES_decl) = 1; + /* NULL terminate the list and fix the decl for output. */ + initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); DECL_INITIAL (_OBJC_SELECTOR_REFERENCES_decl) = (tree) 1; initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)); *************** *** 2149,2153 **** /* info = */ ! initlist = tree_cons (NULLT, build_int_2 (status), initlist); /* instance_size = */ --- 2156,2160 ---- /* info = */ ! initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist); /* instance_size = */ *************** *** 2624,2628 **** && (class_ident = receiver_is_class_object (receiver))) ; ! else if (rtype != id_type && rtype != class_type) { bzero (errbuf, BUFSIZE); --- 2631,2636 ---- && (class_ident = receiver_is_class_object (receiver))) ; ! else if (TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (id_type) ! && TYPE_MAIN_VARIANT (rtype) != TYPE_MAIN_VARIANT (class_type)) { bzero (errbuf, BUFSIZE); *************** *** 2686,2690 **** /* Determine operation return type. */ ! if (rtype == super_type) { tree iface; --- 2694,2698 ---- /* Determine operation return type. */ ! if (TYPE_MAIN_VARIANT (rtype) == TYPE_MAIN_VARIANT (super_type)) { tree iface; *************** *** 3413,3416 **** --- 3421,3432 ---- } + /* Make sure that the class CLASS_NAME is defined + CODE says which kind of thing CLASS_NAME ought to be. + It can be INTERFACE_TYPE, IMPLEMENTATION_TYPE, PROTOCOL_TYPE + or CATEGORY_TYPE. + + If CODE is INTERFACE_TYPE, we also do a push_obstacks_nochange + whose matching pop is in continue_class. */ + tree start_class (code, class_name, super_name) *************** *** 3421,3426 **** tree class; if (!doing_objc_thang) ! fatal ("Objective-C text in C source file"); class = make_node (code); --- 3437,3448 ---- tree class; + if (code == INTERFACE_TYPE) + { + push_obstacks_nochange (); + end_temporary_allocation (); + } + if (!doing_objc_thang) ! fatal ("Objective-C text in C source file"); class = make_node (code); *************** *** 4247,4251 **** /* this prevents `unused variable' warnings when compiling with `-Wall' */ ! TREE_USED (_OBJC_SUPER_decl) = 1; } --- 4269,4273 ---- /* this prevents `unused variable' warnings when compiling with `-Wall' */ ! DECL_IN_SYSTEM_HEADER (_OBJC_SUPER_decl) = 1; } *************** *** 5051,5060 **** = (char *) alloca (strlen (IDENTIFIER_POINTER (TREE_VALUE (chain))) + 30); ! sprintf (string, ".objc_class_name_%s", IDENTIFIER_POINTER (TREE_VALUE (chain))); /* 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); ! TREE_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; --- 5073,5082 ---- = (char *) alloca (strlen (IDENTIFIER_POINTER (TREE_VALUE (chain))) + 30); ! sprintf (string, "__objc_class_name_%s", IDENTIFIER_POINTER (TREE_VALUE (chain))); /* 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; *************** *** 5081,5085 **** = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))) + 30); ! sprintf (string, ".objc_class_name_%s", IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); assemble_global (string); --- 5103,5107 ---- = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))) + 30); ! sprintf (string, "__objc_class_name_%s", IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); assemble_global (string); *************** *** 5096,5100 **** symbols are generated automatically by the compiler, it gives you a handle to pull them into an archive by hand. */ ! sprintf (string, ".objc_category_name_%s_%s", IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)), IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context))); --- 5118,5122 ---- symbols are generated automatically by the compiler, it gives you a handle to pull them into an archive by hand. */ ! sprintf (string, "__objc_category_name_%s_%s", IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)), IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context))); diff -rc2N gcc-2.2.2/objc-parse.y gcc-2.3.1/objc-parse.y *** gcc-2.2.2/objc-parse.y Wed Jun 10 00:53:18 1992 --- gcc-2.3.1/objc-parse.y Fri Oct 16 19:56:37 1992 *************** *** 1,5 **** ! /* YACC parser for C syntax. Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. - Objective-C extensions by s.naroff. This file is part of GNU CC. --- 1,4 ---- ! /* YACC parser for C syntax and for Objective C. -*-c-*- Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 19,41 **** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* 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 36 - /* These are the 8 conflicts you should get in parse.output; - the state numbers may vary if minor changes in the grammar are made. - - State 41 contains 1 shift/reduce conflict. (Two ways to recover from error.) - State 92 contains 1 shift/reduce conflict. (Two ways to recover from error.) - State 99 contains 1 shift/reduce conflict. (Two ways to recover from error.) - State 103 contains 1 shift/reduce conflict. (Two ways to recover from error.) - State 119 contains 1 shift/reduce conflict. (See comment at component_decl.) - State 183 contains 1 shift/reduce conflict. (Two ways to recover from error.) - State 193 contains 1 shift/reduce conflict. (Two ways to recover from error.) - State 199 contains 1 shift/reduce conflict. (Two ways to recover from error.) - */ - %{ #include --- 18,32 ---- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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. + The awk script cond.awk is 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 56 %{ #include *************** *** 50,53 **** --- 41,49 ---- #include "flags.h" + #ifdef MULTIBYTE_CHARS + #include + #include + #endif + #include "objc-actions.h" *************** *** 132,136 **** %left POINTSAT '.' '(' '[' ! /* the Objective-C keywords */ %token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE %token CLASSNAME PUBLIC --- 128,133 ---- %left 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 *************** *** 164,167 **** --- 161,165 ---- %type parmlist parmlist_1 parmlist_2 %type parmlist_or_identifiers parmlist_or_identifiers_1 + %type identifiers_or_typenames %type setspecs *************** *** 209,212 **** --- 207,211 ---- int objc_public_flag; + /* Tell yyparse how to print a token's value, if yydebug is set. */ *************** *** 219,225 **** { if (pedantic) pedwarn ("ANSI C forbids an empty source file"); ! objc_finish (); } | extdefs ! { objc_finish (); } ; --- 218,227 ---- { if (pedantic) pedwarn ("ANSI C forbids an empty source file"); ! objc_finish (); ! } | extdefs ! { ! objc_finish (); ! } ; *************** *** 237,245 **** | datadef | objcdef ! | ASM_KEYWORD '(' string ')' ';' ! { if (pedantic) ! pedwarn ("ANSI C forbids use of `asm' keyword"); ! if (TREE_CHAIN ($3)) $3 = combine_strings ($3); ! assemble_asm ($3); } ; --- 239,250 ---- | 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"); } ; *************** *** 255,259 **** {} | declmods ';' ! { error ("empty declaration"); } | typed_declspecs ';' { shadow_tag ($1); } --- 260,264 ---- {} | declmods ';' ! { pedwarn ("empty declaration"); } | typed_declspecs ';' { shadow_tag ($1); } *************** *** 264,268 **** pedwarn ("ANSI C does not allow extra `;' outside of a function"); } ; ! fndef: typed_declspecs setspecs declarator --- 269,273 ---- pedwarn ("ANSI C does not allow extra `;' outside of a function"); } ; ! fndef: typed_declspecs setspecs declarator *************** *** 287,291 **** { } | setspecs notype_declarator ! { if (! start_function (0, $2, 0)) YYERROR1; reinit_parse_for_function (); } --- 292,296 ---- { } | setspecs notype_declarator ! { if (! start_function (NULL_TREE, $2, 0)) YYERROR1; reinit_parse_for_function (); } *************** *** 358,361 **** --- 363,367 ---- 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)); *************** *** 391,397 **** | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY { tree type = groktypename ($2); if (pedantic) pedwarn ("ANSI C forbids constructor expressions"); ! $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0, 0, 0); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) { --- 397,414 ---- | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY { tree type = groktypename ($2); + char *name; 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 = ""; ! $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), ! NULL_PTR, 0, 0, name); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0) { *************** *** 436,442 **** { $$ = build_conditional_expr ($1, $3, $5); } | expr_no_commas '=' expr_no_commas ! { $$ = build_modify_expr ($1, NOP_EXPR, $3); } | expr_no_commas ASSIGN expr_no_commas ! { $$ = build_modify_expr ($1, $2, $3); } ; --- 453,461 ---- { $$ = build_conditional_expr ($1, $3, $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); ! C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); } ; *************** *** 478,483 **** { if (objc_receiver_context ! && ! (objc_receiver_context ! && strcmp (IDENTIFIER_POINTER ($1), "super"))) /* we have a message to super */ $$ = get_super_receiver (); --- 497,501 ---- { if (objc_receiver_context ! && ! strcmp (IDENTIFIER_POINTER ($1), "super")) /* we have a message to super */ $$ = get_super_receiver (); *************** *** 504,518 **** IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node; IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl; ! } } } ! else { ! if (! TREE_USED ($$)) { ! if (TREE_EXTERNAL ($$)) ! assemble_external ($$); ! TREE_USED ($$) = 1; } /* we have a definition - still check if iVariable */ --- 522,575 ---- 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 */ *************** *** 536,540 **** if (TREE_CODE ($$) == CONST_DECL) ! $$ = DECL_INITIAL ($$); } | CONSTANT --- 593,603 ---- 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 *************** *** 574,577 **** --- 637,644 ---- $$ = 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); } | primary '(' exprlist ')' %prec '.' *************** *** 589,607 **** } else ! $$ = build_component_ref ($1, $3); } | primary POINTSAT identifier { ! tree anExpr = build_indirect_ref ($1, "->"); if (doing_objc_thang) { ! if (is_public (anExpr, $3)) ! $$ = build_component_ref (anExpr, $3); else $$ = error_mark_node; } else ! $$ = build_component_ref (anExpr, $3); } | primary PLUSPLUS --- 656,674 ---- } 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 *************** *** 626,631 **** xdecls: /* empty */ ! | decls ! | decls ELLIPSIS /* ... is used here to indicate a varargs function. */ { c_mark_varargs (); --- 693,698 ---- xdecls: /* empty */ ! | datadecls ! | datadecls ELLIPSIS /* ... is used here to indicate a varargs function. */ { c_mark_varargs (); *************** *** 634,637 **** --- 701,735 ---- ; + /* 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 + ; + + datadecl: + typed_declspecs setspecs initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | declmods setspecs notype_initdecls ';' + { current_declspecs = TREE_VALUE (declspec_stack); + declspec_stack = TREE_CHAIN (declspec_stack); + resume_momentary ($2); } + | typed_declspecs ';' + { shadow_tag_warned ($1, 1); + pedwarn ("empty declaration"); } + | declmods ';' + { pedwarn ("empty declaration"); } + ; + /* This combination which saves a lineno before a decl is the normal thing to use, rather than decl itself. *************** *** 657,661 **** { $$ = suspend_momentary (); pending_xref_error (); ! declspec_stack = tree_cons (0, current_declspecs, declspec_stack); current_declspecs = $0; } --- 755,759 ---- { $$ = suspend_momentary (); pending_xref_error (); ! declspec_stack = tree_cons (NULL_TREE, current_declspecs, declspec_stack); current_declspecs = $0; } *************** *** 701,705 **** { $$ = tree_cons (NULL_TREE, $2, $1); } | reserved_declspecs SCSPEC ! { $$ = tree_cons (NULL_TREE, $2, $1); } ; --- 799,806 ---- { $$ = 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); } ; *************** *** 710,720 **** declmods: TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | declmods TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $2, $1); } | declmods SCSPEC ! { $$ = tree_cons (NULL_TREE, $2, $1); } ; --- 811,827 ---- declmods: TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); ! TREE_STATIC ($$) = 1; } | SCSPEC { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } | declmods TYPE_QUAL ! { $$ = tree_cons (NULL_TREE, $2, $1); ! TREE_STATIC ($$) = 1; } | declmods 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); } ; *************** *** 744,757 **** | structsp | TYPENAME | CLASSNAME { $$ = get_static_reference ($1); } | TYPEOF '(' expr ')' ! { $$ = TREE_TYPE ($3); ! if (pedantic) ! pedwarn ("ANSI C forbids `typeof'"); } | TYPEOF '(' typename ')' ! { $$ = groktypename ($3); ! if (pedantic) ! pedwarn ("ANSI C forbids `typeof'"); } ; --- 851,863 ---- | structsp | TYPENAME + { /* For a typedef name, record the meaning, not the name. + In case of `foo foo, bar;'. */ + $$ = lookup_name ($1); } | CLASSNAME { $$ = get_static_reference ($1); } | TYPEOF '(' expr ')' ! { $$ = TREE_TYPE ($3); } | TYPEOF '(' typename ')' ! { $$ = groktypename ($3); } ; *************** *** 779,784 **** { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; - if (pedantic) - pedwarn ("ANSI C forbids use of `asm' keyword"); } ; --- 885,888 ---- *************** *** 827,833 **** attrib : IDENTIFIER ! { warning ("`%s' attribute directive ignored", ! IDENTIFIER_POINTER ($1)); $$ = $1; } | IDENTIFIER '(' CONSTANT ')' { /* if not "aligned(n)", then issue warning */ --- 931,948 ---- attrib : IDENTIFIER ! { if (strcmp (IDENTIFIER_POINTER ($1), "packed")) ! warning ("`%s' attribute directive ignored", ! IDENTIFIER_POINTER ($1)); $$ = $1; } + | IDENTIFIER '(' IDENTIFIER ')' + { /* If not "mode (m)", then issue warning. */ + if (strcmp (IDENTIFIER_POINTER ($1), "mode") != 0) + { + warning ("`%s' attribute directive ignored", + IDENTIFIER_POINTER ($1)); + $$ = $1; + } + else + $$ = tree_cons ($1, $3, NULL_TREE); } | IDENTIFIER '(' CONSTANT ')' { /* if not "aligned(n)", then issue warning */ *************** *** 840,844 **** } else ! $$ = tree_cons ($1, $3); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ --- 955,959 ---- } else ! $$ = tree_cons ($1, $3, NULL_TREE); } | IDENTIFIER '(' IDENTIFIER ',' CONSTANT ',' CONSTANT ')' { /* if not "format(...)", then issue warning */ *************** *** 852,856 **** } else ! $$ = tree_cons ($1, tree_cons ($3, tree_cons ($5, $7))); } ; --- 967,975 ---- } else ! $$ = tree_cons ($1, ! tree_cons ($3, ! tree_cons ($5, $7, NULL_TREE), ! NULL_TREE), ! NULL_TREE); } ; *************** *** 877,883 **** { $$ = tree_cons (NULL_TREE, $3, $1); } /* These are for labeled elements. */ | '[' expr_no_commas ']' init { $$ = build_tree_list ($2, $4); } ! | initlist ',' CASE expr_no_commas ':' init { $$ = tree_cons ($4, $6, $1); } | identifier ':' init --- 996,1011 ---- { $$ = tree_cons (NULL_TREE, $3, $1); } /* These are for labeled elements. */ + | '[' expr_no_commas ELLIPSIS expr_no_commas ']' init + { $$ = build_tree_list (tree_cons ($2, NULL_TREE, + build_tree_list ($4, NULL_TREE)), + $6); } + | initlist ',' '[' expr_no_commas ELLIPSIS expr_no_commas ']' init + { $$ = tree_cons (tree_cons ($4, NULL_TREE, + build_tree_list ($6, NULL_TREE)), + $8, + $1); } | '[' expr_no_commas ']' init { $$ = build_tree_list ($2, $4); } ! | initlist ',' '[' expr_no_commas ']' init { $$ = tree_cons ($4, $6, $1); } | identifier ':' init *************** *** 1051,1055 **** | component_decl_list2 component_decl { $$ = chainon ($1, $2); ! warning ("no semicolon at end of struct or union"); } ; --- 1179,1183 ---- | component_decl_list2 component_decl { $$ = chainon ($1, $2); ! pedwarn ("no semicolon at end of struct or union"); } ; *************** *** 1060,1064 **** | component_decl_list2 ';' { if (pedantic) ! warning ("extra semicolon in struct or union specified"); } /* foo(sizeof(struct{ @defs(ClassName)})); */ | DEFS '(' CLASSNAME ')' --- 1188,1192 ---- | component_decl_list2 ';' { if (pedantic) ! pedwarn ("extra semicolon in struct or union specified"); } /* foo(sizeof(struct{ @defs(ClassName)})); */ | DEFS '(' CLASSNAME ')' *************** *** 1191,1196 **** stmts: ! lineno_stmt ! | stmts lineno_stmt | stmts errstmt ; --- 1319,1324 ---- stmts: ! lineno_stmt_or_label ! | stmts lineno_stmt_or_label | stmts errstmt ; *************** *** 1211,1215 **** expand_start_bindings (0); if (objc_method_context) ! add_objc_decls (); } ; --- 1339,1344 ---- expand_start_bindings (0); if (objc_method_context) ! add_objc_decls (); ! } ; *************** *** 1229,1233 **** label_decl: ! LABEL identifiers ';' { tree link; for (link = $2; link; link = TREE_CHAIN (link)) --- 1358,1362 ---- label_decl: ! LABEL identifiers_or_typenames ';' { tree link; for (link = $2; link; link = TREE_CHAIN (link)) *************** *** 1242,1248 **** /* This is the body of a function definition. It causes syntax errors to ignore to the next openbrace. */ - - /* allow for: main () { Example *anObject = [Example new]; } */ - compstmt_or_error: compstmt --- 1371,1374 ---- *************** *** 1272,1275 **** --- 1398,1409 ---- /* Value is number of statements counted as of the closeparen. */ simple_if: + if_prefix lineno_labeled_stmt + /* Make sure expand_end_cond is run once + for each call to expand_start_cond. + Otherwise a crash is likely. */ + | if_prefix error + ; + + if_prefix: IF '(' expr ')' { emit_line_note ($-1, $0); *************** *** 1279,1283 **** if_stmt_line = $0; position_after_white_space (); } ! lineno_stmt ; --- 1413,1431 ---- if_stmt_line = $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++; ! emit_line_note ($-1, $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 (); } ; *************** *** 1290,1298 **** ; ! lineno_stmt: save_filename save_lineno stmt { } ; stmt: compstmt --- 1438,1469 ---- ; ! 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 + { } ; + stmt_or_label: + stmt + | label + { int next; + position_after_white_space (); + next = getc (finput); + ungetc (next, finput); + if (pedantic && next == '}') + pedwarn ("ANSI C forbids label at end of compound statement"); + } + ; + + /* Parse a single real statement, not including any labels. */ stmt: compstmt *************** *** 1307,1311 **** $1 = stmt_count; position_after_white_space (); } ! lineno_stmt { expand_end_cond (); if (extra_warnings && stmt_count == $1) --- 1478,1482 ---- $1 = stmt_count; position_after_white_space (); } ! lineno_labeled_stmt { expand_end_cond (); if (extra_warnings && stmt_count == $1) *************** *** 1316,1361 **** warning_with_file_and_line (if_stmt_file, if_stmt_line, "empty body in an if-statement"); } | WHILE ! { emit_nop (); ! stmt_count++; emit_line_note ($-1, $0); ! expand_start_loop (1); } '(' expr ')' ! { emit_line_note (input_filename, lineno); ! expand_exit_loop_if_false (0, truthvalue_conversion ($4)); position_after_white_space (); } ! lineno_stmt { expand_end_loop (); } ! | DO ! { emit_nop (); ! stmt_count++; ! emit_line_note ($-1, $0); ! expand_start_loop_continue_elsewhere (1); ! position_after_white_space (); } ! lineno_stmt WHILE ! { expand_loop_continue_here (); } '(' expr ')' ';' { emit_line_note (input_filename, lineno); ! expand_exit_loop_if_false (0, truthvalue_conversion ($7)); expand_end_loop (); clear_momentary (); } | FOR '(' xexpr ';' ! { emit_nop (); ! stmt_count++; emit_line_note ($-1, $0); if ($3) c_expand_expr_stmt ($3); ! expand_start_loop_continue_elsewhere (1); } xexpr ';' ! { emit_line_note (input_filename, lineno); ! if ($6) ! expand_exit_loop_if_false (0, truthvalue_conversion ($6)); } xexpr ')' ! /* Don't let the tree nodes for $9 be discarded ! by clear_momentary during the parsing of the next stmt. */ ! { push_momentary (); ! position_after_white_space (); } ! lineno_stmt ! { emit_line_note ($-1, $0); expand_loop_continue_here (); if ($9) --- 1487,1561 ---- warning_with_file_and_line (if_stmt_file, if_stmt_line, "empty body in an if-statement"); } + /* Make sure expand_end_cond is run once + for each call to expand_start_cond. + Otherwise a crash is likely. */ + | simple_if ELSE error + { expand_end_cond (); } | WHILE ! { stmt_count++; emit_line_note ($-1, $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 ($-1, $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... */ ! { $7 = lineno; ! $$ = 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 ($8, $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 (); ! $7 = lineno; ! $8 = input_filename; } ! lineno_labeled_stmt ! { /* Emit the increment expression, with a line number. */ ! emit_line_note ($8, $7); expand_loop_continue_here (); if ($9) *************** *** 1371,1378 **** push_momentary (); position_after_white_space (); } ! lineno_stmt { expand_end_case ($3); pop_momentary (); } ! | CASE expr ':' { register tree value = check_case_value ($2); register tree label --- 1571,1650 ---- push_momentary (); position_after_white_space (); } ! lineno_labeled_stmt { expand_end_case ($3); pop_momentary (); } ! | BREAK ';' ! { stmt_count++; ! emit_line_note ($-1, $0); ! if ( ! expand_exit_something ()) ! error ("break statement not within loop or switch"); } ! | CONTINUE ';' ! { stmt_count++; ! emit_line_note ($-1, $0); ! if (! expand_continue_loop (NULL_PTR)) ! error ("continue statement not within a loop"); } ! | RETURN ';' ! { stmt_count++; ! emit_line_note ($-1, $0); ! c_expand_return (NULL_TREE); } ! | RETURN expr ';' ! { stmt_count++; ! emit_line_note ($-1, $0); ! c_expand_return ($2); } ! | ASM_KEYWORD maybe_type_qual '(' expr ')' ';' ! { stmt_count++; ! emit_line_note ($-1, $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 ($-1, $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 ($-1, $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 ($-1, $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 ($-1, $0); ! decl = lookup_label ($2); ! if (decl != 0) ! { ! TREE_USED (decl) = 1; ! expand_goto (decl); ! } ! } ! | GOTO '*' expr ';' ! { stmt_count++; ! emit_line_note ($-1, $0); ! expand_computed_goto (convert (ptr_type_node, $3)); } ! | ';' ! ; ! ! /* 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 ':' { register tree value = check_case_value ($2); register tree label *************** *** 1398,1402 **** } position_after_white_space (); } - lineno_stmt | CASE expr ELLIPSIS expr ':' { register tree value1 = check_case_value ($2); --- 1670,1673 ---- *************** *** 1417,1421 **** { error ("duplicate case value"); ! error_with_decl (duplicate, "this is the first entry overlapping that value"); } else if (success == 3) --- 1688,1692 ---- { error ("duplicate case value"); ! error_with_decl (duplicate, "this is the first entry for that value"); } else if (success == 3) *************** *** 1427,1431 **** } position_after_white_space (); } - lineno_stmt | DEFAULT ':' { --- 1698,1701 ---- *************** *** 1440,1510 **** { error ("multiple default labels in one switch"); ! error_with_decl (duplicate, "this is the first default albel"); } position_after_white_space (); } - lineno_stmt - | BREAK ';' - { stmt_count++; - emit_line_note ($-1, $0); - if ( ! expand_exit_something ()) - error ("break statement not within loop or switch"); } - | CONTINUE ';' - { stmt_count++; - emit_line_note ($-1, $0); - if (! expand_continue_loop (0)) - error ("continue statement not within a loop"); } - | RETURN ';' - { stmt_count++; - emit_line_note ($-1, $0); - c_expand_return (NULL_TREE); } - | RETURN expr ';' - { stmt_count++; - emit_line_note ($-1, $0); - c_expand_return ($2); } - | ASM_KEYWORD maybe_type_qual '(' string ')' ';' - { stmt_count++; - emit_line_note ($-1, $0); - if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - expand_asm ($4); } - /* This is the case with just output operands. */ - | ASM_KEYWORD maybe_type_qual '(' string ':' asm_operands ')' ';' - { stmt_count++; - emit_line_note ($-1, $0); - if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - 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 '(' string ':' asm_operands ':' asm_operands ')' ';' - { stmt_count++; - emit_line_note ($-1, $0); - if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - 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 '(' string ':' asm_operands ':' - asm_operands ':' asm_clobbers ')' ';' - { stmt_count++; - emit_line_note ($-1, $0); - if (TREE_CHAIN ($4)) $4 = combine_strings ($4); - 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 ($-1, $0); - decl = lookup_label ($2); - if (decl != 0) - { - TREE_USED (decl) = 1; - expand_goto (decl); - } - } - | GOTO '*' expr ';' - { stmt_count++; - emit_line_note ($-1, $0); - expand_computed_goto ($3); } | identifier ':' { tree label = define_label (input_filename, lineno, $1); --- 1710,1716 ---- { 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); *************** *** 1514,1519 **** expand_label (label); position_after_white_space (); } - lineno_stmt - | ';' ; --- 1720,1723 ---- *************** *** 1522,1532 **** maybe_type_qual: /* empty */ ! { if (pedantic) ! pedwarn ("ANSI C forbids use of `asm' keyword"); ! emit_line_note (input_filename, lineno); } | TYPE_QUAL ! { if (pedantic) ! pedwarn ("ANSI C forbids use of `asm' keyword"); ! emit_line_note (input_filename, lineno); } ; --- 1726,1732 ---- maybe_type_qual: /* empty */ ! { emit_line_note (input_filename, lineno); } | TYPE_QUAL ! { emit_line_note (input_filename, lineno); } ; *************** *** 1561,1569 **** { $$ = 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); declare_parm_level (0); } parmlist_1 --- 1761,1770 ---- { $$ = 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 *************** *** 1573,1597 **** ; - /* This is referred to 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); - declare_parm_level (1); } - parmlist_or_identifiers_1 - { $$ = $2; - parmlist_tags_warning (); - poplevel (0, 0, 0); } - ; - - parmlist_or_identifiers_1: - parmlist_2 ')' - | identifiers ')' - { $$ = tree_cons (NULL_TREE, NULL_TREE, $1); } - | error ')' - { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); } - ; - parmlist_1: parmlist_2 ')' | error ')' { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); } --- 1774,1789 ---- ; 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); } *************** *** 1602,1605 **** --- 1794,1802 ---- parmlist_2: /* empty */ { $$ = get_parm_info (0); } + | ELLIPSIS + { $$ = get_parm_info (0); + if (pedantic) + pedwarn ("ANSI C requires a named argument before `...'"); + } | parms { $$ = get_parm_info (1); } *************** *** 1630,1633 **** --- 1827,1853 ---- ; + /* 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: *************** *** 1637,1644 **** { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } ; ! /* ! * Objective-C productions. ! */ objcdef: classdef --- 1857,1871 ---- { $$ = 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)); } + ; ! /* Objective-C productions. */ ! objcdef: classdef *************** *** 1995,1999 **** { shadow_tag ($1); } | declmods ';' ! { warning ("empty declaration"); } ; --- 2222,2226 ---- { shadow_tag ($1); } | declmods ';' ! { pedwarn ("empty declaration"); } ; *************** *** 2198,2202 **** --- 2425,2431 ---- } ; + %% + /* If STRING is the name of an Objective C @-keyword (not including the @), return the token type for that keyword. *************** *** 2236,2237 **** --- 2465,2467 ---- return 0; } + diff -rc2N gcc-2.2.2/obstack.c gcc-2.3.1/obstack.c *** gcc-2.2.2/obstack.c Sun Jun 14 18:17:32 1992 --- gcc-2.3.1/obstack.c Sun Nov 1 03:44:31 1992 *************** *** 26,30 **** /* Determine default alignment. */ struct fooalign {char x; double d;}; ! #define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0) /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. But in fact it might be less smart and round addresses to as much as --- 26,31 ---- /* Determine default alignment. */ struct fooalign {char x; double d;}; ! #define DEFAULT_ALIGNMENT \ ! ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0)) /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. But in fact it might be less smart and round addresses to as much as *************** *** 45,48 **** --- 46,69 ---- struct obstack *_obstack; + + /* Define a macro that either calls functions with the traditional malloc/free + calling interface, or calls functions with the mmalloc/mfree interface + (that adds an extra first argument), based on the state of use_extra_arg. + For free, do not use ?:, since some compilers, like the MIPS compilers, + do not allow (expr) ? void : void. */ + + #define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(h)->chunkfun) ((size))) + + #define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(h)->freefun) ((old_chunk)); \ + } while (0) + /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). *************** *** 84,89 **** h->chunk_size = size; h->alignment_mask = alignment - 1; ! chunk = h->chunk = (*h->chunkfun) (h->chunk_size); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit --- 105,157 ---- h->chunk_size = size; h->alignment_mask = alignment - 1; + h->use_extra_arg = 0; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + h->next_free = h->object_base = chunk->contents; + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + } + + void + _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) + struct obstack *h; + int size; + int alignment; + POINTER (*chunkfun) (); + void (*freefun) (); + POINTER arg; + { + register struct _obstack_chunk* chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->extra_arg = arg; + h->use_extra_arg = 1; ! chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); h->next_free = h->object_base = chunk->contents; h->chunk_limit = chunk->limit *************** *** 118,122 **** /* Allocate and initialize the new chunk. */ ! new_chunk = h->chunk = (*h->chunkfun) (new_size); new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; --- 186,190 ---- /* Allocate and initialize the new chunk. */ ! new_chunk = h->chunk = CALL_CHUNKFUN (h, new_size); new_chunk->prev = old_chunk; new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; *************** *** 148,152 **** { new_chunk->prev = old_chunk->prev; ! (*h->freefun) (old_chunk); } --- 216,220 ---- { new_chunk->prev = old_chunk->prev; ! CALL_FREEFUN (h, old_chunk); } *************** *** 204,208 **** { plp = lp->prev; ! (*h->freefun) (lp); lp = plp; /* If we switch chunks, we can't tell whether the new current --- 272,276 ---- { plp = lp->prev; ! CALL_FREEFUN (h, lp); lp = plp; /* If we switch chunks, we can't tell whether the new current *************** *** 238,242 **** { plp = lp->prev; ! (*h->freefun) (lp); lp = plp; /* If we switch chunks, we can't tell whether the new current --- 306,310 ---- { plp = lp->prev; ! CALL_FREEFUN (h, lp); lp = plp; /* If we switch chunks, we can't tell whether the new current diff -rc2N gcc-2.2.2/obstack.h gcc-2.3.1/obstack.h *** gcc-2.2.2/obstack.h Sun Jun 14 18:17:33 1992 --- gcc-2.3.1/obstack.h Sun Nov 1 03:44:32 1992 *************** *** 1,4 **** /* obstack.h - object stack macros ! Copyright (C) 1988 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it --- 1,4 ---- /* obstack.h - object stack macros ! Copyright (C) 1988, 1992 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it *************** *** 42,46 **** One motivation for this package is the problem of growing char strings in symbol tables. Unless you are "fascist pig with a read-only mind" ! [Gosper's immortal quote from HAKMEM item 154, out of context] you would not like to put any arbitrary upper limit on the length of your symbols. --- 42,46 ---- One motivation for this package is the problem of growing char strings in symbol tables. Unless you are "fascist pig with a read-only mind" ! --Gosper's immortal quote from HAKMEM item 154, out of context--you would not like to put any arbitrary upper limit on the length of your symbols. *************** *** 93,97 **** You can run one obstack per control block. You may have as many control blocks as you dare. ! Because of the way we do it, you can `unwind' a obstack back to a previous state. (You may remove objects much as you would with a stack.) --- 93,97 ---- You can run one obstack per control block. You may have as many control blocks as you dare. ! Because of the way we do it, you can `unwind' an obstack back to a previous state. (You may remove objects much as you would with a stack.) *************** *** 116,119 **** --- 116,145 ---- #endif + /* We need the type of the resulting object. In ANSI C it is ptrdiff_t + but in traditional C it is usually long. If we are in ANSI C and + don't already have ptrdiff_t get it. */ + + #if defined (__STDC__) && ! defined (offsetof) + #if defined (__GNUC__) && defined (IN_GCC) + /* On Next machine, the system's stddef.h screws up if included + after we have defined just ptrdiff_t, so include all of gstddef.h. + Otherwise, define just ptrdiff_t, which is all we need. */ + #ifndef __NeXT__ + #define __need_ptrdiff_t + #endif + + /* While building GCC, the stddef.h that goes with GCC has this name. */ + #include "gstddef.h" + #else + #include + #endif + #endif + + #ifdef __STDC__ + #define PTR_INT_TYPE ptrdiff_t + #else + #define PTR_INT_TYPE long + #endif + struct _obstack_chunk /* Lives at front of each chunk. */ { *************** *** 130,141 **** char *next_free; /* where to add next char to current object */ char *chunk_limit; /* address of char after current chunk */ ! int temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ void (*freefun) (); /* User's function to free a chunk. */ ! /* Nonzero means there is a possibility the current chunk contains ! a zero-length object. This prevents freeing the chunk ! if we allocate a bigger chunk to replace it. */ ! char maybe_empty_object; }; --- 156,169 ---- char *next_free; /* where to add next char to current object */ char *chunk_limit; /* address of char after current chunk */ ! PTR_INT_TYPE temp; /* Temporary for some macros. */ int alignment_mask; /* Mask of alignment for each object. */ struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ void (*freefun) (); /* User's function to free a chunk. */ ! char *extra_arg; /* first arg for chunk alloc/dealloc funcs */ ! unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ ! unsigned maybe_empty_object:1;/* There is a possibility that the current ! chunk contains a zero-length object. This ! prevents freeing the chunk if we allocate ! a bigger chunk to replace it. */ }; *************** *** 147,154 **** --- 175,185 ---- extern void _obstack_begin (struct obstack *, int, int, void *(*) (), void (*) ()); + extern void _obstack_begin_1 (struct obstack *, int, int, + void *(*) (), void (*) (), void *); #else extern void _obstack_newchunk (); extern void _obstack_free (); extern void _obstack_begin (); + extern void _obstack_begin_1 (); #endif *************** *** 216,224 **** #define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ ! (void *(*) ()) obstack_chunk_alloc, obstack_chunk_free) #define obstack_begin(h, size) \ _obstack_begin ((h), (size), 0, \ ! (void *(*) ()) obstack_chunk_alloc, obstack_chunk_free) #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) --- 247,263 ---- #define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ ! (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) #define obstack_begin(h, size) \ _obstack_begin ((h), (size), 0, \ ! (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) ! ! #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ ! _obstack_begin ((h), (size), (alignment), \ ! (void *(*) ()) (chunkfun), (void (*) ()) (freefun)) ! ! #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ ! _obstack_begin_1 ((h), (size), (alignment), \ ! (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg)) #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) diff -rc2N gcc-2.2.2/optabs.c gcc-2.3.1/optabs.c *** gcc-2.2.2/optabs.c Mon May 25 15:54:20 1992 --- gcc-2.3.1/optabs.c Mon Oct 5 02:21:02 1992 *************** *** 28,31 **** --- 28,32 ---- #include "insn-config.h" #include "recog.h" + #include /* Each optab contains info on how this target machine *************** *** 73,76 **** --- 74,79 ---- optab ffs_optab; optab sqrt_optab; + optab sin_optab; + optab cos_optab; optab cmp_optab; *************** *** 84,88 **** --- 87,101 ---- rtx extendsfdf2_libfunc; + rtx extendsfxf2_libfunc; + rtx extendsftf2_libfunc; + rtx extenddfxf2_libfunc; + rtx extenddftf2_libfunc; + rtx truncdfsf2_libfunc; + rtx truncxfsf2_libfunc; + rtx trunctfsf2_libfunc; + rtx truncxfdf2_libfunc; + rtx trunctfdf2_libfunc; + rtx memcpy_libfunc; rtx bcopy_libfunc; *************** *** 91,94 **** --- 104,108 ---- rtx memset_libfunc; rtx bzero_libfunc; + rtx eqsf2_libfunc; rtx nesf2_libfunc; *************** *** 97,100 **** --- 111,115 ---- rtx ltsf2_libfunc; rtx lesf2_libfunc; + rtx eqdf2_libfunc; rtx nedf2_libfunc; *************** *** 103,119 **** rtx ltdf2_libfunc; rtx ledf2_libfunc; ! rtx floatdisf_libfunc; rtx floatsisf_libfunc; ! rtx floatdidf_libfunc; rtx floatsidf_libfunc; rtx fixsfsi_libfunc; rtx fixsfdi_libfunc; rtx fixdfsi_libfunc; rtx fixdfdi_libfunc; rtx fixunssfsi_libfunc; rtx fixunssfdi_libfunc; rtx fixunsdfsi_libfunc; rtx fixunsdfdi_libfunc; /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) gives the gen_function to make a branch to test that condition. */ --- 118,187 ---- rtx ltdf2_libfunc; rtx ledf2_libfunc; ! ! rtx eqxf2_libfunc; ! rtx nexf2_libfunc; ! rtx gtxf2_libfunc; ! rtx gexf2_libfunc; ! rtx ltxf2_libfunc; ! rtx lexf2_libfunc; ! ! rtx eqtf2_libfunc; ! rtx netf2_libfunc; ! rtx gttf2_libfunc; ! rtx getf2_libfunc; ! rtx lttf2_libfunc; ! rtx letf2_libfunc; ! rtx floatsisf_libfunc; ! rtx floatdisf_libfunc; ! rtx floattisf_libfunc; ! rtx floatsidf_libfunc; + rtx floatdidf_libfunc; + rtx floattidf_libfunc; + + rtx floatsixf_libfunc; + rtx floatdixf_libfunc; + rtx floattixf_libfunc; + + rtx floatsitf_libfunc; + rtx floatditf_libfunc; + rtx floattitf_libfunc; + rtx fixsfsi_libfunc; rtx fixsfdi_libfunc; + rtx fixsfti_libfunc; + rtx fixdfsi_libfunc; rtx fixdfdi_libfunc; + rtx fixdfti_libfunc; + + rtx fixxfsi_libfunc; + rtx fixxfdi_libfunc; + rtx fixxfti_libfunc; + + rtx fixtfsi_libfunc; + rtx fixtfdi_libfunc; + rtx fixtfti_libfunc; + rtx fixunssfsi_libfunc; rtx fixunssfdi_libfunc; + rtx fixunssfti_libfunc; + rtx fixunsdfsi_libfunc; rtx fixunsdfdi_libfunc; + rtx fixunsdfti_libfunc; + + rtx fixunsxfsi_libfunc; + rtx fixunsxfdi_libfunc; + rtx fixunsxfti_libfunc; + + rtx fixunstfsi_libfunc; + rtx fixunstfdi_libfunc; + rtx fixunstfti_libfunc; + /* from emit-rtl.c */ + extern rtx gen_highpart (); + /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...) gives the gen_function to make a branch to test that condition. */ *************** *** 228,231 **** --- 296,308 ---- } + /* If subtracting an integer constant, convert this into an addition of + the negated constant. */ + + if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT) + { + op1 = negate_rtx (mode, op1); + binoptab = add_optab; + } + /* If we are inside an appropriately-short loop and one operand is an expensive constant, force it into a register. */ *************** *** 238,254 **** op1 = force_reg (shift_op ? word_mode : mode, op1); - #if 0 /* Turned off because it seems to be a kludgy method. */ - /* If subtracting integer from pointer, and the pointer has a special mode, - then change it to an add. We use the add insn of Pmode for combining - integers with pointers, and the sub insn to subtract two pointers. */ - - if (binoptab == sub_optab - && GET_MODE (op0) == Pmode && GET_MODE (op1) != Pmode) - { - op1 = negate_rtx (GET_MODE(op1), op1); - binoptab = add_optab; - } - #endif /* 0 */ - /* Record where to delete back to if we backtrack. */ last = get_last_insn (); --- 315,318 ---- *************** *** 340,345 **** { delete_insns_since (last); ! return expand_binop (mode, binoptab, op0, op1, 0, unsignedp, ! methods); } --- 404,409 ---- { delete_insns_since (last); ! return expand_binop (mode, binoptab, op0, op1, NULL_RTX, ! unsignedp, methods); } *************** *** 351,354 **** --- 415,510 ---- } + /* If this is a multiply, see if we can do a widening operation that + takes operands of this mode and makes a wider mode. */ + + if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode + && (((unsignedp ? umul_widen_optab : smul_widen_optab) + ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code) + != CODE_FOR_nothing)) + { + temp = expand_binop (GET_MODE_WIDER_MODE (mode), + unsignedp ? umul_widen_optab : smul_widen_optab, + op0, op1, 0, unsignedp, OPTAB_DIRECT); + + if (GET_MODE_CLASS (mode) == MODE_INT) + return gen_lowpart (mode, temp); + else + return convert_to_mode (mode, temp, unsignedp); + } + + /* Look for a wider mode of the same class for which we think we + can open-code the operation. Check for a widening multiply at the + wider mode as well. */ + + if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) + && methods != OPTAB_DIRECT && methods != OPTAB_LIB) + for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing + || (binoptab == smul_optab + && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode + && (((unsignedp ? umul_widen_optab : smul_widen_optab) + ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code) + != CODE_FOR_nothing))) + { + rtx xop0 = op0, xop1 = op1; + int no_extend = 0; + + /* For certain integer operations, we need not actually extend + the narrow operands, as long as we will truncate + the results to the same narrowness. Don't do this when + WIDER_MODE is wider than a word since a paradoxical SUBREG + isn't valid for such modes. */ + + if ((binoptab == ior_optab || binoptab == and_optab + || binoptab == xor_optab + || binoptab == add_optab || binoptab == sub_optab + || binoptab == smul_optab + || binoptab == ashl_optab || binoptab == lshl_optab) + && class == MODE_INT + && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD) + no_extend = 1; + + /* If an operand is a constant integer, we might as well + convert it since that is more efficient than using a SUBREG, + unlike the case for other operands. Similarly for + SUBREGs that were made due to promoted objects. */ + + if (no_extend && GET_MODE (xop0) != VOIDmode + && ! (GET_CODE (xop0) == SUBREG + && SUBREG_PROMOTED_VAR_P (xop0))) + xop0 = gen_rtx (SUBREG, wider_mode, + force_reg (GET_MODE (xop0), xop0), 0); + else + xop0 = convert_to_mode (wider_mode, xop0, unsignedp); + + if (no_extend && GET_MODE (xop1) != VOIDmode + && ! (GET_CODE (xop1) == SUBREG + && SUBREG_PROMOTED_VAR_P (xop1))) + xop1 = gen_rtx (SUBREG, wider_mode, + force_reg (GET_MODE (xop1), xop1), 0); + else + xop1 = convert_to_mode (wider_mode, xop1, unsignedp); + + temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX, + unsignedp, OPTAB_DIRECT); + if (temp) + { + if (class != MODE_INT) + { + if (target == 0) + target = gen_reg_rtx (mode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (mode, temp); + } + else + delete_insns_since (last); + } + } + /* These can be done a word at a time. */ if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) *************** *** 589,597 **** != CODE_FOR_nothing) { ! rtx wordm1 = gen_rtx (CONST_INT, VOIDmode, BITS_PER_WORD - 1); product = expand_binop (mode, smul_widen_optab, op0_low, op1_low, target, 1, OPTAB_DIRECT); op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1, ! 0, 1, OPTAB_DIRECT); if (op0_xhigh) op0_xhigh = expand_binop (word_mode, add_optab, op0_high, --- 745,753 ---- != CODE_FOR_nothing) { ! rtx wordm1 = GEN_INT (BITS_PER_WORD - 1); product = expand_binop (mode, smul_widen_optab, op0_low, op1_low, target, 1, OPTAB_DIRECT); op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1, ! NULL_RTX, 1, OPTAB_DIRECT); if (op0_xhigh) op0_xhigh = expand_binop (word_mode, add_optab, op0_high, *************** *** 600,604 **** { op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1, ! 0, 0, OPTAB_DIRECT); if (op0_xhigh) op0_xhigh = expand_binop (word_mode, sub_optab, op0_high, --- 756,760 ---- { op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1, ! NULL_RTX, 0, OPTAB_DIRECT); if (op0_xhigh) op0_xhigh = expand_binop (word_mode, sub_optab, op0_high, *************** *** 608,612 **** op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1, ! 0, 1, OPTAB_DIRECT); if (op1_xhigh) op1_xhigh = expand_binop (word_mode, add_optab, op1_high, --- 764,768 ---- op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1, ! NULL_RTX, 1, OPTAB_DIRECT); if (op1_xhigh) op1_xhigh = expand_binop (word_mode, add_optab, op1_high, *************** *** 615,619 **** { op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1, ! 0, 0, OPTAB_DIRECT); if (op1_xhigh) op1_xhigh = expand_binop (word_mode, sub_optab, op1_high, --- 771,775 ---- { op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1, ! NULL_RTX, 0, OPTAB_DIRECT); if (op1_xhigh) op1_xhigh = expand_binop (word_mode, sub_optab, op1_high, *************** *** 637,642 **** rtx product_piece; rtx product_high = operand_subword (product, high, 1, mode); ! rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, 0, ! 0, OPTAB_DIRECT); if (temp) --- 793,798 ---- rtx product_piece; rtx product_high = operand_subword (product, high, 1, mode); ! rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh, ! NULL_RTX, 0, OPTAB_DIRECT); if (temp) *************** *** 648,653 **** emit_move_insn (product_high, product_piece); ! temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, 0, ! 0, OPTAB_DIRECT); product_piece = expand_binop (word_mode, add_optab, temp, --- 804,809 ---- emit_move_insn (product_high, product_piece); ! temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh, ! NULL_RTX, 0, OPTAB_DIRECT); product_piece = expand_binop (word_mode, add_optab, temp, *************** *** 673,676 **** --- 829,1054 ---- } + /* We need to open-code the complex type operations: '+, -, * and /' */ + + /* At this point we allow operations between two similar complex + numbers, and also if one of the operands is not a complex number + but rather of MODE_FLOAT or MODE_INT. However, the caller + must make sure that the MODE of the non-complex operand matches + the SUBMODE of the complex operand. */ + + if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT) + { + rtx real0 = (rtx) 0; + rtx imag0 = (rtx) 0; + rtx real1 = (rtx) 0; + rtx imag1 = (rtx) 0; + rtx realr; + rtx imagr; + rtx res; + rtx seq; + rtx equiv_value; + + /* Find the correct mode for the real and imaginary parts */ + enum machine_mode submode + = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, + class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, + 0); + + if (submode == BLKmode) + abort (); + + if (! target) + target = gen_reg_rtx (mode); + + start_sequence (); + + realr = gen_realpart (submode, target); + imagr = gen_imagpart (submode, target); + + if (GET_MODE (op0) == mode) + { + real0 = gen_realpart (submode, op0); + imag0 = gen_imagpart (submode, op0); + } + else + real0 = op0; + + if (GET_MODE (op1) == mode) + { + real1 = gen_realpart (submode, op1); + imag1 = gen_imagpart (submode, op1); + } + else + real1 = op1; + + if (! real0 || ! real1 || ! (imag0 || imag1)) + abort (); + + switch (binoptab->code) + { + case PLUS: + case MINUS: + res = expand_binop (submode, binoptab, real0, real1, + realr, unsignedp, methods); + if (res != realr) + emit_move_insn (realr, res); + + if (imag0 && imag1) + res = expand_binop (submode, binoptab, imag0, imag1, + imagr, unsignedp, methods); + else if (imag0) + res = imag0; + else if (binoptab->code == MINUS) + res = expand_unop (submode, neg_optab, imag1, imagr, unsignedp); + else + res = imag1; + + if (res != imagr) + emit_move_insn (imagr, res); + break; + + case MULT: + /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */ + + res = expand_binop (submode, binoptab, real0, real1, + realr, unsignedp, methods); + + if (imag0 && imag1) + { + rtx temp = + expand_binop (submode, sub_optab, res, + expand_binop (submode, binoptab, imag0, imag1, + 0, unsignedp, methods), + realr, unsignedp, methods); + + if (temp != realr) + emit_move_insn (realr, temp); + + res = expand_binop (submode, add_optab, + expand_binop (submode, binoptab, + real0, imag1, + 0, unsignedp, methods), + expand_binop (submode, binoptab, + real1, imag0, + 0, unsignedp, methods), + imagr, unsignedp, methods); + if (res != imagr) + emit_move_insn (imagr, res); + } + else + { + if (res != realr) + emit_move_insn (realr, res); + + if (imag0) + res = expand_binop (submode, binoptab, + real1, imag0, imagr, unsignedp, methods); + else + res = expand_binop (submode, binoptab, + real0, imag1, imagr, unsignedp, methods); + if (res != imagr) + emit_move_insn (imagr, res); + } + break; + + case DIV: + /* (c+id)/(a+ib) == ((c+id)*(a-ib))/(a*a+b*b) */ + + if (! imag1) + { + /* Simply divide the real and imaginary parts by `a' */ + res = expand_binop (submode, binoptab, real0, real1, + realr, unsignedp, methods); + if (res != realr) + emit_move_insn (realr, res); + + res = expand_binop (submode, binoptab, imag0, real1, + imagr, unsignedp, methods); + if (res != imagr) + emit_move_insn (imagr, res); + } + else /* Divider is of complex type */ + { /* X/(a+ib) */ + + rtx divider; + rtx real_t; + rtx imag_t; + + optab mulopt = unsignedp ? umul_widen_optab : smul_optab; + + /* Divider: a*a + b*b */ + divider = expand_binop (submode, add_optab, + expand_binop (submode, mulopt, + real1, real1, + 0, unsignedp, methods), + expand_binop (submode, mulopt, + imag1, imag1, + 0, unsignedp, methods), + 0, unsignedp, methods); + + if (! imag0) /* ((c)(a-ib))/divider */ + { + /* Calculate the divident */ + real_t = expand_binop (submode, mulopt, real0, real1, + 0, unsignedp, methods); + + imag_t + = expand_unop (submode, neg_optab, + expand_binop (submode, mulopt, real0, imag1, + 0, unsignedp, methods), + 0, unsignedp); + } + else /* ((c+id)(a-ib))/divider */ + { + /* Calculate the divident */ + real_t = expand_binop (submode, add_optab, + expand_binop (submode, mulopt, + real0, real1, + 0, unsignedp, methods), + expand_binop (submode, mulopt, + imag0, imag1, + 0, unsignedp, methods), + 0, unsignedp, methods); + + imag_t = expand_binop (submode, sub_optab, + expand_binop (submode, mulopt, + real0, imag1, + 0, unsignedp, methods), + expand_binop (submode, mulopt, + real1, imag0, + 0, unsignedp, methods), + 0, unsignedp, methods); + + } + + res = expand_binop (submode, binoptab, real_t, divider, + realr, unsignedp, methods); + if (res != realr) + emit_move_insn (realr, res); + + res = expand_binop (submode, binoptab, imag_t, divider, + imagr, unsignedp, methods); + if (res != imagr) + emit_move_insn (imagr, res); + } + break; + + default: + abort (); + } + + seq = get_insns (); + end_sequence (); + + if (binoptab->code != UNKNOWN) + equiv_value = gen_rtx (binoptab->code, mode, op0, op1); + else + equiv_value = 0; + + emit_no_conflict_block (seq, target, op0, op1, equiv_value); + + return target; + } + /* It can't be open-coded in this mode. Use a library call if one is available and caller says that's ok. */ *************** *** 681,692 **** rtx insns; rtx funexp = binoptab->handlers[(int) mode].libfunc; start_sequence (); /* Pass 1 for NO_QUEUE so we don't lose any increments if the libcall is cse'd or moved. */ emit_library_call (binoptab->handlers[(int) mode].libfunc, ! 1, mode, 2, op0, mode, op1, ! (shift_op ? word_mode : mode)); insns = get_insns (); --- 1059,1079 ---- rtx insns; rtx funexp = binoptab->handlers[(int) mode].libfunc; + rtx op1x = op1; + enum machine_mode op1_mode = mode; start_sequence (); + if (shift_op) + { + op1_mode = word_mode; + /* Specify unsigned here, + since negative shift counts are meaningless. */ + op1x = convert_to_mode (word_mode, op1, 1); + } + /* Pass 1 for NO_QUEUE so we don't lose any increments if the libcall is cse'd or moved. */ emit_library_call (binoptab->handlers[(int) mode].libfunc, ! 1, mode, 2, op0, mode, op1x, op1_mode); insns = get_insns (); *************** *** 731,735 **** /* For certain integer operations, we need not actually extend the narrow operands, as long as we will truncate ! the results to the same narrowness. */ if ((binoptab == ior_optab || binoptab == and_optab --- 1118,1124 ---- /* For certain integer operations, we need not actually extend the narrow operands, as long as we will truncate ! the results to the same narrowness. Don't do this when ! WIDER_MODE is wider than a word since a paradoxical SUBREG ! isn't valid for such modes. */ if ((binoptab == ior_optab || binoptab == and_optab *************** *** 738,749 **** || binoptab == smul_optab || binoptab == ashl_optab || binoptab == lshl_optab) ! && class == MODE_INT) no_extend = 1; /* If an operand is a constant integer, we might as well convert it since that is more efficient than using a SUBREG, ! unlike the case for other operands. */ ! if (no_extend && GET_MODE (xop0) != VOIDmode) xop0 = gen_rtx (SUBREG, wider_mode, force_reg (GET_MODE (xop0), xop0), 0); --- 1127,1142 ---- || binoptab == smul_optab || binoptab == ashl_optab || binoptab == lshl_optab) ! && class == MODE_INT ! && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD) no_extend = 1; /* If an operand is a constant integer, we might as well convert it since that is more efficient than using a SUBREG, ! unlike the case for other operands. Similarly for ! SUBREGs that were made due to promoted objects.*/ ! if (no_extend && GET_MODE (xop0) != VOIDmode ! && ! (GET_CODE (xop0) == SUBREG ! && SUBREG_PROMOTED_VAR_P (xop0))) xop0 = gen_rtx (SUBREG, wider_mode, force_reg (GET_MODE (xop0), xop0), 0); *************** *** 751,755 **** xop0 = convert_to_mode (wider_mode, xop0, unsignedp); ! if (no_extend && GET_MODE (xop1) != VOIDmode) xop1 = gen_rtx (SUBREG, wider_mode, force_reg (GET_MODE (xop1), xop1), 0); --- 1144,1150 ---- xop0 = convert_to_mode (wider_mode, xop0, unsignedp); ! if (no_extend && GET_MODE (xop1) != VOIDmode ! && ! (GET_CODE (xop1) == SUBREG ! && SUBREG_PROMOTED_VAR_P (xop1))) xop1 = gen_rtx (SUBREG, wider_mode, force_reg (GET_MODE (xop1), xop1), 0); *************** *** 757,761 **** xop1 = convert_to_mode (wider_mode, xop1, unsignedp); ! temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0, unsignedp, methods); if (temp) --- 1152,1156 ---- xop1 = convert_to_mode (wider_mode, xop1, unsignedp); ! temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX, unsignedp, methods); if (temp) *************** *** 1030,1037 **** { if (GET_CODE (pat) == SEQUENCE ! && ! add_equal_note (pat, temp, unoptab->code, xop0, 0)) { delete_insns_since (last); ! return expand_unop (mode, unoptab, op0, 0, unsignedp); } --- 1425,1432 ---- { if (GET_CODE (pat) == SEQUENCE ! && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX)) { delete_insns_since (last); ! return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp); } *************** *** 1044,1047 **** --- 1439,1486 ---- } + /* It can't be done in this mode. Can we open-code it in a wider mode? */ + + if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT) + for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) + { + rtx xop0 = op0; + + /* For certain operations, we need not actually extend + the narrow operand, as long as we will truncate the + results to the same narrowness. But it is faster to + convert a SUBREG due to mode promotion. */ + + if ((unoptab == neg_optab || unoptab == one_cmpl_optab) + && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD + && class == MODE_INT + && ! (GET_CODE (xop0) == SUBREG + && SUBREG_PROMOTED_VAR_P (xop0))) + xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0); + else + xop0 = convert_to_mode (wider_mode, xop0, unsignedp); + + temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, + unsignedp); + + if (temp) + { + if (class != MODE_INT) + { + if (target == 0) + target = gen_reg_rtx (mode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (mode, temp); + } + else + delete_insns_since (last); + } + } + /* These can be done a word at a time. */ if (unoptab == one_cmpl_optab *************** *** 1072,1080 **** end_sequence (); ! emit_no_conflict_block (insns, target, op0, 0, gen_rtx (unoptab->code, mode, op0)); return target; } if (unoptab->handlers[(int) mode].libfunc) { --- 1511,1564 ---- end_sequence (); ! emit_no_conflict_block (insns, target, op0, NULL_RTX, ! gen_rtx (unoptab->code, mode, op0)); ! return target; ! } ! ! /* Open-code the complex negation operation. */ ! else if (unoptab == neg_optab ! && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)) ! { ! rtx target_piece; ! rtx x; ! rtx seq; ! ! /* Find the correct mode for the real and imaginary parts */ ! enum machine_mode submode ! = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, ! class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, ! 0); ! ! if (submode == BLKmode) ! abort (); ! ! if (target == 0) ! target = gen_reg_rtx (mode); ! ! start_sequence (); ! ! target_piece = gen_imagpart (submode, target); ! x = expand_unop (submode, unoptab, ! gen_imagpart (submode, op0), ! target_piece, unsignedp); ! if (target_piece != x) ! emit_move_insn (target_piece, x); ! ! target_piece = gen_realpart (submode, target); ! x = expand_unop (submode, unoptab, ! gen_realpart (submode, op0), ! target_piece, unsignedp); ! if (target_piece != x) ! emit_move_insn (target_piece, x); ! ! seq = gen_sequence (); ! end_sequence (); ! ! emit_no_conflict_block (seq, target, op0, 0, gen_rtx (unoptab->code, mode, op0)); return target; } + /* Now try a library call in this mode. */ if (unoptab->handlers[(int) mode].libfunc) { *************** *** 1116,1125 **** if ((unoptab == neg_optab || unoptab == one_cmpl_optab) ! && class == MODE_INT) xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0); else xop0 = convert_to_mode (wider_mode, xop0, unsignedp); ! temp = expand_unop (wider_mode, unoptab, xop0, 0, unsignedp); if (temp) --- 1600,1613 ---- if ((unoptab == neg_optab || unoptab == one_cmpl_optab) ! && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD ! && class == MODE_INT ! && ! (GET_CODE (xop0) == SUBREG ! && SUBREG_PROMOTED_VAR_P (xop0))) xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0); else xop0 = convert_to_mode (wider_mode, xop0, unsignedp); ! temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, ! unsignedp); if (temp) *************** *** 1144,1147 **** --- 1632,1825 ---- } + /* Emit code to compute the absolute value of OP0, with result to + TARGET if convenient. (TARGET may be 0.) The return value says + where the result actually is to be found. + + MODE is the mode of the operand; the mode of the result is + different but can be deduced from MODE. + + UNSIGNEDP is relevant for complex integer modes. */ + + rtx + expand_complex_abs (mode, op0, target, unsignedp) + enum machine_mode mode; + rtx op0; + rtx target; + int unsignedp; + { + enum mode_class class = GET_MODE_CLASS (mode); + enum machine_mode wider_mode; + register rtx temp; + rtx last = get_last_insn (); + rtx pat; + + /* Find the correct mode for the real and imaginary parts. */ + enum machine_mode submode + = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT, + class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT, + 0); + + if (submode == BLKmode) + abort (); + + op0 = protect_from_queue (op0, 0); + + if (flag_force_mem) + { + op0 = force_not_mem (op0); + } + + if (target) + target = protect_from_queue (target, 1); + + if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + int icode = (int) abs_optab->handlers[(int) mode].insn_code; + enum machine_mode mode0 = insn_operand_mode[icode][1]; + rtx xop0 = op0; + + if (target) + temp = target; + else + temp = gen_reg_rtx (submode); + + if (GET_MODE (xop0) != VOIDmode + && GET_MODE (xop0) != mode0) + xop0 = convert_to_mode (mode0, xop0, unsignedp); + + /* Now, if insn doesn't accept our operand, put it into a pseudo. */ + + if (! (*insn_operand_predicate[icode][1]) (xop0, mode0)) + xop0 = copy_to_mode_reg (mode0, xop0); + + if (! (*insn_operand_predicate[icode][0]) (temp, submode)) + temp = gen_reg_rtx (submode); + + pat = GEN_FCN (icode) (temp, xop0); + if (pat) + { + if (GET_CODE (pat) == SEQUENCE + && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX)) + { + delete_insns_since (last); + return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp); + } + + emit_insn (pat); + + return temp; + } + else + delete_insns_since (last); + } + + /* It can't be done in this mode. Can we open-code it in a wider mode? */ + + for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing) + { + rtx xop0 = op0; + + xop0 = convert_to_mode (wider_mode, xop0, unsignedp); + temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp); + + if (temp) + { + if (class != MODE_COMPLEX_INT) + { + if (target == 0) + target = gen_reg_rtx (submode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (submode, temp); + } + else + delete_insns_since (last); + } + } + + /* Open-code the complex absolute-value operation + if we can open-code sqrt. Otherwise it's not worth while. */ + if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing) + { + rtx real, imag, total; + + real = gen_realpart (submode, op0); + imag = gen_imagpart (submode, op0); + /* Square both parts. */ + real = expand_mult (mode, real, real, NULL_RTX, 0); + imag = expand_mult (mode, imag, imag, NULL_RTX, 0); + /* Sum the parts. */ + total = expand_binop (submode, add_optab, real, imag, 0, + 0, OPTAB_LIB_WIDEN); + /* Get sqrt in TARGET. Set TARGET to where the result is. */ + target = expand_unop (submode, sqrt_optab, total, target, 0); + if (target == 0) + delete_insns_since (last); + else + return target; + } + + /* Now try a library call in this mode. */ + if (abs_optab->handlers[(int) mode].libfunc) + { + rtx insns; + rtx funexp = abs_optab->handlers[(int) mode].libfunc; + + start_sequence (); + + /* Pass 1 for NO_QUEUE so we don't lose any increments + if the libcall is cse'd or moved. */ + emit_library_call (abs_optab->handlers[(int) mode].libfunc, + 1, mode, 1, op0, mode); + insns = get_insns (); + end_sequence (); + + target = gen_reg_rtx (submode); + emit_libcall_block (insns, target, hard_libcall_value (submode), + gen_rtx (abs_optab->code, mode, op0)); + + return target; + } + + /* It can't be done in this mode. Can we do it in a wider mode? */ + + for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; + wider_mode = GET_MODE_WIDER_MODE (wider_mode)) + { + if ((abs_optab->handlers[(int) wider_mode].insn_code + != CODE_FOR_nothing) + || abs_optab->handlers[(int) wider_mode].libfunc) + { + rtx xop0 = op0; + + xop0 = convert_to_mode (wider_mode, xop0, unsignedp); + + temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp); + + if (temp) + { + if (class != MODE_COMPLEX_INT) + { + if (target == 0) + target = gen_reg_rtx (submode); + convert_move (target, temp, 0); + return target; + } + else + return gen_lowpart (submode, temp); + } + else + delete_insns_since (last); + } + } + + return 0; + } + /* Generate an instruction whose insn-code is INSN_CODE, with two operands: an output TARGET and an input OP0. *************** *** 1180,1184 **** if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN) ! add_equal_note (pat, temp, code, op0, 0); emit_insn (pat); --- 1858,1862 ---- if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN) ! add_equal_note (pat, temp, code, op0, NULL_RTX); emit_insn (pat); *************** *** 1484,1490 **** = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0]; rtx result = gen_reg_rtx (result_mode); ! emit_insn (gen_cmpstrqi (result, x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); ! emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0); } else --- 2162,2168 ---- = insn_operand_mode[(int) CODE_FOR_cmpstrqi][0]; rtx result = gen_reg_rtx (result_mode); ! emit_insn (gen_cmpstrqi (result, x, y, size, GEN_INT (align))); ! emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, ! result_mode, 0, 0); } else *************** *** 1498,1504 **** = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0]; rtx result = gen_reg_rtx (result_mode); ! emit_insn (gen_cmpstrhi (result, x, y, size, ! gen_rtx (CONST_INT, VOIDmode, align))); ! emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0); } else --- 2176,2182 ---- = insn_operand_mode[(int) CODE_FOR_cmpstrhi][0]; rtx result = gen_reg_rtx (result_mode); ! emit_insn (gen_cmpstrhi (result, x, y, size, GEN_INT (align))); ! emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, ! result_mode, 0, 0); } else *************** *** 1510,1517 **** = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; rtx result = gen_reg_rtx (result_mode); emit_insn (gen_cmpstrsi (result, x, y, convert_to_mode (SImode, size, 1), ! gen_rtx (CONST_INT, VOIDmode, align))); ! emit_cmp_insn (result, const0_rtx, comparison, 0, result_mode, 0, 0); } else --- 2188,2197 ---- = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0]; rtx result = gen_reg_rtx (result_mode); + size = protect_from_queue (size, 0); emit_insn (gen_cmpstrsi (result, x, y, convert_to_mode (SImode, size, 1), ! GEN_INT (align))); ! emit_cmp_insn (result, const0_rtx, comparison, NULL_RTX, ! result_mode, 0, 0); } else *************** *** 1519,1528 **** { #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcmp_libfunc, 1, TYPE_MODE (integer_type_node), 3, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, size, Pmode); #else ! emit_library_call (bcmp_libfunc, 1, TYPE_MODE (integer_type_node), 3, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, --- 2199,2208 ---- { #ifdef TARGET_MEM_FUNCTIONS ! emit_library_call (memcmp_libfunc, 0, TYPE_MODE (integer_type_node), 3, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, size, Pmode); #else ! emit_library_call (bcmp_libfunc, 0, TYPE_MODE (integer_type_node), 3, XEXP (x, 0), Pmode, XEXP (y, 0), Pmode, *************** *** 1530,1534 **** #endif emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)), ! const0_rtx, comparison, 0, TYPE_MODE (integer_type_node), 0, 0); } --- 2210,2214 ---- #endif emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)), ! const0_rtx, comparison, NULL_RTX, TYPE_MODE (integer_type_node), 0, 0); } *************** *** 1589,1595 **** != CODE_FOR_nothing) { x = convert_to_mode (wider_mode, x, unsignedp); y = convert_to_mode (wider_mode, y, unsignedp); ! emit_cmp_insn (x, y, comparison, 0, wider_mode, unsignedp, align); return; --- 2269,2277 ---- != CODE_FOR_nothing) { + x = protect_from_queue (x, 0); + y = protect_from_queue (y, 0); x = convert_to_mode (wider_mode, x, unsignedp); y = convert_to_mode (wider_mode, y, unsignedp); ! emit_cmp_insn (x, y, comparison, NULL_RTX, wider_mode, unsignedp, align); return; *************** *** 1617,1621 **** emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, ! comparison, 0, SImode, unsignedp, 0); return; } --- 2299,2303 ---- emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, ! comparison, NULL_RTX, SImode, unsignedp, 0); return; } *************** *** 1710,1713 **** --- 2392,2449 ---- break; } + else if (mode == XFmode) + switch (comparison) + { + case EQ: + libfunc = eqxf2_libfunc; + break; + + case NE: + libfunc = nexf2_libfunc; + break; + + case GT: + libfunc = gtxf2_libfunc; + break; + + case GE: + libfunc = gexf2_libfunc; + break; + + case LT: + libfunc = ltxf2_libfunc; + break; + + case LE: + libfunc = lexf2_libfunc; + break; + } + else if (mode == TFmode) + switch (comparison) + { + case EQ: + libfunc = eqtf2_libfunc; + break; + + case NE: + libfunc = netf2_libfunc; + break; + + case GT: + libfunc = gttf2_libfunc; + break; + + case GE: + libfunc = getf2_libfunc; + break; + + case LT: + libfunc = lttf2_libfunc; + break; + + case LE: + libfunc = letf2_libfunc; + break; + } else { *************** *** 1721,1724 **** --- 2457,2462 ---- || (cmp_optab->handlers[(int) wider_mode].libfunc != 0)) { + x = protect_from_queue (x, 0); + y = protect_from_queue (y, 0); x = convert_to_mode (wider_mode, x, 0); y = convert_to_mode (wider_mode, y, 0); *************** *** 1734,1738 **** emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison, ! 0, SImode, 0, 0); } --- 2472,2476 ---- emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, comparison, ! NULL_RTX, SImode, 0, 0); } *************** *** 2091,2094 **** --- 2829,2853 ---- #endif + #ifdef HAVE_fixxfqi2 + if (HAVE_fixxfqi2) + fixtab[(int) XFmode][(int) QImode][0] = CODE_FOR_fixxfqi2; + #endif + #ifdef HAVE_fixxfhi2 + if (HAVE_fixxfhi2) + fixtab[(int) XFmode][(int) HImode][0] = CODE_FOR_fixxfhi2; + #endif + #ifdef HAVE_fixxfsi2 + if (HAVE_fixxfsi2) + fixtab[(int) XFmode][(int) SImode][0] = CODE_FOR_fixxfsi2; + #endif + #ifdef HAVE_fixxfdi2 + if (HAVE_fixxfdi2) + fixtab[(int) XFmode][(int) DImode][0] = CODE_FOR_fixxfdi2; + #endif + #ifdef HAVE_fixxfti2 + if (HAVE_fixxfti2) + fixtab[(int) XFmode][(int) TImode][0] = CODE_FOR_fixxfti2; + #endif + #ifdef HAVE_fixtfqi2 if (HAVE_fixtfqi2) *************** *** 2150,2153 **** --- 2909,2933 ---- #endif + #ifdef HAVE_fixunsxfqi2 + if (HAVE_fixunsxfqi2) + fixtab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixunsxfqi2; + #endif + #ifdef HAVE_fixunsxfhi2 + if (HAVE_fixunsxfhi2) + fixtab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixunsxfhi2; + #endif + #ifdef HAVE_fixunsxfsi2 + if (HAVE_fixunsxfsi2) + fixtab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixunsxfsi2; + #endif + #ifdef HAVE_fixunsxfdi2 + if (HAVE_fixunsxfdi2) + fixtab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixunsxfdi2; + #endif + #ifdef HAVE_fixunsxfti2 + if (HAVE_fixunsxfti2) + fixtab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixunsxfti2; + #endif + #ifdef HAVE_fixunstfqi2 if (HAVE_fixunstfqi2) *************** *** 2189,2193 **** #ifdef HAVE_fix_truncdfqi2 ! if (HAVE_fix_truncdfsi2) fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2; #endif --- 2969,2973 ---- #ifdef HAVE_fix_truncdfqi2 ! if (HAVE_fix_truncdfqi2) fixtrunctab[(int) DFmode][(int) QImode][0] = CODE_FOR_fix_truncdfqi2; #endif *************** *** 2209,2212 **** --- 2989,3013 ---- #endif + #ifdef HAVE_fix_truncxfqi2 + if (HAVE_fix_truncxfqi2) + fixtrunctab[(int) XFmode][(int) QImode][0] = CODE_FOR_fix_truncxfqi2; + #endif + #ifdef HAVE_fix_truncxfhi2 + if (HAVE_fix_truncxfhi2) + fixtrunctab[(int) XFmode][(int) HImode][0] = CODE_FOR_fix_truncxfhi2; + #endif + #ifdef HAVE_fix_truncxfsi2 + if (HAVE_fix_truncxfsi2) + fixtrunctab[(int) XFmode][(int) SImode][0] = CODE_FOR_fix_truncxfsi2; + #endif + #ifdef HAVE_fix_truncxfdi2 + if (HAVE_fix_truncxfdi2) + fixtrunctab[(int) XFmode][(int) DImode][0] = CODE_FOR_fix_truncxfdi2; + #endif + #ifdef HAVE_fix_truncxfti2 + if (HAVE_fix_truncxfti2) + fixtrunctab[(int) XFmode][(int) TImode][0] = CODE_FOR_fix_truncxfti2; + #endif + #ifdef HAVE_fix_trunctfqi2 if (HAVE_fix_trunctfqi2) *************** *** 2268,2271 **** --- 3069,3093 ---- #endif + #ifdef HAVE_fixuns_truncxfqi2 + if (HAVE_fixuns_truncxfqi2) + fixtrunctab[(int) XFmode][(int) QImode][1] = CODE_FOR_fixuns_truncxfqi2; + #endif + #ifdef HAVE_fixuns_truncxfhi2 + if (HAVE_fixuns_truncxfhi2) + fixtrunctab[(int) XFmode][(int) HImode][1] = CODE_FOR_fixuns_truncxfhi2; + #endif + #ifdef HAVE_fixuns_truncxfsi2 + if (HAVE_fixuns_truncxfsi2) + fixtrunctab[(int) XFmode][(int) SImode][1] = CODE_FOR_fixuns_truncxfsi2; + #endif + #ifdef HAVE_fixuns_truncxfdi2 + if (HAVE_fixuns_truncxfdi2) + fixtrunctab[(int) XFmode][(int) DImode][1] = CODE_FOR_fixuns_truncxfdi2; + #endif + #ifdef HAVE_fixuns_truncxfti2 + if (HAVE_fixuns_truncxfti2) + fixtrunctab[(int) XFmode][(int) TImode][1] = CODE_FOR_fixuns_truncxfti2; + #endif + #ifdef HAVE_fixuns_trunctfqi2 if (HAVE_fixuns_trunctfqi2) *************** *** 2353,2356 **** --- 3175,3199 ---- #endif + #ifdef HAVE_floatqixf2 + if (HAVE_floatqixf2) + floattab[(int) XFmode][(int) QImode][0] = CODE_FOR_floatqixf2; + #endif + #ifdef HAVE_floathixf2 + if (HAVE_floathixf2) + floattab[(int) XFmode][(int) HImode][0] = CODE_FOR_floathixf2; + #endif + #ifdef HAVE_floatsixf2 + if (HAVE_floatsixf2) + floattab[(int) XFmode][(int) SImode][0] = CODE_FOR_floatsixf2; + #endif + #ifdef HAVE_floatdixf2 + if (HAVE_floatdixf2) + floattab[(int) XFmode][(int) DImode][0] = CODE_FOR_floatdixf2; + #endif + #ifdef HAVE_floattixf2 + if (HAVE_floattixf2) + floattab[(int) XFmode][(int) TImode][0] = CODE_FOR_floattixf2; + #endif + #ifdef HAVE_floatqitf2 if (HAVE_floatqitf2) *************** *** 2416,2419 **** --- 3259,3283 ---- #endif + #ifdef HAVE_floatunsqixf2 + if (HAVE_floatunsqixf2) + floattab[(int) XFmode][(int) QImode][1] = CODE_FOR_floatunsqixf2; + #endif + #ifdef HAVE_floatunshixf2 + if (HAVE_floatunshixf2) + floattab[(int) XFmode][(int) HImode][1] = CODE_FOR_floatunshixf2; + #endif + #ifdef HAVE_floatunssixf2 + if (HAVE_floatunssixf2) + floattab[(int) XFmode][(int) SImode][1] = CODE_FOR_floatunssixf2; + #endif + #ifdef HAVE_floatunsdixf2 + if (HAVE_floatunsdixf2) + floattab[(int) XFmode][(int) DImode][1] = CODE_FOR_floatunsdixf2; + #endif + #ifdef HAVE_floatunstixf2 + if (HAVE_floatunstixf2) + floattab[(int) XFmode][(int) TImode][1] = CODE_FOR_floatunstixf2; + #endif + #ifdef HAVE_floatunsqitf2 if (HAVE_floatunsqitf2) *************** *** 2476,2484 **** { to = protect_from_queue (to, 1); if (imode != GET_MODE (from)) from = convert_to_mode (imode, from, unsignedp); - else - from = protect_from_queue (from, 0); if (fmode != GET_MODE (to)) --- 3340,3347 ---- { to = protect_from_queue (to, 1); + from = protect_from_queue (from, 0); if (imode != GET_MODE (from)) from = convert_to_mode (imode, from, unsignedp); if (fmode != GET_MODE (to)) *************** *** 2525,2529 **** do_pending_stack_adjust (); ! emit_cmp_insn (from, const0_rtx, GE, 0, GET_MODE (from), 0, 0); emit_jump_insn (gen_bge (label)); /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). --- 3388,3392 ---- do_pending_stack_adjust (); ! emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, GET_MODE (from), 0, 0); emit_jump_insn (gen_bge (label)); /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). *************** *** 2542,2547 **** #endif ! /* No hardware instruction available; call a library ! to convert from SImode or DImode into SFmode or DFmode. */ { rtx libfcn; --- 3405,3410 ---- #endif ! /* No hardware instruction available; call a library rotine to convert from ! SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */ { rtx libfcn; *************** *** 2549,2557 **** to = protect_from_queue (to, 1); if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) from = convert_to_mode (SImode, from, unsignedp); - else - from = protect_from_queue (from, 0); if (flag_force_mem) --- 3412,3419 ---- to = protect_from_queue (to, 1); + from = protect_from_queue (from, 0); if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) from = convert_to_mode (SImode, from, unsignedp); if (flag_force_mem) *************** *** 2564,2567 **** --- 3426,3431 ---- else if (GET_MODE (from) == DImode) libfcn = floatdisf_libfunc; + else if (GET_MODE (from) == TImode) + libfcn = floattisf_libfunc; else abort (); *************** *** 2573,2576 **** --- 3437,3464 ---- else if (GET_MODE (from) == DImode) libfcn = floatdidf_libfunc; + else if (GET_MODE (from) == TImode) + libfcn = floattidf_libfunc; + else + abort (); + } + else if (GET_MODE (to) == XFmode) + { + if (GET_MODE (from) == SImode) + libfcn = floatsixf_libfunc; + else if (GET_MODE (from) == DImode) + libfcn = floatdixf_libfunc; + else if (GET_MODE (from) == TImode) + libfcn = floattixf_libfunc; + else + abort (); + } + else if (GET_MODE (to) == TFmode) + { + if (GET_MODE (from) == SImode) + libfcn = floatsitf_libfunc; + else if (GET_MODE (from) == DImode) + libfcn = floatditf_libfunc; + else if (GET_MODE (from) == TImode) + libfcn = floattitf_libfunc; else abort (); *************** *** 2642,2650 **** { to = protect_from_queue (to, 1); if (fmode != GET_MODE (from)) from = convert_to_mode (fmode, from, 0); - else - from = protect_from_queue (from, 0); if (must_trunc) --- 3530,3537 ---- { to = protect_from_queue (to, 1); + from = protect_from_queue (from, 0); if (fmode != GET_MODE (from)) from = convert_to_mode (fmode, from, 0); if (must_trunc) *************** *** 2672,2676 **** anything with a wider integer mode. */ ! if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT) for (fmode = GET_MODE (from); fmode != VOIDmode; fmode = GET_MODE_WIDER_MODE (fmode)) --- 3559,3563 ---- anything with a wider integer mode. */ ! if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT) for (fmode = GET_MODE (from); fmode != VOIDmode; fmode = GET_MODE_WIDER_MODE (fmode)) *************** *** 2699,2703 **** /* See if we need to do the subtraction. */ do_pending_stack_adjust (); ! emit_cmp_insn (from, limit, GE, 0, GET_MODE (from), 0, 0); emit_jump_insn (gen_bge (lab1)); --- 3586,3590 ---- /* See if we need to do the subtraction. */ do_pending_stack_adjust (); ! emit_cmp_insn (from, limit, GE, NULL_RTX, GET_MODE (from), 0, 0); emit_jump_insn (gen_bge (lab1)); *************** *** 2712,2720 **** emit_label (lab1); target = expand_binop (GET_MODE (from), sub_optab, from, limit, ! 0, 0, OPTAB_LIB_WIDEN); expand_fix (to, target, 0); target = expand_binop (GET_MODE (to), xor_optab, to, ! gen_rtx (CONST_INT, VOIDmode, ! 1 << (bitsize - 1)), to, 1, OPTAB_LIB_WIDEN); --- 3599,3606 ---- emit_label (lab1); target = expand_binop (GET_MODE (from), sub_optab, from, limit, ! NULL_RTX, 0, OPTAB_LIB_WIDEN); expand_fix (to, target, 0); target = expand_binop (GET_MODE (to), xor_optab, to, ! GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)), to, 1, OPTAB_LIB_WIDEN); *************** *** 2750,2753 **** --- 3636,3641 ---- else if (GET_MODE (to) == DImode) libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc; + else if (GET_MODE (to) == TImode) + libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc; else abort (); *************** *** 2759,2762 **** --- 3647,3674 ---- else if (GET_MODE (to) == DImode) libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc; + else if (GET_MODE (to) == TImode) + libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc; + else + abort (); + } + else if (GET_MODE (from) == XFmode) + { + if (GET_MODE (to) == SImode) + libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc; + else if (GET_MODE (to) == DImode) + libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc; + else if (GET_MODE (to) == TImode) + libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc; + else + abort (); + } + else if (GET_MODE (from) == TFmode) + { + if (GET_MODE (to) == SImode) + libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc; + else if (GET_MODE (to) == DImode) + libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc; + else if (GET_MODE (to) == TImode) + libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc; else abort (); *************** *** 2807,2810 **** --- 3719,3815 ---- } + /* Initialize the libfunc fields of an entire group of entries in some + optab. Each entry is set equal to a string consisting of a leading + pair of underscores followed by a generic operation name followed by + a mode name (downshifted to lower case) followed by a single character + representing the number of operands for the given operation (which is + usually one of the characters '2', '3', or '4'). + + OPTABLE is the table in which libfunc fields are to be initialized. + FIRST_MODE is the first machine mode index in the given optab to + initialize. + LAST_MODE is the last machine mode index in the given optab to + initialize. + OPNAME is the generic (string) name of the operation. + SUFFIX is the character which specifies the number of operands for + the given generic operation. + */ + + static void + init_libfuncs (optable, first_mode, last_mode, opname, suffix) + register optab optable; + register char *opname; + register enum machine_mode first_mode; + register enum machine_mode last_mode; + register char suffix; + { + register enum machine_mode mode; + register unsigned opname_len = strlen (opname); + + for (mode = first_mode; mode <= last_mode; mode++) + { + register char *mname = mode_name[(int) mode]; + register unsigned mname_len = strlen (mname); + register char *libfunc_name + = (char *) xmalloc (2 + opname_len + mname_len + 1 + 1); + register char *p; + register char *q; + + p = libfunc_name; + *p++ = '_'; + *p++ = '_'; + for (q = opname; *q; ) + *p++ = *q++; + for (q = mname; *q; q++) + *p++ = tolower (*q); + *p++ = suffix; + *p++ = '\0'; + optable->handlers[(int) mode].libfunc + = gen_rtx (SYMBOL_REF, Pmode, libfunc_name); + } + } + + /* Initialize the libfunc fields of an entire group of entries in some + optab which correspond to all integer mode operations. The parameters + have the same meaning as similarly named ones for the `init_libfuncs' + routine. (See above). */ + + static void + init_integral_libfuncs (optable, opname, suffix) + register optab optable; + register char *opname; + register char suffix; + { + init_libfuncs (optable, SImode, TImode, opname, suffix); + } + + /* Initialize the libfunc fields of an entire group of entries in some + optab which correspond to all real mode operations. The parameters + have the same meaning as similarly named ones for the `init_libfuncs' + routine. (See above). */ + + static void + init_floating_libfuncs (optable, opname, suffix) + register optab optable; + register char *opname; + register char suffix; + { + init_libfuncs (optable, SFmode, TFmode, opname, suffix); + } + + /* Initialize the libfunc fields of an entire group of entries in some + optab which correspond to all complex floating modes. The parameters + have the same meaning as similarly named ones for the `init_libfuncs' + routine. (See above). */ + + static void + init_complex_libfuncs (optable, opname, suffix) + register optab optable; + register char *opname; + register char suffix; + { + init_libfuncs (optable, SCmode, TCmode, opname, suffix); + } + /* Call this once to initialize the contents of the optabs appropriately for the current target machine. */ *************** *** 2855,2858 **** --- 3860,3865 ---- ffs_optab = init_optab (FFS); sqrt_optab = init_optab (SQRT); + sin_optab = init_optab (UNKNOWN); + cos_optab = init_optab (UNKNOWN); strlen_optab = init_optab (UNKNOWN); *************** *** 2889,2900 **** add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3; #endif #ifdef HAVE_addtf3 if (HAVE_addtf3) add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3; #endif ! add_optab->handlers[(int) SFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__addsf3"); ! add_optab->handlers[(int) DFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__adddf3"); #ifdef HAVE_subqi3 --- 3896,3909 ---- add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3; #endif + #ifdef HAVE_addxf3 + if (HAVE_addxf3) + add_optab->handlers[(int) XFmode].insn_code = CODE_FOR_addxf3; + #endif #ifdef HAVE_addtf3 if (HAVE_addtf3) add_optab->handlers[(int) TFmode].insn_code = CODE_FOR_addtf3; #endif ! init_integral_libfuncs (add_optab, "add", '3'); ! init_floating_libfuncs (add_optab, "add", '3'); #ifdef HAVE_subqi3 *************** *** 2930,2941 **** sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3; #endif #ifdef HAVE_subtf3 if (HAVE_subtf3) sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3; #endif ! sub_optab->handlers[(int) SFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__subsf3"); ! sub_optab->handlers[(int) DFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__subdf3"); #ifdef HAVE_mulqi3 --- 3939,3952 ---- sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3; #endif + #ifdef HAVE_subxf3 + if (HAVE_subxf3) + sub_optab->handlers[(int) XFmode].insn_code = CODE_FOR_subxf3; + #endif #ifdef HAVE_subtf3 if (HAVE_subtf3) sub_optab->handlers[(int) TFmode].insn_code = CODE_FOR_subtf3; #endif ! init_integral_libfuncs (sub_optab, "sub", '3'); ! init_floating_libfuncs (sub_optab, "sub", '3'); #ifdef HAVE_mulqi3 *************** *** 2971,2997 **** smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3; #endif #ifdef HAVE_multf3 if (HAVE_multf3) smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3; #endif #ifdef MULSI3_LIBCALL smul_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL); - #else - smul_optab->handlers[(int) SImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__mulsi3"); #endif #ifdef MULDI3_LIBCALL smul_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL); ! #else ! smul_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__muldi3"); #endif - smul_optab->handlers[(int) SFmode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__mulsf3"); - smul_optab->handlers[(int) DFmode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__muldf3"); #ifdef HAVE_mulqihi3 --- 3982,4008 ---- smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3; #endif + #ifdef HAVE_mulxf3 + if (HAVE_mulxf3) + smul_optab->handlers[(int) XFmode].insn_code = CODE_FOR_mulxf3; + #endif #ifdef HAVE_multf3 if (HAVE_multf3) smul_optab->handlers[(int) TFmode].insn_code = CODE_FOR_multf3; #endif + init_integral_libfuncs (smul_optab, "mul", '3'); + init_floating_libfuncs (smul_optab, "mul", '3'); #ifdef MULSI3_LIBCALL smul_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MULSI3_LIBCALL); #endif #ifdef MULDI3_LIBCALL smul_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MULDI3_LIBCALL); ! #endif ! #ifdef MULTI3_LIBCALL ! smul_optab->handlers[(int) TImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, MULTI3_LIBCALL); #endif #ifdef HAVE_mulqihi3 *************** *** 3053,3070 **** sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3; #endif #ifdef DIVSI3_LIBCALL sdiv_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL); - #else - sdiv_optab->handlers[(int) SImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__divsi3"); #endif #ifdef DIVDI3_LIBCALL sdiv_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL); ! #else ! sdiv_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__divdi3"); #endif --- 4064,4080 ---- sdiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_divti3; #endif + init_integral_libfuncs (sdiv_optab, "div", '3'); #ifdef DIVSI3_LIBCALL sdiv_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, DIVSI3_LIBCALL); #endif #ifdef DIVDI3_LIBCALL sdiv_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, DIVDI3_LIBCALL); ! #endif ! #ifdef DIVTI3_LIBCALL ! sdiv_optab->handlers[(int) TImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, DIVTI3_LIBCALL); #endif *************** *** 3093,3110 **** udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3; #endif #ifdef UDIVSI3_LIBCALL udiv_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL); - #else - udiv_optab->handlers[(int) SImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__udivsi3"); #endif #ifdef UDIVDI3_LIBCALL udiv_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL); ! #else ! udiv_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__udivdi3"); #endif --- 4103,4119 ---- udiv_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivti3; #endif + init_integral_libfuncs (udiv_optab, "udiv", '3'); #ifdef UDIVSI3_LIBCALL udiv_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UDIVSI3_LIBCALL); #endif #ifdef UDIVDI3_LIBCALL udiv_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UDIVDI3_LIBCALL); ! #endif ! #ifdef UDIVTI3_LIBCALL ! udiv_optab->handlers[(int) TImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, UDIVTI3_LIBCALL); #endif *************** *** 3129,3132 **** --- 4138,4142 ---- sdivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_divmodti4; #endif + init_integral_libfuncs (sdivmod_optab, "divmod", '4'); #ifdef HAVE_udivmodqi4 *************** *** 3150,3153 **** --- 4160,4164 ---- udivmod_optab->handlers[(int) TImode].insn_code = CODE_FOR_udivmodti4; #endif + init_integral_libfuncs (udivmod_optab, "udivmod", '4'); #ifdef HAVE_modqi3 *************** *** 3175,3192 **** smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3; #endif #ifdef MODSI3_LIBCALL smod_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL); - #else - smod_optab->handlers[(int) SImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__modsi3"); #endif #ifdef MODDI3_LIBCALL smod_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL); ! #else ! smod_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__moddi3"); #endif --- 4186,4202 ---- smod_optab->handlers[(int) TImode].insn_code = CODE_FOR_modti3; #endif + init_integral_libfuncs (smod_optab, "mod", '3'); #ifdef MODSI3_LIBCALL smod_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MODSI3_LIBCALL); #endif #ifdef MODDI3_LIBCALL smod_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, MODDI3_LIBCALL); ! #endif ! #ifdef MODTI3_LIBCALL ! smod_optab->handlers[(int) TImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, MODTI3_LIBCALL); #endif *************** *** 3215,3233 **** umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3; #endif #ifdef UMODSI3_LIBCALL umod_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL); - #else - umod_optab->handlers[(int) SImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__umodsi3"); #endif #ifdef UMODDI3_LIBCALL umod_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL); - #else - umod_optab->handlers[(int) DImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__umoddi3"); #endif #ifdef HAVE_divsf3 --- 4225,4242 ---- umod_optab->handlers[(int) TImode].insn_code = CODE_FOR_umodti3; #endif + init_integral_libfuncs (umod_optab, "umod", '3'); #ifdef UMODSI3_LIBCALL umod_optab->handlers[(int) SImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UMODSI3_LIBCALL); #endif #ifdef UMODDI3_LIBCALL umod_optab->handlers[(int) DImode].libfunc = gen_rtx (SYMBOL_REF, Pmode, UMODDI3_LIBCALL); #endif + #ifdef UMODTI3_LIBCALL + umod_optab->handlers[(int) TImode].libfunc + = gen_rtx (SYMBOL_REF, Pmode, UMODTI3_LIBCALL); + #endif #ifdef HAVE_divsf3 *************** *** 3239,3250 **** flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3; #endif #ifdef HAVE_divtf3 if (HAVE_divtf3) flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3; #endif ! flodiv_optab->handlers[(int) SFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__divsf3"); ! flodiv_optab->handlers[(int) DFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__divdf3"); #ifdef HAVE_ftruncsf2 --- 4248,4260 ---- flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3; #endif + #ifdef HAVE_divxf3 + if (HAVE_divxf3) + flodiv_optab->handlers[(int) XFmode].insn_code = CODE_FOR_divxf3; + #endif #ifdef HAVE_divtf3 if (HAVE_divtf3) flodiv_optab->handlers[(int) TFmode].insn_code = CODE_FOR_divtf3; #endif ! init_floating_libfuncs (flodiv_optab, "div", '3'); #ifdef HAVE_ftruncsf2 *************** *** 3256,3263 **** --- 4266,4278 ---- ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2; #endif + #ifdef HAVE_ftruncxf2 + if (HAVE_ftruncxf2) + ftrunc_optab->handlers[(int) XFmode].insn_code = CODE_FOR_ftruncxf2; + #endif #ifdef HAVE_ftrunctf2 if (HAVE_ftrunctf2) ftrunc_optab->handlers[(int) TFmode].insn_code = CODE_FOR_ftrunctf2; #endif + init_floating_libfuncs (ftrunc_optab, "ftrunc", '2'); #ifdef HAVE_andqi3 *************** *** 3285,3288 **** --- 4300,4304 ---- and_optab->handlers[(int) TImode].insn_code = CODE_FOR_andti3; #endif + init_integral_libfuncs (and_optab, "and", '3'); #ifdef HAVE_iorqi3 *************** *** 3310,3313 **** --- 4326,4330 ---- ior_optab->handlers[(int) TImode].insn_code = CODE_FOR_iorti3; #endif + init_integral_libfuncs (ior_optab, "ior", '3'); #ifdef HAVE_xorqi3 *************** *** 3335,3338 **** --- 4352,4356 ---- xor_optab->handlers[(int) TImode].insn_code = CODE_FOR_xorti3; #endif + init_integral_libfuncs (xor_optab, "xor", '3'); #ifdef HAVE_ashlqi3 *************** *** 3360,3367 **** ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3; #endif ! ashl_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__ashlsi3"); ! ashl_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__ashldi3"); #ifdef HAVE_ashrqi3 --- 4378,4382 ---- ashl_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashlti3; #endif ! init_integral_libfuncs (ashl_optab, "ashl", '3'); #ifdef HAVE_ashrqi3 *************** *** 3389,3396 **** ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3; #endif ! ashr_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__ashrsi3"); ! ashr_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__ashrdi3"); #ifdef HAVE_lshlqi3 --- 4404,4408 ---- ashr_optab->handlers[(int) TImode].insn_code = CODE_FOR_ashrti3; #endif ! init_integral_libfuncs (ashr_optab, "ashr", '3'); #ifdef HAVE_lshlqi3 *************** *** 3418,3425 **** lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3; #endif ! lshl_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__lshlsi3"); ! lshl_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__lshldi3"); #ifdef HAVE_lshrqi3 --- 4430,4434 ---- lshl_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshlti3; #endif ! init_integral_libfuncs (lshl_optab, "lshl", '3'); #ifdef HAVE_lshrqi3 *************** *** 3447,3454 **** lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3; #endif ! lshr_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__lshrsi3"); ! lshr_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__lshrdi3"); #ifdef HAVE_rotlqi3 --- 4456,4460 ---- lshr_optab->handlers[(int) TImode].insn_code = CODE_FOR_lshrti3; #endif ! init_integral_libfuncs (lshr_optab, "lshr", '3'); #ifdef HAVE_rotlqi3 *************** *** 3476,3483 **** rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3; #endif ! rotl_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__rotlsi3"); ! rotl_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__rotldi3"); #ifdef HAVE_rotrqi3 --- 4482,4486 ---- rotl_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotlti3; #endif ! init_integral_libfuncs (rotl_optab, "rotl", '3'); #ifdef HAVE_rotrqi3 *************** *** 3505,3512 **** rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3; #endif ! rotr_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__rotrsi3"); ! rotr_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__rotrdi3"); #ifdef HAVE_sminqi3 --- 4508,4512 ---- rotr_optab->handlers[(int) TImode].insn_code = CODE_FOR_rotrti3; #endif ! init_integral_libfuncs (rotr_optab, "rotr", '3'); #ifdef HAVE_sminqi3 *************** *** 3530,3545 **** smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3; #endif ! #ifdef HAVE_sminsf3 ! if (HAVE_sminsf3) ! smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sminsf3; ! #endif ! #ifdef HAVE_smindf3 ! if (HAVE_smindf3) ! smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_smindf3; ! #endif ! #ifdef HAVE_smintf3 ! if (HAVE_smintf3) ! smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_smintf3; #endif #ifdef HAVE_smaxqi3 --- 4530,4551 ---- smin_optab->handlers[(int) TImode].insn_code = CODE_FOR_sminti3; #endif ! #ifdef HAVE_minsf3 ! if (HAVE_minsf3) ! smin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_minsf3; ! #endif ! #ifdef HAVE_mindf3 ! if (HAVE_mindf3) ! smin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_mindf3; ! #endif ! #ifdef HAVE_minxf3 ! if (HAVE_minxf3) ! smin_optab->handlers[(int) XFmode].insn_code = CODE_FOR_minxf3; ! #endif ! #ifdef HAVE_mintf3 ! if (HAVE_mintf3) ! smin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_mintf3; #endif + init_integral_libfuncs (smin_optab, "min", '3'); + init_floating_libfuncs (smin_optab, "min", '3'); #ifdef HAVE_smaxqi3 *************** *** 3563,3578 **** smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3; #endif ! #ifdef HAVE_smaxsf3 ! if (HAVE_smaxsf3) ! smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_smaxsf3; ! #endif ! #ifdef HAVE_smaxdf3 ! if (HAVE_smaxdf3) ! smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_smaxdf3; ! #endif ! #ifdef HAVE_smaxtf3 ! if (HAVE_smaxtf3) ! smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_smaxtf3; #endif #ifdef HAVE_uminqi3 --- 4569,4590 ---- smax_optab->handlers[(int) TImode].insn_code = CODE_FOR_smaxti3; #endif ! #ifdef HAVE_maxsf3 ! if (HAVE_maxsf3) ! smax_optab->handlers[(int) SFmode].insn_code = CODE_FOR_maxsf3; ! #endif ! #ifdef HAVE_maxdf3 ! if (HAVE_maxdf3) ! smax_optab->handlers[(int) DFmode].insn_code = CODE_FOR_maxdf3; ! #endif ! #ifdef HAVE_maxxf3 ! if (HAVE_maxxf3) ! smax_optab->handlers[(int) XFmode].insn_code = CODE_FOR_maxxf3; ! #endif ! #ifdef HAVE_maxtf3 ! if (HAVE_maxtf3) ! smax_optab->handlers[(int) TFmode].insn_code = CODE_FOR_maxtf3; #endif + init_integral_libfuncs (smax_optab, "max", '3'); + init_floating_libfuncs (smax_optab, "max", '3'); #ifdef HAVE_uminqi3 *************** *** 3596,3599 **** --- 4608,4612 ---- umin_optab->handlers[(int) TImode].insn_code = CODE_FOR_uminti3; #endif + init_integral_libfuncs (umin_optab, "umin", '3'); #ifdef HAVE_umaxqi3 *************** *** 3617,3620 **** --- 4630,4634 ---- umax_optab->handlers[(int) TImode].insn_code = CODE_FOR_umaxti3; #endif + init_integral_libfuncs (umax_optab, "umax", '3'); #ifdef HAVE_negqi2 *************** *** 3650,3665 **** neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2; #endif #ifdef HAVE_negtf2 if (HAVE_negtf2) neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2; #endif ! neg_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__negsi2"); ! neg_optab->handlers[(int) DImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__negdi2"); ! neg_optab->handlers[(int) SFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__negsf2"); ! neg_optab->handlers[(int) DFmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__negdf2"); #ifdef HAVE_absqi2 --- 4664,4677 ---- neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2; #endif + #ifdef HAVE_negxf2 + if (HAVE_negxf2) + neg_optab->handlers[(int) XFmode].insn_code = CODE_FOR_negxf2; + #endif #ifdef HAVE_negtf2 if (HAVE_negtf2) neg_optab->handlers[(int) TFmode].insn_code = CODE_FOR_negtf2; #endif ! init_integral_libfuncs (neg_optab, "neg", '2'); ! init_floating_libfuncs (neg_optab, "neg", '2'); #ifdef HAVE_absqi2 *************** *** 3695,3704 **** abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2; #endif #ifdef HAVE_abstf2 if (HAVE_abstf2) abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2; #endif ! /* No library calls here! If there is no abs instruction, ! expand_expr will generate a conditional negation. */ #ifdef HAVE_sqrtqi2 --- 4707,4723 ---- abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2; #endif + #ifdef HAVE_absxf2 + if (HAVE_absxf2) + abs_optab->handlers[(int) XFmode].insn_code = CODE_FOR_absxf2; + #endif #ifdef HAVE_abstf2 if (HAVE_abstf2) abs_optab->handlers[(int) TFmode].insn_code = CODE_FOR_abstf2; #endif ! ! /* Use cabs for DC complex abs, since systems generally have cabs. ! Don't define any libcall for SCmode, so that cabs will be used. */ ! abs_optab->handlers[(int) DCmode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "cabs"); #ifdef HAVE_sqrtqi2 *************** *** 3741,3744 **** --- 4760,4793 ---- should force the library call. */ + #ifdef HAVE_sinsf2 + if (HAVE_sinsf2) + sin_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sinsf2; + #endif + #ifdef HAVE_sindf2 + if (HAVE_sindf2) + sin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sindf2; + #endif + #ifdef HAVE_sintf2 + if (HAVE_sintf2) + sin_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sintf2; + #endif + /* No library calls here! If there is no sin instruction expand_builtin + should force the library call. */ + + #ifdef HAVE_cossf2 + if (HAVE_cossf2) + cos_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cossf2; + #endif + #ifdef HAVE_cosdf2 + if (HAVE_cosdf2) + cos_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cosdf2; + #endif + #ifdef HAVE_costf2 + if (HAVE_costf2) + cos_optab->handlers[(int) TFmode].insn_code = CODE_FOR_costf2; + #endif + /* No library calls here! If there is no cos instruction expand_builtin + should force the library call. */ + #ifdef HAVE_strlenqi if (HAVE_strlenqi) *************** *** 3792,3797 **** one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2; #endif ! one_cmpl_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "__one_cmplsi2"); #ifdef HAVE_ffsqi2 --- 4841,4845 ---- one_cmpl_optab->handlers[(int) TImode].insn_code = CODE_FOR_one_cmplti2; #endif ! init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2'); #ifdef HAVE_ffsqi2 *************** *** 3819,3824 **** ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2; #endif ! ffs_optab->handlers[(int) SImode].libfunc ! = gen_rtx (SYMBOL_REF, Pmode, "ffs"); #ifdef HAVE_movqi --- 4867,4871 ---- ffs_optab->handlers[(int) TImode].insn_code = CODE_FOR_ffsti2; #endif ! init_integral_libfuncs (ffs_optab, "ffs", '2'); #ifdef HAVE_movqi *************** *** 3854,3857 **** --- 4901,4908 ---- mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf; #endif + #ifdef HAVE_movxf + if (HAVE_movxf) + mov_optab->handlers[(int) XFmode].insn_code = CODE_FOR_movxf; + #endif #ifdef HAVE_movtf if (HAVE_movtf) *************** *** 3924,3931 **** --- 4975,4991 ---- cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf; #endif + #ifdef HAVE_cmpxf + if (HAVE_cmpxf) + cmp_optab->handlers[(int) XFmode].insn_code = CODE_FOR_cmpxf; + #endif #ifdef HAVE_cmptf if (HAVE_cmptf) cmp_optab->handlers[(int) TFmode].insn_code = CODE_FOR_cmptf; #endif + /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ + init_integral_libfuncs (cmp_optab, "cmp", '2'); + init_integral_libfuncs (ucmp_optab, "ucmp", '2'); + init_floating_libfuncs (cmp_optab, "cmp", '2'); + #ifdef HAVE_tstqi if (HAVE_tstqi) *************** *** 3960,3972 **** tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf; #endif #ifdef HAVE_tsttf if (HAVE_tsttf) tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf; #endif - /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */ - cmp_optab->handlers[(int) DImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__cmpdi2"); - ucmp_optab->handlers[(int) DImode].libfunc - = gen_rtx (SYMBOL_REF, Pmode, "__ucmpdi2"); #ifdef HAVE_beq --- 5020,5031 ---- tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf; #endif + #ifdef HAVE_tstxf + if (HAVE_tstxf) + tst_optab->handlers[(int) XFmode].insn_code = CODE_FOR_tstxf; + #endif #ifdef HAVE_tsttf if (HAVE_tsttf) tst_optab->handlers[(int) TFmode].insn_code = CODE_FOR_tsttf; #endif #ifdef HAVE_beq *************** *** 4056,4066 **** extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2"); truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2"); memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy"); bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy"); memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp"); ! bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcmp"); memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset"); bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero"); eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2"); nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2"); --- 5115,5136 ---- extendsfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfdf2"); + extendsfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsfxf2"); + extendsftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extendsftf2"); + extenddfxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddfxf2"); + extenddftf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__extenddftf2"); + truncdfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncdfsf2"); + truncxfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfsf2"); + trunctfsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfsf2"); + truncxfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__truncxfdf2"); + trunctfdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__trunctfdf2"); + memcpy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcpy"); bcopy_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bcopy"); memcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memcmp"); ! bcmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gcc_bcmp"); memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset"); bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero"); + eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqsf2"); nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nesf2"); *************** *** 4069,4072 **** --- 5139,5143 ---- ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltsf2"); lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lesf2"); + eqdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqdf2"); nedf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nedf2"); *************** *** 4075,4090 **** ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2"); ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2"); ! floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf"); floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf"); ! floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf"); floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf"); fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi"); fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi"); fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi"); fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi"); fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi"); fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi"); fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi"); fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi"); } --- 5146,5211 ---- ltdf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltdf2"); ledf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ledf2"); ! ! eqxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqxf2"); ! nexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nexf2"); ! gtxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gtxf2"); ! gexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gexf2"); ! ltxf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__ltxf2"); ! lexf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lexf2"); ! ! eqtf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqtf2"); ! netf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__netf2"); ! gttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gttf2"); ! getf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__getf2"); ! lttf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__lttf2"); ! letf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__letf2"); ! floatsisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsisf"); ! floatdisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdisf"); ! floattisf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattisf"); ! floatsidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsidf"); + floatdidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdidf"); + floattidf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattidf"); + + floatsixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsixf"); + floatdixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatdixf"); + floattixf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattixf"); + + floatsitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatsitf"); + floatditf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floatditf"); + floattitf_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__floattitf"); + fixsfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfsi"); fixsfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfdi"); + fixsfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixsfti"); + fixdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfsi"); fixdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfdi"); + fixdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixdfti"); + + fixxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfsi"); + fixxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfdi"); + fixxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixxfti"); + + fixtfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfsi"); + fixtfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfdi"); + fixtfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixtfti"); + fixunssfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfsi"); fixunssfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfdi"); + fixunssfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunssfti"); + fixunsdfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfsi"); fixunsdfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfdi"); + fixunsdfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsdfti"); + + fixunsxfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfsi"); + fixunsxfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfdi"); + fixunsxfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunsxfti"); + + fixunstfsi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfsi"); + fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi"); + fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti"); } diff -rc2N gcc-2.2.2/output.h gcc-2.3.1/output.h *** gcc-2.2.2/output.h Sat Mar 28 01:33:16 1992 --- gcc-2.3.1/output.h Sat Aug 1 22:44:04 1992 *************** *** 27,30 **** --- 27,38 ---- extern void asm_fprintf (); + /* Print an integer constant expression in assembler syntax. + Addition and subtraction are the only arithmetic + that may appear in these expressions. */ + extern void output_addr_const (); + + /* Output a name (as found inside a symbol_ref) in assembler syntax. */ + extern void assemble_name (); + /* Replace a SUBREG with a REG or a MEM, based on the thing it is a subreg of. */ diff -rc2N gcc-2.2.2/populate gcc-2.3.1/populate *** gcc-2.2.2/populate --- gcc-2.3.1/populate Wed Oct 7 17:30:29 1992 *************** *** 0 **** --- 1,166 ---- + #!/bin/sh + # + # NAME + # populate + # + # SYNOPSIS + # populate target-dir [ source-dir ... ] + # + # DESCRIPTION + # Adjunct script for GNU C++ to populate a directory with C++ + # compatible header files. + # + # For each header file (whose name ends in .h) which resides in one + # of the indicated source-dirs, create a corresponding file in the + # target-dir (with the same name) which looks like: + # + # #ifndef __IN_C_REGION__ + # #define __IN_C_REGION__ + # extern "C" { + # #include_next + # } + # #undef __IN_C_REGION__ + # #else + # #include_next + # #endif + # + # Where "header.h" is the name of the original header file in the + # source-dir. + # + # If a file with the appropriate name already exists in the target + # directory, it will not be overwritten. + # + # NOTES + # This script assumes that your native header files are already + # at least compliant with ANSI C, and that all functions declared + # therein are properly prototyped (as they must be for C++). + # + # Currently, this condition is not fully satisfied by many (if any) + # systems. On System V Release 4, most of the system header files + # do seem to be properly prototyped though, and OSF/1 also has + # prototyped header files, but some of the argument type specifica- + # tions for some function prototypes in some OSF/1 header files may + # lack `const' qualifiers in certain places where they ought to appear. + # (This is due to the fact that OSF/1 conformat to POSIX-1988 rather + # than to the newer POSIX-1990 standard.) + # + # If your system's native include files are not properly prototyped, + # that's OK. This script will still do it's normal job (in the normal + # way) but the resulting (indirect) header files will not be very useful + # for g++ programming unless (and until) somebody puts in all of the + # prototypes for all of the functions which are declared in these files. + # + # Note that in some cases, a header file with a given name may exist + # in two or more of the given source directories. That's perfectly + # alright. Only one (corresponding) header file will be placed into + # the target directory for each such group of kindred source files. + # + # This script should probably be invoked from the GCC Makefile, via: + # + # populate $(libdir)/g++-include $(libsubdir)/include /usr/include + # + # That would insure the creation of a C++ compatible set of headers + # (in the sepcial g++-include directory) corresponding to all of the + # normal GCC header files and all of the native system's header files. + # + # AUTHOR + # Ron Guilmette (rfg@ncd.com) + # + # COPYRIGHT + # 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. + + progname=$0 + progname=`basename $progname` + original_dir=`pwd` + if [ `echo $1 | wc -w` = 0 ] ; then + echo $progname\: usage\: $progname target-dir \[ source-dir \.\.\. \] + exit 1 + fi + rel_target_dir=$1 + shift + + if [ `expr $rel_target_dir : '\(.\)'` != '/' ] ; then + abs_target_dir=$original_dir/$rel_target_dir + else + abs_target_dir=$rel_target_dir + fi + + if [ \! -d $abs_target_dir ] ; then + echo $progname\: creating directory $rel_target_dir + mkdir $abs_target_dir + fi + + echo $progname\: populating \`$rel_target_dir\' + + if [ `echo $* | wc -w` != 0 ] ; then + for rel_source_dir in $*; do + if [ `expr $rel_source_dir : '\(.\)'` != '/' ] ; then + abs_source_dir=$original_dir/$rel_source_dir + else + abs_source_dir=$rel_source_dir + fi + echo $progname\: input dir\: \`$rel_source_dir\' + done + fi + + tmp_file=/tmp/$progname.$$ + rm -f $tmp_file + echo '#ifndef __IN_C_REGION__' > $tmp_file + echo '#define __IN_C_REGION__' >> $tmp_file + echo 'extern "C" {' >> $tmp_file + echo '#include_next <=>' >> $tmp_file + echo '}' >> $tmp_file + echo '#undef __IN_C_REGION__' >> $tmp_file + echo '#else' >> $tmp_file + echo '#include_next <=>' >> $tmp_file + echo '#endif' >> $tmp_file + + if [ `echo $* | wc -w` != 0 ] ; then + for rel_source_dir in $*; do + if [ `expr $rel_source_dir : '\(.\)'` != '/' ] ; then + abs_source_dir=$original_dir/$rel_source_dir + else + abs_source_dir=$rel_source_dir + fi + if [ \! -d $abs_source_dir ] ; then + echo $progname\: warning\: no such directory\: \`$rel_source_dir\' + continue + fi + cd $abs_source_dir + rel_source_subdirs=`find . -type d -print | sed 's%^\./%%' | sed 's/\.//'` + if [ `echo $rel_source_subdirs | wc -w` != 0 ] ; then + for rel_source_subdir in $rel_source_subdirs; do + abs_target_subdir=$abs_target_dir/$rel_source_subdir + if [ \! -d $abs_target_subdir ] ; then + mkdir $abs_target_subdir + fi + done + fi + rel_source_files=`find . -type f -name \*.h -print | sed 's%^\./%%'` + if [ `echo $rel_source_files | wc -w` != 0 ] ; then + for rel_source_file in $rel_source_files; do + abs_source_file=$abs_source_dir/$rel_source_file + abs_target_file=$abs_target_dir/$rel_source_file + if [ \! -f $abs_target_file ] ; then + sed 's%=%'"$rel_source_file"'%' $tmp_file > $abs_target_file + fi + done + fi + done + fi + rm -f $tmp_file + exit 0 diff -rc2N gcc-2.2.2/print-rtl.c gcc-2.3.1/print-rtl.c *** gcc-2.2.2/print-rtl.c Thu Apr 2 03:44:47 1992 --- gcc-2.3.1/print-rtl.c Mon Oct 12 18:24:49 1992 *************** *** 1,4 **** /* Print RTL for GNU C Compiler. ! Copyright (C) 1987, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Print RTL for GNU C Compiler. ! Copyright (C) 1987-1991 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 25,28 **** --- 25,44 ---- + /* How to print out a register name. + We don't use PRINT_REG because some definitions of PRINT_REG + don't work here. */ + #ifndef DEBUG_PRINT_REG + #define DEBUG_PRINT_REG(RTX, CODE, FILE) \ + fprintf ((FILE), "%d %s", REGNO (RTX), reg_names[REGNO (RTX)]) + #endif + + /* Array containing all of the register names */ + + #ifdef DEBUG_REGISTER_NAMES + static char *reg_names[] = DEBUG_REGISTER_NAMES; + #else + static char *reg_names[] = REGISTER_NAMES; + #endif + static FILE *outfile; *************** *** 141,150 **** break; case 'i': ! fprintf (outfile, " %d", XINT (in_rtx, i)); if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) && insn_name_ptr && XINT (in_rtx, i) >= 0) ! fprintf (outfile, " {%s}", insn_name_ptr[XINT (in_rtx, i)]); sawclose = 0; break; --- 157,186 ---- break; + case 'w': + fprintf (outfile, + #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + " %d", + #else + " %ld", + #endif + XWINT (in_rtx, i)); + break; + case 'i': ! { ! register int value = XINT (in_rtx, i); ! ! if (GET_CODE (in_rtx) == REG && value < FIRST_PSEUDO_REGISTER) ! { ! fputc (' ', outfile); ! DEBUG_PRINT_REG (in_rtx, 0, outfile); ! } ! else ! fprintf (outfile, " %d", value); ! } if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) && insn_name_ptr && XINT (in_rtx, i) >= 0) ! fprintf (outfile, " {%s}", insn_name_ptr[XINT (in_rtx, i)]); sawclose = 0; break; diff -rc2N gcc-2.2.2/print-tree.c gcc-2.3.1/print-tree.c *** gcc-2.2.2/print-tree.c Mon Apr 27 12:54:16 1992 --- gcc-2.3.1/print-tree.c Fri Oct 23 20:09:26 1992 *************** *** 80,85 **** if (indent > 0) fprintf (file, " "); ! fprintf (file, "%s <%s %x", prefix, ! tree_code_name[(int) TREE_CODE (node)], (int) node); if (class == 'd') --- 80,85 ---- if (indent > 0) fprintf (file, " "); ! fprintf (file, "%s <%s ", prefix, tree_code_name[(int) TREE_CODE (node)]); ! fprintf (file, HOST_PTR_PRINTF, node); if (class == 'd') *************** *** 111,117 **** fprintf (file, " -%1u", -TREE_INT_CST_LOW (node)); else ! fprintf (file, " 0x%x%08x", ! TREE_INT_CST_HIGH (node), ! TREE_INT_CST_LOW (node)); } if (TREE_CODE (node) == REAL_CST) --- 111,129 ---- fprintf (file, " -%1u", -TREE_INT_CST_LOW (node)); else ! fprintf (file, ! #if HOST_BITS_PER_WIDE_INT == 64 ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%016lx", ! #else ! " 0x%x%016x", ! #endif ! #else ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%08lx", ! #else ! " 0x%x%08x", ! #endif ! #endif ! TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node)); } if (TREE_CODE (node) == REAL_CST) *************** *** 194,198 **** } ! hash = ((int) node & ~(1 << (HOST_BITS_PER_INT - 1))) % HASH_SIZE; /* If node is in the table, just mention its address. */ --- 206,210 ---- } ! hash = ((unsigned HOST_WIDE_INT) node) % HASH_SIZE; /* If node is in the table, just mention its address. */ *************** *** 214,219 **** /* Print the slot this node is in, and its code, and address. */ ! fprintf (file, "%s <%s %x", prefix, ! tree_code_name[(int) TREE_CODE (node)], (int) node); /* Print the name, if any. */ --- 226,231 ---- /* Print the slot this node is in, and its code, and address. */ ! fprintf (file, "%s <%s ", prefix, tree_code_name[(int) TREE_CODE (node)]); ! fprintf (file, HOST_PTR_PRINTF, node); /* Print the name, if any. */ *************** *** 276,279 **** --- 288,293 ---- if (TREE_USED (node)) fputs (" used", file); + if (TREE_RAISES (node)) + fputs (" raises", file); if (TREE_PERMANENT (node)) fputs (" permanent", file); *************** *** 304,314 **** mode = DECL_MODE (node); ! if (TREE_EXTERNAL (node)) fputs (" external", file); ! if (TREE_NONLOCAL (node)) fputs (" nonlocal", file); ! if (TREE_REGDECL (node)) fputs (" regdecl", file); ! if (TREE_INLINE (node)) fputs (" inline", file); if (DECL_BIT_FIELD (node)) --- 318,328 ---- mode = DECL_MODE (node); ! if (DECL_EXTERNAL (node)) fputs (" external", file); ! if (DECL_NONLOCAL (node)) fputs (" nonlocal", file); ! if (DECL_REGISTER (node)) fputs (" regdecl", file); ! if (DECL_INLINE (node)) fputs (" inline", file); if (DECL_BIT_FIELD (node)) *************** *** 316,323 **** if (DECL_VIRTUAL_P (node)) fputs (" virtual", file); - if (DECL_FROM_INLINE (node)) - fputs (" from_inline", file); if (DECL_IGNORED_P (node)) fputs (" ignored", file); if (DECL_LANG_FLAG_0 (node)) fputs (" decl_0", file); --- 330,337 ---- if (DECL_VIRTUAL_P (node)) fputs (" virtual", file); if (DECL_IGNORED_P (node)) fputs (" ignored", file); + if (DECL_IN_SYSTEM_HEADER (node)) + fputs (" in_system_header", file); if (DECL_LANG_FLAG_0 (node)) fputs (" decl_0", file); *************** *** 346,350 **** if (TREE_CODE (node) != FUNCTION_DECL) fprintf (file, " align %d", DECL_ALIGN (node)); ! else if (TREE_INLINE (node)) fprintf (file, " frame_size %d", DECL_FRAME_SIZE (node)); else if (DECL_BUILT_IN (node)) --- 360,364 ---- if (TREE_CODE (node) != FUNCTION_DECL) fprintf (file, " align %d", DECL_ALIGN (node)); ! else if (DECL_INLINE (node)) fprintf (file, " frame_size %d", DECL_FRAME_SIZE (node)); else if (DECL_BUILT_IN (node)) *************** *** 353,356 **** --- 367,372 ---- print_node (file, "bitpos", DECL_FIELD_BITPOS (node), indent + 4); print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4); + print_node_brief (file, "abstract_origin", + DECL_ABSTRACT_ORIGIN (node), indent + 4); print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4); *************** *** 375,379 **** } else if (TREE_CODE (node) == FUNCTION_DECL) ! fprintf (file, "saved-insns 0x%x", DECL_SAVED_INSNS (node)); } --- 391,398 ---- } else if (TREE_CODE (node) == FUNCTION_DECL) ! { ! fprintf (file, "saved-insns "); ! fprintf (file, HOST_PTR_PRINTF, DECL_SAVED_INSNS (node)); ! } } *************** *** 414,418 **** if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE) print_node (file, "domain", TYPE_DOMAIN (node), indent + 4); ! else if (TREE_CODE (node) == INTEGER_TYPE) { fprintf (file, " precision %d", TYPE_PRECISION (node)); --- 433,439 ---- if (TREE_CODE (node) == ARRAY_TYPE || TREE_CODE (node) == SET_TYPE) print_node (file, "domain", TYPE_DOMAIN (node), indent + 4); ! else if (TREE_CODE (node) == INTEGER_TYPE ! || TREE_CODE (node) == BOOLEAN_TYPE ! || TREE_CODE (node) == CHAR_TYPE) { fprintf (file, " precision %d", TYPE_PRECISION (node)); *************** *** 449,452 **** --- 470,483 ---- break; + case 'b': + print_node (file, "vars", BLOCK_VARS (node), indent + 4); + print_node (file, "tags", BLOCK_TYPE_TAGS (node), indent + 4); + print_node (file, "supercontext", BLOCK_SUPERCONTEXT (node), indent + 4); + print_node (file, "subblocks", BLOCK_SUBBLOCKS (node), indent + 4); + print_node (file, "chain", BLOCK_CHAIN (node), indent + 4); + print_node (file, "abstract_origin", + BLOCK_ABSTRACT_ORIGIN (node), indent + 4); + return; + case 'e': case '<': *************** *** 457,468 **** switch (TREE_CODE (node)) { - case BLOCK: - print_node (file, "vars", BLOCK_VARS (node), indent + 4); - print_node (file, "tags", BLOCK_TYPE_TAGS (node), indent + 4); - print_node (file, "supercontext", BLOCK_SUPERCONTEXT (node), indent + 4); - print_node (file, "subblocks", BLOCK_SUBBLOCKS (node), indent + 4); - print_node (file, "chain", BLOCK_CHAIN (node), indent + 4); - return; - case BIND_EXPR: print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4); --- 488,491 ---- *************** *** 526,532 **** fprintf (file, " -%1u", -TREE_INT_CST_LOW (node)); else ! fprintf (file, " 0x%x%08x", ! TREE_INT_CST_HIGH (node), ! TREE_INT_CST_LOW (node)); break; --- 549,567 ---- fprintf (file, " -%1u", -TREE_INT_CST_LOW (node)); else ! fprintf (file, ! #if HOST_BITS_PER_WIDE_INT == 64 ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%016lx", ! #else ! " 0x%x%016x", ! #endif ! #else ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! " 0x%lx%08lx", ! #else ! " 0x%x%08x", ! #endif ! #endif ! TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node)); break; *************** *** 567,576 **** len = TREE_VEC_LENGTH (node); for (i = 0; i < len; i++) ! { ! char temp[10]; ! sprintf (temp, "elt %d", i); ! indent_to (file, indent + 4); ! print_node_brief (file, temp, TREE_VEC_ELT (node, i), 0); ! } break; --- 602,612 ---- len = TREE_VEC_LENGTH (node); for (i = 0; i < len; i++) ! if (TREE_VEC_ELT (node, i)) ! { ! char temp[10]; ! sprintf (temp, "elt %d", i); ! indent_to (file, indent + 4); ! print_node_brief (file, temp, TREE_VEC_ELT (node, i), 0); ! } break; *************** *** 582,584 **** --- 618,622 ---- break; } + + fprintf (file, ">"); } diff -rc2N gcc-2.2.2/protoize.c gcc-2.3.1/protoize.c *** gcc-2.2.2/protoize.c Sun Jun 14 17:11:55 1992 --- gcc-2.3.1/protoize.c Sat Oct 17 16:50:54 1992 *************** *** 51,55 **** #ifdef POSIX /* We should be able to define _POSIX_SOURCE unconditionally, but some systems respond in buggy ways to it, ! including Sunos 4.1.1. Which we don't classify as POSIX. */ /* In case this is a POSIX system with an ANSI C compiler, ask for definition of all POSIX facilities. */ --- 51,55 ---- #ifdef POSIX /* We should be able to define _POSIX_SOURCE unconditionally, but some systems respond in buggy ways to it, ! including SunOS 4.1.1. Which we don't classify as POSIX. */ /* In case this is a POSIX system with an ANSI C compiler, ask for definition of all POSIX facilities. */ *************** *** 76,79 **** --- 76,80 ---- #define getopt getopt_loser #include "getopt.h" + #undef getopt extern int errno; *************** *** 173,177 **** extern int strncmp (); extern char * strncpy (); ! extern char * strrchr (); /* Fork is not declared because the declaration caused a conflict --- 174,178 ---- extern int strncmp (); extern char * strncpy (); ! extern char * rindex (); /* Fork is not declared because the declaration caused a conflict *************** *** 195,207 **** #endif - /* POSIX systems will not have definitions for WIFEXITED or WEXITSTATUS. - Define them correctly and so that they work for all environments. */ - - #undef WIFEXITED - #define WIFEXITED(status_word) ((*((int *)&status_word) & 0xff) == 0x00) - - #undef WEXITSTATUS - #define WEXITSTATUS(status_word) ((*((int *)&status_word) & 0xff00) >> 8) - /* Define a default place to find the SYSCALLS.X file. */ --- 196,199 ---- *************** *** 607,612 **** if (rv == NULL) { ! fprintf (stderr, "\n%s: fatal error: can't allocate %u more bytes of memory\n", ! pname, byte_count); exit (1); return 0; /* avoid warnings */ --- 599,603 ---- if (rv == NULL) { ! fprintf (stderr, "\n%s: virtual memory exceeded\n", pname); exit (1); return 0; /* avoid warnings */ *************** *** 628,633 **** if (rv == NULL) { ! fprintf (stderr, "\n%s: fatal error: can't allocate %u more bytes of memory\n", ! pname, byte_count); exit (1); return 0; /* avoid warnings */ --- 619,623 ---- if (rv == NULL) { ! fprintf (stderr, "\n%s: virtual memory exceeded\n", pname); exit (1); return 0; /* avoid warnings */ *************** *** 814,818 **** strcpy (dir_name, path); ! dir_last_slash = strrchr (dir_name, '/'); if (dir_last_slash) *dir_last_slash = '\0'; --- 804,808 ---- strcpy (dir_name, path); ! dir_last_slash = rindex (dir_name, '/'); if (dir_last_slash) *dir_last_slash = '\0'; *************** *** 848,852 **** strcpy (dir_name, path); ! dir_last_slash = strrchr (dir_name, '/'); if (dir_last_slash) *dir_last_slash = '\0'; --- 838,842 ---- strcpy (dir_name, path); ! dir_last_slash = rindex (dir_name, '/'); if (dir_last_slash) *dir_last_slash = '\0'; *************** *** 1416,1420 **** if (my_stat (filename, &stat_buf) == -1) { ! fprintf (stderr, "%s: error: can't get status of `%s': %s\n", pname, shortpath (NULL, filename), sys_errlist[errno]); stat_buf.st_mtime = (time_t) -1; --- 1406,1410 ---- if (my_stat (filename, &stat_buf) == -1) { ! fprintf (stderr, "%s: %s: can't get status: %s\n", pname, shortpath (NULL, filename), sys_errlist[errno]); stat_buf.st_mtime = (time_t) -1; *************** *** 1453,1457 **** /* Given a pointer to the closing right parenthesis for a particular formals ! list (in a aux_info file) find the corresponding left parenthesis and return a pointer to it. */ --- 1443,1447 ---- /* Given a pointer to the closing right parenthesis for a particular formals ! list (in an aux_info file) find the corresponding left parenthesis and return a pointer to it. */ *************** *** 1753,1761 **** if (strcmp (def_dec_p->ansi_decl, other->ansi_decl)) { ! fprintf (stderr, "%s: error: declaration of function `%s' at %s(%d) takes different forms\n", ! pname, ! def_dec_p->hash_entry->symbol, def_dec_p->file->hash_entry->symbol, ! def_dec_p->line); exit (1); } --- 1743,1750 ---- if (strcmp (def_dec_p->ansi_decl, other->ansi_decl)) { ! fprintf (stderr, "%s:%d: declaration of function `%s' takes different forms\n", def_dec_p->file->hash_entry->symbol, ! def_dec_p->line, ! def_dec_p->hash_entry->symbol); exit (1); } *************** *** 2011,2015 **** if (child_pid == -1) { ! fprintf (stderr, "%s: error: could not fork process: %s\n", pname, sys_errlist[errno]); return 0; --- 2000,2004 ---- if (child_pid == -1) { ! fprintf (stderr, "%s: could not fork process: %s\n", pname, sys_errlist[errno]); return 0; *************** *** 2093,2096 **** --- 2082,2086 ---- time_t aux_info_mtime; size_t aux_info_size; + int must_create; /* Construct the aux_info filename from the base source filename. */ *************** *** 2102,2139 **** exist, try to create it (once only). */ start_over: ; ! { ! int retries = 0; ! retry: ! if (my_access (aux_info_filename, R_OK) == -1) ! { ! if (errno == ENOENT && retries == 0) ! { ! if (is_syscalls) ! { ! fprintf (stderr, "%s: warning: missing SYSCALLS file `%s'\n", ! pname, aux_info_filename); ! return; ! } ! if (!gen_aux_info_file (base_source_filename)) ! { ! errors++; ! return; ! } ! retries++; ! goto retry; ! } ! else ! { ! fprintf (stderr, "%s: error: can't read aux info file `%s': %s\n", ! pname, shortpath (NULL, aux_info_filename), ! sys_errlist[errno]); ! errors++; ! return; ! } ! } ! } { --- 2092,2152 ---- exist, try to create it (once only). */ + /* If file doesn't exist, set must_create. + Likewise if it exists and we can read it but it is obsolete. + Otherwise, report an error. */ + must_create = 0; + + /* Come here with must_create set to 1 if file is out of date. */ start_over: ; ! if (my_access (aux_info_filename, R_OK) == -1) ! { ! if (errno == ENOENT) ! { ! if (is_syscalls) ! { ! fprintf (stderr, "%s: warning: missing SYSCALLS file `%s'\n", ! pname, aux_info_filename); ! return; ! } ! must_create = 1; ! } ! else ! { ! fprintf (stderr, "%s: can't read aux info file `%s': %s\n", ! pname, shortpath (NULL, aux_info_filename), ! sys_errlist[errno]); ! errors++; ! return; ! } ! } ! #if 0 /* There is code farther down to take care of this. */ ! else ! { ! struct stat s1, s2; ! stat (aux_info_file_name, &s1); ! stat (base_source_file_name, &s2); ! if (s2.st_mtime > s1.st_mtime) ! must_create = 1; ! } ! #endif /* 0 */ ! /* If we need a .X file, create it, and verify we can read it. */ ! if (must_create) ! { ! if (!gen_aux_info_file (base_source_filename)) ! { ! errors++; ! return; ! } ! if (my_access (aux_info_filename, R_OK) == -1) ! { ! fprintf (stderr, "%s: can't read aux info file `%s': %s\n", ! pname, shortpath (NULL, aux_info_filename), ! sys_errlist[errno]); ! errors++; ! return; ! } ! } { *************** *** 2144,2148 **** if (my_stat (aux_info_filename, &stat_buf) == -1) { ! fprintf (stderr, "%s: error: can't get status of aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); --- 2157,2161 ---- if (my_stat (aux_info_filename, &stat_buf) == -1) { ! fprintf (stderr, "%s: can't get status of aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); *************** *** 2162,2165 **** --- 2175,2199 ---- aux_info_mtime = stat_buf.st_mtime; + + if (!is_syscalls) + { + /* Compare mod time with the .c file; update .X file if obsolete. + The code later on can fail to check the .c file + if it did not directly define any functions. */ + + if (my_stat (base_source_filename, &stat_buf) == -1) + { + fprintf (stderr, "%s: can't get status of aux info file `%s': %s\n", + pname, shortpath (NULL, base_source_filename), + sys_errlist[errno]); + errors++; + return; + } + if (stat_buf.st_mtime > aux_info_mtime) + { + must_create = 1; + goto start_over; + } + } } *************** *** 2171,2175 **** if ((aux_info_file = my_open (aux_info_filename, O_RDONLY, 0444 )) == -1) { ! fprintf (stderr, "%s: error: can't open aux info file `%s' for reading: %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); --- 2205,2209 ---- if ((aux_info_file = my_open (aux_info_filename, O_RDONLY, 0444 )) == -1) { ! fprintf (stderr, "%s: can't open aux info file `%s' for reading: %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); *************** *** 2187,2191 **** if (read (aux_info_file, aux_info_base, aux_info_size) != aux_info_size) { ! fprintf (stderr, "%s: error: while reading aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); --- 2221,2225 ---- if (read (aux_info_file, aux_info_base, aux_info_size) != aux_info_size) { ! fprintf (stderr, "%s: error reading aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); *************** *** 2199,2203 **** if (close (aux_info_file)) { ! fprintf (stderr, "%s: error: while closing aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); --- 2233,2237 ---- if (close (aux_info_file)) { ! fprintf (stderr, "%s: error closing aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); *************** *** 2211,2217 **** fails for some reason, don't even worry about it. */ ! if (!keep_it) if (my_unlink (aux_info_filename) == -1) ! fprintf (stderr, "%s: error: can't delete aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); --- 2245,2251 ---- fails for some reason, don't even worry about it. */ ! if (must_create && !keep_it) if (my_unlink (aux_info_filename) == -1) ! fprintf (stderr, "%s: can't delete aux info file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); *************** *** 2248,2252 **** aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename)); strcpy (aux_info_relocated_name, base_source_filename); ! dir_end = strrchr (aux_info_relocated_name, '/'); if (dir_end) dir_end++; --- 2282,2286 ---- aux_info_relocated_name = xmalloc (base_len + (p-invocation_filename)); strcpy (aux_info_relocated_name, base_source_filename); ! dir_end = rindex (aux_info_relocated_name, '/'); if (dir_end) dir_end++; *************** *** 2279,2283 **** if (keep_it && my_unlink (aux_info_filename) == -1) { ! fprintf (stderr, "%s: error: can't delete file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); --- 2313,2317 ---- if (keep_it && my_unlink (aux_info_filename) == -1) { ! fprintf (stderr, "%s: can't delete file `%s': %s\n", pname, shortpath (NULL, aux_info_filename), sys_errlist[errno]); *************** *** 2487,2491 **** { conflict_noted = 1; ! fprintf (stderr, "%s: error: conflicting extern definitions of '%s'\n", pname, head->hash_entry->symbol); if (!quiet_flag) --- 2521,2525 ---- { conflict_noted = 1; ! fprintf (stderr, "%s: conflicting extern definitions of '%s'\n", pname, head->hash_entry->symbol); if (!quiet_flag) *************** *** 2609,2613 **** else if (num_static_defs > 1) { ! fprintf (stderr, "%s: error: multiple static defs of `%s' in file `%s'\n", pname, head->hash_entry->symbol, shortpath (NULL, user->file->hash_entry->symbol)); --- 2643,2647 ---- else if (num_static_defs > 1) { ! fprintf (stderr, "%s: multiple static defs of `%s' in file `%s'\n", pname, head->hash_entry->symbol, shortpath (NULL, user->file->hash_entry->symbol)); *************** *** 4059,4063 **** if (my_stat ((char *)convert_filename, &stat_buf) == -1) { ! fprintf (stderr, "%s: error: can't get status for file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); return; --- 4093,4097 ---- if (my_stat ((char *)convert_filename, &stat_buf) == -1) { ! fprintf (stderr, "%s: can't get status for file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); return; *************** *** 4093,4097 **** if ((input_file = my_open (convert_filename, O_RDONLY, 0444)) == -1) { ! fprintf (stderr, "%s: error: can't open file `%s' for reading: %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); --- 4127,4131 ---- if ((input_file = my_open (convert_filename, O_RDONLY, 0444)) == -1) { ! fprintf (stderr, "%s: can't open file `%s' for reading: %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); *************** *** 4106,4110 **** { close (input_file); ! fprintf (stderr, "\n%s: error: while reading input file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); --- 4140,4144 ---- { close (input_file); ! fprintf (stderr, "\n%s: error reading input file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); *************** *** 4139,4143 **** if ((clean_file = creat (clean_filename, 0666)) == -1) { ! fprintf (stderr, "%s: error: can't create/open clean file `%s': %s\n", pname, shortpath (NULL, clean_filename), sys_errlist[errno]); --- 4173,4177 ---- if ((clean_file = creat (clean_filename, 0666)) == -1) { ! fprintf (stderr, "%s: can't create/open clean file `%s': %s\n", pname, shortpath (NULL, clean_filename), sys_errlist[errno]); *************** *** 4148,4152 **** if (write (clean_file, new_clean_text_base, clean_size) != clean_size) ! fprintf (stderr, "%s: error: while writing file `%s': %s\n", pname, shortpath (NULL, clean_filename), sys_errlist[errno]); --- 4182,4186 ---- if (write (clean_file, new_clean_text_base, clean_size) != clean_size) ! fprintf (stderr, "%s: error writing file `%s': %s\n", pname, shortpath (NULL, clean_filename), sys_errlist[errno]); *************** *** 4248,4252 **** else { ! fprintf (stderr, "%s: error: can't link file `%s' to `%s': %s\n", pname, shortpath (NULL, convert_filename), --- 4282,4286 ---- else { ! fprintf (stderr, "%s: can't link file `%s' to `%s': %s\n", pname, shortpath (NULL, convert_filename), *************** *** 4260,4264 **** if (my_unlink (convert_filename) == -1) { ! fprintf (stderr, "%s: error: can't delete file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); return; --- 4294,4298 ---- if (my_unlink (convert_filename) == -1) { ! fprintf (stderr, "%s: can't delete file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); return; *************** *** 4272,4276 **** if ((output_file = creat (convert_filename, 0666)) == -1) { ! fprintf (stderr, "%s: error: can't create/open output file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); --- 4306,4310 ---- if ((output_file = creat (convert_filename, 0666)) == -1) { ! fprintf (stderr, "%s: can't create/open output file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); *************** *** 4284,4288 **** if (write (output_file, repl_text_base, out_size) != out_size) ! fprintf (stderr, "%s: error: while writing file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); --- 4318,4322 ---- if (write (output_file, repl_text_base, out_size) != out_size) ! fprintf (stderr, "%s: error writing file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); *************** *** 4302,4306 **** /* The cast avoids an erroneous warning on AIX. */ if (my_chmod ((char *)convert_filename, stat_buf.st_mode) == -1) ! fprintf (stderr, "%s: error: can't change mode of file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); --- 4336,4340 ---- /* The cast avoids an erroneous warning on AIX. */ if (my_chmod ((char *)convert_filename, stat_buf.st_mode) == -1) ! fprintf (stderr, "%s: can't change mode of file `%s': %s\n", pname, shortpath (NULL, convert_filename), sys_errlist[errno]); *************** *** 4439,4443 **** const char *params = ""; ! pname = strrchr (argv[0], '/'); pname = pname ? pname+1 : argv[0]; --- 4473,4477 ---- const char *params = ""; ! pname = rindex (argv[0], '/'); pname = pname ? pname+1 : argv[0]; *************** *** 4455,4461 **** while ((c = getopt_long (argc, argv, #ifdef UNPROTOIZE ! "c:d:i:knNp:qVx:", #else ! "B:c:Cd:gklnNp:qVx:", #endif longopts, &longind)) != EOF) --- 4489,4495 ---- while ((c = getopt_long (argc, argv, #ifdef UNPROTOIZE ! "c:d:i:knNp:qvVx:", #else ! "B:c:Cd:gklnNp:qvVx:", #endif longopts, &longind)) != EOF) *************** *** 4476,4479 **** --- 4510,4514 ---- break; + case 'v': case 'V': version_flag = 1; diff -rc2N gcc-2.2.2/real.h gcc-2.3.1/real.h *** gcc-2.2.2/real.h Wed May 27 15:36:39 1992 --- gcc-2.3.1/real.h Sat Aug 1 22:46:34 1992 *************** *** 54,58 **** #ifndef REAL_VALUE_TYPE #define REAL_VALUE_TYPE \ ! struct real_value { long i[sizeof (double) / sizeof (long)]; } #endif /* no REAL_VALUE_TYPE */ #endif /* formats differ */ --- 54,58 ---- #ifndef REAL_VALUE_TYPE #define REAL_VALUE_TYPE \ ! struct real_value{ HOST_WIDE_INT i[sizeof (double)/sizeof (HOST_WIDE_INT)]; } #endif /* no REAL_VALUE_TYPE */ #endif /* formats differ */ *************** *** 155,158 **** --- 155,161 ---- size and where `float' is SFmode. */ + /* Don't use REAL_VALUE_TRUNCATE directly--always call real_value_truncate. */ + extern REAL_VALUE_TYPE real_value_truncate (); + #ifndef REAL_VALUE_TRUNCATE #define REAL_VALUE_TRUNCATE(mode, x) \ *************** *** 194,198 **** { REAL_VALUE_TYPE d; ! int i[sizeof (REAL_VALUE_TYPE) / sizeof (int)]; }; --- 197,201 ---- { REAL_VALUE_TYPE d; ! HOST_WIDE_INT i[sizeof (REAL_VALUE_TYPE) / sizeof (HOST_WIDE_INT)]; }; *************** *** 204,209 **** and CONST_DOUBLE_LOW is the one that should come first *in memory*. So use &CONST_DOUBLE_LOW(r) as the address of an array of ints. */ ! #define CONST_DOUBLE_LOW(r) XINT (r, 2) ! #define CONST_DOUBLE_HIGH(r) XINT (r, 3) /* Link for chain of all CONST_DOUBLEs in use in current function. */ --- 207,212 ---- and CONST_DOUBLE_LOW is the one that should come first *in memory*. So use &CONST_DOUBLE_LOW(r) as the address of an array of ints. */ ! #define CONST_DOUBLE_LOW(r) XWINT (r, 2) ! #define CONST_DOUBLE_HIGH(r) XWINT (r, 3) /* Link for chain of all CONST_DOUBLEs in use in current function. */ diff -rc2N gcc-2.2.2/recog.c gcc-2.3.1/recog.c *** gcc-2.2.2/recog.c Wed May 27 06:21:31 1992 --- gcc-2.3.1/recog.c Sun Oct 11 16:26:41 1992 *************** *** 1,4 **** /* Subroutines used by or related to instruction recognition. ! Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Subroutines used by or related to instruction recognition. ! Copyright (C) 1987, 1988, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 97,101 **** { if (INSN_CODE (insn) < 0) ! INSN_CODE (insn) = recog (PATTERN (insn), insn, 0); return INSN_CODE (insn); } --- 97,101 ---- { if (INSN_CODE (insn) < 0) ! INSN_CODE (insn) = recog (PATTERN (insn), insn, NULL_PTR); return INSN_CODE (insn); } *************** *** 118,122 **** operands = (rtx *) alloca (noperands * sizeof (rtx)); ! decode_asm_operands (x, operands, 0, 0, 0); for (i = 0; i < noperands; i++) --- 118,122 ---- operands = (rtx *) alloca (noperands * sizeof (rtx)); ! decode_asm_operands (x, operands, NULL_PTR, NULL_PTR, NULL_PTR); for (i = 0; i < noperands; i++) *************** *** 488,493 **** MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (to); ! validate_change (object, &XEXP (x, 2), ! gen_rtx (CONST_INT, VOIDmode, pos), 1); validate_change (object, &XEXP (x, 0), newmem, 1); } --- 488,492 ---- MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (to); ! validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1); validate_change (object, &XEXP (x, 0), newmem, 1); } *************** *** 763,767 **** if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT) return 0; --- 762,767 ---- if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT ! && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; *************** *** 903,907 **** if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT) return 0; --- 903,908 ---- if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT ! && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; *************** *** 936,940 **** if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT) return 0; --- 937,942 ---- if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT ! && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; *************** *** 966,970 **** if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT) return 0; --- 968,973 ---- if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode ! && GET_MODE_CLASS (mode) != MODE_INT ! && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; *************** *** 1330,1336 **** } - extern rtx plus_constant_for_output (); - extern rtx copy_rtx (); - /* Given an rtx *P, if it is a sum containing an integer constant term, return the location (type rtx *) of the pointer to that constant term. --- 1333,1336 ---- *************** *** 1780,1784 **** we can examine the bits of it reliably. */ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_INT != BITS_PER_WORD) && GET_MODE (op) != VOIDmode && ! flag_pretend_float) break; --- 1780,1784 ---- we can examine the bits of it reliably. */ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) && GET_MODE (op) != VOIDmode && ! flag_pretend_float) break; diff -rc2N gcc-2.2.2/reg-stack.c gcc-2.3.1/reg-stack.c *** gcc-2.2.2/reg-stack.c Sun May 24 14:57:01 1992 --- gcc-2.3.1/reg-stack.c Sat Aug 29 00:41:59 1992 *************** *** 246,250 **** int stack_regs_mentioned_p (pat) ! register rtx pat; { register char *fmt; --- 246,250 ---- int stack_regs_mentioned_p (pat) ! rtx pat; { register char *fmt; *************** *** 447,480 **** return pat; } - - /* If REG is a stack register that is marked dead in REGSTACK, then - record that it is now live. If REG is not DEST, add a death note to - INSN if there isn't one already. If DEST is not a reg, it is safe to - assume that it does not mention a reg anywhere within. */ - - static void - record_note_if_dead (insn, regstack, reg, dest) - rtx insn; - stack regstack; - rtx reg, dest; - { - reg = * get_true_reg (& reg); - - if (STACK_REG_P (reg)) - { - if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (reg))) - { - if ((! REG_P (dest) || REGNO (dest) != REGNO (reg)) - && ! find_regno_note (insn, REG_DEAD, REGNO (reg))) - REG_NOTES (insn) = gen_rtx (EXPR_LIST, - REG_DEAD, reg, REG_NOTES (insn)); - - SET_HARD_REG_BIT (regstack->reg_set, REGNO (reg)); - } - } - else - if (stack_regs_mentioned_p (reg)) - abort (); - } /* Scan the OPERANDS and OPERAND_CONSTRAINTS of an asm_operands. --- 447,450 ---- *************** *** 656,660 **** we can examine the bits of it reliably. */ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_INT != BITS_PER_WORD) && GET_CODE (op) != VOIDmode && ! flag_pretend_float) break; --- 626,630 ---- we can examine the bits of it reliably. */ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) && GET_CODE (op) != VOIDmode && ! flag_pretend_float) break; *************** *** 797,801 **** rtx *clobber_reg; ! /* Find out what the constraints required. If no constraint alternative matches, that is a compiler bug: we should have caught such an insn during reload. */ --- 767,771 ---- rtx *clobber_reg; ! /* Find out what the constraints require. If no constraint alternative matches, that is a compiler bug: we should have caught such an insn during reload. */ *************** *** 982,1082 **** } ! /* Scan PAT, which is part of INSN, and record the life & death of ! stack registers in REGSTACK. If a register was dead, but is an input ! operand in this insn, then mark the register live and record a death ! note. - If a register is dead after this insn, but is an output operand in - this insn, record a REG_UNUSED note. - This function does not know about SET_DESTs that are both input and output (such as ZERO_EXTRACT) - this cannot happen on a 387. */ ! static void ! record_reg_life_pat (insn, regstack, pat) ! rtx insn; ! stack regstack; rtx pat; { ! rtx src, dest; ! ! /* We should have already handled any asm. */ ! if (GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ASM_OPERANDS) ! abort (); ! ! if (GET_CODE (pat) != SET) ! return; ! ! dest = * get_true_reg (& SET_DEST (pat)); ! ! /* The destination is dead before this insn. If the destination is ! not used after this insn, record this with REG_UNUSED. */ ! if (STACK_REG_P (dest)) { ! /* ??? This check is unnecessary. */ ! if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) ! abort (); ! ! if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (dest))) ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_UNUSED, dest, ! REG_NOTES (insn)); ! CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); } - else - if (dest != cc0_rtx && stack_regs_mentioned_p (dest)) - abort (); ! src = * get_true_reg (& SET_SRC (pat)); ! ! switch (GET_CODE (src)) { ! /* ??? get_true_reg will make some of these cases redundant. */ ! ! case PLUS: ! case MINUS: ! case MULT: ! case DIV: ! case COMPARE: ! record_note_if_dead (insn, regstack, XEXP (src, 0), dest); ! record_note_if_dead (insn, regstack, XEXP (src, 1), dest); ! break; ! ! case ABS: ! case NEG: ! case SQRT: ! case FLOAT_EXTEND: ! case FLOAT_TRUNCATE: ! case FLOAT: ! case UNSIGNED_FLOAT: ! record_note_if_dead (insn, regstack, XEXP (src, 0), dest); ! break; ! ! case UNSIGNED_FIX: ! case FIX: ! src = XEXP (src, 0); ! if (GET_CODE (src) == FIX) ! record_note_if_dead (insn, regstack, XEXP (src, 0), dest); ! else ! record_note_if_dead (insn, regstack, src, dest); ! break; ! ! case ASM_OPERANDS: ! case ASM_INPUT: ! abort (); /* we should have caught this already. */ ! break; ! case REG: ! record_note_if_dead (insn, regstack, src, dest); ! break; ! default: ! /* If a stack register appears in the src RTL, it is a bug, and ! code should be added above to handle it. */ ! if (stack_regs_mentioned_p (src)) ! abort (); } } --- 952,1003 ---- } ! /* Scan PAT, which is part of INSN, and record registers appearing in ! a SET_DEST in DEST, and other registers in SRC. This function does not know about SET_DESTs that are both input and output (such as ZERO_EXTRACT) - this cannot happen on a 387. */ ! void ! record_reg_life_pat (pat, src, dest) rtx pat; + HARD_REG_SET *src, *dest; { ! register char *fmt; ! register int i; ! if (STACK_REG_P (pat)) { ! if (src) ! SET_HARD_REG_BIT (*src, REGNO (pat)); ! if (dest) ! SET_HARD_REG_BIT (*dest, REGNO (pat)); ! return; } ! if (GET_CODE (pat) == SET) { ! record_reg_life_pat (XEXP (pat, 0), NULL_PTR, dest); ! record_reg_life_pat (XEXP (pat, 1), src, NULL_PTR); ! return; ! } ! /* We don't need to consider either of these cases. */ ! if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) ! return; ! fmt = GET_RTX_FORMAT (GET_CODE (pat)); ! for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) ! { ! if (fmt[i] == 'E') ! { ! register int j; ! for (j = XVECLEN (pat, i) - 1; j >= 0; j--) ! record_reg_life_pat (XVECEXP (pat, i, j), src, dest); ! } ! else if (fmt[i] == 'e') ! record_reg_life_pat (XEXP (pat, i), src, dest); } } *************** *** 1161,1165 **** char **constraints = (char **) alloca (n_operands * sizeof (char *)); ! decode_asm_operands (body, operands, 0, constraints, 0); get_asm_operand_lengths (body, n_operands, &n_inputs, &n_outputs); record_asm_reg_life (insn, regstack, operands, constraints, --- 1082,1086 ---- char **constraints = (char **) alloca (n_operands * sizeof (char *)); ! decode_asm_operands (body, operands, NULL_PTR, constraints, NULL_PTR); get_asm_operand_lengths (body, n_operands, &n_inputs, &n_outputs); record_asm_reg_life (insn, regstack, operands, constraints, *************** *** 1168,1180 **** } ! if (GET_CODE (PATTERN (insn)) == PARALLEL) { ! register int i; ! for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) ! record_reg_life_pat (insn, regstack, XVECEXP (PATTERN (insn), 0, i)); } - else if (GET_MODE (insn) == QImode) - record_reg_life_pat (insn, regstack, PATTERN (insn)); /* There might be a reg that is live after a function call. --- 1089,1119 ---- } ! /* An insn referencing a stack reg has a mode of QImode. */ ! if (GET_MODE (insn) == QImode) { ! HARD_REG_SET src, dest; ! int regno; ! ! CLEAR_HARD_REG_SET (src); ! CLEAR_HARD_REG_SET (dest); ! record_reg_life_pat (PATTERN (insn), &src, &dest); ! for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++) ! if (! TEST_HARD_REG_BIT (regstack->reg_set, regno)) ! { ! if (TEST_HARD_REG_BIT (src, regno) ! && ! TEST_HARD_REG_BIT (dest, regno)) ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD, ! FP_mode_reg[regno][(int) DFmode], ! REG_NOTES (insn)); ! else if (TEST_HARD_REG_BIT (dest, regno)) ! REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_UNUSED, ! FP_mode_reg[regno][(int) DFmode], ! REG_NOTES (insn)); ! } ! ! AND_COMPL_HARD_REG_SET (regstack->reg_set, dest); ! IOR_HARD_REG_SET (regstack->reg_set, src); } /* There might be a reg that is live after a function call. *************** *** 1187,1192 **** /* If a stack reg is mentioned in a CALL_INSN, it must be as the ! return value; conversely, if a float is returned, a stack reg ! must be mentioned. */ if (stack_regs_mentioned_p (PATTERN (insn))) --- 1126,1130 ---- /* If a stack reg is mentioned in a CALL_INSN, it must be as the ! return value. */ if (stack_regs_mentioned_p (PATTERN (insn))) *************** *** 1318,1329 **** struct stack_def regstack; ! if (current_function_returns_real) { /* Find all RETURN insns and mark them. */ for (block = blocks - 1; block >= 0; block--) if (GET_CODE (block_end[block]) == JUMP_INSN && GET_CODE (PATTERN (block_end[block])) == RETURN) ! SET_HARD_REG_BIT (block_out_reg_set[block], FIRST_STACK_REG); /* Mark of the end of last block if we "fall off" the end of the --- 1256,1270 ---- struct stack_def regstack; ! if (current_function_returns_real ! && STACK_REG_P (DECL_RTL (DECL_RESULT (current_function_decl)))) { /* Find all RETURN insns and mark them. */ + int value_regno = REGNO (DECL_RTL (DECL_RESULT (current_function_decl))); + for (block = blocks - 1; block >= 0; block--) if (GET_CODE (block_end[block]) == JUMP_INSN && GET_CODE (PATTERN (block_end[block])) == RETURN) ! SET_HARD_REG_BIT (block_out_reg_set[block], value_regno); /* Mark of the end of last block if we "fall off" the end of the *************** *** 1332,1336 **** if (GET_CODE (block_end[blocks-1]) != JUMP_INSN || GET_CODE (PATTERN (block_end[blocks-1])) == RETURN) ! SET_HARD_REG_BIT (block_out_reg_set[blocks-1], FIRST_STACK_REG); } --- 1273,1277 ---- if (GET_CODE (block_end[blocks-1]) != JUMP_INSN || GET_CODE (PATTERN (block_end[blocks-1])) == RETURN) ! SET_HARD_REG_BIT (block_out_reg_set[blocks-1], value_regno); } *************** *** 2036,2039 **** --- 1977,2012 ---- break; + case UNSPEC: + switch (XINT (SET_SRC (pat), 1)) + { + case 1: /* sin */ + case 2: /* cos */ + /* These insns only operate on the top of the stack. */ + + src1 = get_true_reg (&XVECEXP (SET_SRC (pat), 0, 0)); + + emit_swap_insn (insn, regstack, *src1, emit_insn_before); + + src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); + + if (STACK_REG_P (*dest)) + replace_reg (dest, FIRST_STACK_REG); + + if (src1_note) + { + replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); + regstack->top--; + CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1)); + } + + replace_reg (src1, FIRST_STACK_REG); + + break; + + default: + abort (); + } + break; + default: abort (); *************** *** 2384,2388 **** = (char **) alloca (n_operands * sizeof (char *)); ! decode_asm_operands (body, operands, operands_loc, constraints, 0); get_asm_operand_lengths (body, n_operands, &n_inputs, &n_outputs); subst_asm_stack_regs (insn, regstack, operands, operands_loc, --- 2357,2362 ---- = (char **) alloca (n_operands * sizeof (char *)); ! decode_asm_operands (body, operands, operands_loc, ! constraints, NULL_PTR); get_asm_operand_lengths (body, n_operands, &n_inputs, &n_outputs); subst_asm_stack_regs (insn, regstack, operands, operands_loc, *************** *** 2392,2396 **** if (GET_CODE (PATTERN (insn)) == PARALLEL) ! for (i = 0; i < XVECLEN (PATTERN (insn) , 0); i++) { if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i))) --- 2366,2370 ---- if (GET_CODE (PATTERN (insn)) == PARALLEL) ! for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) { if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i))) diff -rc2N gcc-2.2.2/regclass.c gcc-2.3.1/regclass.c *** gcc-2.2.2/regclass.c Thu May 7 02:37:30 1992 --- gcc-2.3.1/regclass.c Mon Oct 12 18:19:25 1992 *************** *** 1,4 **** /* Compute register class preferences for pseudo-registers. ! Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Compute register class preferences for pseudo-registers. ! Copyright (C) 1987, 1988, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 31,34 **** --- 31,36 ---- #include "insn-config.h" #include "recog.h" + #include "reload.h" + #include "real.h" #ifndef REGISTER_MOVE_COST *************** *** 37,42 **** #ifndef MEMORY_MOVE_COST ! #define MEMORY_MOVE_COST(x) 2 #endif /* Register tables used by many passes. */ --- 39,54 ---- #ifndef MEMORY_MOVE_COST ! #define MEMORY_MOVE_COST(x) 4 #endif + + /* If we have auto-increment or auto-decrement and we can have secondary + reloads, we are not allowed to use classes requiring secondary + reloads for psuedos auto-incremented since reload can't handle it. */ + + #ifdef AUTO_INC_DEC + #if defined(SECONARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS) + #define FORBIDDEN_INC_DEC_CLASSES + #endif + #endif /* Register tables used by many passes. */ *************** *** 102,107 **** /* For each reg class, a HARD_REG_SET saying which registers are in it. */ ! HARD_REG_SET reg_class_contents[] = REG_CLASS_CONTENTS; /* For each reg class, number of regs it contains. */ --- 114,129 ---- /* For each reg class, a HARD_REG_SET saying which registers are in it. */ ! HARD_REG_SET reg_class_contents[N_REG_CLASSES]; ! ! /* The same information, but as an array of ints. We copy from these ! ints to the table above. This is done so that the tm.h files do ! not have to be aware of the wordsize for machines with <= 64 regs. */ + #define N_REG_INTS \ + ((FIRST_PSEUDO_REGISTER + (HOST_BITS_PER_INT - 1)) / HOST_BITS_PER_INT) + + static int int_reg_class_contents[N_REG_CLASSES][N_REG_INTS] + = REG_CLASS_CONTENTS; + /* For each reg class, number of regs it contains. */ *************** *** 130,134 **** char *reg_names[] = REGISTER_NAMES; - /* Indexed by n, gives number of times (REG n) is set or clobbered. This information remains valid for the rest of the compilation --- 152,155 ---- *************** *** 140,143 **** --- 161,188 ---- short *reg_n_sets; + /* Maximum cost of moving from a register in one class to a register in + another class. Based on REGISTER_MOVE_COST. */ + + static int move_cost[N_REG_CLASSES][N_REG_CLASSES]; + + /* Similar, but here we don't have to move if the first index is a subset + of the second so in that case the cost is zero. */ + + static int may_move_cost[N_REG_CLASSES][N_REG_CLASSES]; + + #ifdef FORBIDDEN_INC_DEC_CLASSES + + /* These are the classes that regs which are auto-incremented or decremented + cannot be put in. */ + + static int forbidden_inc_dec_class[N_REG_CLASSES]; + + /* Indexed by n, is non-zero if (REG n) is used in an auto-inc or auto-dec + context. */ + + static char *in_inc_dec; + + #endif /* FORBIDDEN_INC_DEC_CLASSES */ + /* Function called only once to initialize the above data on reg usage. Once this is done, various switches may override. */ *************** *** 148,151 **** --- 193,209 ---- register int i, j; + /* First copy the register information from the initial int form into + the regsets. */ + + for (i = 0; i < N_REG_CLASSES; i++) + { + CLEAR_HARD_REG_SET (reg_class_contents[i]); + + for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) + if (int_reg_class_contents[i][j / HOST_BITS_PER_INT] + & (1 << (j % HOST_BITS_PER_INT))) + SET_HARD_REG_BIT (reg_class_contents[i], j); + } + bcopy (initial_fixed_regs, fixed_regs, sizeof fixed_regs); bcopy (initial_call_used_regs, call_used_regs, sizeof call_used_regs); *************** *** 254,257 **** --- 312,347 ---- } } + + /* Initialize the move cost table. Find every subset of each class + and take the maximum cost of moving any subset to any other. */ + + for (i = 0; i < N_REG_CLASSES; i++) + for (j = 0; j < N_REG_CLASSES; j++) + { + int cost = i == j ? 2 : REGISTER_MOVE_COST (i, j); + enum reg_class *p1, *p2; + + for (p2 = ®_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++) + if (*p2 != i) + cost = MAX (cost, REGISTER_MOVE_COST (i, *p2)); + + for (p1 = ®_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++) + { + if (*p1 != j) + cost = MAX (cost, REGISTER_MOVE_COST (*p1, j)); + + for (p2 = ®_class_subclasses[j][0]; + *p2 != LIM_REG_CLASSES; p2++) + if (*p1 != *p2) + cost = MAX (cost, REGISTER_MOVE_COST (*p1, *p2)); + } + + move_cost[i][j] = cost; + + if (reg_class_subset_p (i, j)) + cost = 0; + + may_move_cost[i][j] = cost; + } } *************** *** 341,357 **** just before local-alloc. */ ! /* savings[R].savings[CL] is twice the amount saved by putting register R ! in class CL. This data is used within `regclass' and freed ! when it is finished. */ ! ! struct savings ! { ! short savings[N_REG_CLASSES]; ! short memcost; ! short nrefs; }; ! static struct savings *savings; /* (enum reg_class) prefclass[R] is the preferred class for pseudo number R. This is available after `regclass' is run. */ --- 431,454 ---- just before local-alloc. */ ! /* The `costs' struct records the cost of using a hard register of each class ! and of using memory for each pseudo. We use this data to set up ! register class preferences. */ ! ! struct costs ! { ! int cost[N_REG_CLASSES]; ! int mem_cost; }; ! /* Record the cost of each class for each pseudo. */ + static struct costs *costs; + + /* Record the same data by operand number, accumulated for each alternative + in an insn. The contribution to a pseudo is that of the minimum-cost + alternative. */ + + static struct costs op_costs[MAX_RECOG_OPERANDS]; + /* (enum reg_class) prefclass[R] is the preferred class for pseudo number R. This is available after `regclass' is run. */ *************** *** 359,376 **** static char *prefclass; ! /* preferred_or_nothing[R] is nonzero if we should put pseudo number R ! in memory if we can't get its preferred class. This is available after `regclass' is run. */ ! static char *preferred_or_nothing; ! /* Record the depth of loops that we are in, 1 for no loops. */ static int loop_depth; ! void reg_class_record (); ! void record_address_regs (); /* Return the reg_class in which pseudo reg number REGNO is best allocated. This function is sometimes called before the info has been computed. --- 456,485 ---- static char *prefclass; ! /* altclass[R] is a register class that we should use for allocating ! pseudo number R if no register in the preferred class is available. ! If no register in this class is available, memory is preferred. ! ! It might appear to be more general to have a bitmask of classes here, ! but since it is recommended that there be a class corresponding to the ! union of most major pair of classes, that generality is not required. ! This is available after `regclass' is run. */ ! static char *altclass; ! /* Record the depth of loops that we are in. */ static int loop_depth; ! /* Account for the fact that insns within a loop are executed very commonly, ! but don't keep doing this as loops go too deep. */ + static int loop_cost; + static int copy_cost (); + static void record_reg_classes (); + static void record_address_regs (); + + /* Return the reg_class in which pseudo reg number REGNO is best allocated. This function is sometimes called before the info has been computed. *************** *** 386,395 **** } ! int ! reg_preferred_or_nothing (regno) { if (prefclass == 0) ! return 0; ! return preferred_or_nothing[regno]; } --- 495,505 ---- } ! enum reg_class ! reg_alternate_class (regno) { if (prefclass == 0) ! return ALL_REGS; ! ! return (enum reg_class) altclass[regno]; } *************** *** 415,591 **** #ifdef REGISTER_CONSTRAINTS register rtx insn; ! register int i; init_recog (); ! /* Zero out our accumulation of the cost of each class for each reg. */ ! savings = (struct savings *) alloca (nregs * sizeof (struct savings)); ! bzero (savings, nregs * sizeof (struct savings)); ! loop_depth = 1; ! /* Scan the instructions and record each time it would ! save code to put a certain register in a certain class. */ ! ! for (insn = f; insn; insn = NEXT_INSN (insn)) ! { ! if (GET_CODE (insn) == NOTE ! && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) ! loop_depth++; ! else if (GET_CODE (insn) == NOTE ! && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) ! loop_depth--; ! else if ((GET_CODE (insn) == INSN ! && GET_CODE (PATTERN (insn)) != USE ! && GET_CODE (PATTERN (insn)) != CLOBBER ! && GET_CODE (PATTERN (insn)) != ASM_INPUT) ! || (GET_CODE (insn) == JUMP_INSN ! && GET_CODE (PATTERN (insn)) != ADDR_VEC ! && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) ! || GET_CODE (insn) == CALL_INSN) ! { ! if (GET_CODE (insn) == INSN && asm_noperands (PATTERN (insn)) >= 0) ! { ! int noperands = asm_noperands (PATTERN (insn)); ! /* We don't use alloca because alloca would not free ! any of the space until this function returns. */ ! rtx *operands = (rtx *) oballoc (noperands * sizeof (rtx)); ! char **constraints ! = (char **) oballoc (noperands * sizeof (char *)); ! decode_asm_operands (PATTERN (insn), operands, 0, constraints, 0); ! for (i = noperands - 1; i >= 0; i--) ! reg_class_record (operands[i], i, constraints); ! obfree (operands); ! } ! else ! { ! int insn_code_number = recog_memoized (insn); ! rtx set = single_set (insn); ! insn_extract (insn); ! for (i = insn_n_operands[insn_code_number] - 1; i >= 0; i--) ! reg_class_record (recog_operand[i], i, ! insn_operand_constraint[insn_code_number]); ! ! /* If this insn loads a parameter from its stack slot, ! then it represents a savings, rather than a cost, ! if the parameter is stored in memory. Record this fact. */ ! if (set != 0 && GET_CODE (SET_DEST (set)) == REG ! && GET_CODE (SET_SRC (set)) == MEM) { ! rtx note = find_reg_note (insn, REG_EQUIV, 0); ! if (note != 0 && GET_CODE (XEXP (note, 0)) == MEM) ! savings[REGNO (SET_DEST (set))].memcost ! -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set))) ! * loop_depth); } ! ! /* Improve handling of two-address insns such as ! (set X (ashift CONST Y)) where CONST must be made to match X. ! Change it into two insns: (set X CONST) (set X (ashift X Y)). ! If we left this for reloading, it would probably get three ! insns because X and Y might go in the same place. ! This prevents X and Y from receiving the same hard reg. ! ! We can only do this if the modes of operands 0 and 1 (which ! might not be the same) are tieable. */ ! ! if (optimize ! && insn_n_operands[insn_code_number] >= 3 ! && insn_operand_constraint[insn_code_number][1][0] == '0' ! && insn_operand_constraint[insn_code_number][1][1] == 0 ! && CONSTANT_P (recog_operand[1]) ! && ! rtx_equal_p (recog_operand[0], recog_operand[1]) ! && ! rtx_equal_p (recog_operand[0], recog_operand[2]) ! && GET_CODE (recog_operand[0]) == REG ! && MODES_TIEABLE_P (GET_MODE (recog_operand[0]), ! insn_operand_mode[insn_code_number][1])) { ! rtx previnsn = prev_real_insn (insn); ! rtx dest ! = gen_lowpart (insn_operand_mode[insn_code_number][1], ! recog_operand[0]); ! rtx newinsn ! = emit_insn_before (gen_move_insn (dest, recog_operand[1]), ! insn); ! /* If this insn was the start of a basic block, ! include the new insn in that block. */ ! if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN) { ! int b; ! for (b = 0; b < n_basic_blocks; b++) ! if (insn == basic_block_head[b]) ! basic_block_head[b] = newinsn; } ! /* This makes one more setting of new insns's destination. */ ! reg_n_sets[REGNO (recog_operand[0])]++; ! *recog_operand_loc[1] = recog_operand[0]; ! for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--) ! if (recog_dup_num[i] == 1) ! *recog_dup_loc[i] = recog_operand[0]; } } } - } ! /* Now for each register look at how desirable each class is ! and find which class is preferred. Store that in `prefclass[REGNO]'. */ ! prefclass = (char *) oballoc (nregs); ! ! preferred_or_nothing = (char *) oballoc (nregs); ! ! for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) ! { ! register int best_savings = 0; ! enum reg_class best = ALL_REGS; ! ! /* This is an enum reg_class, but we call it an int ! to save lots of casts. */ ! register int class; ! register struct savings *p = &savings[i]; ! for (class = (int) ALL_REGS - 1; class > 0; class--) { ! if (p->savings[class] > best_savings) ! { ! best_savings = p->savings[class]; ! best = (enum reg_class) class; ! } ! else if (p->savings[class] == best_savings) { ! best = reg_class_subunion[(int)best][class]; } - } ! #if 0 ! /* Note that best_savings is twice number of places something ! is saved. */ ! if ((best_savings - p->savings[(int) GENERAL_REGS]) * 5 < reg_n_refs[i]) ! prefclass[i] = (int) GENERAL_REGS; ! else ! prefclass[i] = (int) best; ! #else ! /* We cast to (int) because (char) hits bugs in some compilers. */ ! prefclass[i] = (int) best; #endif ! ! /* reg_n_refs + p->memcost measures the cost of putting in memory. ! If a GENERAL_REG is no better, don't even try for one. ! Since savings and memcost are 2 * number of refs, ! this effectively counts each memory operand not needing reloading ! as costing 1/2 of a reload insn. */ ! if (reg_n_refs != 0) ! preferred_or_nothing[i] ! = ((best_savings - p->savings[(int) GENERAL_REGS]) ! >= p->nrefs + p->memcost); } #endif /* REGISTER_CONSTRAINTS */ --- 525,913 ---- #ifdef REGISTER_CONSTRAINTS register rtx insn; ! register int i, j; ! struct costs init_cost; ! rtx set; ! int pass; init_recog (); ! costs = (struct costs *) alloca (nregs * sizeof (struct costs)); ! #ifdef FORBIDDEN_INC_DEC_CLASSES ! in_inc_dec = (char *) alloca (nregs); ! /* Initialize information about which register classes can be used for ! pseudos that are auto-incremented or auto-decremented. It would ! seem better to put this in init_reg_sets, but we need to be able ! to allocate rtx, which we can't do that early. */ ! for (i = 0; i < N_REG_CLASSES; i++) ! { ! rtx r = gen_rtx (REG, VOIDmode, 0); ! enum machine_mode m; ! for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) ! if (TEST_HARD_REG_BIT (reg_class_contents[i], j)) ! { ! REGNO (r) = j; ! for (m = VOIDmode; (int) m < (int) MAX_MACHINE_MODE; ! m = (enum machine_mode) ((int) m) + 1) ! if (HARD_REGNO_MODE_OK (j, m)) ! { ! PUT_MODE (r, m); ! if (0 ! #ifdef SECONDARY_INPUT_RELOAD_CLASS ! || (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r) ! != NO_REGS) ! #endif ! #ifdef SECONDARY_OUTPUT_RELOAD_CLASS ! || (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r) ! != NO_REGS) ! #endif ! ) ! forbidden_inc_dec_class[i] = 1; ! } ! } ! } ! #endif /* FORBIDDEN_INC_DEC_CLASSES */ ! ! init_cost.mem_cost = 10000; ! for (i = 0; i < N_REG_CLASSES; i++) ! init_cost.cost[i] = 10000; ! ! /* Normally we scan the insns once and determine the best class to use for ! each register. However, if -fexpensive_optimizations are on, we do so ! twice, the second time using the tentative best classes to guide the ! selection. */ ! ! for (pass = 0; pass <= flag_expensive_optimizations; pass++) ! { ! /* Zero out our accumulation of the cost of each class for each reg. */ ! bzero (costs, nregs * sizeof (struct costs)); ! #ifdef FORBIDDEN_INC_DEC_CLASSES ! bzero (in_inc_dec, nregs); ! #endif ! ! loop_depth = 0, loop_cost = 1; ! ! /* Scan the instructions and record each time it would ! save code to put a certain register in a certain class. */ ! ! for (insn = f; insn; insn = NEXT_INSN (insn)) ! { ! char *constraints[MAX_RECOG_OPERANDS]; ! enum machine_mode modes[MAX_RECOG_OPERANDS]; ! int nalternatives; ! int noperands; ! ! /* Show that an insn inside a loop is likely to be executed three ! times more than insns outside a loop. This is much more agressive ! than the assumptions made elsewhere and is being tried as an ! experiment. */ ! ! if (GET_CODE (insn) == NOTE ! && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) ! loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5)); ! else if (GET_CODE (insn) == NOTE ! && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) ! loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5)); ! ! else if ((GET_CODE (insn) == INSN ! && GET_CODE (PATTERN (insn)) != USE ! && GET_CODE (PATTERN (insn)) != CLOBBER ! && GET_CODE (PATTERN (insn)) != ASM_INPUT) ! || (GET_CODE (insn) == JUMP_INSN ! && GET_CODE (PATTERN (insn)) != ADDR_VEC ! && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) ! || GET_CODE (insn) == CALL_INSN) ! { ! if (GET_CODE (insn) == INSN ! && (noperands = asm_noperands (PATTERN (insn))) >= 0) { ! decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR, ! constraints, modes); ! nalternatives = (noperands == 0 ? 0 ! : n_occurrences (',', constraints[0]) + 1); } ! else { ! int insn_code_number = recog_memoized (insn); ! rtx note; ! ! set = single_set (insn); ! insn_extract (insn); ! ! nalternatives = insn_n_alternatives[insn_code_number]; ! noperands = insn_n_operands[insn_code_number]; ! ! /* If this insn loads a parameter from its stack slot, then ! it represents a savings, rather than a cost, if the ! parameter is stored in memory. Record this fact. */ ! ! if (set != 0 && GET_CODE (SET_DEST (set)) == REG ! && GET_CODE (SET_SRC (set)) == MEM ! && (note = find_reg_note (insn, REG_EQUIV, ! NULL_RTX)) != 0 ! && GET_CODE (XEXP (note, 0)) == MEM) ! { ! costs[REGNO (SET_DEST (set))].mem_cost ! -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set))) ! * loop_cost); ! record_address_regs (XEXP (SET_SRC (set), 0), ! BASE_REG_CLASS, loop_cost * 2); ! continue; ! } ! ! /* Improve handling of two-address insns such as ! (set X (ashift CONST Y)) where CONST must be made to ! match X. Change it into two insns: (set X CONST) ! (set X (ashift X Y)). If we left this for reloading, it ! would probably get three insns because X and Y might go ! in the same place. This prevents X and Y from receiving ! the same hard reg. ! ! We can only do this if the modes of operands 0 and 1 ! (which might not be the same) are tieable and we only need ! do this during our first pass. */ ! ! if (pass == 0 && optimize ! && noperands >= 3 ! && insn_operand_constraint[insn_code_number][1][0] == '0' ! && insn_operand_constraint[insn_code_number][1][1] == 0 ! && CONSTANT_P (recog_operand[1]) ! && ! rtx_equal_p (recog_operand[0], recog_operand[1]) ! && ! rtx_equal_p (recog_operand[0], recog_operand[2]) ! && GET_CODE (recog_operand[0]) == REG ! && MODES_TIEABLE_P (GET_MODE (recog_operand[0]), ! insn_operand_mode[insn_code_number][1])) ! { ! rtx previnsn = prev_real_insn (insn); ! rtx dest ! = gen_lowpart (insn_operand_mode[insn_code_number][1], ! recog_operand[0]); ! rtx newinsn ! = emit_insn_before (gen_move_insn (dest, ! recog_operand[1]), ! insn); ! ! /* If this insn was the start of a basic block, ! include the new insn in that block. ! We need not check for code_label here; ! while a basic block can start with a code_label, ! INSN could not be at the beginning of that block. */ ! if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN) ! { ! int b; ! for (b = 0; b < n_basic_blocks; b++) ! if (insn == basic_block_head[b]) ! basic_block_head[b] = newinsn; ! } ! ! /* This makes one more setting of new insns's dest. */ ! reg_n_sets[REGNO (recog_operand[0])]++; ! ! *recog_operand_loc[1] = recog_operand[0]; ! for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--) ! if (recog_dup_num[i] == 1) ! *recog_dup_loc[i] = recog_operand[0]; ! insn = PREV_INSN (newinsn); ! continue; ! } ! ! /* If this is setting a pseudo from another pseudo or the ! sum of a pseudo and a constant integer and the other ! pseudo is known to be a pointer, set the destination to ! be a pointer as well. ! ! Likewise if it is setting the destination from an address ! or from a value equivalent to an address or to the sum of ! an address and something else. ! ! But don't do any of this if the pseudo corresponds to ! a user variable since it should have already been set ! as a pointer based on the type. ! ! There is no point in doing this during our second ! pass since not enough should have changed. */ ! ! if (pass == 0 && set != 0 && GET_CODE (SET_DEST (set)) == REG ! && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER ! && ! REG_USERVAR_P (SET_DEST (set)) ! && ! REGNO_POINTER_FLAG (REGNO (SET_DEST (set))) ! && ((GET_CODE (SET_SRC (set)) == REG ! && REGNO_POINTER_FLAG (REGNO (SET_SRC (set)))) ! || ((GET_CODE (SET_SRC (set)) == PLUS ! || GET_CODE (SET_SRC (set)) == LO_SUM) ! && (GET_CODE (XEXP (SET_SRC (set), 1)) ! == CONST_INT) ! && GET_CODE (XEXP (SET_SRC (set), 0)) == REG ! && REGNO_POINTER_FLAG (REGNO (XEXP (SET_SRC (set), 0)))) ! || GET_CODE (SET_SRC (set)) == CONST ! || GET_CODE (SET_SRC (set)) == SYMBOL_REF ! || GET_CODE (SET_SRC (set)) == LABEL_REF ! || (GET_CODE (SET_SRC (set)) == HIGH ! && (GET_CODE (XEXP (SET_SRC (set), 0)) == CONST ! || (GET_CODE (XEXP (SET_SRC (set), 0)) ! == SYMBOL_REF) ! || (GET_CODE (XEXP (SET_SRC (set), 0)) ! == LABEL_REF))) ! || ((GET_CODE (SET_SRC (set)) == PLUS ! || GET_CODE (SET_SRC (set)) == LO_SUM) ! && (GET_CODE (XEXP (SET_SRC (set), 1)) == CONST ! || (GET_CODE (XEXP (SET_SRC (set), 1)) ! == SYMBOL_REF) ! || (GET_CODE (XEXP (SET_SRC (set), 1)) ! == LABEL_REF))) ! || ((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 ! && (GET_CODE (XEXP (note, 0)) == CONST ! || GET_CODE (XEXP (note, 0)) == SYMBOL_REF ! || GET_CODE (XEXP (note, 0)) == LABEL_REF)))) ! REGNO_POINTER_FLAG (REGNO (SET_DEST (set))) = 1; ! ! for (i = 0; i < noperands; i++) { ! constraints[i] ! = insn_operand_constraint[insn_code_number][i]; ! modes[i] = insn_operand_mode[insn_code_number][i]; } + } ! /* If we get here, we are set up to record the costs of all the ! operands for this insn. Start by initializing the costs. ! Then handle any address registers. Finally record the desired ! classes for any pseudos, doing it twice if some pair of ! operands are commutative. */ ! ! for (i = 0; i < noperands; i++) ! { ! op_costs[i] = init_cost; ! ! if (GET_CODE (recog_operand[i]) == SUBREG) ! recog_operand[i] = SUBREG_REG (recog_operand[i]); ! if (GET_CODE (recog_operand[i]) == MEM) ! record_address_regs (XEXP (recog_operand[i], 0), ! BASE_REG_CLASS, loop_cost * 2); ! else if (constraints[i][0] == 'p') ! record_address_regs (recog_operand[i], ! BASE_REG_CLASS, loop_cost * 2); } + + /* Check for commutative in a separate loop so everything will + have been initialized. Don't bother doing anything if the + second operand is a constant since that is the case + for which the constraints should have been written. */ + + for (i = 0; i < noperands - 1; i++) + if (constraints[i][0] == '%' + && ! CONSTANT_P (recog_operand[i+1])) + { + char *xconstraints[MAX_RECOG_OPERANDS]; + int j; + + /* Handle commutative operands by swapping the constraints. + We assume the modes are the same. */ + + for (j = 0; j < noperands; j++) + xconstraints[j] = constraints[j]; + + xconstraints[i] = constraints[i+1]; + xconstraints[i+1] = constraints[i]; + record_reg_classes (nalternatives, noperands, + recog_operand, modes, xconstraints, + insn); + } + + record_reg_classes (nalternatives, noperands, recog_operand, + modes, constraints, insn); + + /* Now add the cost for each operand to the total costs for + its register. */ + + for (i = 0; i < noperands; i++) + if (GET_CODE (recog_operand[i]) == REG + && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER) + { + int regno = REGNO (recog_operand[i]); + struct costs *p = &costs[regno], *q = &op_costs[i]; + + p->mem_cost += q->mem_cost * loop_cost; + for (j = 0; j < N_REG_CLASSES; j++) + p->cost[j] += q->cost[j] * loop_cost; + } } } ! /* Now for each register look at how desirable each class is ! and find which class is preferred. Store that in ! `prefclass[REGNO]'. Record in `altclass[REGNO]' the largest register ! class any of whose registers is better than memory. */ ! if (pass == 0) ! { ! prefclass = (char *) oballoc (nregs); ! altclass = (char *) oballoc (nregs); ! } ! for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) { ! register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; ! enum reg_class best = ALL_REGS, alt = NO_REGS; ! /* This is an enum reg_class, but we call it an int ! to save lots of casts. */ ! register int class; ! register struct costs *p = &costs[i]; ! ! for (class = (int) ALL_REGS - 1; class > 0; class--) { ! /* Ignore classes that are too small for this operand or ! invalid for a operand that was auto-incremented. */ ! if (CLASS_MAX_NREGS (class, PSEUDO_REGNO_MODE (i)) ! > reg_class_size[class] ! #ifdef FORBIDDEN_INC_DEC_CLASSES ! || (in_inc_dec[i] && forbidden_inc_dec_class[class]) ! #endif ! ) ! ; ! else if (p->cost[class] < best_cost) ! { ! best_cost = p->cost[class]; ! best = (enum reg_class) class; ! } ! else if (p->cost[class] == best_cost) ! best = reg_class_subunion[(int)best][class]; } ! /* Record the alternate register class; i.e., a class for which ! every register in it is better than using memory. If adding a ! class would make a smaller class (i.e., no union of just those ! classes exists), skip that class. The major unions of classes ! should be provided as a register class. Don't do this if we ! will be doing it again later. */ ! ! if (pass == 1 || ! flag_expensive_optimizations) ! for (class = 0; class < N_REG_CLASSES; class++) ! if (p->cost[class] < p->mem_cost ! && (reg_class_size[reg_class_subunion[(int) alt][class]] ! > reg_class_size[(int) alt]) ! #ifdef FORBIDDEN_INC_DEC_CLASSES ! && ! (in_inc_dec[i] && forbidden_inc_dec_class[class]) #endif ! ) ! alt = reg_class_subunion[(int) alt][class]; ! ! /* If we don't add any classes, nothing to try. */ ! if (alt == best) ! alt = (int) NO_REGS; ! ! /* We cast to (int) because (char) hits bugs in some compilers. */ ! prefclass[i] = (int) best; ! altclass[i] = (int) alt; ! } } #endif /* REGISTER_CONSTRAINTS */ *************** *** 594,806 **** #ifdef REGISTER_CONSTRAINTS ! /* Scan an operand OP for register class preferences. ! OPNO is the operand number, and CONSTRAINTS is the constraint ! vector for the insn. ! ! Record the preferred register classes from the constraint for OP ! if OP is a register. If OP is a memory reference, record suitable ! preferences for registers used in the address. */ ! void ! reg_class_record (op, opno, constraints) ! rtx op; ! int opno; ! char **constraints; ! { ! char *constraint = constraints[opno]; ! register char *p; ! register enum reg_class class = NO_REGS; ! char *next = 0; ! int memok = 0; ! int double_cost = 0; ! if (op == 0) ! return; ! while (1) ! { ! if (GET_CODE (op) == SUBREG) ! op = SUBREG_REG (op); ! else break; ! } ! /* Memory reference: scan the address. */ ! if (GET_CODE (op) == MEM) ! record_address_regs (XEXP (op, 0), 2, 0); ! if (GET_CODE (op) != REG) ! { ! /* If the constraint says the operand is supposed to BE an address, ! scan it as one. */ ! if (constraint != 0 && constraint[0] == 'p') ! record_address_regs (op, 2, 0); ! return; ! } ! /* Operand is a register: examine the constraint for specified classes. */ ! for (p = constraint; *p || next; p++) { ! enum reg_class new_class = NO_REGS; ! if (*p == 0) ! { ! p = next; ! next = 0; ! } ! switch (*p) { ! case '=': ! case '?': ! case '#': ! case '&': ! case '!': ! case '%': ! case 'E': ! case 'F': ! case 'G': ! case 'H': ! case 'i': ! case 'n': ! case 's': ! case 'p': ! case ',': ! case 'I': ! case 'J': ! case 'K': ! case 'L': ! case 'M': ! case 'N': ! case 'O': ! case 'P': ! #ifdef EXTRA_CONSTRAINT ! case 'Q': ! case 'R': ! case 'S': ! case 'T': ! case 'U': ! #endif ! case 'V': ! case 'X': ! break; ! ! case '+': ! /* An input-output operand is twice as costly if it loses. */ ! double_cost = 1; ! break; ! ! case 'm': ! case 'o': ! memok = 1; ! break; ! ! /* * means ignore following letter ! when choosing register preferences. */ ! case '*': ! p++; ! break; ! ! case 'g': ! case 'r': ! new_class = GENERAL_REGS; ! break; ! ! case '0': ! case '1': ! case '2': ! case '3': ! case '4': ! /* If constraint says "match another operand", ! use that operand's constraint to choose preferences. */ ! if (*p - '0' < opno) { ! opno = *p - '0'; ! next = constraints[opno]; } - break; ! default: ! new_class = REG_CLASS_FROM_LETTER (*p); ! break; ! } ! /* If this object can fit into the class requested, compute the subunion ! of the requested class and classes found so far. */ ! if (CLASS_MAX_NREGS (new_class, GET_MODE (op)) ! <= reg_class_size[(int) new_class]) ! class = reg_class_subunion[(int) class][(int) new_class]; ! } ! ! { ! register int i; ! register struct savings *pp; ! register enum reg_class class1; ! int cost = 2 * (1 + double_cost) * loop_depth; ! pp = &savings[REGNO (op)]; ! /* Increment the savings for this reg ! for each class contained in the one the constraint asks for. */ ! if (class != NO_REGS && class != ALL_REGS) ! { ! int extracost; ! pp->savings[(int) class] += cost; ! for (i = 0; ; i++) ! { ! class1 = reg_class_subclasses[(int)class][i]; ! if (class1 == LIM_REG_CLASSES) ! break; ! pp->savings[(int) class1] += cost; ! } ! /* If it's slow to move data between this class and GENERAL_REGS, ! record that fact. */ ! extracost = (REGISTER_MOVE_COST (class, GENERAL_REGS) - 2) * loop_depth; ! if (extracost > 0) ! { ! /* Check that this class and GENERAL_REGS don't overlap. ! REGISTER_MOVE_COST is meaningless if there is overlap. */ ! HARD_REG_SET temp; ! COMPL_HARD_REG_SET (temp, reg_class_contents[(int) class]); ! GO_IF_HARD_REG_SUBSET (reg_class_contents[(int) GENERAL_REGS], ! temp, label1); ! /* Overlap. */ ! goto label2; ! ! label1: /* No overlap. */ ! /* Charge this extra cost to GENERAL_REGS ! and all its subclasses (none of which overlap this class). */ ! extracost = extracost * cost / (2 * loop_depth); ! pp->savings[(int) GENERAL_REGS] -= extracost; ! for (i = 0; ; i++) { ! class1 = reg_class_subclasses[(int)GENERAL_REGS][i]; ! if (class1 == LIM_REG_CLASSES) break; ! pp->savings[(int) class1] -= extracost; } ! label2: ; ! } ! } ! if (! memok) ! pp->memcost += (MEMORY_MOVE_COST (GET_MODE (op)) * (1 + double_cost) ! - 1) * loop_depth; ! pp->nrefs += loop_depth; ! } } /* Record the pseudo registers we must reload into hard registers in a subexpression of a memory address, X. - BCOST is the cost if X is a register and it fails to be in BASE_REG_CLASS. - ICOST is the cost if it fails to be in INDEX_REG_CLASS. */ ! void ! record_address_regs (x, bcost, icost) rtx x; ! int bcost, icost; { register enum rtx_code code = GET_CODE (x); --- 916,1364 ---- #ifdef REGISTER_CONSTRAINTS ! /* Record the cost of using memory or registers of various classes for ! the operands in INSN. ! N_ALTS is the number of alternatives. ! N_OPS is the number of operands. ! OPS is an array of the operands. ! MODES are the modes of the operands, in case any are VOIDmode. ! CONSTRAINTS are the constraints to use for the operands. This array ! is modified by this procedure. ! This procedure works alternative by alternative. For each alternative ! we assume that we will be able to allocate all pseudos to their ideal ! register class and calculate the cost of using that alternative. Then ! we compute for each operand that is a pseudo-register, the cost of ! having the pseudo allocated to each register class and using it in that ! alternative. To this cost is added the cost of the alternative. ! The cost of each class for this insn is its lowest cost among all the ! alternatives. */ ! static void ! record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) ! int n_alts; ! int n_ops; ! rtx *ops; ! enum machine_mode *modes; ! char **constraints; ! rtx insn; ! { ! int alt; ! enum op_type {OP_READ, OP_WRITE, OP_READ_WRITE} op_types[MAX_RECOG_OPERANDS]; ! int i, j; ! ! /* By default, each operand is an input operand. */ ! ! for (i = 0; i < n_ops; i++) ! op_types[i] = OP_READ; ! /* Process each alternative, each time minimizing an operand's cost with ! the cost for each operand in that alternative. */ ! ! for (alt = 0; alt < n_alts; alt++) { ! struct costs this_op_costs[MAX_RECOG_OPERANDS]; ! int alt_fail = 0; ! int alt_cost = 0; ! enum reg_class classes[MAX_RECOG_OPERANDS]; ! int class; ! for (i = 0; i < n_ops; i++) { ! char *p = constraints[i]; ! rtx op = ops[i]; ! enum machine_mode mode = modes[i]; ! int allows_mem = 0; ! int win = 0; ! char c; ! ! /* If this operand has no constraints at all, we can conclude ! nothing about it since anything is valid. */ ! ! if (*p == 0) { ! if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER) ! bzero ((char *) &this_op_costs[i], sizeof this_op_costs[i]); ! ! continue; } ! if (*p == '%') ! p++; ! /* If this alternative is only relevant when this operand ! matches a previous operand, we do different things depending ! on whether this operand is a pseudo-reg or not. */ ! if (p[0] >= '0' && p[0] <= '0' + i && (p[1] == ',' || p[1] == 0)) ! { ! j = p[0] - '0'; ! classes[i] = classes[j]; ! if (GET_CODE (op) != REG || REGNO (op) < FIRST_PSEUDO_REGISTER) ! { ! /* If this matches the other operand, we have no added ! cost. */ ! if (rtx_equal_p (ops[j], op)) ! ; ! ! /* If we can't put the other operand into a register, this ! alternative can't be used. */ ! ! else if (classes[j] == NO_REGS) ! alt_fail = 1; ! ! /* Otherwise, add to the cost of this alternative the cost ! to copy this operand to the register used for the other ! operand. */ ! else ! alt_cost += copy_cost (op, mode, classes[j], 1); ! } ! else if (GET_CODE (ops[j]) != REG ! || REGNO (ops[j]) < FIRST_PSEUDO_REGISTER) ! { ! /* This op is a pseudo but the one it matches is not. */ ! ! /* If we can't put the other operand into a register, this ! alternative can't be used. */ ! ! if (classes[j] == NO_REGS) ! alt_fail = 1; ! ! /* Otherwise, add to the cost of this alternative the cost ! to copy the other operand to the register used for this ! operand. */ ! ! else ! alt_cost += copy_cost (ops[j], mode, classes[j], 1); ! } ! else ! { ! /* The costs of this operand are the same as that of the ! other operand. However, if we cannot tie them, this ! alternative needs to do a copy, which is one ! instruction. */ ! ! this_op_costs[i] = this_op_costs[j]; ! if (! find_reg_note (insn, REG_DEAD, op)) ! alt_cost += 2; ! ! /* This is in place of ordinary cost computation ! for this operand. */ ! continue; ! } ! } ! ! /* Scan all the constraint letters. See if the operand matches ! any of the constraints. Collect the valid register classes ! and see if this operand accepts memory. */ ! ! classes[i] = NO_REGS; ! while (*p && (c = *p++) != ',') ! switch (c) { ! case '=': ! op_types[i] = OP_WRITE; ! break; ! ! case '+': ! op_types[i] = OP_READ_WRITE; ! break; ! ! case '*': ! /* Ignore the next letter for this pass. */ ! p++; ! break; ! ! case '%': ! case '?': case '!': case '#': ! case '&': ! case '0': case '1': case '2': case '3': case '4': ! case 'p': ! break; ! ! case 'm': case 'o': case 'V': ! /* It doesn't seem worth distingishing between offsettable ! and non-offsettable addresses here. */ ! allows_mem = 1; ! if (GET_CODE (op) == MEM) ! win = 1; ! break; ! ! case '<': ! if (GET_CODE (op) == MEM ! && (GET_CODE (XEXP (op, 0)) == PRE_DEC ! || GET_CODE (XEXP (op, 0)) == POST_DEC)) ! win = 1; ! break; ! ! case '>': ! if (GET_CODE (op) == MEM ! && (GET_CODE (XEXP (op, 0)) == PRE_INC ! || GET_CODE (XEXP (op, 0)) == POST_INC)) ! win = 1; ! break; ! ! case 'E': ! /* Match any floating double constant, but only if ! we can examine the bits of it reliably. */ ! if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) ! && GET_MODE (op) != VOIDmode && ! flag_pretend_float) break; ! if (GET_CODE (op) == CONST_DOUBLE) ! win = 1; ! break; ! ! case 'F': ! if (GET_CODE (op) == CONST_DOUBLE) ! win = 1; ! break; ! ! case 'G': ! case 'H': ! if (GET_CODE (op) == CONST_DOUBLE ! && CONST_DOUBLE_OK_FOR_LETTER_P (op, c)) ! win = 1; ! break; ! ! case 's': ! if (GET_CODE (op) == CONST_INT ! || (GET_CODE (op) == CONST_DOUBLE ! && GET_MODE (op) == VOIDmode)) ! break; ! case 'i': ! if (CONSTANT_P (op) ! #ifdef LEGITIMATE_PIC_OPERAND_P ! && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) ! #endif ! ) ! win = 1; ! break; ! ! case 'n': ! if (GET_CODE (op) == CONST_INT ! || (GET_CODE (op) == CONST_DOUBLE ! && GET_MODE (op) == VOIDmode)) ! win = 1; ! break; ! ! case 'I': ! case 'J': ! case 'K': ! case 'L': ! case 'M': ! case 'N': ! case 'O': ! case 'P': ! if (GET_CODE (op) == CONST_INT ! && CONST_OK_FOR_LETTER_P (INTVAL (op), c)) ! win = 1; ! break; ! ! case 'X': ! win = 1; ! break; ! ! #ifdef EXTRA_CONSTRAINT ! case 'Q': ! case 'R': ! case 'S': ! case 'T': ! case 'U': ! if (EXTRA_CONSTRAINT (op, c)) ! win = 1; ! break; ! #endif ! ! case 'g': ! if (GET_CODE (op) == MEM ! || (CONSTANT_P (op) ! #ifdef LEGITIMATE_PIC_OPERAND_P ! && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) ! #endif ! )) ! win = 1; ! allows_mem = 1; ! case 'r': ! classes[i] ! = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS]; ! break; ! ! default: ! classes[i] ! = reg_class_subunion[(int) classes[i]] ! [(int) REG_CLASS_FROM_LETTER (c)]; } ! constraints[i] = p; ! ! /* How we account for this operand now depends on whether it is a ! pseudo register or not. If it is, we first check if any ! register classes are valid. If not, we ignore this alternative, ! since we want to assume that all pseudos get allocated for ! register preferencing. If some register class is valid, compute ! the costs of moving the pseudo into that class. */ ! ! if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER) ! { ! if (classes[i] == NO_REGS) ! alt_fail = 1; ! else ! { ! struct costs *pp = &this_op_costs[i]; ! ! for (class = 0; class < N_REG_CLASSES; class++) ! pp->cost[class] = may_move_cost[class][(int) classes[i]]; ! ! /* If the alternative actually allows memory, make things ! a bit cheaper since we won't need an extra insn to ! load it. */ ! ! pp->mem_cost = MEMORY_MOVE_COST (mode) - allows_mem; ! ! /* If we have assigned a class to this register in our ! first pass, add a cost to this alternative corresponding ! to what we would add if this register were not in the ! appropriate class. */ ! ! if (prefclass) ! alt_cost ! += may_move_cost[prefclass[REGNO (op)]][(int) classes[i]]; ! } ! } ! ! /* Otherwise, if this alternative wins, either because we ! have already determined that or if we have a hard register of ! the proper class, there is no cost for this alternative. */ ! ! else if (win ! || (GET_CODE (op) == REG ! && reg_fits_class_p (op, classes[i], 0, GET_MODE (op)))) ! ; ! ! /* If registers are valid, the cost of this alternative includes ! copying the object to and/or from a register. */ ! ! else if (classes[i] != NO_REGS) ! { ! if (op_types[i] != OP_WRITE) ! alt_cost += copy_cost (op, mode, classes[i], 1); ! ! if (op_types[i] != OP_READ) ! alt_cost += copy_cost (op, mode, classes[i], 0); ! } ! ! /* The only other way this alternative can be used is if this is a ! constant that could be placed into memory. */ ! ! else if (CONSTANT_P (op) && allows_mem) ! alt_cost += MEMORY_MOVE_COST (mode); ! else ! alt_fail = 1; ! } ! ! if (alt_fail) ! continue; ! ! /* Finally, update the costs with the information we've calculated ! about this alternative. */ ! for (i = 0; i < n_ops; i++) ! if (GET_CODE (ops[i]) == REG ! && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) ! { ! struct costs *pp = &op_costs[i], *qq = &this_op_costs[i]; ! int scale = 1 + (op_types[i] == OP_READ_WRITE); ! ! pp->mem_cost = MIN (pp->mem_cost, ! (qq->mem_cost + alt_cost) * scale); ! ! for (class = 0; class < N_REG_CLASSES; class++) ! pp->cost[class] = MIN (pp->cost[class], ! (qq->cost[class] + alt_cost) * scale); ! } ! } } + + /* Compute the cost of loading X into (if TO_P is non-zero) or from (if + TO_P is zero) a register of class CLASS in mode MODE. + + X must not be a pseudo. */ + + static int + copy_cost (x, mode, class, to_p) + rtx x; + enum machine_mode mode; + enum reg_class class; + int to_p; + { + enum reg_class secondary_class = NO_REGS; + + /* If X is a SCRATCH, there is actually nothing to move since we are + assuming optimal allocation. */ + + if (GET_CODE (x) == SCRATCH) + return 0; + + /* Get the class we will actually use for a reload. */ + class = PREFERRED_RELOAD_CLASS (x, class); + + #ifdef HAVE_SECONDARY_RELOADS + /* If we need a secondary reload (we assume here that we are using + the secondary reload as an intermediate, not a scratch register), the + cost is that to load the input into the intermediate register, then + to copy them. We use a special value of TO_P to avoid recursion. */ + + #ifdef SECONDARY_INPUT_RELOAD_CLASS + if (to_p == 1) + secondary_class = SECONDARY_INPUT_RELOAD_CLASS (class, mode, x); + #endif + + #ifdef SECONARY_OUTPUT_RELOAD_CLASS + if (! to_p) + secondary_class = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, x); + #endif + + if (secondary_class != NO_REGS) + return (move_cost[(int) secondary_class][(int) class] + + copy_cost (x, mode, secondary_class, 2)); + #endif /* HAVE_SECONARY_RELOADS */ + + /* For memory, use the memory move cost, for (hard) registers, use the + cost to move between the register classes, and use 2 for everything + else (constants). */ + if (GET_CODE (x) == MEM || class == NO_REGS) + return MEMORY_MOVE_COST (mode); + + else if (GET_CODE (x) == REG) + return move_cost[(int) REGNO_REG_CLASS (REGNO (x))][(int) class]; + + else + /* If this is a constant, we may eventually want to call rtx_cost here. */ + return 2; + } + /* Record the pseudo registers we must reload into hard registers in a subexpression of a memory address, X. ! CLASS is the class that the register needs to be in and is either ! BASE_REG_CLASS or INDEX_REG_CLASS. ! ! SCALE is twice the amount to multiply the cost by (it is twice so we ! can represent half-cost adjustments). */ ! ! static void ! record_address_regs (x, class, scale) rtx x; ! enum reg_class class; ! int scale; { register enum rtx_code code = GET_CODE (x); *************** *** 821,825 **** If there is a sum of two registers, we must choose one to be the "base". Luckily, we can use the REGNO_POINTER_FLAG ! to make a good choice most of the time. */ { rtx arg0 = XEXP (x, 0); --- 1379,1390 ---- If there is a sum of two registers, we must choose one to be the "base". Luckily, we can use the REGNO_POINTER_FLAG ! to make a good choice most of the time. We only need to do this ! on machines that can have two registers in an address and where ! the base and index register classes are different. ! ! ??? This code used to set REGNO_POINTER_FLAG in some cases, but ! that seems bogus since it should only be set when we are sure ! the register is being used as a pointer. */ ! { rtx arg0 = XEXP (x, 0); *************** *** 827,884 **** register enum rtx_code code0 = GET_CODE (arg0); register enum rtx_code code1 = GET_CODE (arg1); - int icost0 = 0; - int icost1 = 0; - int suppress1 = 0; - int suppress0 = 0; /* Look inside subregs. */ ! while (code0 == SUBREG) arg0 = SUBREG_REG (arg0), code0 = GET_CODE (arg0); ! while (code1 == SUBREG) arg1 = SUBREG_REG (arg1), code1 = GET_CODE (arg1); ! if (code0 == MULT || code1 == MEM) ! icost0 = 2; ! else if (code1 == MULT || code0 == MEM) ! icost1 = 2; ! else if (code0 == CONST_INT) ! suppress0 = 1; ! else if (code1 == CONST_INT) ! suppress1 = 1; ! else if (code0 == REG && code1 == REG) { ! if (REGNO_POINTER_FLAG (REGNO (arg0))) ! icost1 = 2; ! else if (REGNO_POINTER_FLAG (REGNO (arg1))) ! icost0 = 2; ! else ! icost0 = icost1 = 1; } ! else if (code0 == REG) { ! if (code1 == PLUS ! && ! REGNO_POINTER_FLAG (REGNO (arg0))) ! icost0 = 2; ! else ! REGNO_POINTER_FLAG (REGNO (arg0)) = 1; } ! else if (code1 == REG) { ! if (code0 == PLUS ! && ! REGNO_POINTER_FLAG (REGNO (arg1))) ! icost1 = 2; ! else ! REGNO_POINTER_FLAG (REGNO (arg1)) = 1; } ! /* ICOST0 determines whether we are treating operand 0 ! as a base register or as an index register. ! SUPPRESS0 nonzero means it isn't a register at all. ! ICOST1 and SUPPRESS1 are likewise for operand 1. */ ! ! if (! suppress0) ! record_address_regs (arg0, 2 - icost0, icost0); ! if (! suppress1) ! record_address_regs (arg1, 2 - icost1, icost1); } break; --- 1392,1464 ---- register enum rtx_code code0 = GET_CODE (arg0); register enum rtx_code code1 = GET_CODE (arg1); /* Look inside subregs. */ ! if (code0 == SUBREG) arg0 = SUBREG_REG (arg0), code0 = GET_CODE (arg0); ! if (code1 == SUBREG) arg1 = SUBREG_REG (arg1), code1 = GET_CODE (arg1); ! /* If this machine only allows one register per address, it must ! be in the first operand. */ ! ! if (MAX_REGS_PER_ADDRESS == 1) ! record_address_regs (arg0, class, scale); ! ! /* If index and base registers are the same on this machine, just ! record registers in any non-constant operands. We assume here, ! as well as in the tests below, that all addresses are in ! canonical form. */ ! ! else if (INDEX_REG_CLASS == BASE_REG_CLASS) { ! record_address_regs (arg0, class, scale); ! if (! CONSTANT_P (arg1)) ! record_address_regs (arg1, class, scale); } ! ! /* If the second operand is a constant integer, it doesn't change ! what class the first operand must be. */ ! ! else if (code1 == CONST_INT || code1 == CONST_DOUBLE) ! record_address_regs (arg0, class, scale); ! ! /* If the second operand is a symbolic constant, the first operand ! must be an index register. */ ! ! else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF) ! record_address_regs (arg0, INDEX_REG_CLASS, scale); ! ! /* If this the sum of two registers where the first is known to be a ! pointer, it must be a base register with the second an index. */ ! ! else if (code0 == REG && code1 == REG ! && REGNO_POINTER_FLAG (REGNO (arg0))) { ! record_address_regs (arg0, BASE_REG_CLASS, scale); ! record_address_regs (arg1, INDEX_REG_CLASS, scale); } ! ! /* If this is the sum of two registers and neither is known to ! be a pointer, count equal chances that each might be a base ! or index register. This case should be rare. */ ! ! else if (code0 == REG && code1 == REG ! && ! REGNO_POINTER_FLAG (REGNO (arg0)) ! && ! REGNO_POINTER_FLAG (REGNO (arg1))) { ! record_address_regs (arg0, BASE_REG_CLASS, scale / 2); ! record_address_regs (arg0, INDEX_REG_CLASS, scale / 2); ! record_address_regs (arg1, BASE_REG_CLASS, scale / 2); ! record_address_regs (arg1, INDEX_REG_CLASS, scale / 2); } ! /* In all other cases, the first operand is an index and the ! second is the base. */ ! ! else ! { ! record_address_regs (arg0, INDEX_REG_CLASS, scale); ! record_address_regs (arg1, BASE_REG_CLASS, scale); ! } } break; *************** *** 890,939 **** /* Double the importance of a pseudo register that is incremented or decremented, since it would take two extra insns ! if it ends up in the wrong place. */ ! record_address_regs (XEXP (x, 0), 2 * bcost, 2 * icost); break; case REG: { ! register struct savings *pp; ! register enum reg_class class, class1; ! pp = &savings[REGNO (x)]; ! pp->nrefs += loop_depth; ! ! /* We have an address (or part of one) that is just one register. */ ! ! /* Record BCOST worth of savings for classes contained ! in BASE_REG_CLASS. */ ! ! class = BASE_REG_CLASS; ! if (class != NO_REGS && class != ALL_REGS) ! { ! register int i; ! pp->savings[(int) class] += bcost * loop_depth; ! for (i = 0; ; i++) ! { ! class1 = reg_class_subclasses[(int)class][i]; ! if (class1 == LIM_REG_CLASSES) ! break; ! pp->savings[(int) class1] += bcost * loop_depth; ! } ! } ! /* Record ICOST worth of savings for classes contained ! in INDEX_REG_CLASS. */ ! class = INDEX_REG_CLASS; ! if (icost != 0 && class != NO_REGS && class != ALL_REGS) ! { ! register int i; ! pp->savings[(int) class] += icost * loop_depth; ! for (i = 0; ; i++) ! { ! class1 = reg_class_subclasses[(int)class][i]; ! if (class1 == LIM_REG_CLASSES) ! break; ! pp->savings[(int) class1] += icost * loop_depth; ! } ! } } break; --- 1470,1494 ---- /* Double the importance of a pseudo register that is incremented or decremented, since it would take two extra insns ! if it ends up in the wrong place. If the operand is a pseudo, ! show it is being used in an INC_DEC context. */ ! ! #ifdef FORBIDDEN_INC_DEC_CLASSES ! if (GET_CODE (XEXP (x, 0)) == REG ! && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER) ! in_inc_dec[REGNO (XEXP (x, 0))] = 1; ! #endif ! ! record_address_regs (XEXP (x, 0), class, 2 * scale); break; case REG: { ! register struct costs *pp = &costs[REGNO (x)]; ! register int i; ! pp->mem_cost += (MEMORY_MOVE_COST (Pmode) * scale) / 2; ! for (i = 0; i < N_REG_CLASSES; i++) ! pp->cost[i] += (may_move_cost[i][(int) class] * scale) / 2; } break; *************** *** 945,949 **** for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') ! record_address_regs (XEXP (x, i), bcost, icost); } } --- 1500,1504 ---- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') ! record_address_regs (XEXP (x, i), class, scale); } } *************** *** 963,972 **** (as of the time reg_scan is called). */ ! short *regno_first_uid; /* Indexed by pseudo register number, gives uid of last insn using the reg (as of the time reg_scan is called). */ ! short *regno_last_uid; /* Record the number of registers we used when we allocated the above two --- 1518,1527 ---- (as of the time reg_scan is called). */ ! int *regno_first_uid; /* Indexed by pseudo register number, gives uid of last insn using the reg (as of the time reg_scan is called). */ ! int *regno_last_uid; /* Record the number of registers we used when we allocated the above two *************** *** 997,1009 **** highest_regno_in_uid_map = nregs + nregs / 20; regno_first_uid ! = (short *) oballoc (highest_regno_in_uid_map * sizeof (short)); regno_last_uid ! = (short *) oballoc (highest_regno_in_uid_map * sizeof (short)); reg_n_sets = (short *) oballoc (highest_regno_in_uid_map * sizeof (short)); } ! bzero (regno_first_uid, highest_regno_in_uid_map * sizeof (short)); ! bzero (regno_last_uid, highest_regno_in_uid_map * sizeof (short)); bzero (reg_n_sets, highest_regno_in_uid_map * sizeof (short)); --- 1552,1564 ---- highest_regno_in_uid_map = nregs + nregs / 20; regno_first_uid ! = (int *) oballoc (highest_regno_in_uid_map * sizeof (int)); regno_last_uid ! = (int *) oballoc (highest_regno_in_uid_map * sizeof (int)); reg_n_sets = (short *) oballoc (highest_regno_in_uid_map * sizeof (short)); } ! bzero (regno_first_uid, highest_regno_in_uid_map * sizeof (int)); ! bzero (regno_last_uid, highest_regno_in_uid_map * sizeof (int)); bzero (reg_n_sets, highest_regno_in_uid_map * sizeof (short)); diff -rc2N gcc-2.2.2/regs.h gcc-2.3.1/regs.h *** gcc-2.2.2/regs.h Mon Sep 23 22:25:58 1991 --- gcc-2.3.1/regs.h Tue Oct 20 17:12:40 1992 *************** *** 85,89 **** and is used infrequently enough that it should not get a hard register. -2 is used to mark a pseudo reg for a parameter, when a frame pointer ! is not required. global-alloc.c makes an allocno for this but does not try to assign a hard register to it. */ --- 85,89 ---- and is used infrequently enough that it should not get a hard register. -2 is used to mark a pseudo reg for a parameter, when a frame pointer ! is not required. global.c makes an allocno for this but does not try to assign a hard register to it. */ *************** *** 109,113 **** but not adjusted by cse even if cse invalidates it. */ ! extern short *regno_first_uid; /* Vector indexed by regno; gives uid of last insn using that reg. --- 109,113 ---- but not adjusted by cse even if cse invalidates it. */ ! extern int *regno_first_uid; /* Vector indexed by regno; gives uid of last insn using that reg. *************** *** 117,121 **** This is harmless since cse won't scan through a loop end. */ ! extern short *regno_last_uid; /* Vector indexed by regno; contains 1 for a register is considered a pointer. --- 117,121 ---- This is harmless since cse won't scan through a loop end. */ ! extern int *regno_last_uid; /* Vector indexed by regno; contains 1 for a register is considered a pointer. diff -rc2N gcc-2.2.2/reload.c gcc-2.3.1/reload.c *** gcc-2.2.2/reload.c Sat Jun 6 21:10:42 1992 --- gcc-2.3.1/reload.c Wed Oct 28 17:03:35 1992 *************** *** 208,211 **** --- 208,222 ---- static int n_memlocs; + #ifdef SECONDARY_MEMORY_NEEDED + + /* Save MEMs needed to copy from one class of registers to another. One MEM + is used per mode, but normally only one or two modes are ever used. + + We keep two versions, before and after register elimination. */ + + static rtx secondary_memlocs[NUM_MACHINE_MODES]; + static rtx secondary_memlocs_elim[NUM_MACHINE_MODES]; + #endif + /* The instruction we are doing reloads for; so we can test whether a register dies in it. */ *************** *** 243,246 **** --- 254,258 ---- static rtx subst_reg_equivs (); static rtx subst_indexed_address (); + void copy_replacements (); rtx find_equiv_reg (); static int find_inc_amount (); *************** *** 370,373 **** --- 382,452 ---- #endif /* HAVE_SECONDARY_RELOADS */ + #ifdef SECONDARY_MEMORY_NEEDED + + /* Return a memory location that will be used to copy X in mode MODE. + If we haven't already made a location for this mode in this insn, + call find_reloads_address on the location being returned. */ + + rtx + get_secondary_mem (x, mode) + rtx x; + enum machine_mode mode; + { + rtx loc; + int mem_valid; + + /* If MODE is narrower than a word, widen it. This is required because + most machines that require these memory locations do not support + short load and stores from all registers (e.g., FP registers). We could + possibly conditionalize this, but we lose nothing by doing the wider + mode. */ + + if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD) + mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0); + + /* If we already have made a MEM for this insn, return it. */ + if (secondary_memlocs_elim[(int) mode] != 0) + return secondary_memlocs_elim[(int) mode]; + + /* If this is the first time we've tried to get a MEM for this mode, + allocate a new one. `something_changed' in reload will get set + by noticing that the frame size has changed. */ + + if (secondary_memlocs[(int) mode] == 0) + secondary_memlocs[(int) mode] + = assign_stack_local (mode, GET_MODE_SIZE (mode), 0); + + /* Get a version of the address doing any eliminations needed. If that + didn't give us a new MEM, make a new one if it isn't valid. */ + + loc = eliminate_regs (secondary_memlocs[(int) mode], 0, NULL_RTX); + mem_valid = strict_memory_address_p (mode, XEXP (loc, 0)); + + if (! mem_valid && loc == secondary_memlocs[(int) mode]) + loc = copy_rtx (loc); + + /* The only time the call below will do anything is if the stack + offset is too large. In that case IND_LEVELS doesn't matter, so we + can just pass a zero. */ + if (! mem_valid) + find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0), x, 0); + + secondary_memlocs_elim[(int) mode] = loc; + + return loc; + } + + /* Clear any secondary memory locations we've made. */ + + void + clear_secondary_mem () + { + int i; + + for (i = 0; i < NUM_MACHINE_MODES; i++) + secondary_memlocs[i] = 0; + } + #endif /* SECONDARY_MEMORY_NEEDED */ + /* Record one (sometimes two) reload that needs to be performed. IN is an rtx saying where the data are to be found before this instruction. *************** *** 477,481 **** Similarly, we must reload the inside expression if we have a ! STRICT_LOW_PART (presumably, in == out in the cas). */ if (in != 0 && GET_CODE (in) == SUBREG --- 556,563 ---- Similarly, we must reload the inside expression if we have a ! STRICT_LOW_PART (presumably, in == out in the cas). ! ! Also reload the inner expression if it does not require a secondary ! reload but the SUBREG does. */ if (in != 0 && GET_CODE (in) == SUBREG *************** *** 495,499 **** / UNITS_PER_WORD) != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)), ! GET_MODE (SUBREG_REG (in))))))))) { in_subreg_loc = inloc; --- 577,589 ---- / UNITS_PER_WORD) != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)), ! GET_MODE (SUBREG_REG (in))))))) ! #ifdef SECONDARY_INPUT_RELOAD_CLASS ! || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS ! && (SECONDARY_INPUT_RELOAD_CLASS (class, ! GET_MODE (SUBREG_REG (in)), ! SUBREG_REG (in)) ! == NO_REGS)) ! #endif ! )) { in_subreg_loc = inloc; *************** *** 530,534 **** / UNITS_PER_WORD) != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)), ! GET_MODE (SUBREG_REG (out))))))))) { out_subreg_loc = outloc; --- 620,632 ---- / UNITS_PER_WORD) != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)), ! GET_MODE (SUBREG_REG (out))))))) ! #ifdef SECONDARY_OUTPUT_RELOAD_CLASS ! || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS ! && (SECONDARY_OUTPUT_RELOAD_CLASS (class, ! GET_MODE (SUBREG_REG (out)), ! SUBREG_REG (out)) ! == NO_REGS)) ! #endif ! )) { out_subreg_loc = outloc; *************** *** 551,554 **** --- 649,667 ---- dont_share = 1; + /* If IN is a SUBREG of a hard register, make a new REG. This + simplifies some of the cases below. */ + + if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG + && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER) + in = gen_rtx (REG, GET_MODE (in), + REGNO (SUBREG_REG (in)) + SUBREG_WORD (in)); + + /* Similarly for OUT. */ + if (out != 0 && GET_CODE (out) == SUBREG + && GET_CODE (SUBREG_REG (out)) == REG + && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER) + out = gen_rtx (REG, GET_MODE (out), + REGNO (SUBREG_REG (out)) + SUBREG_WORD (out)); + /* Narrow down the class of register wanted if that is desirable on this machine for efficiency. */ *************** *** 556,559 **** --- 669,678 ---- class = PREFERRED_RELOAD_CLASS (in, class); + /* Output reloads may need analagous treatment, different in detail. */ + #ifdef PREFERRED_OUTPUT_RELOAD_CLASS + if (out != 0) + class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class); + #endif + /* Make sure we use a class that can handle the actual pseudo inside any subreg. For example, on the 386, QImode regs *************** *** 710,715 **** || secondary_out_icode != CODE_FOR_nothing)) { ! push_reload (0, out, 0, outloc, class, VOIDmode, outmode, ! strict_low, optional, needed_for); out = 0; outloc = 0; --- 829,834 ---- || secondary_out_icode != CODE_FOR_nothing)) { ! push_reload (NULL_RTX, out, NULL_PTR, outloc, class, ! VOIDmode, outmode, strict_low, optional, needed_for); out = 0; outloc = 0; *************** *** 840,843 **** --- 959,975 ---- n_reloads++; i = n_reloads; + + #ifdef SECONDARY_MEMORY_NEEDED + /* If we need a memory location to copy between the two + reload regs, set it up now. */ + + if (in != 0 && secondary_icode == CODE_FOR_nothing + && SECONDARY_MEMORY_NEEDED (secondary_class, class, inmode)) + get_secondary_mem (in, inmode); + + if (out != 0 && secondary_icode == CODE_FOR_nothing + && SECONDARY_MEMORY_NEEDED (class, secondary_class, outmode)) + get_secondary_mem (out, outmode); + #endif } } *************** *** 865,868 **** --- 997,1015 ---- n_reloads++; + + #ifdef SECONDARY_MEMORY_NEEDED + /* If a memory location is needed for the copy, make one. */ + if (in != 0 && GET_CODE (in) == REG + && REGNO (in) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)), + class, inmode)) + get_secondary_mem (in, inmode); + + if (out != 0 && GET_CODE (out) == REG + && REGNO (out) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)), + outmode)) + get_secondary_mem (out, outmode); + #endif } else *************** *** 1237,1240 **** --- 1384,1388 ---- register int regno = REGNO (out) + out_offset; int nwords = HARD_REGNO_NREGS (regno, GET_MODE (real_out)); + rtx saved_rtx; /* When we consider whether the insn uses OUT, *************** *** 1247,1250 **** --- 1395,1399 ---- that counts. We can't be sure it's the "same" operand so it might not go through this reload. */ + saved_rtx = *inloc; *inloc = const0_rtx; *************** *** 1273,1277 **** } ! *inloc = real_in; } --- 1422,1426 ---- } ! *inloc = saved_rtx; } *************** *** 1293,1297 **** int nwords = HARD_REGNO_NREGS (regno, GET_MODE (real_in)); ! if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, 0) && ! hard_reg_set_here_p (regno, regno + nwords, PATTERN (this_insn))) --- 1442,1446 ---- int nwords = HARD_REGNO_NREGS (regno, GET_MODE (real_in)); ! if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, NULL_PTR) && ! hard_reg_set_here_p (regno, regno + nwords, PATTERN (this_insn))) *************** *** 1473,1476 **** --- 1622,1630 ---- switch (fmt[i]) { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + case 'i': if (XINT (x, i) != XINT (y, i)) *************** *** 1503,1507 **** /* Return the number of times character C occurs in string S. */ ! static int n_occurrences (c, s) char c; --- 1657,1661 ---- /* Return the number of times character C occurs in string S. */ ! int n_occurrences (c, s) char c; *************** *** 1519,1524 **** int safe; rtx base; ! int start; ! int end; }; --- 1673,1678 ---- int safe; rtx base; ! HOST_WIDE_INT start; ! HOST_WIDE_INT end; }; *************** *** 1663,1667 **** if (ydata.reg_flag) ! return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, 0); if (ydata.safe) return 1; --- 1817,1821 ---- if (ydata.reg_flag) ! return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, NULL_PTR); if (ydata.safe) return 1; *************** *** 1697,1701 **** } ! /* Similiar, but calls decompose. */ int --- 1851,1855 ---- } ! /* Similar, but calls decompose. */ int *************** *** 1806,1809 **** --- 1960,1970 ---- #endif + #ifdef SECONDARY_MEMORY_NEEDED + /* The eliminated forms of any secondary memory locations are per-insn, so + clear them out here. */ + + bzero (secondary_memlocs_elim, sizeof secondary_memlocs_elim); + #endif + /* Find what kind of insn this is. NOPERANDS gets number of operands. Make OPERANDS point to a vector of operand values. *************** *** 1931,1934 **** --- 2092,2106 ---- operands_match[c][i] = operands_match_p (recog_operand[c], recog_operand[i]); + + /* An operand may not match itself. */ + if (c == i) + { + if (this_insn_is_asm) + warning_for_asm (this_insn, + "operand %d has constraint %d", i, c); + else + abort (); + } + /* If C can be commuted with C+1, and C might need to match I, then C+1 might also need to match I. */ *************** *** 1971,1975 **** if (constraints[i][0] == 'p') { ! find_reloads_address (VOIDmode, 0, recog_operand[i], recog_operand_loc[i], recog_operand[i], ind_levels); --- 2143,2147 ---- if (constraints[i][0] == 'p') { ! find_reloads_address (VOIDmode, NULL_PTR, recog_operand[i], recog_operand_loc[i], recog_operand[i], ind_levels); *************** *** 2042,2050 **** code = GET_CODE (recog_operand[i]); preferred_class[i] ! = ((code == REG && REGNO (recog_operand[i]) > FIRST_PSEUDO_REGISTER) ? reg_preferred_class (REGNO (recog_operand[i])) : NO_REGS); pref_or_nothing[i] ! = (code == REG && REGNO (recog_operand[i]) > FIRST_PSEUDO_REGISTER ! && reg_preferred_or_nothing (REGNO (recog_operand[i]))); } --- 2214,2222 ---- code = GET_CODE (recog_operand[i]); preferred_class[i] ! = ((code == REG && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER) ? reg_preferred_class (REGNO (recog_operand[i])) : NO_REGS); pref_or_nothing[i] ! = (code == REG && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER ! && reg_alternate_class (REGNO (recog_operand[i])) == NO_REGS); } *************** *** 2126,2137 **** be a problem accessing the register in the outer mode. */ if (GET_CODE (operand) != REG ! #ifdef BYTE_LOADS_ZERO_EXTEND /* Nonparadoxical subreg of a pseudoreg. Don't to load the full width if on this machine ! we expected the fetch to zero-extend. */ || ((GET_MODE_SIZE (operand_mode[i]) > GET_MODE_SIZE (GET_MODE (operand))) && REGNO (operand) >= FIRST_PSEUDO_REGISTER) ! #endif /* BYTE_LOADS_ZERO_EXTEND */ /* Subreg of a hard reg which can't handle the subreg's mode or which would handle that mode in the wrong number of --- 2298,2313 ---- be a problem accessing the register in the outer mode. */ if (GET_CODE (operand) != REG ! #if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND) ! /* ??? The comment below clearly does not match the code. ! What the code below actually does is set force_reload ! for a paradoxical subreg of a pseudo. rms and kenner ! can't see the point of doing this. */ /* Nonparadoxical subreg of a pseudoreg. Don't to load the full width if on this machine ! we expected the fetch to extend. */ || ((GET_MODE_SIZE (operand_mode[i]) > GET_MODE_SIZE (GET_MODE (operand))) && REGNO (operand) >= FIRST_PSEUDO_REGISTER) ! #endif /* Subreg of a hard reg which can't handle the subreg's mode or which would handle that mode in the wrong number of *************** *** 2183,2187 **** case '%': ! commutative = i; break; --- 2359,2365 ---- case '%': ! /* The last operand should not be marked commutative. */ ! if (i != noperands - 1) ! commutative = i; break; *************** *** 2344,2348 **** we can examine the bits of it reliably. */ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_INT != BITS_PER_WORD) && GET_MODE (operand) != VOIDmode && ! flag_pretend_float) break; --- 2522,2526 ---- we can examine the bits of it reliably. */ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT ! || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD) && GET_MODE (operand) != VOIDmode && ! flag_pretend_float) break; *************** *** 2791,2798 **** { operand_reloadnum[i] ! = push_reload (XEXP (recog_operand[i], 0), 0, ! &XEXP (recog_operand[i], 0), 0, BASE_REG_CLASS, GET_MODE (XEXP (recog_operand[i], 0)), ! VOIDmode, 0, 0, 0); reload_inc[operand_reloadnum[i]] = GET_MODE_SIZE (GET_MODE (recog_operand[i])); --- 2969,2976 ---- { operand_reloadnum[i] ! = push_reload (XEXP (recog_operand[i], 0), NULL_RTX, ! &XEXP (recog_operand[i], 0), NULL_PTR, BASE_REG_CLASS, GET_MODE (XEXP (recog_operand[i], 0)), ! VOIDmode, 0, 0, NULL_RTX); reload_inc[operand_reloadnum[i]] = GET_MODE_SIZE (GET_MODE (recog_operand[i])); *************** *** 2809,2813 **** (insn_code_number < 0 ? 0 : insn_operand_strict_low[insn_code_number][i]), ! 0, 0); /* In a matching pair of operands, one must be input only and the other must be output only. --- 2987,2991 ---- (insn_code_number < 0 ? 0 : insn_operand_strict_low[insn_code_number][i]), ! 0, NULL_RTX); /* In a matching pair of operands, one must be input only and the other must be output only. *************** *** 2824,2828 **** operand_mode[i], operand_mode[goal_alternative_matched[i]], ! 0, 0, 0); operand_reloadnum[goal_alternative_matched[i]] = output_reloadnum; } --- 3002,3006 ---- operand_mode[i], operand_mode[goal_alternative_matched[i]], ! 0, 0, NULL_RTX); operand_reloadnum[goal_alternative_matched[i]] = output_reloadnum; } *************** *** 2838,2842 **** operand_mode[goal_alternative_matched[i]], operand_mode[i], ! 0, 0, 0); operand_reloadnum[i] = output_reloadnum; } --- 3016,3020 ---- operand_mode[goal_alternative_matched[i]], operand_mode[i], ! 0, 0, NULL_RTX); operand_reloadnum[i] = output_reloadnum; } *************** *** 2882,2886 **** (insn_code_number < 0 ? 0 : insn_operand_strict_low[insn_code_number][i]), ! 1, 0); /* Make an optional reload for an explicit mem ref. */ else if (GET_CODE (operand) == MEM --- 3060,3064 ---- (insn_code_number < 0 ? 0 : insn_operand_strict_low[insn_code_number][i]), ! 1, NULL_RTX); /* Make an optional reload for an explicit mem ref. */ else if (GET_CODE (operand) == MEM *************** *** 2900,2904 **** (insn_code_number < 0 ? 0 : insn_operand_strict_low[insn_code_number][i]), ! 1, 0); else non_reloaded_operands[n_non_reloaded_operands++] = recog_operand[i]; --- 3078,3082 ---- (insn_code_number < 0 ? 0 : insn_operand_strict_low[insn_code_number][i]), ! 1, NULL_RTX); else non_reloaded_operands[n_non_reloaded_operands++] = recog_operand[i]; *************** *** 3001,3005 **** /* Now get the operand values out of the insn. */ ! decode_asm_operands (body, recog_operand, recog_operand_loc, 0, 0); break; } --- 3179,3184 ---- /* Now get the operand values out of the insn. */ ! decode_asm_operands (body, recog_operand, recog_operand_loc, ! NULL_PTR, NULL_PTR); break; } *************** *** 3024,3028 **** if (insn_code_number >= 0) if (insn_operand_address_p[insn_code_number][i]) ! find_reloads_address (VOIDmode, 0, recog_operand[i], recog_operand_loc[i], recog_operand[i], ind_levels); --- 3203,3207 ---- if (insn_code_number >= 0) if (insn_operand_address_p[insn_code_number][i]) ! find_reloads_address (VOIDmode, NULL_PTR, recog_operand[i], recog_operand_loc[i], recog_operand[i], ind_levels); *************** *** 3114,3117 **** --- 3293,3303 ---- if (output_address && reload_when_needed[i] == RELOAD_OTHER) reload_needed_for_multiple[i] = 1; + + /* If we have earlyclobbers, make sure nothing overlaps them. */ + if (n_earlyclobbers > 0) + { + reload_when_needed[i] = RELOAD_OTHER; + reload_needed_for_multiple[i] = 1; + } } } *************** *** 3192,3196 **** x = gen_rtx (MEM, GET_MODE (x), addr); RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]); ! find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0), x, ind_levels); --- 3378,3382 ---- x = gen_rtx (MEM, GET_MODE (x), addr); RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]); ! find_reloads_address (GET_MODE (x), NULL_PTR, XEXP (x, 0), &XEXP (x, 0), x, ind_levels); *************** *** 3249,3258 **** invalid address on big-endian machines. ! For machines that zero-extend byte loads, we must not reload using a wider mode if we have a paradoxical SUBREG. find_reloads will force a reload in that case. So we should not do anything here. */ else if (regno >= FIRST_PSEUDO_REGISTER ! #ifdef BYTE_LOADS_ZERO_EXTEND && (GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) --- 3435,3444 ---- invalid address on big-endian machines. ! For machines that extend byte loads, we must not reload using a wider mode if we have a paradoxical SUBREG. find_reloads will force a reload in that case. So we should not do anything here. */ else if (regno >= FIRST_PSEUDO_REGISTER ! #if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND) && (GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) *************** *** 3275,3279 **** x = gen_rtx (MEM, GET_MODE (x), addr); RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]); ! find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0), x, ind_levels); --- 3461,3465 ---- x = gen_rtx (MEM, GET_MODE (x), addr); RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]); ! find_reloads_address (GET_MODE (x), NULL_PTR, XEXP (x, 0), &XEXP (x, 0), x, ind_levels); *************** *** 3363,3369 **** { tem = make_memloc (ad, regno); ! find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0), &XEXP (tem, 0), operand, ind_levels); ! push_reload (tem, 0, loc, 0, BASE_REG_CLASS, GET_MODE (ad), VOIDmode, 0, 0, operand); --- 3549,3555 ---- { tem = make_memloc (ad, regno); ! find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0), &XEXP (tem, 0), operand, ind_levels); ! push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS, GET_MODE (ad), VOIDmode, 0, 0, operand); *************** *** 3400,3404 **** /* If we do not have one of the cases above, we must do the reload. */ ! push_reload (ad, 0, loc, 0, BASE_REG_CLASS, GET_MODE (ad), VOIDmode, 0, 0, operand); return 1; --- 3586,3590 ---- /* If we do not have one of the cases above, we must do the reload. */ ! push_reload (ad, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS, GET_MODE (ad), VOIDmode, 0, 0, operand); return 1; *************** *** 3445,3448 **** --- 3631,3647 ---- find_reloads_address (GET_MODE (ad), &tem, XEXP (ad, 0), &XEXP (ad, 0), operand, ind_levels == 0 ? 0 : ind_levels - 1); + + /* If tem was changed, then we must create a new memory reference to + hold it and store it back into memrefloc. */ + if (tem != ad && memrefloc) + { + rtx oldref = *memrefloc; + *memrefloc = copy_rtx (*memrefloc); + copy_replacements (tem, XEXP (*memrefloc, 0)); + loc = &XEXP (*memrefloc, 0); + if (operand == oldref) + operand = *memrefloc; + } + /* Check similar cases as for indirect addresses as above except that we can allow pseudos and a MEM since they should have been *************** *** 3459,3463 **** /* Must use TEM here, not AD, since it is the one that will have any subexpressions reloaded, if needed. */ ! push_reload (tem, 0, loc, 0, BASE_REG_CLASS, GET_MODE (tem), VOIDmode, 0, 0, operand); --- 3658,3662 ---- /* Must use TEM here, not AD, since it is the one that will have any subexpressions reloaded, if needed. */ ! push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS, GET_MODE (tem), VOIDmode, 0, 0, operand); *************** *** 3602,3606 **** /* If constants aren't valid addresses, reload the constant address into a register. */ ! if (CONSTANT_ADDRESS_P (ad) && ! strict_memory_address_p (mode, ad)) { /* If AD is in address in the constant pool, the MEM rtx may be shared. --- 3801,3805 ---- /* If constants aren't valid addresses, reload the constant address into a register. */ ! if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad)) { /* If AD is in address in the constant pool, the MEM rtx may be shared. *************** *** 3914,3918 **** int reloadnum ! = push_reload (x, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), GET_MODE (x), VOIDmode, 0, operand); --- 4113,4117 ---- int reloadnum ! = push_reload (x, NULL_RTX, loc, NULL_PTR, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), GET_MODE (x), VOIDmode, 0, operand); *************** *** 3954,3958 **** operand, ind_levels); ! reloadnum = push_reload (x, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); --- 4153,4157 ---- operand, ind_levels); ! reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); *************** *** 3984,3988 **** operand, ind_levels); ! push_reload (*loc, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); --- 4183,4187 ---- operand, ind_levels); ! push_reload (*loc, NULL_RTX, loc, NULL_PTR, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); *************** *** 3995,4001 **** if (reg_equiv_constant[regno] != 0) { ! push_reload (reg_equiv_constant[regno], 0, loc, 0, ! context ? INDEX_REG_CLASS : BASE_REG_CLASS, ! GET_MODE (x), VOIDmode, 0, 0, operand); return 1; } --- 4194,4201 ---- if (reg_equiv_constant[regno] != 0) { ! find_reloads_address_part (reg_equiv_constant[regno], loc, ! (context ? INDEX_REG_CLASS ! : BASE_REG_CLASS), ! GET_MODE (x), operand, ind_levels); return 1; } *************** *** 4005,4009 **** if (reg_equiv_mem[regno] != 0) { ! push_reload (reg_equiv_mem[regno], 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); --- 4205,4209 ---- if (reg_equiv_mem[regno] != 0) { ! push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); *************** *** 4024,4028 **** : REGNO_OK_FOR_BASE_P (regno)))) { ! push_reload (x, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); --- 4224,4228 ---- : REGNO_OK_FOR_BASE_P (regno)))) { ! push_reload (x, NULL_RTX, loc, NULL_PTR, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); *************** *** 4036,4040 **** if (regno_clobbered_p (regno, this_insn)) { ! push_reload (x, 0, loc, 0, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); --- 4236,4240 ---- if (regno_clobbered_p (regno, this_insn)) { ! push_reload (x, NULL_RTX, loc, NULL_PTR, context ? INDEX_REG_CLASS : BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, operand); *************** *** 4102,4106 **** } ! push_reload (x, 0, loc, 0, class, mode, VOIDmode, 0, 0, needed_for); } --- 4302,4307 ---- } ! push_reload (x, NULL_RTX, loc, NULL_PTR, class, ! mode, VOIDmode, 0, 0, needed_for); } *************** *** 4271,4275 **** if (reg_equiv_memory_loc[i]) return refers_to_regno_for_reload_p (regno, endregno, ! reg_equiv_memory_loc[i], 0); if (reg_equiv_constant[i]) --- 4472,4477 ---- if (reg_equiv_memory_loc[i]) return refers_to_regno_for_reload_p (regno, endregno, ! reg_equiv_memory_loc[i], ! NULL_PTR); if (reg_equiv_constant[i]) *************** *** 4403,4407 **** ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1); ! return refers_to_regno_for_reload_p (regno, endregno, in, 0); } --- 4605,4609 ---- ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1); ! return refers_to_regno_for_reload_p (regno, endregno, in, NULL_PTR); } *************** *** 4625,4632 **** and something equivalent to that constant was copied into a reg, we can use that reg. */ ! || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0)) && rtx_equal_p (XEXP (tem, 0), goal) && (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0) ! || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0)) && GET_CODE (SET_DEST (pat)) == REG && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE --- 4827,4836 ---- and something equivalent to that constant was copied into a reg, we can use that reg. */ ! || (goal_const && (tem = find_reg_note (p, REG_EQUIV, ! NULL_RTX)) && rtx_equal_p (XEXP (tem, 0), goal) && (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0) ! || (goal_const && (tem = find_reg_note (p, REG_EQUIV, ! NULL_RTX)) && GET_CODE (SET_DEST (pat)) == REG && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE *************** *** 4637,4641 **** VOIDmode)) && (valueno = true_regnum (valtry)) >= 0) ! || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0)) && GET_CODE (SET_DEST (pat)) == REG && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE --- 4841,4846 ---- VOIDmode)) && (valueno = true_regnum (valtry)) >= 0) ! || (goal_const && (tem = find_reg_note (p, REG_EQUIV, ! NULL_RTX)) && GET_CODE (SET_DEST (pat)) == REG && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE *************** *** 4688,4692 **** (valueno + HARD_REGNO_NREGS (valueno, mode)), ! goal, 0)) return 0; --- 4893,4897 ---- (valueno + HARD_REGNO_NREGS (valueno, mode)), ! goal, NULL_PTR)) return 0; diff -rc2N gcc-2.2.2/reload.h gcc-2.3.1/reload.h *** gcc-2.2.2/reload.h Fri May 22 17:20:28 1992 --- gcc-2.3.1/reload.h Sat Aug 1 22:47:10 1992 *************** *** 110,113 **** --- 110,114 ---- extern void find_reloads (); extern void subst_reloads (); + extern rtx get_secondary_mem (); extern rtx eliminate_regs (); extern rtx gen_input_reload (); diff -rc2N gcc-2.2.2/reload1.c gcc-2.3.1/reload1.c *** gcc-2.2.2/reload1.c Thu Jun 4 17:50:56 1992 --- gcc-2.3.1/reload1.c Fri Oct 30 16:34:33 1992 *************** *** 19,22 **** --- 19,23 ---- + #include #include "config.h" #include "rtl.h" *************** *** 33,37 **** #include "basic-block.h" #include "output.h" - #include /* This file contains the reload pass of the compiler, which is --- 34,37 ---- *************** *** 247,253 **** #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - /* List of labels that must never be deleted. */ extern rtx forced_labels; --- 247,250 ---- *************** *** 320,323 **** --- 317,321 ---- static void alter_reg (); static void delete_dead_insn (); + static void spill_failure (); static int new_spill_reg(); static void set_label_offsets (); *************** *** 351,355 **** gen_rtx (PLUS, Pmode, gen_rtx (REG, Pmode, LAST_VIRTUAL_REGISTER + 1), ! gen_rtx (CONST_INT, VOIDmode, 4))); spill_indirect_levels = 0; --- 349,353 ---- gen_rtx (PLUS, Pmode, gen_rtx (REG, Pmode, LAST_VIRTUAL_REGISTER + 1), ! GEN_INT (4))); spill_indirect_levels = 0; *************** *** 367,377 **** /* See if reg+reg is a valid (and offsettable) address. */ ! tem = gen_rtx (PLUS, Pmode, ! gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM), ! gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM)); ! /* This way, we make sure that reg+reg is an offsettable address. */ ! tem = plus_constant (tem, 4); ! double_reg_address_ok = memory_address_p (QImode, tem); /* Initialize obstack for our rtl allocation. */ --- 365,382 ---- /* See if reg+reg is a valid (and offsettable) address. */ ! for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! { ! tem = gen_rtx (PLUS, Pmode, ! gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM), ! gen_rtx (REG, Pmode, i)); ! /* This way, we make sure that reg+reg is an offsettable address. */ ! tem = plus_constant (tem, 4); ! if (memory_address_p (QImode, tem)) ! { ! double_reg_address_ok = 1; ! break; ! } ! } /* Initialize obstack for our rtl allocation. */ *************** *** 478,484 **** If it is nonzero, messages are written to it to describe which registers are seized as reload regs, which pseudo regs ! are spilled from them, and where the pseudo regs are reallocated to. */ ! void reload (first, global, dumpfile) rtx first; --- 483,492 ---- If it is nonzero, messages are written to it to describe which registers are seized as reload regs, which pseudo regs ! are spilled from them, and where the pseudo regs are reallocated to. ! Return value is nonzero if reload failed ! and we must not do any more for this function. */ ! ! int reload (first, global, dumpfile) rtx first; *************** *** 498,501 **** --- 506,512 ---- int caller_save_group_size = 1; + /* Nonzero means we couldn't get enough spill regs. */ + int failure = 0; + /* The basic block number currently being processed for INSN. */ int this_block; *************** *** 510,513 **** --- 521,529 ---- basic_block_needs[i] = 0; + #ifdef SECONDARY_MEMORY_NEEDED + /* Initialize the secondary memory table. */ + clear_secondary_mem (); + #endif + /* Remember which hard regs appear explicitly before we merge into `regs_ever_live' the ones in which *************** *** 533,537 **** /* Make sure that the last insn in the chain is not something that needs reloading. */ ! emit_note (0, NOTE_INSN_DELETED); /* Find all the pseudo registers that didn't get hard regs --- 549,553 ---- /* Make sure that the last insn in the chain is not something that needs reloading. */ ! emit_note (NULL_PTR, NOTE_INSN_DELETED); /* Find all the pseudo registers that didn't get hard regs *************** *** 568,572 **** if (set != 0 && GET_CODE (SET_DEST (set)) == REG) { ! rtx note = find_reg_note (insn, REG_EQUIV, 0); if (note #ifdef LEGITIMATE_PIC_OPERAND_P --- 584,588 ---- if (set != 0 && GET_CODE (SET_DEST (set)) == REG) { ! rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); if (note #ifdef LEGITIMATE_PIC_OPERAND_P *************** *** 742,745 **** --- 758,764 ---- } + /* From now on, we need to emit any moves without making new pseudos. */ + reload_in_progress = 1; + /* This loop scans the entire function each go-round and repeats until one repetition spills no additional hard regs. */ *************** *** 778,782 **** --- 797,807 ---- otherwise we can't handle the complexity. */ enum machine_mode group_mode[N_REG_CLASSES]; + /* Record the insn where each maximum need is first found. */ + rtx max_needs_insn[N_REG_CLASSES]; + rtx max_groups_insn[N_REG_CLASSES]; + rtx max_nongroups_insn[N_REG_CLASSES]; rtx x; + int starting_frame_size = get_frame_size (); + static char *reg_class_names[] = REG_CLASS_NAMES; something_changed = 0; *************** *** 784,787 **** --- 809,815 ---- bzero (max_groups, sizeof max_groups); bzero (max_nongroups, sizeof max_nongroups); + bzero (max_needs_insn, sizeof max_needs_insn); + bzero (max_groups_insn, sizeof max_groups_insn); + bzero (max_nongroups_insn, sizeof max_nongroups_insn); bzero (group_size, sizeof group_size); for (i = 0; i < N_REG_CLASSES; i++) *************** *** 826,830 **** for (x = forced_labels; x; x = XEXP (x, 1)) if (XEXP (x, 0)) ! set_label_offsets (XEXP (x, 0), 0, 1); /* For each pseudo register that has an equivalent location defined, --- 854,858 ---- for (x = forced_labels; x; x = XEXP (x, 1)) if (XEXP (x, 0)) ! set_label_offsets (XEXP (x, 0), NULL_RTX, 1); /* For each pseudo register that has an equivalent location defined, *************** *** 854,858 **** if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i]) { ! rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, 0); if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]), --- 882,886 ---- if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i]) { ! rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX); if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]), *************** *** 1272,1281 **** { if (max_needs[i] < insn_needs[i]) ! max_needs[i] = insn_needs[i]; if (max_groups[i] < insn_groups[i]) ! max_groups[i] = insn_groups[i]; if (insn_total_groups > 0) if (max_nongroups[i] < insn_needs[i]) ! max_nongroups[i] = insn_needs[i]; } } --- 1300,1318 ---- { if (max_needs[i] < insn_needs[i]) ! { ! max_needs[i] = insn_needs[i]; ! max_needs_insn[i] = insn; ! } if (max_groups[i] < insn_groups[i]) ! { ! max_groups[i] = insn_groups[i]; ! max_groups_insn[i] = insn; ! } if (insn_total_groups > 0) if (max_nongroups[i] < insn_needs[i]) ! { ! max_nongroups[i] = insn_needs[i]; ! max_nongroups_insn[i] = insn; ! } } } *************** *** 1283,1286 **** --- 1320,1349 ---- } + /* If we allocated any new memory locations, make another pass + since it might have changed elimination offsets. */ + if (starting_frame_size != get_frame_size ()) + something_changed = 1; + + if (dumpfile) + for (i = 0; i < N_REG_CLASSES; i++) + { + if (max_needs[i] > 0) + fprintf (dumpfile, + ";; Need %d reg%s of class %s (for insn %d).\n", + max_needs[i], max_needs[i] == 1 ? "" : "s", + reg_class_names[i], INSN_UID (max_needs_insn[i])); + if (max_nongroups[i] > 0) + fprintf (dumpfile, + ";; Need %d nongroup reg%s of class %s (for insn %d).\n", + max_nongroups[i], max_nongroups[i] == 1 ? "" : "s", + reg_class_names[i], INSN_UID (max_nongroups_insn[i])); + if (max_groups[i] > 0) + fprintf (dumpfile, + ";; Need %d group%s (%smode) of class %s (for insn %d).\n", + max_groups[i], max_groups[i] == 1 ? "" : "s", + mode_name[(int) group_mode[i]], + reg_class_names[i], INSN_UID (max_groups_insn[i])); + } + /* If we have caller-saves, set up the save areas and see if caller-save will need a spill register. */ *************** *** 1568,1574 **** of the new reload reg we have found. */ ! something_changed ! |= new_spill_reg (i, class, max_needs, 0, ! global, dumpfile); } else --- 1631,1645 ---- of the new reload reg we have found. */ ! if (i >= FIRST_PSEUDO_REGISTER) ! { ! /* There are no groups left to spill. */ ! spill_failure (max_groups_insn[class]); ! failure = 1; ! goto failed; ! } ! else ! something_changed ! |= new_spill_reg (i, class, max_needs, NULL_PTR, ! global, dumpfile); } else *************** *** 1581,1585 **** int j = potential_reload_regs[i]; int k; ! if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER && HARD_REGNO_MODE_OK (j, group_mode[class])) { --- 1652,1657 ---- int j = potential_reload_regs[i]; int k; ! if (j >= 0 ! && j + group_size[class] <= FIRST_PSEUDO_REGISTER && HARD_REGNO_MODE_OK (j, group_mode[class])) { *************** *** 1602,1606 **** break; something_changed ! |= new_spill_reg (idx, class, max_needs, 0, global, dumpfile); } --- 1674,1679 ---- break; something_changed ! |= new_spill_reg (idx, class, ! max_needs, NULL_PTR, global, dumpfile); } *************** *** 1618,1624 **** } /* We couldn't find any registers for this reload. ! Abort to avoid going into an infinite loop. */ ! if (i == FIRST_PSEUDO_REGISTER) ! abort (); } } --- 1691,1702 ---- } /* We couldn't find any registers for this reload. ! Avoid going into an infinite loop. */ ! if (i >= FIRST_PSEUDO_REGISTER) ! { ! /* There are no groups left. */ ! spill_failure (max_groups_insn[class]); ! failure = 1; ! goto failed; ! } } } *************** *** 1646,1655 **** break; /* I should be the index in potential_reload_regs of the new reload reg we have found. */ ! something_changed ! |= new_spill_reg (i, class, max_needs, max_nongroups, ! global, dumpfile); } } --- 1724,1759 ---- break; + /* If we couldn't get a register, try to get one even if we + might foreclose possible groups. This may cause problems + later, but that's better than aborting now, since it is + possible that we will, in fact, be able to form the needed + group even with this allocation. */ + + if (i >= FIRST_PSEUDO_REGISTER + && (asm_noperands (max_needs[class] > 0 + ? max_needs_insn[class] + : max_nongroups_insn[class]) + < 0)) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (potential_reload_regs[i] >= 0 + && TEST_HARD_REG_BIT (reg_class_contents[class], + potential_reload_regs[i])) + break; + /* I should be the index in potential_reload_regs of the new reload reg we have found. */ ! if (i >= FIRST_PSEUDO_REGISTER) ! { ! /* There are no possible registers left to spill. */ ! spill_failure (max_needs[class] > 0 ? max_needs_insn[class] ! : max_nongroups_insn[class]); ! failure = 1; ! goto failed; ! } ! else ! something_changed ! |= new_spill_reg (i, class, max_needs, max_nongroups, ! global, dumpfile); } } *************** *** 1663,1669 **** mark_elimination (ep->from, ep->to); - /* From now on, we need to emit any moves without making new pseudos. */ - reload_in_progress = 1; - /* Insert code to save and restore call-clobbered hard regs around calls. Tell if what mode to use so that we will process --- 1767,1770 ---- *************** *** 1705,1710 **** --- 1806,1826 ---- reload_as_needed (first, global); + /* If we were able to eliminate the frame pointer, show that it is no + longer live at the start of any basic block. If it is live by + virtue of being in a pseudo, that pseudo will be marked live + and hence the frame pointer will be known to be live via that + pseudo. */ + + if (! frame_pointer_needed) + for (i = 0; i < n_basic_blocks; i++) + basic_block_live_at_start[i][FRAME_POINTER_REGNUM / REGSET_ELT_BITS] + &= ~ ((REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS)); + reload_in_progress = 0; + /* Come here (with failure set nonzero) if we can't get enough spill regs + and we decide not to abort about it. */ + failed: + /* Now eliminate all pseudo regs by modifying them into their equivalent memory references. *************** *** 1767,1770 **** --- 1883,1888 ---- reg_equiv_constant = 0; reg_equiv_memory_loc = 0; + + return failure; } *************** *** 1918,1921 **** --- 2036,2052 ---- } + /* Handle the failure to find a register to spill. + INSN should be one of the insns which needed this particular spill reg. */ + + static void + spill_failure (insn) + rtx insn; + { + if (asm_noperands (PATTERN (insn)) >= 0) + error_for_asm (insn, "`asm' needs too many reloads"); + else + abort (); + } + /* Add a new register to the tables of available spill-registers (as well as spilling all pseudos allocated to the register). *************** *** 2176,2179 **** --- 2307,2313 ---- { case LABEL_REF: + if (LABEL_REF_NONLOCAL_P (x)) + return; + x = XEXP (x, 0); *************** *** 2389,2393 **** reference to the pseudo. Ensure we make a copy of the address in case it is shared. */ ! new = eliminate_regs (reg_equiv_memory_loc[regno], mem_mode, 0); if (new != reg_equiv_memory_loc[regno]) return copy_rtx (new); --- 2523,2528 ---- reference to the pseudo. Ensure we make a copy of the address in case it is shared. */ ! new = eliminate_regs (reg_equiv_memory_loc[regno], ! mem_mode, NULL_RTX); if (new != reg_equiv_memory_loc[regno]) return copy_rtx (new); *************** *** 2417,2421 **** eliminate_regs_in_insn, so just replace a PLUS with a PLUS here, unless inside a MEM. */ ! if (mem_mode && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == - ep->previous_offset) return ep->to_rtx; --- 2552,2556 ---- eliminate_regs_in_insn, so just replace a PLUS with a PLUS here, unless inside a MEM. */ ! if (mem_mode != 0 && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == - ep->previous_offset) return ep->to_rtx; *************** *** 2445,2450 **** { ! rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, 0); ! rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, 0); if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) --- 2580,2585 ---- { ! rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, NULL_RTX); ! rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, NULL_RTX); if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) *************** *** 2483,2487 **** if (XEXP (x, 0)) { ! new = eliminate_regs (XEXP (x, 0), mem_mode, 0); if (new != XEXP (x, 0)) x = gen_rtx (EXPR_LIST, REG_NOTE_KIND (x), new, XEXP (x, 1)); --- 2618,2622 ---- if (XEXP (x, 0)) { ! new = eliminate_regs (XEXP (x, 0), mem_mode, NULL_RTX); if (new != XEXP (x, 0)) x = gen_rtx (EXPR_LIST, REG_NOTE_KIND (x), new, XEXP (x, 1)); *************** *** 2496,2500 **** if (XEXP (x, 1)) { ! new = eliminate_regs (XEXP (x, 1), mem_mode, 0); if (new != XEXP (x, 1)) return gen_rtx (INSN_LIST, GET_MODE (x), XEXP (x, 0), new); --- 2631,2635 ---- if (XEXP (x, 1)) { ! new = eliminate_regs (XEXP (x, 1), mem_mode, NULL_RTX); if (new != XEXP (x, 1)) return gen_rtx (INSN_LIST, GET_MODE (x), XEXP (x, 0), new); *************** *** 2515,2520 **** case LE: case LT: case LEU: case LTU: { ! rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, 0); ! rtx new1 = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, 0) : 0; if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) --- 2650,2656 ---- case LE: case LT: case LEU: case LTU: { ! rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, NULL_RTX); ! rtx new1 ! = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, NULL_RTX) : 0; if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) *************** *** 2547,2551 **** case SQRT: case FFS: ! new = eliminate_regs (XEXP (x, 0), mem_mode, 0); if (new != XEXP (x, 0)) return gen_rtx (code, GET_MODE (x), new); --- 2683,2687 ---- case SQRT: case FFS: ! new = eliminate_regs (XEXP (x, 0), mem_mode, NULL_RTX); if (new != XEXP (x, 0)) return gen_rtx (code, GET_MODE (x), new); *************** *** 2566,2570 **** { new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))], ! mem_mode, 0); /* If we didn't change anything, we must retain the pseudo. */ --- 2702,2706 ---- { new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))], ! mem_mode, NULL_RTX); /* If we didn't change anything, we must retain the pseudo. */ *************** *** 2577,2581 **** } else ! new = eliminate_regs (SUBREG_REG (x), mem_mode, 0); if (new != XEXP (x, 0)) --- 2713,2717 ---- } else ! new = eliminate_regs (SUBREG_REG (x), mem_mode, NULL_RTX); if (new != XEXP (x, 0)) *************** *** 2627,2631 **** for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) temp_vec[i] = eliminate_regs (ASM_OPERANDS_INPUT (x, i), ! mem_mode, 0); for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) --- 2763,2767 ---- for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) temp_vec[i] = eliminate_regs (ASM_OPERANDS_INPUT (x, i), ! mem_mode, NULL_RTX); for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++) *************** *** 2697,2702 **** /* Now avoid the loop below in this common case. */ { ! rtx new0 = eliminate_regs (SET_DEST (x), 0, 0); ! rtx new1 = eliminate_regs (SET_SRC (x), 0, 0); /* If SET_DEST changed from a REG to a MEM and INSN is non-zero, --- 2833,2838 ---- /* Now avoid the loop below in this common case. */ { ! rtx new0 = eliminate_regs (SET_DEST (x), 0, NULL_RTX); ! rtx new1 = eliminate_regs (SET_SRC (x), 0, NULL_RTX); /* If SET_DEST changed from a REG to a MEM and INSN is non-zero, *************** *** 2716,2720 **** recursive call and copy the flags. While we are here, handle this case more efficiently. */ ! new = eliminate_regs (XEXP (x, 0), GET_MODE (x), 0); if (new != XEXP (x, 0)) { --- 2852,2856 ---- recursive call and copy the flags. While we are here, handle this case more efficiently. */ ! new = eliminate_regs (XEXP (x, 0), GET_MODE (x), NULL_RTX); if (new != XEXP (x, 0)) { *************** *** 2736,2740 **** if (*fmt == 'e') { ! new = eliminate_regs (XEXP (x, i), mem_mode, 0); if (new != XEXP (x, i) && ! copied) { --- 2872,2876 ---- if (*fmt == 'e') { ! new = eliminate_regs (XEXP (x, i), mem_mode, NULL_RTX); if (new != XEXP (x, i) && ! copied) { *************** *** 2858,2870 **** common case. */ ! new_body = eliminate_regs (old_body, 0, replace ? insn : 0); if (new_body != old_body) { ! if (GET_CODE (old_body) != SET || GET_CODE (SET_SRC (old_body)) != PLUS ! || ! validate_change (insn, &PATTERN (insn), new_body, 0)) PATTERN (insn) = new_body; if (replace && REG_NOTES (insn)) ! REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, 0); val = 1; } --- 2994,3020 ---- common case. */ ! new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX); if (new_body != old_body) { ! /* If we had a move insn but now we don't, rerecognize it. */ ! if ((GET_CODE (old_body) == SET && GET_CODE (SET_SRC (old_body)) == REG ! && (GET_CODE (new_body) != SET ! || GET_CODE (SET_SRC (new_body)) != REG)) ! /* If this was an add insn before, rerecognize. */ ! || ! (GET_CODE (old_body) == SET ! && GET_CODE (SET_SRC (old_body)) == PLUS)) ! { ! if (! validate_change (insn, &PATTERN (insn), new_body, 0)) ! /* If recognition fails, store the new body anyway. ! It's normal to have recognition failures here ! due to bizarre memory addresses; reloading will fix them. */ ! PATTERN (insn) = new_body; ! } ! else PATTERN (insn) = new_body; if (replace && REG_NOTES (insn)) ! REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, NULL_RTX); val = 1; } *************** *** 3241,3245 **** { INITIAL_ELIMINATION_OFFSET (reg_eliminate[i].from, reg_eliminate[i].to, ! reg_eliminate[i].initial_offset) reg_eliminate[i].previous_offset = reg_eliminate[i].offset = reg_eliminate[i].initial_offset; --- 3391,3395 ---- { INITIAL_ELIMINATION_OFFSET (reg_eliminate[i].from, reg_eliminate[i].to, ! reg_eliminate[i].initial_offset); reg_eliminate[i].previous_offset = reg_eliminate[i].offset = reg_eliminate[i].initial_offset; *************** *** 3313,3317 **** XEXP (XEXP (PATTERN (insn), 0), 0) = eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0), ! GET_MODE (XEXP (PATTERN (insn), 0)), 0); /* If we need to do register elimination processing, do so. --- 3463,3467 ---- XEXP (XEXP (PATTERN (insn), 0), 0) = eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0), ! GET_MODE (XEXP (PATTERN (insn), 0)), NULL_RTX); /* If we need to do register elimination processing, do so. *************** *** 3489,3497 **** register int regno; int nr; if (GET_CODE (x) != REG) return; ! regno = REGNO (x); if (regno >= FIRST_PSEUDO_REGISTER) --- 3639,3655 ---- register int regno; int nr; + int offset = 0; + + /* note_stores does give us subregs of hard regs. */ + while (GET_CODE (x) == SUBREG) + { + offset += SUBREG_WORD (x); + x = SUBREG_REG (x); + } if (GET_CODE (x) != REG) return; ! regno = REGNO (x) + offset; if (regno >= FIRST_PSEUDO_REGISTER) *************** *** 3887,3891 **** if (noerror) return 0; ! abort (); } --- 4045,4049 ---- if (noerror) return 0; ! goto failure; } *************** *** 3930,3933 **** --- 4088,4092 ---- return 0; + failure: if (asm_noperands (PATTERN (insn)) < 0) /* It's the compiler's fault. */ *************** *** 4141,4147 **** reload_reg_used_in_op_addr); ! /* Try first with inheritance, then turning it off. */ ! for (inheritance = 1; inheritance >= 0; inheritance--) { /* Process the reloads in order of preference just found. --- 4300,4310 ---- reload_reg_used_in_op_addr); ! /* If -O, try first with inheritance, then turning it off. ! If not -O, don't do inheritance. ! Using inheritance when not optimizing leads to paradoxes ! with fp on the 68k: fp numbers (not NaNs) fail to be equal to themselves ! because one side of the comparison might be inherited. */ ! for (inheritance = optimize > 0; inheritance >= 0; inheritance--) { /* Process the reloads in order of preference just found. *************** *** 4284,4288 **** register rtx equiv = find_equiv_reg (reload_in[r], insn, reload_reg_class[r], ! -1, 0, 0, reload_mode[r]); int regno; --- 4447,4451 ---- register rtx equiv = find_equiv_reg (reload_in[r], insn, reload_reg_class[r], ! -1, NULL_PTR, 0, reload_mode[r]); int regno; *************** *** 4500,4509 **** { register int nregno = REGNO (reload_out[r]); ! int nr = HARD_REGNO_NREGS (nregno, reload_mode[r]); while (--nr >= 0) { ! reg_has_output_reload[nregno + nr] = 1; ! if (i >= 0) SET_HARD_REG_BIT (reg_is_output_reload, spill_regs[i] + nr); } --- 4663,4678 ---- { register int nregno = REGNO (reload_out[r]); ! int nr = 1; ! ! if (nregno < FIRST_PSEUDO_REGISTER) ! nr = HARD_REGNO_NREGS (nregno, reload_mode[r]); while (--nr >= 0) + reg_has_output_reload[nregno + nr] = 1; + + if (i >= 0) { ! nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode[r]); ! while (--nr >= 0) SET_HARD_REG_BIT (reg_is_output_reload, spill_regs[i] + nr); } *************** *** 4610,4618 **** if (reload_secondary_reload[j] >= 0 ! && reload_secondary_icode[j] == CODE_FOR_nothing) oldequiv = find_equiv_reg (old, insn, reload_reg_class[reload_secondary_reload[j]], ! -1, 0, 0, mode); #endif --- 4779,4788 ---- if (reload_secondary_reload[j] >= 0 ! && reload_secondary_icode[j] == CODE_FOR_nothing ! && optimize) oldequiv = find_equiv_reg (old, insn, reload_reg_class[reload_secondary_reload[j]], ! -1, NULL_PTR, 0, mode); #endif *************** *** 4625,4629 **** because we will use this equiv reg right away. */ ! if (oldequiv == 0 && (GET_CODE (old) == MEM || (GET_CODE (old) == REG --- 4795,4799 ---- because we will use this equiv reg right away. */ ! if (oldequiv == 0 && optimize && (GET_CODE (old) == MEM || (GET_CODE (old) == REG *************** *** 4631,4635 **** && reg_renumber[REGNO (old)] < 0))) oldequiv = find_equiv_reg (old, insn, GENERAL_REGS, ! -1, 0, 0, mode); if (oldequiv) --- 4801,4805 ---- && reg_renumber[REGNO (old)] < 0))) oldequiv = find_equiv_reg (old, insn, GENERAL_REGS, ! -1, NULL_PTR, 0, mode); if (oldequiv) *************** *** 4850,4855 **** else second_reload_reg ! = gen_reg_rtx (REG, new_mode, ! REGNO (second_reload_reg)); } } --- 5020,5025 ---- else second_reload_reg ! = gen_rtx (REG, new_mode, ! REGNO (second_reload_reg)); } } *************** *** 5221,5224 **** --- 5391,5423 ---- (reloadreg, second_reloadreg, third_reloadreg)); } + #ifdef SECONDARY_MEMORY_NEEDED + /* If we need a memory location to do the move, do it that way. */ + else if (GET_CODE (reloadreg) == REG + && REGNO (reloadreg) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (reloadreg)), + REGNO_REG_CLASS (REGNO (second_reloadreg)), + GET_MODE (second_reloadreg))) + { + /* Get the memory to use and rewrite both registers + to its mode. */ + rtx loc = get_secondary_mem (reloadreg, + GET_MODE (second_reloadreg)); + rtx tmp_reloadreg; + + if (GET_MODE (loc) != GET_MODE (second_reloadreg)) + second_reloadreg = gen_rtx (REG, GET_MODE (loc), + REGNO (second_reloadreg)); + + if (GET_MODE (loc) != GET_MODE (reloadreg)) + tmp_reloadreg = gen_rtx (REG, GET_MODE (loc), + REGNO (reloadreg)); + else + tmp_reloadreg = reloadreg; + + emit_insn_before (gen_move_insn (loc, second_reloadreg), + first_output_reload_insn); + pat = gen_move_insn (tmp_reloadreg, loc); + } + #endif else pat = gen_move_insn (reloadreg, second_reloadreg); *************** *** 5232,5237 **** /* Output the last reload insn. */ if (! special) ! emit_insn_before (gen_move_insn (old, reloadreg), ! first_output_reload_insn); #ifdef PRESERVE_DEATH_INFO_REGNO_P --- 5431,5463 ---- /* Output the last reload insn. */ if (! special) ! { ! #ifdef SECONDARY_MEMORY_NEEDED ! /* If we need a memory location to do the move, do it that way. */ ! if (GET_CODE (old) == REG && REGNO (old) < FIRST_PSEUDO_REGISTER ! && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (old)), ! REGNO_REG_CLASS (REGNO (reloadreg)), ! GET_MODE (reloadreg))) ! { ! /* Get the memory to use and rewrite both registers to ! its mode. */ ! rtx loc = get_secondary_mem (old, GET_MODE (reloadreg)); ! ! if (GET_MODE (loc) != GET_MODE (reloadreg)) ! reloadreg = gen_rtx (REG, GET_MODE (loc), ! REGNO (reloadreg)); ! ! if (GET_MODE (loc) != GET_MODE (old)) ! old = gen_rtx (REG, GET_MODE (loc), REGNO (old)); ! ! emit_insn_before (gen_move_insn (loc, reloadreg), ! first_output_reload_insn); ! emit_insn_before (gen_move_insn (old, loc), ! first_output_reload_insn); ! } ! else ! #endif ! emit_insn_before (gen_move_insn (old, reloadreg), ! first_output_reload_insn); ! } #ifdef PRESERVE_DEATH_INFO_REGNO_P *************** *** 5482,5486 **** It might be better not to actually emit the insn unless it is valid, but we need to pass the insn as an operand to `recog' and ! `insn_extract'and it is simpler to emit and then delete the insn if not valid than to dummy things up. */ --- 5708,5712 ---- It might be better not to actually emit the insn unless it is valid, but we need to pass the insn as an operand to `recog' and ! `insn_extract' and it is simpler to emit and then delete the insn if not valid than to dummy things up. */ *************** *** 5539,5545 **** --- 5765,5800 ---- emit_insn_before (gen_move_insn (reloadreg, op0), before_insn); + + /* If OP0 and OP1 are the same, we can use RELOADREG for OP1. + This fixes a problem on the 32K where the stack pointer cannot + be used as an operand of an add insn. */ + + if (rtx_equal_p (op0, op1)) + op1 = reloadreg; + emit_insn_before (gen_add2_insn (reloadreg, op1), before_insn); } + #ifdef SECONDARY_MEMORY_NEEDED + /* If we need a memory location to do the move, do it that way. */ + else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)), + REGNO_REG_CLASS (REGNO (reloadreg)), + GET_MODE (reloadreg))) + { + /* Get the memory to use and rewrite both registers to its mode. */ + rtx loc = get_secondary_mem (in, GET_MODE (reloadreg)); + + if (GET_MODE (loc) != GET_MODE (reloadreg)) + reloadreg = gen_rtx (REG, GET_MODE (loc), REGNO (reloadreg)); + + if (GET_MODE (loc) != GET_MODE (in)) + in = gen_rtx (REG, GET_MODE (loc), REGNO (in)); + + emit_insn_before (gen_move_insn (loc, in), before_insn); + emit_insn_before (gen_move_insn (reloadreg, loc), before_insn); + } + #endif + /* If IN is a simple operand, use gen_move_insn. */ else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG) *************** *** 5659,5663 **** /* Output reload-insns to reload VALUE into RELOADREG. ! VALUE is a autoincrement or autodecrement RTX whose operand is a register or memory location; so reloading involves incrementing that location. --- 5914,5918 ---- /* Output reload-insns to reload VALUE into RELOADREG. ! VALUE is an autoincrement or autodecrement RTX whose operand is a register or memory location; so reloading involves incrementing that location. *************** *** 5696,5700 **** inc_amount = - inc_amount; ! inc = gen_rtx (CONST_INT, VOIDmode, inc_amount); /* If this is post-increment, first copy the location to the reload reg. */ --- 5951,5955 ---- inc_amount = - inc_amount; ! inc = GEN_INT (inc_amount); /* If this is post-increment, first copy the location to the reload reg. */ *************** *** 5754,5760 **** emit_insn_before (gen_add2_insn (reloadreg, inc), insn); emit_insn_before (gen_move_insn (incloc, reloadreg), insn); ! emit_insn_before (gen_add2_insn (reloadreg, ! gen_rtx (CONST_INT, VOIDmode, ! -inc_amount)), insn); } --- 6009,6013 ---- emit_insn_before (gen_add2_insn (reloadreg, inc), insn); emit_insn_before (gen_move_insn (incloc, reloadreg), insn); ! emit_insn_before (gen_add2_insn (reloadreg, GEN_INT (-inc_amount)), insn); } diff -rc2N gcc-2.2.2/reorg.c gcc-2.3.1/reorg.c *** gcc-2.2.2/reorg.c Sun Jun 7 17:08:20 1992 --- gcc-2.3.1/reorg.c Wed Oct 14 18:16:54 1992 *************** *** 20,28 **** the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - - #include "insn-attr.h" - - #ifdef DELAY_SLOTS - /* Instruction reorganization pass. --- 20,23 ---- *************** *** 76,80 **** `fill_eager_delay_slots' tries to guess the direction the branch will go; if it guesses right 100% of the time, it can reduce the ! branch penalty as much as `fill_eager_delay_slots' does. If it guesses wrong 100% of the time, it might as well schedule nops (or on the m88k, unexpose the branch slot). When --- 71,75 ---- `fill_eager_delay_slots' tries to guess the direction the branch will go; if it guesses right 100% of the time, it can reduce the ! branch penalty as much as `fill_simple_delay_slots' does. If it guesses wrong 100% of the time, it might as well schedule nops (or on the m88k, unexpose the branch slot). When *************** *** 126,136 **** #include "output.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - #ifndef ANNUL_IFTRUE_SLOTS #define eligible_for_annul_true(INSN, SLOTS, TRIAL) 0 --- 121,131 ---- #include "output.h" #include "obstack.h" + #include "insn-attr.h" + + #ifdef DELAY_SLOTS #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free #ifndef ANNUL_IFTRUE_SLOTS #define eligible_for_annul_true(INSN, SLOTS, TRIAL) 0 *************** *** 171,174 **** --- 166,172 ---- CLEAR_HARD_REG_SET ((RES)->regs); } while (0) + /* Indicates what resources are required at the beginning of the epilogue. */ + static struct resources start_of_epilogue_needs; + /* Indicates what resources are required at function end. */ static struct resources end_of_function_needs; *************** *** 398,405 **** } ! /* Given an insn, INSN, and a pointer to a `struct resource', RES, indicate ! which resources are modified by the insn. If INCLUDE_CALLED_ROUTINE ! is TRUE, also mark resources potentially set by the called routine. We never mark the insn as modifying the condition code unless it explicitly SETs CC0 even though this is not totally correct. The reason for this is --- 396,406 ---- } ! /* Given X, a part of an insn, and a pointer to a `struct resource', RES, ! indicate which resources are modified by the insn. If INCLUDE_CALLED_ROUTINE ! is nonzero, also mark resources potentially set by the called routine. + If IN_DEST is nonzero, it means we are inside a SET. Otherwise, + objects are being referenced instead of set. + We never mark the insn as modifying the condition code unless it explicitly SETs CC0 even though this is not totally correct. The reason for this is *************** *** 409,427 **** static void ! mark_set_resources (insn, res, include_called_routine) ! register rtx insn; register struct resources *res; int include_called_routine; { ! register int i; ! switch (GET_CODE (insn)) { case NOTE: case BARRIER: case CODE_LABEL: /* These don't set any resources. */ return; case CALL_INSN: /* Called routine modifies the condition code, memory, any registers --- 410,447 ---- static void ! mark_set_resources (x, res, in_dest, include_called_routine) ! register rtx x; register struct resources *res; + int in_dest; int include_called_routine; { ! register enum rtx_code code; ! register int i, j; ! register char *format_ptr; ! restart: ! ! code = GET_CODE (x); ! ! switch (code) { case NOTE: case BARRIER: case CODE_LABEL: + case USE: + case CONST_INT: + case CONST_DOUBLE: + case LABEL_REF: + case SYMBOL_REF: + case CONST: + case PC: /* These don't set any resources. */ return; + case CC0: + if (in_dest) + res->cc = 1; + return; + case CALL_INSN: /* Called routine modifies the condition code, memory, any registers *************** *** 431,435 **** if (include_called_routine) { ! rtx next = NEXT_INSN (insn); res->cc = res->memory = 1; --- 451,455 ---- if (include_called_routine) { ! rtx next = NEXT_INSN (x); res->cc = res->memory = 1; *************** *** 445,449 **** && GET_CODE (PATTERN (next)) == CLOBBER); next = NEXT_INSN (next)) ! mark_referenced_resources (XEXP (PATTERN (next), 0), res, 0); } --- 465,469 ---- && GET_CODE (PATTERN (next)) == CLOBBER); next = NEXT_INSN (next)) ! mark_set_resources (XEXP (PATTERN (next), 0), res, 1, 0); } *************** *** 452,508 **** case JUMP_INSN: case INSN: - { - register rtx body = PATTERN (insn); - register rtx note; ! /* An insn consisting of just a CLOBBER (or USE) is ! just for flow and doesn't actually do anything, so we don't check ! for it. ! ! If the source of a SET is a CALL, this is actually done by ! the called routine. So only include it if we are to include the ! effects of the calling routine. */ ! ! if (GET_CODE (body) == SET ! && (include_called_routine || GET_CODE (SET_SRC (body)) != CALL)) ! mark_referenced_resources (SET_DEST (body), res, 0); ! else if (GET_CODE (body) == PARALLEL) ! { ! for (i = 0; i < XVECLEN (body, 0); i++) ! if ((GET_CODE (XVECEXP (body, 0, i)) == SET ! && (include_called_routine ! || GET_CODE (SET_SRC (XVECEXP (body, 0, i))) != CALL)) ! || GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) ! mark_referenced_resources (SET_DEST (XVECEXP (body, 0, i)), ! res, 0); ! } ! else if (GET_CODE (body) == SEQUENCE) ! for (i = 0; i < XVECLEN (body, 0); i++) ! if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0)) ! && INSN_FROM_TARGET_P (XVECEXP (body, 0, i)))) ! mark_set_resources (XVECEXP (body, 0, i), res, ! include_called_routine); ! ! #ifdef AUTO_INC_DEC ! /* If any register are incremented or decremented in an address, ! they are set here. */ ! for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) ! if (REG_NOTE_KIND (note) == REG_INC) ! mark_referenced_resources (XEXP (note, 0), res, 0); ! #endif ! ! #ifdef PUSH_ROUNDING ! /* An insn that has a PRE_DEC on SP will not have a REG_INC note. ! Until we fix this correctly, consider all insns as modifying ! SP on such machines. So far, we don't have delay slot scheduling ! on any machines with PUSH_ROUNDING. */ ! SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM); ! #endif ! return; ! } ! default: ! abort (); } } --- 472,554 ---- case JUMP_INSN: case INSN: ! /* An insn consisting of just a CLOBBER (or USE) is just for flow ! and doesn't actually do anything, so we ignore it. */ ! x = PATTERN (x); ! if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER) ! goto restart; ! return; ! ! case SET: ! /* If the source of a SET is a CALL, this is actually done by ! the called routine. So only include it if we are to include the ! effects of the calling routine. */ ! ! mark_set_resources (SET_DEST (x), res, ! (include_called_routine ! || GET_CODE (SET_SRC (x)) != CALL), ! 0); ! ! mark_set_resources (SET_SRC (x), res, 0, 0); ! return; ! ! case CLOBBER: ! mark_set_resources (XEXP (x, 0), res, 1, 0); ! return; ! ! case SEQUENCE: ! for (i = 0; i < XVECLEN (x, 0); i++) ! if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0)) ! && INSN_FROM_TARGET_P (XVECEXP (x, 0, i)))) ! mark_set_resources (XVECEXP (x, 0, i), res, 0, ! include_called_routine); ! return; ! ! case POST_INC: ! case PRE_INC: ! case POST_DEC: ! case PRE_DEC: ! mark_set_resources (XEXP (x, 0), res, 1, 0); ! return; ! ! case ZERO_EXTRACT: ! mark_set_resources (XEXP (x, 0), res, in_dest, 0); ! mark_set_resources (XEXP (x, 1), res, 0, 0); ! mark_set_resources (XEXP (x, 2), res, 0, 0); ! return; ! ! case MEM: ! if (in_dest) ! { ! res->memory = 1; ! res->volatil = MEM_VOLATILE_P (x); ! } ! ! mark_set_resources (XEXP (x, 0), res, 0, 0); ! return; ! ! case REG: ! if (in_dest) ! for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++) ! SET_HARD_REG_BIT (res->regs, REGNO (x) + i); ! return; } + + /* Process each sub-expression and flag what it needs. */ + format_ptr = GET_RTX_FORMAT (code); + for (i = 0; i < GET_RTX_LENGTH (code); i++) + switch (*format_ptr++) + { + case 'e': + mark_set_resources (XEXP (x, i), res, in_dest, include_called_routine); + break; + + case 'E': + for (j = 0; j < XVECLEN (x, i); j++) + mark_set_resources (XVECEXP (x, i, j), res, in_dest, + include_called_routine); + break; + } } *************** *** 605,609 **** CLEAR_RESOURCE (&insn_sets); ! mark_set_resources (insn, &insn_sets, include_called_routine); return resource_conflicts_p (&insn_sets, res); } --- 651,655 ---- CLEAR_RESOURCE (&insn_sets); ! mark_set_resources (insn, &insn_sets, 0, include_called_routine); return resource_conflicts_p (&insn_sets, res); } *************** *** 772,776 **** /* If we have an empty list, just make a new list element. */ if (delay_list == 0) ! return gen_rtx (INSN_LIST, VOIDmode, insn, 0); /* Otherwise this must be an INSN_LIST. Add INSN to the end of the --- 818,822 ---- /* If we have an empty list, just make a new list element. */ if (delay_list == 0) ! return gen_rtx (INSN_LIST, VOIDmode, insn, NULL_RTX); /* Otherwise this must be an INSN_LIST. Add INSN to the end of the *************** *** 851,855 **** if (reg_mentioned_p (cc0_rtx, insn)) { ! rtx note = find_reg_note (insn, REG_CC_SETTER, 0); /* If a reg-note was found, it points to an insn to set CC0. This --- 897,901 ---- if (reg_mentioned_p (cc0_rtx, insn)) { ! rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); /* If a reg-note was found, it points to an insn to set CC0. This *************** *** 858,862 **** if (note) { ! if (! FIND_REG_INC_NOTE (XEXP (note, 0), 0) && sets_cc0_p (PATTERN (XEXP (note, 0))) == 1) delete_from_delay_slot (XEXP (note, 0)); --- 904,908 ---- if (note) { ! if (! FIND_REG_INC_NOTE (XEXP (note, 0), NULL_RTX) && sets_cc0_p (PATTERN (XEXP (note, 0))) == 1) delete_from_delay_slot (XEXP (note, 0)); *************** *** 978,982 **** } ! delay_list = add_to_delay_list (trial, 0); next_trial = next_active_insn (trial); update_block (trial, trial); --- 1024,1028 ---- } ! delay_list = add_to_delay_list (trial, NULL_RTX); next_trial = next_active_insn (trial); update_block (trial, trial); *************** *** 1116,1119 **** --- 1162,1167 ---- GET_MODE (XEXP (src, 0)), XEXP (XEXP (src, 0), 0), XEXP (XEXP (src, 0), 1)); + + return 0; } *************** *** 1207,1211 **** /* If TRIAL sets CC0, we can't copy it, so we can't steal this delay list. */ ! || find_reg_note (trial, REG_CC_USER, 0) #endif /* If TRIAL is from the fallthrough code of an annulled branch insn --- 1255,1259 ---- /* If TRIAL sets CC0, we can't copy it, so we can't steal this delay list. */ ! || find_reg_note (trial, REG_CC_USER, NULL_RTX) #endif /* If TRIAL is from the fallthrough code of an annulled branch insn *************** *** 1406,1410 **** } ! mark_set_resources (trial, &set, 1); mark_referenced_resources (trial, &needed, 1); } --- 1454,1458 ---- } ! mark_set_resources (trial, &set, 0, 1); mark_referenced_resources (trial, &needed, 1); } *************** *** 1553,1557 **** CLEAR_RESOURCE (&needed); CLEAR_RESOURCE (&set); ! mark_set_resources (insn, &set, 1); mark_referenced_resources (insn, &needed, 1); --- 1601,1605 ---- CLEAR_RESOURCE (&needed); CLEAR_RESOURCE (&set); ! mark_set_resources (insn, &set, 0, 1); mark_referenced_resources (insn, &needed, 1); *************** *** 1887,1890 **** --- 1935,1939 ---- rtx insn, next; rtx jump_insn = 0; + rtx jump_target; HARD_REG_SET scratch; struct resources set, needed; *************** *** 1948,1952 **** { regset regs_live = basic_block_live_at_start[b]; ! int offset, bit, j; int regno; rtx start_insn, stop_insn; --- 1997,2002 ---- { regset regs_live = basic_block_live_at_start[b]; ! int offset, j; ! REGSET_ELT_TYPE bit; int regno; rtx start_insn, stop_insn; *************** *** 1965,1969 **** { if (regs_live[offset] == 0) ! i += HOST_BITS_PER_INT; else for (bit = 1; bit && i < max_regno; bit <<= 1, i++) --- 2015,2019 ---- { if (regs_live[offset] == 0) ! i += REGSET_ELT_BITS; else for (bit = 1; bit && i < max_regno; bit <<= 1, i++) *************** *** 2005,2011 **** underlying insn. */ if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE ! && (GET_CODE (XEXP (PATTERN (insn), 0)) == INSN ! || GET_CODE (XEXP (PATTERN (insn), 0)) == CALL_INSN ! || GET_CODE (XEXP (PATTERN (insn), 0)) == JUMP_INSN)) real_insn = XEXP (PATTERN (insn), 0); --- 2055,2059 ---- underlying insn. */ if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE ! && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i') real_insn = XEXP (PATTERN (insn), 0); *************** *** 2080,2084 **** } ! if (GET_CODE (real_insn) == CODE_LABEL) { /* A label clobbers the pending dead registers since neither --- 2128,2132 ---- } ! else if (GET_CODE (real_insn) == CODE_LABEL) { /* A label clobbers the pending dead registers since neither *************** *** 2087,2090 **** --- 2135,2145 ---- CLEAR_HARD_REG_SET (pending_dead_regs); } + + /* The beginning of the epilogue corresponds to the end of the + RTL chain when there are no epilogue insns. Certain resources + are implicitly required at that point. */ + else if (GET_CODE (real_insn) == NOTE + && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG) + IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs); } *************** *** 2108,2112 **** for (insn = target; insn; insn = next) { ! rtx main_insn = insn; next = NEXT_INSN (insn); --- 2163,2167 ---- for (insn = target; insn; insn = next) { ! rtx this_jump_insn = insn; next = NEXT_INSN (insn); *************** *** 2124,2143 **** case INSN: ! if (GET_CODE (PATTERN (insn)) == USE ! || GET_CODE (PATTERN (insn)) == CLOBBER) continue; ! if (GET_CODE (PATTERN (insn)) == SEQUENCE) ! main_insn = XVECEXP (PATTERN (insn), 0, 0); } ! if (GET_CODE (main_insn) == JUMP_INSN) { if (jump_count++ < 10 ! && (simplejump_p (main_insn) ! || GET_CODE (PATTERN (main_insn)) == RETURN)) { ! next = next_active_insn (JUMP_LABEL (main_insn)); if (jump_insn == 0) ! jump_insn = insn; } else --- 2179,2220 ---- case INSN: ! if (GET_CODE (PATTERN (insn)) == USE) ! { ! /* If INSN is a USE made by update_block, we care about the ! underlying insn. Any registers set by the underlying insn ! are live since the insn is being done somewhere else. */ ! if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i') ! mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1); ! ! /* All other USE insns are to be ignored. */ ! continue; ! } ! else if (GET_CODE (PATTERN (insn)) == CLOBBER) continue; ! else if (GET_CODE (PATTERN (insn)) == SEQUENCE) ! { ! /* An unconditional jump can be used to fill the delay slot ! of a call, so search for a JUMP_INSN in any position. */ ! for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) ! { ! this_jump_insn = XVECEXP (PATTERN (insn), 0, i); ! if (GET_CODE (this_jump_insn) == JUMP_INSN) ! break; ! } ! } } ! if (GET_CODE (this_jump_insn) == JUMP_INSN) { if (jump_count++ < 10 ! && (simplejump_p (this_jump_insn) ! || GET_CODE (PATTERN (this_jump_insn)) == RETURN)) { ! next = next_active_insn (JUMP_LABEL (this_jump_insn)); if (jump_insn == 0) ! { ! jump_insn = insn; ! jump_target = JUMP_LABEL (this_jump_insn); ! } } else *************** *** 2146,2150 **** mark_referenced_resources (insn, &needed, 1); ! mark_set_resources (insn, &set, 1); COPY_HARD_REG_SET (scratch, set.regs); --- 2223,2227 ---- mark_referenced_resources (insn, &needed, 1); ! mark_set_resources (insn, &set, 0, 1); COPY_HARD_REG_SET (scratch, set.regs); *************** *** 2163,2169 **** if (jump_insn && jump_count < 10) { - rtx jump_target = (GET_CODE (jump_insn) == INSN - ? JUMP_LABEL (XVECEXP (PATTERN (jump_insn), 0, 0)) - : JUMP_LABEL (jump_insn)); struct resources new_resources; rtx stop_insn = next_active_insn (jump_insn); --- 2240,2243 ---- *************** *** 2182,2186 **** IOR_HARD_REG_SET (new_resources.regs, scratch); ! mark_set_resources (insn, &set, 1); } --- 2256,2260 ---- IOR_HARD_REG_SET (new_resources.regs, scratch); ! mark_set_resources (insn, &set, 0, 1); } *************** *** 2210,2214 **** { register rtx insn, pat, trial, next_trial; ! register int i; int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base; struct resources needed, set; --- 2284,2288 ---- { register rtx insn, pat, trial, next_trial; ! register int i, j; int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base; struct resources needed, set; *************** *** 2235,2242 **** /* This insn needs, or can use, some delay slots. SLOTS_TO_FILL ! says how many. After initialization, scan backwards from the ! insn to search for a potential delay-slot candidate. Stop ! searching when a label or jump is hit. ! For each candidate, if it is to go into the delay slot (moved forward in execution sequence), it must not need or set any resources --- 2309,2354 ---- /* This insn needs, or can use, some delay slots. SLOTS_TO_FILL ! says how many. After initialization, first try optimizing ! ! call _foo call _foo ! nop add %o7,.-L1,%o7 ! b,a L1 ! nop ! ! If this case applies, the delay slot of the call is filled with ! the unconditional jump. This is done first to avoid having the ! delay slot of the call filled in the backward scan. Also, since ! the unconditional jump is likely to also have a delay slot, that ! insn must exist when it is subsequently scanned. */ ! ! slots_filled = 0; ! delay_list = 0; ! ! if (GET_CODE (insn) == CALL_INSN ! && (trial = next_active_insn (insn)) ! && GET_CODE (trial) == JUMP_INSN ! && simplejump_p (trial) ! && eligible_for_delay (insn, slots_filled, trial) ! && no_labels_between_p (insn, trial)) ! { ! slots_filled++; ! delay_list = add_to_delay_list (trial, delay_list); ! /* Remove the unconditional jump from consideration for delay slot ! filling and unthread it. */ ! if (unfilled_slots_base[i + 1] == trial) ! unfilled_slots_base[i + 1] = 0; ! { ! rtx next = NEXT_INSN (trial); ! rtx prev = PREV_INSN (trial); ! if (prev) ! NEXT_INSN (prev) = next; ! if (next) ! PREV_INSN (next) = prev; ! } ! } ! ! /* Now, scan backwards from the insn to search for a potential ! delay-slot candidate. Stop searching when a label or jump is hit. ! For each candidate, if it is to go into the delay slot (moved forward in execution sequence), it must not need or set any resources *************** *** 2248,2314 **** the setting). */ ! slots_filled = 0; ! delay_list = 0; ! CLEAR_RESOURCE (&needed); ! CLEAR_RESOURCE (&set); ! mark_set_resources (insn, &set, 0); ! mark_referenced_resources (insn, &needed, 0); ! ! for (trial = prev_nonnote_insn (insn); ! stop_search_p (trial, 1); ! trial = next_trial) { ! next_trial = prev_nonnote_insn (trial); ! /* This must be an INSN or CALL_INSN. */ ! pat = PATTERN (trial); ! /* USE and CLOBBER at this level was just for flow; ignore it. */ ! if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) ! continue; ! /* Check for resource conflict first, to avoid unnecessary ! splitting. */ ! if (! insn_references_resource_p (trial, &set, 1) ! && ! insn_sets_resource_p (trial, &set, 1) ! && ! insn_sets_resource_p (trial, &needed, 1) #ifdef HAVE_cc0 ! /* Can't separate set of cc0 from its use. */ ! && ! (reg_mentioned_p (cc0_rtx, pat) ! && ! sets_cc0_p (cc0_rtx, pat)) #endif ! ) ! { ! trial = try_split (pat, trial, 1); ! next_trial = prev_nonnote_insn (trial); ! if (eligible_for_delay (insn, slots_filled, trial)) { ! /* In this case, we are searching backward, so if we ! find insns to put on the delay list, we want ! to put them at the head, rather than the ! tail, of the list. */ ! ! delay_list = gen_rtx (INSN_LIST, VOIDmode, ! trial, delay_list); ! update_block (trial, trial); ! delete_insn (trial); ! if (slots_to_fill == ++slots_filled) ! break; ! continue; } - } ! mark_set_resources (trial, &set, 1); ! mark_referenced_resources (trial, &needed, 1); } - if (slots_filled == slots_to_fill) - /* happy. */ ; - /* If all needed slots haven't been filled, we come here. */ /* Try to optimize case of jumping around a single insn. */ #if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS) ! else if (delay_list == 0 ! && GET_CODE (insn) == JUMP_INSN && condjump_p (insn)) { delay_list = optimize_skip (insn); --- 2360,2425 ---- the setting). */ ! if (slots_filled < slots_to_fill) { ! CLEAR_RESOURCE (&needed); ! CLEAR_RESOURCE (&set); ! mark_set_resources (insn, &set, 0, 0); ! mark_referenced_resources (insn, &needed, 0); ! for (trial = prev_nonnote_insn (insn); ! stop_search_p (trial, 1); ! trial = next_trial) ! { ! next_trial = prev_nonnote_insn (trial); ! /* This must be an INSN or CALL_INSN. */ ! pat = PATTERN (trial); ! ! /* USE and CLOBBER at this level was just for flow; ignore it. */ ! if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) ! continue; ! /* Check for resource conflict first, to avoid unnecessary ! splitting. */ ! if (! insn_references_resource_p (trial, &set, 1) ! && ! insn_sets_resource_p (trial, &set, 1) ! && ! insn_sets_resource_p (trial, &needed, 1) #ifdef HAVE_cc0 ! /* Can't separate set of cc0 from its use. */ ! && ! (reg_mentioned_p (cc0_rtx, pat) ! && ! sets_cc0_p (cc0_rtx, pat)) #endif ! ) { ! trial = try_split (pat, trial, 1); ! next_trial = prev_nonnote_insn (trial); ! if (eligible_for_delay (insn, slots_filled, trial)) ! { ! /* In this case, we are searching backward, so if we ! find insns to put on the delay list, we want ! to put them at the head, rather than the ! tail, of the list. */ ! ! delay_list = gen_rtx (INSN_LIST, VOIDmode, ! trial, delay_list); ! update_block (trial, trial); ! delete_insn (trial); ! if (slots_to_fill == ++slots_filled) ! break; ! continue; ! } } ! mark_set_resources (trial, &set, 0, 1); ! mark_referenced_resources (trial, &needed, 1); ! } } /* If all needed slots haven't been filled, we come here. */ /* Try to optimize case of jumping around a single insn. */ #if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS) ! if (slots_filled != slots_to_fill ! && delay_list == 0 ! && GET_CODE (insn) == JUMP_INSN && condjump_p (insn)) { delay_list = optimize_skip (insn); *************** *** 2318,2330 **** #endif - /* @@ This would be a good place to optimize: - - call _foo call _foo - nop add %o7,.-L1,%o7 - b,a L1 - nop - - Someday... */ - /* Try to get insns from beyond the insn needing the delay slot. These insns can neither set or reference resources set in insns being --- 2429,2432 ---- *************** *** 2342,2348 **** care about the number of uses of our label. */ ! else if (GET_CODE (insn) != JUMP_INSN ! || (condjump_p (insn) && ! simplejump_p (insn) ! && JUMP_LABEL (insn) != 0)) { rtx target = 0; --- 2444,2451 ---- care about the number of uses of our label. */ ! if (slots_filled != slots_to_fill ! && (GET_CODE (insn) != JUMP_INSN ! || (condjump_p (insn) && ! simplejump_p (insn) ! && JUMP_LABEL (insn) != 0))) { rtx target = 0; *************** *** 2357,2370 **** if (GET_CODE (insn) == CALL_INSN) { ! mark_set_resources (insn, &set, 1); mark_referenced_resources (insn, &needed, 1); maybe_never = 1; } ! else if (GET_CODE (insn) == JUMP_INSN) { ! /* Get our target and show how many more uses we want to ! see before we hit the label. */ ! target = JUMP_LABEL (insn); ! target_uses = LABEL_NUSES (target) - 1; } --- 2460,2479 ---- if (GET_CODE (insn) == CALL_INSN) { ! mark_set_resources (insn, &set, 0, 1); mark_referenced_resources (insn, &needed, 1); maybe_never = 1; } ! else { ! mark_set_resources (insn, &set, 0, 0); ! mark_referenced_resources (insn, &needed, 0); ! if (GET_CODE (insn) == JUMP_INSN) ! { ! /* Get our target and show how many more uses we want to ! see before we hit the label. */ ! target = JUMP_LABEL (insn); ! target_uses = LABEL_NUSES (target) - 1; ! } ! } *************** *** 2457,2461 **** } ! mark_set_resources (trial, &set, 1); mark_referenced_resources (trial, &needed, 1); --- 2566,2570 ---- } ! mark_set_resources (trial, &set, 0, 1); mark_referenced_resources (trial, &needed, 1); *************** *** 2486,2491 **** && ! insn_sets_resource_p (next_trial, &needed, 1) #ifdef HAVE_cc0 ! && ! (reg_mentioned_p (cc0_rtx, PATTERN (next_trial)) ! && ! sets_cc0_p (PATTERN (next_trial))) #endif && ! (maybe_never && may_trap_p (PATTERN (next_trial))) --- 2595,2599 ---- && ! insn_sets_resource_p (next_trial, &needed, 1) #ifdef HAVE_cc0 ! && ! reg_mentioned_p (cc0_rtx, PATTERN (next_trial)) #endif && ! (maybe_never && may_trap_p (PATTERN (next_trial))) *************** *** 2576,2580 **** } ! mark_set_resources (trial, &set, 1); mark_referenced_resources (trial, &needed, 1); } --- 2684,2688 ---- } ! mark_set_resources (trial, &set, 0, 1); mark_referenced_resources (trial, &needed, 1); } *************** *** 2786,2790 **** /* This insn can't go into a delay slot. */ lose = 1; ! mark_set_resources (trial, &set, 1); mark_referenced_resources (trial, &needed, 1); --- 2894,2898 ---- /* This insn can't go into a delay slot. */ lose = 1; ! mark_set_resources (trial, &set, 0, 1); mark_referenced_resources (trial, &needed, 1); *************** *** 2907,2911 **** INSN_FROM_TARGET_P (ninsn) = 1; ! delay_list = add_to_delay_list (ninsn, 0); (*pslots_filled)++; } --- 3015,3019 ---- INSN_FROM_TARGET_P (ninsn) = 1; ! delay_list = add_to_delay_list (ninsn, NULL_RTX); (*pslots_filled)++; } *************** *** 2928,2932 **** && (simplejump_p (new_thread) || GET_CODE (PATTERN (new_thread)) == RETURN)) ! new_thread = follow_jumps (JUMP_LABEL (new_thread), 1); if (new_thread == 0) --- 3036,3040 ---- && (simplejump_p (new_thread) || GET_CODE (PATTERN (new_thread)) == RETURN)) ! new_thread = follow_jumps (JUMP_LABEL (new_thread)); if (new_thread == 0) *************** *** 3004,3008 **** { fallthrough_insn = next_active_insn (insn); ! own_fallthrough = own_thread_p (NEXT_INSN (insn), 0, 1); prediction = mostly_true_jump (insn, condition); } --- 3112,3116 ---- { fallthrough_insn = next_active_insn (insn); ! own_fallthrough = own_thread_p (NEXT_INSN (insn), NULL_RTX, 1); prediction = mostly_true_jump (insn, condition); } *************** *** 3089,3093 **** && (target_label = JUMP_LABEL (insn)) != 0) { ! target_label = follow_jumps (target_label, 1); target_label = prev_label (next_active_insn (target_label)); --- 3197,3201 ---- && (target_label = JUMP_LABEL (insn)) != 0) { ! target_label = follow_jumps (target_label); target_label = prev_label (next_active_insn (target_label)); *************** *** 3201,3205 **** /* If this jump goes to another unconditional jump, thread it, but don't convert a jump into a RETURN here. */ ! trial = follow_jumps (target_label, 1); trial = prev_label (next_active_insn (trial)); if (trial == 0 && target_label != 0) --- 3309,3313 ---- /* If this jump goes to another unconditional jump, thread it, but don't convert a jump into a RETURN here. */ ! trial = follow_jumps (target_label); trial = prev_label (next_active_insn (trial)); if (trial == 0 && target_label != 0) *************** *** 3254,3258 **** but it doesn't seem worthwhile in this uncommon case. */ && ! find_reg_note (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1), ! REG_CC_USER, 0) #endif ) --- 3362,3366 ---- but it doesn't seem worthwhile in this uncommon case. */ && ! find_reg_note (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1), ! REG_CC_USER, NULL_RTX) #endif ) *************** *** 3375,3379 **** /* If we can't make the jump into a RETURN, redirect it to the best RETURN and go on to the next insn. */ ! if (! redirect_jump (jump_insn, 0)) { redirect_jump (jump_insn, real_return_label); --- 3483,3487 ---- /* If we can't make the jump into a RETURN, redirect it to the best RETURN and go on to the next insn. */ ! if (! redirect_jump (jump_insn, NULL_RTX)) { redirect_jump (jump_insn, real_return_label); *************** *** 3452,3456 **** FILE *file; { ! rtx insn, next; int i; #if 0 --- 3560,3564 ---- FILE *file; { ! rtx insn, next, epilogue_insn = 0; int i; #if 0 *************** *** 3469,3474 **** INSN_UID's to position in code. */ for (max_uid = 0, insn = first; insn; insn = NEXT_INSN (insn)) ! if (INSN_UID (insn) > max_uid) ! max_uid = INSN_UID (insn); uid_to_ruid = (int *) alloca ((max_uid + 1) * sizeof (int *)); --- 3577,3587 ---- INSN_UID's to position in code. */ for (max_uid = 0, insn = first; insn; insn = NEXT_INSN (insn)) ! { ! if (INSN_UID (insn) > max_uid) ! max_uid = INSN_UID (insn); ! if (GET_CODE (insn) == NOTE ! && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) ! epilogue_insn = insn; ! } uid_to_ruid = (int *) alloca ((max_uid + 1) * sizeof (int *)); *************** *** 3538,3541 **** --- 3651,3676 ---- SET_HARD_REG_BIT (end_of_function_needs.regs, i); + /* The registers required to be live at the end of the function are + represented in the flow information as being dead just prior to + reaching the end of the function. For example, the return of a value + might be represented by a USE of the return register immediately + followed by an unconditional jump to the return label where the + return label is the end of the RTL chain. The end of the RTL chain + is then taken to mean that the return register is live. + + This sequence is no longer maintained when epilogue instructions are + added to the RTL chain. To reconstruct the original meaning, the + start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the + point where these registers become live (start_of_epilogue_needs). + If epilogue instructions are present, the registers set by those + instructions won't have been processed by flow. Thus, those + registers are additionally required at the end of the RTL chain + (end_of_function_needs). */ + + start_of_epilogue_needs = end_of_function_needs; + + while (epilogue_insn = next_nonnote_insn (epilogue_insn)) + mark_set_resources (epilogue_insn, &end_of_function_needs, 0, 0); + /* Show we haven't computed an end-of-function label yet. */ end_of_function_label = 0; *************** *** 3574,3580 **** if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE ! && (GET_CODE (XEXP (PATTERN (insn), 0)) == INSN ! || GET_CODE (XEXP (PATTERN (insn), 0)) == JUMP_INSN ! || GET_CODE (XEXP (PATTERN (insn), 0)) == CALL_INSN)) next = delete_insn (insn); } --- 3709,3713 ---- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE ! && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i') next = delete_insn (insn); } *************** *** 3595,3598 **** --- 3728,3735 ---- /* It is not clear why the line below is needed, but it does seem to be. */ unfilled_firstobj = (rtx *) obstack_alloc (&unfilled_slots_obstack, 0); + + /* Reposition the prologue and epilogue notes in case we moved the + prologue/epilogue insns. */ + reposition_prologue_and_epilogue_notes (first); if (file) diff -rc2N gcc-2.2.2/rtl.c gcc-2.3.1/rtl.c *** gcc-2.2.2/rtl.c Wed May 13 18:27:52 1992 --- gcc-2.3.1/rtl.c Sat Sep 19 15:33:11 1992 *************** *** 27,32 **** #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); /* Obstack used for allocating RTL objects. --- 27,30 ---- *************** *** 38,42 **** extern struct obstack *rtl_obstack; ! extern long ftell(); /* Indexed by rtx code, gives number of operands for an rtx with that code. --- 36,42 ---- extern struct obstack *rtl_obstack; ! #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT ! extern long atol(); ! #endif /* Indexed by rtx code, gives number of operands for an rtx with that code. *************** *** 139,142 **** --- 139,144 ---- prints the integer "n" like "i", but prints entries from `note_insn_name' + "w" an integer of width HOST_BITS_PER_WIDE_INT + prints the integer "s" a pointer to a string prints the string *************** *** 172,176 **** "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END", "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP", ! "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP" }; char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0", --- 174,180 ---- "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END", "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP", ! "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP", ! "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG", ! "NOTE_INSN_DELETED_LABEL"}; char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0", *************** *** 283,286 **** --- 287,295 ---- break; + case '0': + case 'u': + XEXP (copy, i) = XEXP (orig, i); + break; + case 'E': case 'V': *************** *** 294,300 **** break; ! default: XINT (copy, i) = XINT (orig, i); break; } } --- 303,321 ---- break; ! case 'w': ! XWINT (copy, i) = XWINT (orig, i); ! break; ! ! case 'i': XINT (copy, i) = XINT (orig, i); break; + + case 's': + case 'S': + XSTR (copy, i) = XSTR (orig, i); + break; + + default: + abort (); } } *************** *** 352,355 **** --- 373,381 ---- break; + case '0': + case 'u': + XEXP (copy, i) = XEXP (orig, i); + break; + case 'E': case 'V': *************** *** 364,370 **** break; ! default: XINT (copy, i) = XINT (orig, i); break; } } --- 390,409 ---- break; ! case 'w': ! XWINT (copy, i) = XWINT (orig, i); ! break; ! ! case 'n': ! case 'i': XINT (copy, i) = XINT (orig, i); break; + + case 's': + case 'S': + XSTR (copy, i) = XSTR (orig, i); + break; + + default: + abort (); } } *************** *** 493,496 **** --- 532,536 ---- register int c; int tmp_int; + HOST_WIDE_INT tmp_wide; /* Linked list structure for making RTXs: */ *************** *** 605,610 **** /* get vector length and allocate it */ XVEC (return_rtx, i) = (list_counter ! ? rtvec_alloc (list_counter) ! : (struct rtvec_def *) NULL); if (list_counter > 0) { --- 645,649 ---- /* get vector length and allocate it */ XVEC (return_rtx, i) = (list_counter ! ? rtvec_alloc (list_counter) : NULL_RTVEC); if (list_counter > 0) { *************** *** 677,680 **** --- 716,729 ---- break; + case 'w': + read_name (tmp_char, infile); + #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + tmp_wide = atoi (tmp_char); + #else + tmp_wide = atol (tmp_char); + #endif + XWINT (return_rtx, i) = tmp_wide; + break; + case 'i': case 'n': *************** *** 730,734 **** of as many `i's as we now have elements. */ for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++) ! *s++ = 'i'; *s++ = 0; } --- 779,783 ---- of as many `i's as we now have elements. */ for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++) ! *s++ = 'w'; *s++ = 0; } diff -rc2N gcc-2.2.2/rtl.def gcc-2.3.1/rtl.def *** gcc-2.2.2/rtl.def Thu May 7 02:37:53 1992 --- gcc-2.3.1/rtl.def Tue Aug 25 16:13:49 1992 *************** *** 155,158 **** --- 155,163 ---- /* Appears only in machine descriptions. + Means match only something equal to what is stored in the operand table + at the index specified by the argument. For MATCH_PARALLEL. */ + DEF_RTL_EXPR(MATCH_PAR_DUP, "match_par_dup", "iE", 'm') + + /* Appears only in machine descriptions. Defines the pattern for one kind of instruction. Operand: *************** *** 232,236 **** operands must be the same for each operation for the same function unit. ! All delays are specified in units of COST_PER_CYCLE. 1st operand: Name of function unit (mostly for documentation) --- 237,241 ---- operands must be the same for each operation for the same function unit. ! All delays are specified in cycles. 1st operand: Name of function unit (mostly for documentation) *************** *** 246,262 **** not the next operand is supplied. 7th operand: If this operand is not specified, the 6th operand gives the ! cost of scheduling another operation on this unit while a ! previous one is active. A value of zero should be used for a ! pipelined unit. If only one operation can be executed a time ! and the unit is busy for the entire time, the 3rd operand ! should be specified as 1 and the 6th and 7th operands will ! be ignored. If this operand is specified, it is a list of attribute expressions. If an insn for which any of these expressions is true is currently executing on the function unit, the ! delay will be given by the 6th operand. Otherwise, the ! insn can be immediately scheduled (subject to the limit on ! the number of simultaneous operations executing on the unit.) */ DEF_RTL_EXPR(DEFINE_FUNCTION_UNIT, "define_function_unit", "siieiiV", 'x') --- 251,269 ---- not the next operand is supplied. 7th operand: If this operand is not specified, the 6th operand gives the ! number of cycles after the instruction matching the 4th ! operand begins using the function unit until a subsequent ! insn can begin. A value of zero should be used for a ! unit with no issue constraints. If only one operation can ! be executed a time and the unit is busy for the entire time, ! the 3rd operand should be specified as 1, the 6th operand ! sould be specified as 0, and the 7th operand should not ! be specified. If this operand is specified, it is a list of attribute expressions. If an insn for which any of these expressions is true is currently executing on the function unit, the ! issue delay will be given by the 6th operand. Otherwise, ! the insn can be immediately scheduled (subject to the limit ! on the number of simultaneous operations executing on the unit.) */ DEF_RTL_EXPR(DEFINE_FUNCTION_UNIT, "define_function_unit", "siieiiV", 'x') *************** *** 465,469 **** /* numeric integer constant */ ! DEF_RTL_EXPR(CONST_INT, "const_int", "i", 'o') /* numeric double constant. --- 472,476 ---- /* numeric integer constant */ ! DEF_RTL_EXPR(CONST_INT, "const_int", "w", 'o') /* numeric double constant. *************** *** 474,478 **** The number of operands may be more than 2 if cross-compiling; see init_rtl. */ ! DEF_RTL_EXPR(CONST_DOUBLE, "const_double", "e0ii", 'o') /* String constant. Used only for attributes right now. */ --- 481,485 ---- The number of operands may be more than 2 if cross-compiling; see init_rtl. */ ! DEF_RTL_EXPR(CONST_DOUBLE, "const_double", "e0ww", 'o') /* String constant. Used only for attributes right now. */ diff -rc2N gcc-2.2.2/rtl.h gcc-2.3.1/rtl.h *** gcc-2.2.2/rtl.h Thu May 7 02:37:55 1992 --- gcc-2.3.1/rtl.h Fri Oct 23 07:38:26 1992 *************** *** 1,4 **** /* Register Transfer Language (RTL) definitions for GNU C-Compiler ! Copyright (C) 1987, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Register Transfer Language (RTL) definitions for GNU C-Compiler ! Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 56,59 **** --- 56,60 ---- typedef union rtunion_def { + HOST_WIDE_INT rtwint; int rtint; char *rtstr; *************** *** 87,90 **** --- 88,92 ---- during the current function, even though it is not manifestly constant. + 1 in a SUBREG if it is from a promoted variable that is unsigned. 1 in a SYMBOL_REF if it addresses something in the per-function constants pool. *************** *** 98,102 **** 1 in a REG expression if corresponds to a variable declared by the user. 0 for an internally generated temporary. ! In a SYMBOL_REF, this flag is used for machine-specific purposes. */ unsigned int volatil : 1; /* 1 in a MEM referring to a field of a structure (not a union!). --- 100,105 ---- 1 in a REG expression if corresponds to a variable declared by the user. 0 for an internally generated temporary. ! In a SYMBOL_REF, this flag is used for machine-specific purposes. ! In a LABEL_REF or in a REG_LABEL note, this is LABEL_REF_NONLOCAL_P. */ unsigned int volatil : 1; /* 1 in a MEM referring to a field of a structure (not a union!). *************** *** 104,107 **** --- 107,112 ---- 1 if it was the result of a . or -> operator (on a struct) in C. 1 in a REG if the register is used only in exit code a loop. + 1 in a SUBREG expression if was generated from a variable with a + promoted mode. 1 in a CODE_LABEL if the label is used for nonlocal gotos and must not be deleted even if its count is zero. *************** *** 131,136 **** --- 136,168 ---- } *rtx; + /* Add prototype support. */ + #ifndef PROTO + #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) + #define PROTO(ARGS) ARGS + #else + #define PROTO(ARGS) () + #endif + #endif + #define NULL_RTX (rtx) 0 + /* Define a generic NULL if one hasn't already been defined. */ + + #ifndef NULL + #define NULL 0 + #endif + + #ifndef GENERIC_PTR + #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) + #define GENERIC_PTR void * + #else + #define GENERIC_PTR char * + #endif + #endif + + #ifndef NULL_PTR + #define NULL_PTR ((GENERIC_PTR)0) + #endif + /* Define macros to access the `code' field of the rtx. */ *************** *** 180,183 **** --- 212,216 ---- #define XEXP(RTX, N) ((RTX)->fld[N].rtx) #define XINT(RTX, N) ((RTX)->fld[N].rtint) + #define XWINT(RTX, N) ((RTX)->fld[N].rtwint) #define XSTR(RTX, N) ((RTX)->fld[N].rtstr) #define XVEC(RTX, N) ((RTX)->fld[N].rtvec) *************** *** 303,309 **** /* In a NOTE that is a line number, this is a string for the file name ! that the line is in. */ #define NOTE_SOURCE_FILE(INSN) ((INSN)->fld[3].rtstr) /* In a NOTE that is a line number, this is the line number. --- 336,346 ---- /* In a NOTE that is a line number, this is a string for the file name ! that the line is in. We use the same field to record block numbers ! temporarily in NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes. ! (We avoid lots of casts between ints and pointers if we use a ! different macro for the bock number.) */ #define NOTE_SOURCE_FILE(INSN) ((INSN)->fld[3].rtstr) + #define NOTE_BLOCK_NUMBER(INSN) ((INSN)->fld[3].rtint) /* In a NOTE that is a line number, this is the line number. *************** *** 337,342 **** --- 374,387 ---- /* Generated at the start of a duplicated exit test. */ #define NOTE_INSN_LOOP_VTOP -9 + /* This marks the point immediately after the last prologue insn. */ + #define NOTE_INSN_PROLOGUE_END -10 + /* This marks the point immediately prior to the first epilogue insn. */ + #define NOTE_INSN_EPILOGUE_BEG -11 + /* Generated in place of user-declared labels when they are deleted. */ + #define NOTE_INSN_DELETED_LABEL -12 /* Don't forget to change note_insn_name in rtl.c. */ + + #if 0 /* These are not used, and I don't know what they were for. --rms. */ #define NOTE_DECL_NAME(INSN) ((INSN)->fld[3].rtstr) #define NOTE_DECL_CODE(INSN) ((INSN)->fld[4].rtint) *************** *** 344,347 **** --- 389,393 ---- #define NOTE_DECL_IDENTIFIER(INSN) ((INSN)->fld[6].rtint) #define NOTE_DECL_TYPE(INSN) ((INSN)->fld[7].rtint) + #endif /* 0 */ /* Names for NOTE insn's other than line numbers. */ *************** *** 394,398 **** /* For a CONST_INT rtx, INTVAL extracts the integer. */ ! #define INTVAL(RTX) ((RTX)->fld[0].rtint) /* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of. --- 440,444 ---- /* For a CONST_INT rtx, INTVAL extracts the integer. */ ! #define INTVAL(RTX) ((RTX)->fld[0].rtwint) /* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of. *************** *** 402,405 **** --- 448,462 ---- #define SUBREG_WORD(RTX) ((RTX)->fld[1].rtint) + /* 1 if the REG contained in SUBREG_REG is already known to be + sign- or zero-extended from the mode of the SUBREG to the mode of + the reg. SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the + extension. + + When used as a LHS, is means that this extension must be done + when assigning to SUBREG_REG. */ + + #define SUBREG_PROMOTED_VAR_P(RTX) ((RTX)->in_struct) + #define SUBREG_PROMOTED_UNSIGNED_P(RTX) ((RTX)->unchanging) + /* Access various components of an ASM_OPERANDS rtx. */ *************** *** 427,430 **** --- 484,491 ---- #define LABEL_OUTSIDE_LOOP_P(RTX) ((RTX)->in_struct) + /* For a LABEL_REF, 1 means it is for a nonlocal label. */ + /* Likewise in an EXPR_LIST for a REG_LABEL note. */ + #define LABEL_REF_NONLOCAL_P(RTX) ((RTX)->volatil) + /* For a CODE_LABEL, 1 means always consider this label to be needed. */ #define LABEL_PRESERVE_P(RTX) ((RTX)->in_struct) *************** *** 437,440 **** --- 498,511 ---- #define SCHED_GROUP_P(INSN) ((INSN)->in_struct) + /* During sched, for the LOG_LINKS of an insn, these cache the adjusted + cost of the dependence link. The cost of executing an instruction + may vary based on how the results are used. LINK_COST_ZERO is 1 when + the cost through the link varies and is unchanged (i.e., the link has + zero additional cost). LINK_COST_FREE is 1 when the cost through the + link is zero (i.e., the link makes the cost free). In other cases, + the adjustment to the cost is recomputed each time it is needed. */ + #define LINK_COST_ZERO(X) ((X)->jump) + #define LINK_COST_FREE(X) ((X)->call) + /* For a SET rtx, SET_DEST is the place that is set and SET_SRC is the value it is set to. */ *************** *** 527,634 **** /* Generally useful functions. */ ! extern rtx rtx_alloc (); ! extern rtvec rtvec_alloc (); ! extern rtx find_reg_note (); ! extern rtx find_regno_note (); ! extern int get_integer_term (); ! extern rtx get_related_value (); ! extern rtx single_set (); ! extern rtx find_last_value (); extern rtx gen_rtx (); - extern rtx copy_rtx (); - extern rtx copy_rtx_if_shared (); - extern rtx copy_most_rtx (); - extern rtx replace_rtx (); extern rtvec gen_rtvec (); ! extern rtvec gen_rtvec_v (); extern rtx read_rtx (); ! extern rtx gen_reg_rtx (); ! extern rtx gen_label_rtx (); ! extern rtx gen_inline_header_rtx (); ! extern rtx gen_lowpart_common (); ! extern rtx gen_lowpart (); ! extern rtx gen_lowpart_if_possible (); ! extern rtx operand_subword (); ! extern rtx operand_subword_force (); ! extern int subreg_lowpart_p (); ! extern rtx make_safe_from (); ! extern rtx memory_address (); ! extern rtx get_insns (); ! extern rtx get_last_insn (); ! extern rtx get_last_insn_anywhere (); ! extern void start_sequence (); ! extern void push_to_sequence (); ! extern void end_sequence (); ! extern rtx gen_sequence (); ! extern rtx expand_expr (); ! extern rtx output_constant_def (); ! extern rtx immed_real_const (); ! extern rtx immed_real_const_1 (); ! extern rtx immed_double_const (); ! extern rtx force_const_mem (); ! extern rtx get_pool_constant (); ! extern enum machine_mode get_pool_mode (); ! extern int get_pool_offset (); ! extern rtx get_parm_real_loc (); ! extern rtx assign_stack_local (); ! extern rtx assign_stack_temp (); ! extern rtx protect_from_queue (); ! extern void emit_queue (); ! extern rtx emit_move_insn (); ! extern rtx emit_insn_before (); ! extern rtx emit_jump_insn_before (); ! extern rtx emit_call_insn_before (); ! extern rtx emit_barrier_before (); ! extern rtx emit_note_before (); ! extern rtx emit_insn_after (); ! extern rtx emit_jump_insn_after (); ! extern rtx emit_barrier_after (); ! extern rtx emit_label_after (); ! extern rtx emit_note_after (); ! extern rtx emit_line_note_after (); ! extern rtx emit_insn (); ! extern rtx emit_insns (); ! extern rtx emit_insns_before (); ! extern rtx emit_jump_insn (); ! extern rtx emit_call_insn (); ! extern rtx emit_label (); ! extern rtx emit_barrier (); ! extern rtx emit_line_note (); ! extern rtx emit_note (); ! extern rtx emit_line_note_force (); ! extern rtx make_insn_raw (); ! extern rtx previous_insn (); ! extern rtx next_insn (); ! extern rtx prev_nonnote_insn (); ! extern rtx next_nonnote_insn (); ! extern rtx prev_real_insn (); ! extern rtx next_real_insn (); ! extern rtx prev_active_insn (); ! extern rtx next_active_insn (); ! extern rtx prev_label (); ! extern rtx next_label (); ! extern rtx next_cc0_user (); ! extern rtx prev_cc0_setter (); ! extern rtx reg_set_last (); ! extern rtx next_nondeleted_insn (); ! extern enum rtx_code reverse_condition (); ! extern enum rtx_code swap_condition (); ! extern enum rtx_code unsigned_condition (); ! extern enum rtx_code signed_condition (); ! extern rtx plus_constant (), plus_constant_for_output (); ! extern rtx find_equiv_reg (); ! extern rtx squeeze_notes (); ! extern rtx delete_insn (); ! extern void delete_jump (); ! extern rtx get_label_before (); ! extern rtx get_label_after (); ! extern rtx follow_jumps (); ! extern rtx adj_offsettable_operand (); ! extern rtx try_split (); ! extern rtx split_insns (); ! extern rtx simplify_unary_operation (), simplify_binary_operation (); ! extern rtx simplify_ternary_operation (), simplify_relational_operation (); ! extern rtx nonlocal_label_rtx_list (); /* Maximum number of parallel sets and clobbers in any insn in this fn. Always at least 3, since the combiner could put that many togetherm --- 598,761 ---- /* Generally useful functions. */ ! /* The following functions accept a wide integer argument. Rather than ! having to cast on every function call, we use a macro instead, that is ! defined here and in tree.h. */ ! ! #ifndef exact_log2 ! #define exact_log2(N) exact_log2_wide ((HOST_WIDE_INT) (N)) ! #define floor_log2(N) floor_log2_wide ((HOST_WIDE_INT) (N)) ! #endif ! ! #define plus_constant(X,C) plus_constant_wide (X, (HOST_WIDE_INT) (C)) ! ! #define plus_constant_for_output(X,C) \ ! plus_constant_for_output_wide (X, (HOST_WIDE_INT) (C)) ! ! extern rtx plus_constant_wide PROTO((rtx, HOST_WIDE_INT)); ! extern rtx plus_constant_for_output_wide PROTO((rtx, HOST_WIDE_INT)); ! ! #define GEN_INT(N) gen_rtx (CONST_INT, VOIDmode, (N)) ! ! #if 0 ! /* We cannot define prototypes for the variable argument functions, ! since they have not been ANSI-fied, and an ANSI compiler would ! complain when compiling the definition of these functions. */ ! ! extern rtx gen_rtx PROTO((enum rtx_code, enum machine_mode, ...)); ! extern rtvec gen_rtvec PROTO((int, ...)); ! ! #else extern rtx gen_rtx (); extern rtvec gen_rtvec (); ! #endif ! ! #ifdef BUFSIZ /* stdio.h has been included */ ! extern rtx read_rtx PROTO((FILE *)); ! #else extern rtx read_rtx (); ! #endif ! ! #if 0 ! /* At present, don't prototype xrealloc, since all of the callers don't ! cast their pointers to char *, and all of the xrealloc's don't use ! void * yet. */ ! extern char *xrealloc PROTO((void *, unsigned)); ! #else ! extern char *xrealloc (); ! #endif + extern char *xmalloc PROTO((unsigned)); + extern char *oballoc PROTO((int)); + extern char *permalloc PROTO((int)); + extern void free PROTO((void *)); + extern rtx rtx_alloc PROTO((RTX_CODE)); + extern rtvec rtvec_alloc PROTO((int)); + extern rtx find_reg_note PROTO((rtx, enum reg_note, rtx)); + extern rtx find_regno_note PROTO((rtx, enum reg_note, int)); + extern HOST_WIDE_INT get_integer_term PROTO((rtx)); + extern rtx get_related_value PROTO((rtx)); + extern rtx single_set PROTO((rtx)); + extern rtx find_last_value PROTO((rtx, rtx *, rtx)); + extern rtx copy_rtx PROTO((rtx)); + extern rtx copy_rtx_if_shared PROTO((rtx)); + extern rtx copy_most_rtx PROTO((rtx, rtx)); + extern rtx replace_rtx PROTO((rtx, rtx, rtx)); + extern rtvec gen_rtvec_v PROTO((int, rtx *)); + extern rtx gen_reg_rtx PROTO((enum machine_mode)); + extern rtx gen_label_rtx PROTO((void)); + extern rtx gen_inline_header_rtx PROTO((rtx, rtx, int, int, int, int, int, int, rtx, int, int, rtvec, rtx)); + extern rtx gen_lowpart_common PROTO((enum machine_mode, rtx)); + extern rtx gen_lowpart PROTO((enum machine_mode, rtx)); + extern rtx gen_lowpart_if_possible PROTO((enum machine_mode, rtx)); + extern rtx gen_highpart PROTO((enum machine_mode, rtx)); + extern rtx gen_realpart PROTO((enum machine_mode, rtx)); + extern rtx gen_imagpart PROTO((enum machine_mode, rtx)); + extern rtx operand_subword PROTO((rtx, int, int, enum machine_mode)); + extern rtx operand_subword_force PROTO((rtx, int, enum machine_mode)); + extern int subreg_lowpart_p PROTO((rtx)); + extern rtx make_safe_from PROTO((rtx, rtx)); + extern rtx memory_address PROTO((enum machine_mode, rtx)); + extern rtx get_insns PROTO((void)); + extern rtx get_last_insn PROTO((void)); + extern rtx get_last_insn_anywhere PROTO((void)); + extern void start_sequence PROTO((void)); + extern void push_to_sequence PROTO((rtx)); + extern void end_sequence PROTO((void)); + extern rtx gen_sequence PROTO((void)); + extern rtx immed_double_const PROTO((HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode)); + extern rtx force_const_mem PROTO((enum machine_mode, rtx)); + extern rtx force_reg PROTO((enum machine_mode, rtx)); + extern rtx get_pool_constant PROTO((rtx)); + extern enum machine_mode get_pool_mode PROTO((rtx)); + extern int get_pool_offset PROTO((rtx)); + extern rtx simplify_subtraction PROTO((rtx)); + extern rtx assign_stack_local PROTO((enum machine_mode, int, int)); + extern rtx assign_stack_temp PROTO((enum machine_mode, int, int)); + extern rtx protect_from_queue PROTO((rtx, int)); + extern void emit_queue PROTO((void)); + extern rtx emit_move_insn PROTO((rtx, rtx)); + extern rtx emit_insn_before PROTO((rtx, rtx)); + extern rtx emit_jump_insn_before PROTO((rtx, rtx)); + extern rtx emit_call_insn_before PROTO((rtx, rtx)); + extern rtx emit_barrier_before PROTO((rtx)); + extern rtx emit_note_before PROTO((int, rtx)); + extern rtx emit_insn_after PROTO((rtx, rtx)); + extern rtx emit_jump_insn_after PROTO((rtx, rtx)); + extern rtx emit_barrier_after PROTO((rtx)); + extern rtx emit_label_after PROTO((rtx, rtx)); + extern rtx emit_note_after PROTO((int, rtx)); + extern rtx emit_line_note_after PROTO((char *, int, rtx)); + extern rtx emit_insn PROTO((rtx)); + extern rtx emit_insns PROTO((rtx)); + extern rtx emit_insns_before PROTO((rtx, rtx)); + extern rtx emit_jump_insn PROTO((rtx)); + extern rtx emit_call_insn PROTO((rtx)); + extern rtx emit_label PROTO((rtx)); + extern rtx emit_barrier PROTO((void)); + extern rtx emit_line_note PROTO((char *, int)); + extern rtx emit_note PROTO((char *, int)); + extern rtx emit_line_note_force PROTO((char *, int)); + extern rtx make_insn_raw PROTO((rtx)); + extern rtx previous_insn PROTO((rtx)); + extern rtx next_insn PROTO((rtx)); + extern rtx prev_nonnote_insn PROTO((rtx)); + extern rtx next_nonnote_insn PROTO((rtx)); + extern rtx prev_real_insn PROTO((rtx)); + extern rtx next_real_insn PROTO((rtx)); + extern rtx prev_active_insn PROTO((rtx)); + extern rtx next_active_insn PROTO((rtx)); + extern rtx prev_label PROTO((rtx)); + extern rtx next_label PROTO((rtx)); + extern rtx next_cc0_user PROTO((rtx)); + extern rtx prev_cc0_setter PROTO((rtx)); + extern rtx reg_set_last PROTO((rtx, rtx)); + extern rtx next_nondeleted_insn PROTO((rtx)); + extern enum rtx_code reverse_condition PROTO((enum rtx_code)); + extern enum rtx_code swap_condition PROTO((enum rtx_code)); + extern enum rtx_code unsigned_condition PROTO((enum rtx_code)); + extern enum rtx_code signed_condition PROTO((enum rtx_code)); + extern rtx find_equiv_reg PROTO((rtx, rtx, enum reg_class, int, short *, int, enum machine_mode)); + extern rtx squeeze_notes PROTO((rtx, rtx)); + extern rtx delete_insn PROTO((rtx)); + extern void delete_jump PROTO((rtx)); + extern rtx get_label_before PROTO((rtx)); + extern rtx get_label_after PROTO((rtx)); + extern rtx follow_jumps PROTO((rtx)); + extern rtx adj_offsettable_operand PROTO((rtx, int)); + extern rtx try_split PROTO((rtx, rtx, int)); + extern rtx split_insns PROTO((rtx, rtx)); + extern rtx simplify_unary_operation PROTO((enum rtx_code, enum machine_mode, rtx, enum machine_mode)); + extern rtx simplify_binary_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx)); + extern rtx simplify_ternary_operation PROTO((enum rtx_code, enum machine_mode, enum machine_mode, rtx, rtx, rtx)); + extern rtx simplify_relational_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx)); + extern rtx nonlocal_label_rtx_list PROTO((void)); + extern rtx gen_move_insn PROTO((rtx, rtx)); + extern rtx gen_jump PROTO((rtx)); + extern rtx gen_beq PROTO((rtx)); + extern rtx gen_bge PROTO((rtx)); + extern rtx gen_ble PROTO((rtx)); + extern rtx eliminate_constant_term PROTO((rtx, rtx *)); + extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int)); + /* Maximum number of parallel sets and clobbers in any insn in this fn. Always at least 3, since the combiner could put that many togetherm *************** *** 637,649 **** extern int max_parallel; ! extern int asm_noperands (); ! extern char *decode_asm_operands (); ! #ifdef BITS_PER_WORD ! /* Conditional is to detect when config.h has been included. */ ! extern enum reg_class reg_preferred_class (); ! #endif ! extern rtx get_first_nonparm_insn (); /* Standard pieces of rtx, to be substituted directly into things. */ --- 764,774 ---- extern int max_parallel; ! extern int asm_noperands PROTO((rtx)); ! extern char *decode_asm_operands PROTO((rtx, rtx *, rtx **, char **, enum machine_mode *)); ! extern enum reg_class reg_preferred_class PROTO((int)); ! extern enum reg_class reg_alternate_class PROTO((int)); ! extern rtx get_first_nonparm_insn PROTO((void)); /* Standard pieces of rtx, to be substituted directly into things. */ *************** *** 722,727 **** #define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 3) ! extern rtx find_next_ref (); ! extern rtx *find_single_use (); /* Define a default value for STORE_FLAG_VALUE. */ --- 847,871 ---- #define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 3) ! extern rtx find_next_ref PROTO((rtx, rtx)); ! extern rtx *find_single_use PROTO((rtx, rtx, rtx *)); ! ! /* It is hard to write the prototype for expand_expr, since it needs ! expr.h to be included for the enumeration. */ ! ! extern rtx expand_expr (); ! extern rtx immed_real_const_1(); ! ! #ifdef TREE_CODE ! /* rtl.h and tree.h were included. */ ! extern rtx output_constant_def PROTO((tree)); ! extern rtx immed_real_const PROTO((tree)); ! extern rtx immed_real_const_1 PROTO((REAL_VALUE_TYPE, enum machine_mode)); ! extern tree make_tree PROTO((tree, rtx)); ! ! #else ! extern rtx output_constant_def (); ! extern rtx immed_real_const (); ! extern rtx immed_real_const_1 (); ! #endif /* Define a default value for STORE_FLAG_VALUE. */ diff -rc2N gcc-2.2.2/rtl.texi gcc-2.3.1/rtl.texi *** gcc-2.2.2/rtl.texi Mon Apr 20 12:48:43 1992 --- gcc-2.3.1/rtl.texi Fri Oct 23 20:28:26 1992 *************** *** 49,58 **** @cindex RTL expression @cindex RTX (See RTL) ! RTL uses four kinds of objects: expressions, integers, strings and vectors. ! Expressions are the most important ones. An RTL expression (``RTX'', for ! short) is a C structure, but it is usually referred to with a pointer; a ! type that is given the typedef name @code{rtx}. An integer is simply an @code{int}; their written form uses decimal digits. A string is a sequence of characters. In core it is represented as a --- 49,61 ---- @cindex RTL expression @cindex RTX (See RTL) ! RTL uses five kinds of objects: expressions, integers, wide integers, ! strings and vectors. Expressions are the most important ones. An RTL ! expression (``RTX'', for short) is a C structure, but it is usually ! referred to with a pointer; a type that is given the typedef name ! @code{rtx}. An integer is simply an @code{int}; their written form uses decimal digits. + A wide integer is an integral object whose type is @code{HOST_WIDE_INT} + (@pxref{Config}); their written form used decimal digits. A string is a sequence of characters. In core it is represented as a *************** *** 113,122 **** @cindex RTL format ! For each expression type @file{rtl.def} specifies the number of contained ! objects and their kinds, with four possibilities: @samp{e} for expression ! (actually a pointer to an expression), @samp{i} for integer, @samp{s} for ! string, and @samp{E} for vector of expressions. The sequence of letters ! for an expression code is called its @dfn{format}. Thus, the format of ! @code{subreg} is @samp{ei}.@refill @cindex RTL format characters --- 116,126 ---- @cindex RTL format ! For each expression type @file{rtl.def} specifies the number of ! contained objects and their kinds, with four possibilities: @samp{e} for ! expression (actually a pointer to an expression), @samp{i} for integer, ! @samp{w} for wide integer, @samp{s} for string, and @samp{E} for vector ! of expressions. The sequence of letters for an expression code is ! called its @dfn{format}. Thus, the format of @code{subreg} is ! @samp{ei}.@refill @cindex RTL format characters *************** *** 212,220 **** @findex XEXP @findex XINT @findex XSTR Operands of expressions are accessed using the macros @code{XEXP}, ! @code{XINT} and @code{XSTR}. Each of these macros takes two arguments: an ! expression-pointer (RTX) and an operand number (counting from zero). ! Thus,@refill @example --- 216,225 ---- @findex XEXP @findex XINT + @findex XWINT @findex XSTR Operands of expressions are accessed using the macros @code{XEXP}, ! @code{XINT}, @code{XWINT} and @code{XSTR}. Each of these macros takes ! two arguments: an expression-pointer (RTX) and an operand number ! (counting from zero). Thus,@refill @example *************** *** 337,340 **** --- 342,367 ---- in this kind of use. + @findex SUBREG_PROMOTED_VAR_P + @cindex @code{subreg} and @samp{/s} + @cindex @code{in_struct}, in @code{subreg} + @item SUBREG_PROMOTED_VAR_P + Nonzero in a @code{subreg} if it was made when accessing an object that + was promoted to a wider mode in accord with the @code{PROMOTED_MODE} machine + description macro (@pxref{Storage Layout}). In this case, the mode of + the @code{subreg} is the declared mode of the object and the mode of + @code{SUBREG_REG} is the mode of the register that holds the object. + Promoted variables are always either sign- or zero-extended to the wider + mode on every assignment. Stored in the @code{in_struct} field and + printed as @samp{/s}. + + @findex SUBREG_PROMOTED_UNSIGNED_P + @cindex @code{subreg} and @samp{/u} + @cindex @code{unchanging}, in @code{subreg} + @item SUBREG_PROMOTED_UNSIGNED_P + Nonzero in a @code{subreg} that has @code{SUBREG_PROMOTED_VAR_P} nonzero + if the object being referenced is kept zero-extended and zero if it + is kept sign-extended. Stored in the @code{unchanging} field and + printed as @samp{/u}. + @findex RTX_UNCHANGING_P @cindex @code{reg} and @samp{/u} *************** *** 428,432 **** @item LABEL_PRESERVE_P (@var{x}) In a @code{code_label}, indicates that the label can never be deleted. ! Labels referenced by a a non-local goto will have this bit set. Stored in the @code{in_struct} field and printed as @samp{/s}. --- 455,459 ---- @item LABEL_PRESERVE_P (@var{x}) In a @code{code_label}, indicates that the label can never be deleted. ! Labels referenced by a non-local goto will have this bit set. Stored in the @code{in_struct} field and printed as @samp{/s}. *************** *** 461,465 **** @findex volatil @item volatil ! This flag is used in @code{mem},@code{symbol_ref} and @code{reg} expressions and in insns. In RTL dump files, it is printed as @samp{/v}. --- 488,492 ---- @findex volatil @item volatil ! This flag is used in @code{mem}, @code{symbol_ref} and @code{reg} expressions and in insns. In RTL dump files, it is printed as @samp{/v}. *************** *** 494,497 **** --- 521,527 ---- contained within the test expression of some loopl. + In @code{subreg} expressions, 1 means that the @code{subreg} is accessing + an object that has had its mode promoted from a wider mode. + In @code{label_ref} expressions, 1 means that the referenced label is outside the innermost loop containing the insn in which the @code{label_ref} *************** *** 508,511 **** --- 538,544 ---- that the value of the expression never changes. + In @code{subreg} expressions, it is 1 if the @code{subreg} references an + unsigned object whose mode has been promoted to a wider mode. + In an insn, 1 means that this is an annulling branch. *************** *** 786,797 **** This type of expression represents the integer value @var{i}. @var{i} is customarily accessed with the macro @code{INTVAL} as in ! @code{INTVAL (@var{exp})}, which is equivalent to @code{XINT (@var{exp}, 0)}. ! ! Keep in mind that the result of @code{INTVAL} is an integer on the host ! machine. If the host machine has more bits in an @code{int} than the ! target machine has in the mode in which the constant will be used, then ! some of the bits you get from @code{INTVAL} will be superfluous. In ! many cases, for proper results, you must carefully disregard the values ! of those bits. @findex const0_rtx --- 819,823 ---- This type of expression represents the integer value @var{i}. @var{i} is customarily accessed with the macro @code{INTVAL} as in ! @code{INTVAL (@var{exp})}, which is equivalent to @code{XWINT (@var{exp}, 0)}. @findex const0_rtx *************** *** 820,824 **** @item (const_double:@var{m} @var{addr} @var{i0} @var{i1} @dots{}) Represents either a floating-point constant of mode @var{m} or an ! integer constant that is too large to fit into @code{HOST_BITS_PER_INT} bits but small enough to fit within twice that number of bits (GNU CC does not provide a mechanism to represent even larger constants). In --- 846,850 ---- @item (const_double:@var{m} @var{addr} @var{i0} @var{i1} @dots{}) Represents either a floating-point constant of mode @var{m} or an ! integer constant that is too large to fit into @code{HOST_BITS_PER_WIDE_INT} bits but small enough to fit within twice that number of bits (GNU CC does not provide a mechanism to represent even larger constants). In *************** *** 1669,1673 **** @cindex @code{subreg}, in @code{strict_low_part} @item (strict_low_part (subreg:@var{m} (reg:@var{n} @var{r}) 0)) ! This expression code is used in only one context: operand 0 of a @code{set} expression. In addition, the operand of this expression must be a non-paradoxical @code{subreg} expression. --- 1695,1699 ---- @cindex @code{subreg}, in @code{strict_low_part} @item (strict_low_part (subreg:@var{m} (reg:@var{n} @var{r}) 0)) ! This expression code is used in only one context: as the destination operand of a @code{set} expression. In addition, the operand of this expression must be a non-paradoxical @code{subreg} expression. *************** *** 2311,2315 **** @code{clobber}, @code{return}, @code{asm_input}, @code{asm_output}, @code{addr_vec}, @code{addr_diff_vec}, @code{trap_if}, @code{unspec}, ! @code{unspec_volatile}, or @code{parallel}. If it is a @code{parallel}, each element of the @code{parallel} must be one these codes, except that @code{parallel} expressions cannot be nested and @code{addr_vec} and --- 2337,2341 ---- @code{clobber}, @code{return}, @code{asm_input}, @code{asm_output}, @code{addr_vec}, @code{addr_diff_vec}, @code{trap_if}, @code{unspec}, ! @code{unspec_volatile}, @code{parallel}, or @code{sequence}. If it is a @code{parallel}, each element of the @code{parallel} must be one these codes, except that @code{parallel} expressions cannot be nested and @code{addr_vec} and *************** *** 2378,2382 **** @findex REG_NOTE_KIND @findex PUT_REG_NOTE_KIND ! The macro @code{REG_NOTE_KIND (@var{x})} returns the the kind of register note. Its counterpart, the macro @code{PUT_REG_NOTE_KIND (@var{x}, @var{newkind})} sets the register note type of @var{x} to be --- 2404,2408 ---- @findex REG_NOTE_KIND @findex PUT_REG_NOTE_KIND ! The macro @code{REG_NOTE_KIND (@var{x})} returns the kind of register note. Its counterpart, the macro @code{PUT_REG_NOTE_KIND (@var{x}, @var{newkind})} sets the register note type of @var{x} to be diff -rc2N gcc-2.2.2/rtlanal.c gcc-2.3.1/rtlanal.c *** gcc-2.2.2/rtlanal.c Tue Jan 28 14:31:58 1992 --- gcc-2.3.1/rtlanal.c Wed Oct 14 00:01:33 1992 *************** *** 1,4 **** /* Analyze RTL for C-Compiler ! Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc. This file is part of GNU CC. --- 1,4 ---- /* Analyze RTL for C-Compiler ! Copyright (C) 1987, 1988, 1991, 1992 Free Software Foundation, Inc. This file is part of GNU CC. *************** *** 185,189 **** This is used in cse.c with the `related_value' field.*/ ! int get_integer_term (x) rtx x; --- 185,189 ---- This is used in cse.c with the `related_value' field.*/ ! HOST_WIDE_INT get_integer_term (x) rtx x; *************** *** 529,535 **** for (i = 0, set = 0; i < XVECLEN (PATTERN (insn), 0); i++) if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET ! && ! (find_reg_note (insn, REG_UNUSED, ! SET_DEST (XVECEXP (PATTERN (insn), 0, i))) ! || side_effects_p (XVECEXP (PATTERN (insn), 0, i)))) { if (set) --- 529,535 ---- for (i = 0, set = 0; i < XVECLEN (PATTERN (insn), 0); i++) if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET ! && (! find_reg_note (insn, REG_UNUSED, ! SET_DEST (XVECEXP (PATTERN (insn), 0, i))) ! || side_effects_p (XVECEXP (PATTERN (insn), 0, i)))) { if (set) *************** *** 562,566 **** { rtx set = single_set (p); ! rtx note = find_reg_note (p, REG_EQUAL, 0); if (set && rtx_equal_p (x, SET_DEST (set))) --- 562,566 ---- { rtx set = single_set (p); ! rtx note = find_reg_note (p, REG_EQUAL, NULL_RTX); if (set && rtx_equal_p (x, SET_DEST (set))) *************** *** 736,740 **** ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1); ! return refers_to_regno_p (regno, endregno, in, 0); } --- 736,740 ---- ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1); ! return refers_to_regno_p (regno, endregno, in, NULL_PTR); } *************** *** 780,785 **** find it easily, return 0. ! We only return a REG or constant because it is too hard to check if a ! MEM remains unchanged. */ rtx --- 780,785 ---- find it easily, return 0. ! We only return a REG, SUBREG, or constant because it is too hard to ! check if a MEM remains unchanged. */ rtx *************** *** 819,823 **** { if (CONSTANT_P (reg_set_last_value) ! || (GET_CODE (reg_set_last_value) == REG && ! reg_set_between_p (reg_set_last_value, NEXT_INSN (insn), orig_insn))) --- 819,824 ---- { if (CONSTANT_P (reg_set_last_value) ! || ((GET_CODE (reg_set_last_value) == REG ! || GET_CODE (reg_set_last_value) == SUBREG) && ! reg_set_between_p (reg_set_last_value, NEXT_INSN (insn), orig_insn))) *************** *** 887,890 **** --- 888,896 ---- switch (fmt[i]) { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + case 'n': case 'i': diff -rc2N gcc-2.2.2/sched.c gcc-2.3.1/sched.c *** gcc-2.2.2/sched.c Thu May 7 02:37:59 1992 --- gcc-2.3.1/sched.c Wed Oct 14 18:56:33 1992 *************** *** 47,56 **** consider this insn scheduled by setting the pointer to the "end" of the list to point to the previous insn. When an insn has no ! predecessors, we also add it to the ready list. When all insns down ! to the lowest priority have been scheduled, the critical path of the ! basic block has been made as short as possible. The remaining insns ! are then scheduled in remaining slots. ! The following list shows the order in which we want to break ties: 1. choose insn with lowest conflict cost, ties broken by --- 47,69 ---- consider this insn scheduled by setting the pointer to the "end" of the list to point to the previous insn. When an insn has no ! predecessors, we either queue it until sufficient time has elapsed ! or add it to the ready list. As the instructions are scheduled or ! when stalls are introduced, the queue advances and dumps insns into ! the ready list. When all insns down to the lowest priority have ! been scheduled, the critical path of the basic block has been made ! as short as possible. The remaining insns are then scheduled in ! remaining slots. ! ! Function unit conflicts are resolved during reverse list scheduling ! by tracking the time when each insn is committed to the schedule ! and from that, the time the function units it uses must be free. ! As insns on the ready list are considered for scheduling, those ! that would result in a blockage of the already committed insns are ! queued until no blockage will result. Among the remaining insns on ! the ready list to be considered, the first one with the largest ! potential for causing a subsequent blockage is chosen. ! The following list shows the order in which we want to break ties ! among insns in the ready list: 1. choose insn with lowest conflict cost, ties broken by *************** *** 112,115 **** --- 125,129 ---- #include "insn-attr.h" + #ifdef INSN_SCHEDULING /* Arrays set up by scheduling for the same respective purposes as similar-named arrays set up by flow analysis. We work with these *************** *** 141,144 **** --- 155,182 ---- #define INSN_COST(INSN) insn_costs[INSN_UID (INSN)] + /* Vector indexed by INSN_UID giving an encoding of the function units + used. */ + static short *insn_units; + #define INSN_UNIT(INSN) insn_units[INSN_UID (INSN)] + + /* Vector indexed by INSN_UID giving an encoding of the blockage range + function. The unit and the range are encoded. */ + static unsigned int *insn_blockage; + #define INSN_BLOCKAGE(INSN) insn_blockage[INSN_UID (INSN)] + #define UNIT_BITS 5 + #define BLOCKAGE_MASK ((1 << BLOCKAGE_BITS) - 1) + #define ENCODE_BLOCKAGE(U,R) \ + ((((U) << UNIT_BITS) << BLOCKAGE_BITS \ + | MIN_BLOCKAGE_COST (R)) << BLOCKAGE_BITS \ + | MAX_BLOCKAGE_COST (R)) + #define UNIT_BLOCKED(B) ((B) >> (2 * BLOCKAGE_BITS)) + #define BLOCKAGE_RANGE(B) \ + (((((B) >> BLOCKAGE_BITS) & BLOCKAGE_MASK) << (HOST_BITS_PER_INT / 2)) \ + | (B) & BLOCKAGE_MASK) + + /* Encodings of the `_unit_blockage_range' function. */ + #define MIN_BLOCKAGE_COST(R) ((R) >> (HOST_BITS_PER_INT / 2)) + #define MAX_BLOCKAGE_COST(R) ((R) & ((1 << (HOST_BITS_PER_INT / 2)) - 1)) + #define DONE_PRIORITY -1 #define MAX_PRIORITY 0x7fffffff *************** *** 189,220 **** have already been scheduled. It is important to ensure that all insns which use its result will not be executed until its result ! has been computed. We maintain three lists (conceptually): ! (1) a "Ready" list of unscheduled, uncommitted insns ! (2) a "Scheduled" list of scheduled insns ! (3) a "Pending" list of insns which can be scheduled, but ! for stalls. ! ! Insns move from the "Ready" list to the "Pending" list when ! all insns following them have been scheduled. ! ! Insns move from the "Pending" list to the "Scheduled" list ! when there is sufficient space in the pipeline to prevent ! stalls between the insn and scheduled insns which use it. ! ! The "Pending" list acts as a buffer to prevent insns ! from avalanching. ! ! The "Ready" list is implemented by the variable `ready'. ! The "Pending" list are the insns in the LOG_LINKS of ready insns. ! The "Scheduled" list is the new insn chain built by this pass. */ ! ! /* Implement a circular buffer from which instructions are issued. */ ! #define Q_SIZE 128 ! static rtx insn_queue[Q_SIZE]; static int q_ptr = 0; static int q_size = 0; ! #define NEXT_Q(X) (((X)+1) & (Q_SIZE-1)) ! #define NEXT_Q_AFTER(X,C) (((X)+C) & (Q_SIZE-1)) /* Forward declarations. */ --- 227,283 ---- have already been scheduled. It is important to ensure that all insns which use its result will not be executed until its result ! has been computed. An insn is maintained in one of four structures: ! (P) the "Pending" set of insns which cannot be scheduled until ! their dependencies have been satisfied. ! (Q) the "Queued" set of insns that can be scheduled when sufficient ! time has passed. ! (R) the "Ready" list of unscheduled, uncommitted insns. ! (S) the "Scheduled" list of insns. ! ! Initially, all insns are either "Pending" or "Ready" depending on ! whether their dependencies are satisfied. ! ! Insns move from the "Ready" list to the "Scheduled" list as they ! are committed to the schedule. As this occurs, the insns in the ! "Pending" list have their dependencies satisfied and move to either ! the "Ready" list or the "Queued" set depending on whether ! sufficient time has passed to make them ready. As time passes, ! insns move from the "Queued" set to the "Ready" list. Insns may ! move from the "Ready" list to the "Queued" set if they are blocked ! due to a function unit conflict. ! ! The "Pending" list (P) are the insns in the LOG_LINKS of the unscheduled ! insns, i.e., those that are ready, queued, and pending. ! The "Queued" set (Q) is implemented by the variable `insn_queue'. ! The "Ready" list (R) is implemented by the variables `ready' and ! `n_ready'. ! The "Scheduled" list (S) is the new insn chain built by this pass. ! ! The transition (R->S) is implemented in the scheduling loop in ! `schedule_block' when the best insn to schedule is chosen. ! The transition (R->Q) is implemented in `schedule_select' when an ! insn is found to to have a function unit conflict with the already ! committed insns. ! The transitions (P->R and P->Q) are implemented in `schedule_insn' as ! insns move from the ready list to the scheduled list. ! The transition (Q->R) is implemented at the top of the scheduling ! loop in `schedule_block' as time passes or stalls are introduced. */ ! ! /* Implement a circular buffer to delay instructions until sufficient ! time has passed. INSN_QUEUE_SIZE is a power of two larger than ! MAX_BLOCKAGE and MAX_READY_COST computed by genattr.c. This is the ! longest time an isnsn may be queued. */ ! static rtx insn_queue[INSN_QUEUE_SIZE]; static int q_ptr = 0; static int q_size = 0; ! #define NEXT_Q(X) (((X)+1) & (INSN_QUEUE_SIZE-1)) ! #define NEXT_Q_AFTER(X,C) (((X)+C) & (INSN_QUEUE_SIZE-1)) ! ! /* Vector indexed by INSN_UID giving the minimum clock tick at which ! the insn becomes ready. This is used to note timing constraints for ! insns in the pending list. */ ! static int *insn_tick; ! #define INSN_TICK(INSN) (insn_tick[INSN_UID (INSN)]) /* Forward declarations. */ *************** *** 224,227 **** --- 287,291 ---- /* Main entry point of this file. */ void schedule_insns (); + #endif /* INSN_SCHEDULING */ #define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X))) *************** *** 285,289 **** && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 && reg_n_sets[REGNO (SET_DEST (set))] == 1) ! || (note = find_reg_note (insn, REG_EQUIV, 0)) != 0) && GET_CODE (XEXP (note, 0)) != EXPR_LIST) reg_known_value[REGNO (SET_DEST (set))] = XEXP (note, 0); --- 349,353 ---- && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0 && reg_n_sets[REGNO (SET_DEST (set))] == 1) ! || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0) && GET_CODE (XEXP (note, 0)) != EXPR_LIST) reg_known_value[REGNO (SET_DEST (set))] = XEXP (note, 0); *************** *** 347,350 **** --- 411,419 ---- switch (fmt[i]) { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + case 'n': case 'i': *************** *** 450,454 **** rtx x, y; int xsize, ysize; ! int c; { if (GET_CODE (x) == HIGH) --- 519,523 ---- rtx x, y; int xsize, ysize; ! HOST_WIDE_INT c; { if (GET_CODE (x) == HIGH) *************** *** 649,653 **** rtx x; { ! if (RTX_UNCHANGING_P (x)) return 0; --- 718,729 ---- rtx x; { ! /* If X is an unchanging read, then it can't possibly conflict with any ! non-unchanging store. It may conflict with an unchanging write though, ! because there may be a single store to this address to initialize it. ! Just fall through to the code below to resolve the case where we have ! both an unchanging read and an unchanging write. This won't handle all ! cases optimally, but the possible performance loss should be ! negligible. */ ! if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem)) return 0; *************** *** 668,671 **** --- 744,750 ---- rtx x; { + /* If MEM is an unchanging read, then it can't possibly conflict with + the store to X, because there is at most one store to MEM, and it must + have occured somewhere before MEM. */ if (RTX_UNCHANGING_P (mem)) return 0; *************** *** 894,929 **** } ! /* Compute cost of executing INSN. This is the number of virtual ! cycles taken between instruction issue and instruction results. */ __inline static int ! insn_cost (insn) rtx insn; { ! register int cost; ! if (INSN_COST (insn)) ! return INSN_COST (insn); ! recog_memoized (insn); ! /* A USE insn, or something else we don't need to understand. ! We can't pass these directly to result_ready_cost because it will trigger ! a fatal error for unrecognizable insns. */ ! if (INSN_CODE (insn) < 0) { ! INSN_COST (insn) = 1; ! return 1; } else { ! cost = result_ready_cost (insn); ! if (cost < 1) ! cost = 1; ! INSN_COST (insn) = cost; ! return cost; } } --- 973,1309 ---- } ! /* Compute the function units used by INSN. This caches the value ! returned by function_units_used. A function unit is encoded as the ! unit number if the value is non-negative and the compliment of a ! mask if the value is negative. A function unit index is the ! non-negative encoding. */ __inline static int ! insn_unit (insn) rtx insn; { ! register int unit = INSN_UNIT (insn); ! ! if (unit == 0) ! { ! recog_memoized (insn); ! /* A USE insn, or something else we don't need to understand. ! We can't pass these directly to function_units_used because it will ! trigger a fatal error for unrecognizable insns. */ ! if (INSN_CODE (insn) < 0) ! unit = -1; ! else ! { ! unit = function_units_used (insn); ! /* Increment non-negative values so we can cache zero. */ ! if (unit >= 0) unit++; ! } ! /* We only cache 16 bits of the result, so if the value is out of ! range, don't cache it. */ ! if (FUNCTION_UNITS_SIZE < HOST_BITS_PER_SHORT ! || unit >= 0 ! || (~unit & ((1 << (HOST_BITS_PER_SHORT - 1)) - 1)) == 0) ! INSN_UNIT (insn) = unit; ! } ! return (unit > 0 ? unit - 1 : unit); ! } ! /* Compute the blockage range for executing INSN on UNIT. This caches ! the value returned by the blockage_range_function for the unit. ! These values are encoded in an int where the upper half gives the ! minimum value and the lower half gives the maximum value. */ ! ! __inline static unsigned int ! blockage_range (unit, insn) ! int unit; ! rtx insn; ! { ! unsigned int blockage = INSN_BLOCKAGE (insn); ! unsigned int range; ! if (UNIT_BLOCKED (blockage) != unit + 1) { ! range = function_units[unit].blockage_range_function (insn); ! /* We only cache the blockage range for one unit and then only if ! the values fit. */ ! if (HOST_BITS_PER_INT >= UNIT_BITS + 2 * BLOCKAGE_BITS) ! INSN_BLOCKAGE (insn) = ENCODE_BLOCKAGE (unit + 1, range); ! } ! else ! range = BLOCKAGE_RANGE (blockage); ! ! return range; ! } ! ! /* A vector indexed by function unit instance giving the last insn to use ! the unit. The value of the function unit instance index for unit U ! instance I is (U + I * FUNCTION_UNITS_SIZE). */ ! static rtx unit_last_insn[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY]; ! ! /* A vector indexed by function unit instance giving the minimum time when ! the unit will unblock based on the maximum blockage cost. */ ! static int unit_tick[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY]; ! ! /* A vector indexed by function unit number giving the number of insns ! that remain to use the unit. */ ! static int unit_n_insns[FUNCTION_UNITS_SIZE]; ! ! /* Reset the function unit state to the null state. */ ! ! static void ! clear_units () ! { ! int unit; ! ! bzero (unit_last_insn, sizeof (unit_last_insn)); ! bzero (unit_tick, sizeof (unit_tick)); ! bzero (unit_n_insns, sizeof (unit_n_insns)); ! } ! ! /* Record an insn as one that will use the units encoded by UNIT. */ ! ! __inline static void ! prepare_unit (unit) ! int unit; ! { ! int i; ! ! if (unit >= 0) ! unit_n_insns[unit]++; ! else ! for (i = 0, unit = ~unit; unit; i++, unit >>= 1) ! if ((unit & 1) != 0) ! prepare_unit (i); ! } ! ! /* Return the actual hazard cost of executing INSN on the unit UNIT, ! instance INSTANCE at time CLOCK if the previous actual hazard cost ! was COST. */ ! ! __inline static int ! actual_hazard_this_instance (unit, instance, insn, clock, cost) ! int unit, instance, clock, cost; ! rtx insn; ! { ! int i; ! int tick = unit_tick[instance]; ! ! if (tick - clock > cost) ! { ! /* The scheduler is operating in reverse, so INSN is the executing ! insn and the unit's last insn is the candidate insn. We want a ! more exact measure of the blockage if we execute INSN at CLOCK ! given when we committed the execution of the unit's last insn. ! ! The blockage value is given by either the unit's max blockage ! constant, blockage range function, or blockage function. Use ! the most exact form for the given unit. */ ! ! if (function_units[unit].blockage_range_function) ! { ! if (function_units[unit].blockage_function) ! tick += (function_units[unit].blockage_function ! (insn, unit_last_insn[instance]) ! - function_units[unit].max_blockage); ! else ! tick += ((int) MAX_BLOCKAGE_COST (blockage_range (unit, insn)) ! - function_units[unit].max_blockage); ! } ! if (tick - clock > cost) ! cost = tick - clock; ! } ! return cost; ! } ! ! /* Record INSN as having begun execution on the units encoded by UNIT at ! time CLOCK. */ ! ! __inline static void ! schedule_unit (unit, insn, clock) ! int unit, clock; ! rtx insn; ! { ! int i; ! ! if (unit >= 0) ! { ! int instance = unit; ! #if MAX_MULTIPLICITY > 1 ! /* Find the first free instance of the function unit and use that ! one. We assume that one is free. */ ! for (i = function_units[unit].multiplicity - 1; i > 0; i--) ! { ! if (! actual_hazard_this_instance (unit, instance, insn, clock, 0)) ! break; ! instance += FUNCTION_UNITS_SIZE; ! } ! #endif ! unit_last_insn[instance] = insn; ! unit_tick[instance] = (clock + function_units[unit].max_blockage); } else + for (i = 0, unit = ~unit; unit; i++, unit >>= 1) + if ((unit & 1) != 0) + schedule_unit (i, insn, clock); + } + + /* Return the actual hazard cost of executing INSN on the units encoded by + UNIT at time CLOCK if the previous actual hazard cost was COST. */ + + __inline static int + actual_hazard (unit, insn, clock, cost) + int unit, clock, cost; + rtx insn; + { + int i; + + if (unit >= 0) + { + /* Find the instance of the function unit with the minimum hazard. */ + int instance = unit; + int best = instance; + int best_cost = actual_hazard_this_instance (unit, instance, insn, + clock, cost); + int this_cost; + + #if MAX_MULTIPLICITY > 1 + if (best_cost > cost) + { + for (i = function_units[unit].multiplicity - 1; i > 0; i--) + { + instance += FUNCTION_UNITS_SIZE; + this_cost = actual_hazard_this_instance (unit, instance, insn, + clock, cost); + if (this_cost < best_cost) + { + best = instance; + best_cost = this_cost; + if (this_cost <= cost) + break; + } + } + } + #endif + cost = MAX (cost, best_cost); + } + else + for (i = 0, unit = ~unit; unit; i++, unit >>= 1) + if ((unit & 1) != 0) + cost = actual_hazard (i, insn, clock, cost); + + return cost; + } + + /* Return the potential hazard cost of executing an instruction on the + units encoded by UNIT if the previous potential hazard cost was COST. + An insn with a large blockage time is chosen in preference to one + with a smaller time; an insn that uses a unit that is more likely + to be used is chosen in preference to one with a unit that is less + used. We are trying to minimize a subsequent actual hazard. */ + + __inline static int + potential_hazard (unit, insn, cost) + int unit, cost; + rtx insn; + { + int i, ncost; + unsigned int minb, maxb; + + if (unit >= 0) + { + minb = maxb = function_units[unit].max_blockage; + if (maxb > 1) + { + if (function_units[unit].blockage_range_function) + { + maxb = minb = blockage_range (unit, insn); + maxb = MAX_BLOCKAGE_COST (maxb); + minb = MIN_BLOCKAGE_COST (minb); + } + + if (maxb > 1) + { + /* Make the number of instructions left dominate. Make the + minimum delay dominate the maximum delay. If all these + are the same, use the unit number to add an arbitrary + ordering. Other terms can be added. */ + ncost = minb * 0x40 + maxb; + ncost *= (unit_n_insns[unit] - 1) * 0x1000 + unit; + if (ncost > cost) + cost = ncost; + } + } + } + else + for (i = 0, unit = ~unit; unit; i++, unit >>= 1) + if ((unit & 1) != 0) + cost = potential_hazard (i, insn, cost); + + return cost; + } + + /* Compute cost of executing INSN given the dependence LINK on the insn USED. + This is the number of virtual cycles taken between instruction issue and + instruction results. */ + + __inline static int + insn_cost (insn, link, used) + rtx insn, link, used; + { + register int cost = INSN_COST (insn); + + if (cost == 0) { ! recog_memoized (insn); ! ! /* A USE insn, or something else we don't need to understand. ! We can't pass these directly to result_ready_cost because it will ! trigger a fatal error for unrecognizable insns. */ ! if (INSN_CODE (insn) < 0) ! { ! INSN_COST (insn) = 1; ! return 1; ! } ! else ! { ! cost = result_ready_cost (insn); ! ! if (cost < 1) ! cost = 1; ! ! INSN_COST (insn) = cost; ! } ! } ! ! /* A USE insn should never require the value used to be computed. This ! allows the computation of a function's result and parameter values to ! overlap the return and call. */ ! recog_memoized (used); ! if (INSN_CODE (used) < 0) ! LINK_COST_FREE (link) = 1; ! /* If some dependencies vary the cost, compute the adjustment. Most ! commonly, the adjustment is complete: either the cost is ignored ! (in the case of an output- or anti-dependence), or the cost is ! unchanged. These values are cached in the link as LINK_COST_FREE ! and LINK_COST_ZERO. */ ! ! if (LINK_COST_FREE (link)) ! cost = 1; ! #ifdef ADJUST_COST ! else if (! LINK_COST_ZERO (link)) ! { ! int ncost = cost; ! ADJUST_COST (used, link, insn, ncost); ! if (ncost <= 1) ! LINK_COST_FREE (link) = ncost = 1; ! if (cost == ncost) ! LINK_COST_ZERO (link) = 1; ! cost = ncost; } + #endif + return cost; } *************** *** 971,974 **** --- 1351,1360 ---- } + /* Clear the link cost adjustment bits. */ + LINK_COST_FREE (prev) = 0; + #ifdef ADJUST_COST + LINK_COST_ZERO (prev) = 0; + #endif + /* This priority calculation was chosen because it results in the least instruction movement, and does not hurt the performance *************** *** 989,993 **** if (REG_NOTE_KIND (prev) == 0) /* Data dependence. */ ! prev_priority = priority (x) + insn_cost (x) - 1; else /* Anti or output dependence. Don't add the latency of this --- 1375,1379 ---- if (REG_NOTE_KIND (prev) == 0) /* Data dependence. */ ! prev_priority = priority (x) + insn_cost (x, prev, insn) - 1; else /* Anti or output dependence. Don't add the latency of this *************** *** 1000,1003 **** --- 1386,1390 ---- } + prepare_unit (insn_unit (insn)); INSN_PRIORITY (insn) = max_priority; return INSN_PRIORITY (insn); *************** *** 1331,1335 **** /* Make a copy of all dependencies on the immediately previous insn, and add to this insn. This is so that all the dependencies will ! apply to the group. */ prev = PREV_INSN (insn); --- 1718,1723 ---- /* Make a copy of all dependencies on the immediately previous insn, and add to this insn. This is so that all the dependencies will ! apply to the group. Remove an explicit dependence on this insn ! as SCHED_GROUP_P now represents it. */ prev = PREV_INSN (insn); *************** *** 1337,1340 **** --- 1725,1731 ---- prev = PREV_INSN (prev); + if (find_insn_list (prev, LOG_LINKS (insn))) + remove_dependence (insn, prev); + for (link = LOG_LINKS (prev); link; link = XEXP (link, 1)) add_dependence (insn, XEXP (link, 0), GET_MODE (link)); *************** *** 1385,1428 **** /* Reading memory. */ ! /* Don't create a dependence for memory references which are known to ! be unchanging, such as constant pool accesses. These will never ! conflict with any other memory access. */ ! if (RTX_UNCHANGING_P (x) == 0) { ! rtx pending, pending_mem; ! pending = pending_read_insns; ! pending_mem = pending_read_mems; ! while (pending) ! { ! /* If a dependency already exists, don't create a new one. */ ! if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn))) ! if (read_dependence (XEXP (pending_mem, 0), x)) ! add_dependence (insn, XEXP (pending, 0), REG_DEP_ANTI); ! pending = XEXP (pending, 1); ! pending_mem = XEXP (pending_mem, 1); ! } ! pending = pending_write_insns; ! pending_mem = pending_write_mems; ! while (pending) ! { ! /* If a dependency already exists, don't create a new one. */ ! if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn))) ! if (true_dependence (XEXP (pending_mem, 0), x)) ! add_dependence (insn, XEXP (pending, 0), 0); ! pending = XEXP (pending, 1); ! pending_mem = XEXP (pending_mem, 1); ! } ! if (last_pending_memory_flush) ! add_dependence (insn, last_pending_memory_flush, REG_DEP_ANTI); - /* Always add these dependencies to pending_reads, since - this insn may be followed by a write. */ - add_insn_mem_dependence (&pending_read_insns, &pending_read_mems, - insn, x); - } /* Take advantage of tail recursion here. */ sched_analyze_2 (XEXP (x, 0), insn); --- 1776,1814 ---- /* Reading memory. */ ! rtx pending, pending_mem; ! ! pending = pending_read_insns; ! pending_mem = pending_read_mems; ! while (pending) { ! /* If a dependency already exists, don't create a new one. */ ! if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn))) ! if (read_dependence (XEXP (pending_mem, 0), x)) ! add_dependence (insn, XEXP (pending, 0), REG_DEP_ANTI); ! pending = XEXP (pending, 1); ! pending_mem = XEXP (pending_mem, 1); ! } ! pending = pending_write_insns; ! pending_mem = pending_write_mems; ! while (pending) ! { ! /* If a dependency already exists, don't create a new one. */ ! if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn))) ! if (true_dependence (XEXP (pending_mem, 0), x)) ! add_dependence (insn, XEXP (pending, 0), 0); ! pending = XEXP (pending, 1); ! pending_mem = XEXP (pending_mem, 1); ! } ! if (last_pending_memory_flush) ! add_dependence (insn, last_pending_memory_flush, REG_DEP_ANTI); ! /* Always add these dependencies to pending_reads, since ! this insn may be followed by a write. */ ! add_insn_mem_dependence (&pending_read_insns, &pending_read_mems, ! insn, x); /* Take advantage of tail recursion here. */ sched_analyze_2 (XEXP (x, 0), insn); *************** *** 1475,1479 **** case PRE_INC: case POST_INC: ! /* These read and modify the result; just consider them writes. */ sched_analyze_1 (x, insn); return; --- 1861,1871 ---- case PRE_INC: case POST_INC: ! /* These both read and modify the result. We must handle them as writes ! to get proper dependencies for following instructions. We must handle ! them as reads to get proper dependencies from this to previous ! instructions. Thus we need to pass them to both sched_analyze_1 ! and sched_analyze_2. We must call sched_analyze_2 first in order ! to get the proper antecedent for the read. */ ! sched_analyze_2 (XEXP (x, 0), insn); sched_analyze_1 (x, insn); return; *************** *** 1651,1659 **** /* Must treat modification of just one hardware register of a multi-reg value or just a byte field of a register exactly the same way that ! mark_set_1 in flow.c does. */ ! if (GET_CODE (reg) == ZERO_EXTRACT ! || GET_CODE (reg) == SIGN_EXTRACT ! || (GET_CODE (reg) == SUBREG ! && REG_SIZE (SUBREG_REG (reg)) > REG_SIZE (reg))) subreg_p = 1; --- 2043,2050 ---- /* Must treat modification of just one hardware register of a multi-reg value or just a byte field of a register exactly the same way that ! mark_set_1 in flow.c does, i.e. anything except a paradoxical subreg ! does not kill the entire register. */ ! if (GET_CODE (reg) != SUBREG ! || REG_SIZE (SUBREG_REG (reg)) > REG_SIZE (reg)) subreg_p = 1; *************** *** 1671,1675 **** { register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); if (death) --- 2062,2067 ---- { register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); if (death) *************** *** 1687,1691 **** { offset = (regno + j) / REGSET_ELT_BITS; ! bit = 1 << ((regno + j) % REGSET_ELT_BITS); bb_live_regs[offset] &= ~bit; --- 2079,2083 ---- { offset = (regno + j) / REGSET_ELT_BITS; ! bit = (REGSET_ELT_TYPE) 1 << ((regno + j) % REGSET_ELT_BITS); bb_live_regs[offset] &= ~bit; *************** *** 1708,1712 **** { offset = (regno + j) / REGSET_ELT_BITS; ! bit = 1 << ((regno + j) % REGSET_ELT_BITS); bb_live_regs[offset] |= bit; --- 2100,2104 ---- { offset = (regno + j) / REGSET_ELT_BITS; ! bit = (REGSET_ELT_TYPE) 1 << ((regno + j) % REGSET_ELT_BITS); bb_live_regs[offset] |= bit; *************** *** 1743,1747 **** rtx tmp = *y; rtx tmp2 = *x; ! rtx tmp_dep, tmp2_dep; int tmp_class, tmp2_class; int value; --- 2135,2139 ---- rtx tmp = *y; rtx tmp2 = *x; ! rtx link; int tmp_class, tmp2_class; int value; *************** *** 1758,1773 **** 3) Independent of last scheduled insn, or has latency of one. Choose the insn from the highest numbered class if different. */ ! tmp_dep = find_insn_list (tmp, LOG_LINKS (last_scheduled_insn)); ! if (tmp_dep == 0 || insn_cost (tmp) == 1) tmp_class = 3; ! else if (REG_NOTE_KIND (tmp_dep) == 0) tmp_class = 1; else tmp_class = 2; ! tmp2_dep = find_insn_list (tmp2, LOG_LINKS (last_scheduled_insn)); ! if (tmp2_dep == 0 || insn_cost (tmp2) == 1) tmp2_class = 3; ! else if (REG_NOTE_KIND (tmp2_dep) == 0) tmp2_class = 1; else --- 2150,2165 ---- 3) Independent of last scheduled insn, or has latency of one. Choose the insn from the highest numbered class if different. */ ! link = find_insn_list (tmp, LOG_LINKS (last_scheduled_insn)); ! if (link == 0 || insn_cost (tmp, link, last_scheduled_insn) == 1) tmp_class = 3; ! else if (REG_NOTE_KIND (link) == 0) /* Data dependence. */ tmp_class = 1; else tmp_class = 2; ! link = find_insn_list (tmp2, LOG_LINKS (last_scheduled_insn)); ! if (link == 0 || insn_cost (tmp2, link, last_scheduled_insn) == 1) tmp2_class = 3; ! else if (REG_NOTE_KIND (link) == 0) /* Data dependence. */ tmp2_class = 1; else *************** *** 1836,1840 **** int i = REGNO (dest); int offset = i / REGSET_ELT_BITS; ! int bit = 1 << (i % REGSET_ELT_BITS); /* It would be more accurate to use refers_to_regno_p or --- 2228,2232 ---- int i = REGNO (dest); int offset = i / REGSET_ELT_BITS; ! REGSET_ELT_TYPE bit = (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS); /* It would be more accurate to use refers_to_regno_p or *************** *** 1856,1878 **** } ! /* If PREV is an insn which is immediately ready to execute, return 1, ! otherwise return 0. We may adjust its priority if that will help shorten ! register lifetimes. */ ! static int ! launch_link (prev) rtx prev; { - rtx pat = PATTERN (prev); - rtx note; - /* MAX of (a) number of cycles needed by prev - (b) number of cycles before needed resources are free. */ - int n_cycles = insn_cost (prev); - int n_deaths = 0; - /* Trying to shorten register lives after reload has completed is useless and wrong. It gives inaccurate schedules. */ if (reload_completed == 0) { for (note = REG_NOTES (prev); note; note = XEXP (note, 1)) if (REG_NOTE_KIND (note) == REG_DEAD) --- 2248,2265 ---- } ! /* PREV is an insn that is ready to execute. Adjust its priority if that ! will help shorten register lifetimes. */ ! __inline static void ! adjust_priority (prev) rtx prev; { /* Trying to shorten register lives after reload has completed is useless and wrong. It gives inaccurate schedules. */ if (reload_completed == 0) { + rtx note; + int n_deaths = 0; + for (note = REG_NOTES (prev); note; note = XEXP (note, 1)) if (REG_NOTE_KIND (note) == REG_DEAD) *************** *** 1895,1899 **** break; case 0: ! if (birthing_insn_p (pat)) { int max = max_priority; --- 2282,2286 ---- break; case 0: ! if (birthing_insn_p (PATTERN (prev))) { int max = max_priority; *************** *** 1905,1913 **** } } - - if (n_cycles <= 1) - return 1; - queue_insn (prev, n_cycles); - return 0; } --- 2292,2295 ---- *************** *** 1915,1933 **** waiting on INSN (in the backwards dataflow sense). READY is a vector of insns which are ready to fire. N_READY is the number of ! elements in READY. */ static int ! launch_links (insn, ready, n_ready) rtx insn; rtx *ready; int n_ready; { rtx link; int new_ready = n_ready; if (LOG_LINKS (insn) == 0) return n_ready; ! /* This is used by the function launch_link above. */ if (n_ready > 0) max_priority = MAX (INSN_PRIORITY (ready[0]), INSN_PRIORITY (insn)); --- 2297,2319 ---- waiting on INSN (in the backwards dataflow sense). READY is a vector of insns which are ready to fire. N_READY is the number of ! elements in READY. CLOCK is the current virtual cycle. */ static int ! schedule_insn (insn, ready, n_ready, clock) rtx insn; rtx *ready; int n_ready; + int clock; { rtx link; int new_ready = n_ready; + if (MAX_BLOCKAGE > 1) + schedule_unit (insn_unit (insn), insn, clock); + if (LOG_LINKS (insn) == 0) return n_ready; ! /* This is used by the function adjust_priority above. */ if (n_ready > 0) max_priority = MAX (INSN_PRIORITY (ready[0]), INSN_PRIORITY (insn)); *************** *** 1938,1946 **** { rtx prev = XEXP (link, 0); ! if ((INSN_REF_COUNT (prev) -= 1) == 0 && launch_link (prev)) ! ready[new_ready++] = prev; } return new_ready; } --- 2324,2449 ---- { rtx prev = XEXP (link, 0); + int cost = insn_cost (prev, link, insn); + + if ((INSN_REF_COUNT (prev) -= 1) != 0) + { + /* We satisfied one requirement to fire PREV. Record the earliest + time when PREV can fire. No need to do this if the cost is 1, + because PREV can fire no sooner than the next cycle. */ + if (cost > 1) + INSN_TICK (prev) = MAX (INSN_TICK (prev), clock + cost); + } + else + { + /* We satisfied the last requirement to fire PREV. Ensure that all + timing requirements are satisfied. */ + if (INSN_TICK (prev) - clock > cost) + cost = INSN_TICK (prev) - clock; + + /* Adjust the priority of PREV and either put it on the ready + list or queue it. */ + adjust_priority (prev); + if (cost <= 1) + ready[new_ready++] = prev; + else + queue_insn (prev, cost); + } + } + + return new_ready; + } + + /* Given N_READY insns in the ready list READY at time CLOCK, queue + those that are blocked due to function unit hazards and rearrange + the remaining ones to minimize subsequent function unit hazards. */ + + static int + schedule_select (ready, n_ready, clock, file) + rtx *ready; + int n_ready, clock; + FILE *file; + { + int pri = INSN_PRIORITY (ready[0]); + int i, j, k, q, cost, best_cost, best_insn = 0, new_ready = n_ready; + rtx insn; + + /* Work down the ready list in groups of instructions with the same + priority value. Queue insns in the group that are blocked and + select among those that remain for the one with the largest + potential hazard. */ + for (i = 0; i < n_ready; i = j) + { + int opri = pri; + for (j = i + 1; j < n_ready; j++) + if ((pri = INSN_PRIORITY (ready[j])) != opri) + break; + + /* Queue insns in the group that are blocked. */ + for (k = i, q = 0; k < j; k++) + { + insn = ready[k]; + if ((cost = actual_hazard (insn_unit (insn), insn, clock, 0)) != 0) + { + q++; + ready[k] = 0; + queue_insn (insn, cost); + if (file) + fprintf (file, "\n;; blocking insn %d for %d cycles", + INSN_UID (insn), cost); + } + } + new_ready -= q; ! /* Check the next group if all insns were queued. */ ! if (j - i - q == 0) ! continue; ! ! /* If more than one remains, select the first one with the largest ! potential hazard. */ ! else if (j - i - q > 1) ! { ! best_cost = -1; ! for (k = i; k < j; k++) ! { ! if ((insn = ready[k]) == 0) ! continue; ! if ((cost = potential_hazard (insn_unit (insn), insn, 0)) ! > best_cost) ! { ! best_cost = cost; ! best_insn = k; ! } ! } ! } ! /* We have found a suitable insn to schedule. */ ! break; ! } ! ! /* Move the best insn to be front of the ready list. */ ! if (best_insn != 0) ! { ! if (file) ! { ! fprintf (file, ", now"); ! for (i = 0; i < n_ready; i++) ! if (ready[i]) ! fprintf (file, " %d", INSN_UID (ready[i])); ! fprintf (file, "\n;; insn %d has a greater potential hazard", ! INSN_UID (ready[best_insn])); ! } ! for (i = best_insn; i > 0; i--) ! { ! insn = ready[i-1]; ! ready[i-1] = ready[i]; ! ready[i] = insn; ! } } + /* Compact the ready list. */ + if (new_ready < n_ready) + for (i = j = 0; i < n_ready; i++) + if (ready[i]) + ready[j++] = ready[i]; + return new_ready; } *************** *** 2016,2022 **** register int regno = REGNO (x); register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); ! int all_needed = (old_live_regs[offset] & bit); ! int some_needed = (old_live_regs[offset] & bit); if (set_p) --- 2519,2526 ---- register int regno = REGNO (x); register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); ! REGSET_ELT_TYPE all_needed = (old_live_regs[offset] & bit); ! REGSET_ELT_TYPE some_needed = (old_live_regs[offset] & bit); if (set_p) *************** *** 2031,2037 **** { some_needed |= (old_live_regs[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)); all_needed &= (old_live_regs[(regno + n) / REGSET_ELT_BITS] ! & 1 << ((regno + n) % REGSET_ELT_BITS)); } } --- 2535,2543 ---- { some_needed |= (old_live_regs[(regno + n) / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 ! << ((regno + n) % REGSET_ELT_BITS))); all_needed &= (old_live_regs[(regno + n) / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 ! << ((regno + n) % REGSET_ELT_BITS))); } } *************** *** 2078,2082 **** i >= 0; i--) if ((old_live_regs[(regno + i) / REGSET_ELT_BITS] ! & 1 << ((regno +i) % REGSET_ELT_BITS)) == 0 && ! dead_or_set_regno_p (insn, regno + i)) create_reg_dead_note (gen_rtx (REG, word_mode, --- 2584,2589 ---- i >= 0; i--) if ((old_live_regs[(regno + i) / REGSET_ELT_BITS] ! & ((REGSET_ELT_TYPE) 1 ! << ((regno +i) % REGSET_ELT_BITS))) == 0 && ! dead_or_set_regno_p (insn, regno + i)) create_reg_dead_note (gen_rtx (REG, word_mode, *************** *** 2093,2097 **** { offset = (regno + j) / REGSET_ELT_BITS; ! bit = 1 << ((regno + j) % REGSET_ELT_BITS); bb_dead_regs[offset] &= ~bit; --- 2600,2605 ---- { offset = (regno + j) / REGSET_ELT_BITS; ! bit ! = (REGSET_ELT_TYPE) 1 << ((regno + j) % REGSET_ELT_BITS); bb_dead_regs[offset] &= ~bit; *************** *** 2174,2186 **** attach_deaths (SET_DEST (XVECEXP (x, 0, i)), insn, 1); } ! else if (code == CLOBBER) ! attach_deaths (XEXP (XVECEXP (x, 0, i), 0), insn, 1); ! else attach_deaths (XVECEXP (x, 0, i), insn, 0); } } ! else if (code == CLOBBER) ! attach_deaths (XEXP (x, 0), insn, 1); ! else attach_deaths (x, insn, 0); } --- 2682,2694 ---- attach_deaths (SET_DEST (XVECEXP (x, 0, i)), insn, 1); } ! /* Flow does not add REG_DEAD notes to registers that die in ! clobbers, so we can't either. */ ! else if (code != CLOBBER) attach_deaths (XVECEXP (x, 0, i), insn, 0); } } ! /* Flow does not add REG_DEAD notes to registers that die in ! clobbers, so we can't either. */ ! else if (code != CLOBBER) attach_deaths (x, insn, 0); } *************** *** 2295,2298 **** --- 2803,2807 ---- int i, j, n_ready = 0, new_ready, n_insns = 0; int sched_n_insns = 0; + int clock; #define NEED_NOTHING 0 #define NEED_HEAD 1 *************** *** 2323,2326 **** --- 2832,2836 ---- reg_last_sets = (rtx *) alloca (i * sizeof (rtx)); bzero (reg_last_sets, i * sizeof (rtx)); + clear_units (); /* Remove certain insns at the beginning from scheduling, *************** *** 2387,2457 **** #endif - /* Exclude certain insns at the end of the basic block by advancing TAIL. */ - /* This isn't correct. Instead of advancing TAIL, should assign very - high priorities to these insns to guarantee that they get scheduled last. - If these insns are ignored, as is currently done, the register life info - may be incorrectly computed. */ - if (GET_CODE (tail) == INSN && GET_CODE (PATTERN (tail)) == USE) - { - /* Don't try to reorder any USE insns at the end of any block. - They must be last to ensure proper register allocation. - Exclude them all from scheduling. */ - do - { - /* If we are down to one USE insn, then there are no insns to - schedule. */ - if (head == tail) - return; - - tail = prev_nonnote_insn (tail); - } - while (GET_CODE (tail) == INSN - && GET_CODE (PATTERN (tail)) == USE); - - #if 0 - /* This short-cut does not work. See comment above. */ - if (head == tail) - return; - #endif - } - else if (GET_CODE (tail) == JUMP_INSN - && SCHED_GROUP_P (tail) == 0 - && GET_CODE (PREV_INSN (tail)) == INSN - && GET_CODE (PATTERN (PREV_INSN (tail))) == USE - && REG_FUNCTION_VALUE_P (XEXP (PATTERN (PREV_INSN (tail)), 0))) - { - /* Don't let the setting of the function's return value register - move from this jump. For the same reason we want to get the - parameters into pseudo registers as quickly as possible, we - want to set the function's return value register as late as - possible. */ - - /* If this is the only insn in the block, then there is no need to - schedule the block. */ - if (head == tail) - return; - - tail = PREV_INSN (tail); - if (head == tail) - return; - - tail = prev_nonnote_insn (tail); - - #if 0 - /* This shortcut does not work. See comment above. */ - if (head == tail) - return; - #endif - } - - #ifdef HAVE_cc0 - /* This is probably wrong. Instead of doing this, should give this insn - a very high priority to guarantee that it gets scheduled last. */ - /* Can not separate an insn that sets the condition code from one that - uses it. So we must leave an insn that sets cc0 where it is. */ - if (sets_cc0_p (PATTERN (tail))) - tail = PREV_INSN (tail); - #endif - /* Now HEAD through TAIL are the insns actually to be rearranged; Let PREV_HEAD and NEXT_TAIL enclose them. */ --- 2897,2900 ---- *************** *** 2489,2502 **** insn = tail; ! /* If the last insn is a branch, force it to be the last insn after ! scheduling. Also, don't try to reorder calls at the ends the basic ! block -- this will only lead to worse register allocation. */ ! if (GET_CODE (tail) == CALL_INSN || GET_CODE (tail) == JUMP_INSN) ! { ! priority (tail); ! ready[n_ready++] = tail; ! INSN_PRIORITY (tail) = TAIL_PRIORITY; ! INSN_REF_COUNT (tail) = 0; ! insn = PREV_INSN (tail); } --- 2932,2982 ---- insn = tail; ! /* For all branches, calls, uses, and cc0 setters, force them to remain ! in order at the end of the block by adding dependencies and giving ! the last a high priority. There may be notes present, and prev_head ! may also be a note. ! ! Branches must obviously remain at the end. Calls should remain at the ! end since moving them results in worse register allocation. Uses remain ! at the end to ensure proper register allocation. cc0 setters remaim ! at the end because they can't be moved away from their cc0 user. */ ! last = 0; ! while (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN ! || (GET_CODE (insn) == INSN ! && (GET_CODE (PATTERN (insn)) == USE ! #ifdef HAVE_cc0 ! || sets_cc0_p (PATTERN (insn)) ! #endif ! )) ! || GET_CODE (insn) == NOTE) ! { ! if (GET_CODE (insn) != NOTE) ! { ! priority (insn); ! if (last == 0) ! { ! ready[n_ready++] = insn; ! INSN_PRIORITY (insn) = TAIL_PRIORITY - i; ! INSN_REF_COUNT (insn) = 0; ! } ! else if (! find_insn_list (insn, LOG_LINKS (last))) ! { ! add_dependence (last, insn, REG_DEP_ANTI); ! INSN_REF_COUNT (insn)++; ! } ! last = insn; ! ! /* Skip over insns that are part of a group. */ ! while (SCHED_GROUP_P (insn)) ! { ! insn = prev_nonnote_insn (insn); ! priority (insn); ! } ! } ! ! insn = PREV_INSN (insn); ! /* Don't overrun the bounds of the basic block. */ ! if (insn == prev_head) ! break; } *************** *** 2514,2518 **** priority (insn); if (INSN_REF_COUNT (insn) == 0) ! ready[n_ready++] = insn; if (SCHED_GROUP_P (insn)) { --- 2994,3008 ---- priority (insn); if (INSN_REF_COUNT (insn) == 0) ! { ! if (last == 0) ! ready[n_ready++] = insn; ! else ! { ! /* Make this dependent on the last of the instructions ! that must remain in order at the end of the block. */ ! add_dependence (last, insn, REG_DEP_ANTI); ! INSN_REF_COUNT (insn) = 1; ! } ! } if (SCHED_GROUP_P (insn)) { *************** *** 2624,2628 **** register int regno = REGNO (XEXP (link, 0)); register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); if (regno < FIRST_PSEUDO_REGISTER) --- 3114,3119 ---- register int regno = REGNO (XEXP (link, 0)); register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); if (regno < FIRST_PSEUDO_REGISTER) *************** *** 2633,2637 **** { offset = (regno + j) / REGSET_ELT_BITS; ! bit = 1 << ((regno + j) % REGSET_ELT_BITS); bb_live_regs[offset] &= ~bit; --- 3124,3129 ---- { offset = (regno + j) / REGSET_ELT_BITS; ! bit = ((REGSET_ELT_TYPE) 1 ! << ((regno + j) % REGSET_ELT_BITS)); bb_live_regs[offset] &= ~bit; *************** *** 2727,2731 **** register int regno = REGNO (XEXP (link, 0)); register int offset = regno / REGSET_ELT_BITS; ! register int bit = 1 << (regno % REGSET_ELT_BITS); /* Only unlink REG_DEAD notes; leave REG_UNUSED notes --- 3219,3224 ---- register int regno = REGNO (XEXP (link, 0)); register int offset = regno / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS); /* Only unlink REG_DEAD notes; leave REG_UNUSED notes *************** *** 2750,2754 **** { offset = (regno + j) / REGSET_ELT_BITS; ! bit = 1 << ((regno + j) % REGSET_ELT_BITS); bb_live_regs[offset] &= ~bit; --- 3243,3248 ---- { offset = (regno + j) / REGSET_ELT_BITS; ! bit = ((REGSET_ELT_TYPE) 1 ! << ((regno + j) % REGSET_ELT_BITS)); bb_live_regs[offset] &= ~bit; *************** *** 2779,2789 **** for (j = 0; j < regset_size; j++) { ! int live = bb_live_regs[j]; old_live_regs[j] = live; if (live) { ! register int bit; for (bit = 0; bit < REGSET_ELT_BITS; bit++) ! if (live & (1 << bit)) sometimes_max = new_sometimes_live (regs_sometimes_live, j, bit, sometimes_max); --- 3273,3283 ---- for (j = 0; j < regset_size; j++) { ! REGSET_ELT_TYPE live = bb_live_regs[j]; old_live_regs[j] = live; if (live) { ! register REGSET_ELT_TYPE bit; for (bit = 0; bit < REGSET_ELT_BITS; bit++) ! if (live & ((REGSET_ELT_TYPE) 1 << bit)) sometimes_max = new_sometimes_live (regs_sometimes_live, j, bit, sometimes_max); *************** *** 2810,2817 **** /* Now HEAD and TAIL are going to become disconnected entirely from the insn chain. */ ! tail = ready[0]; /* Q_SIZE will always be zero here. */ ! q_ptr = 0; bzero (insn_queue, sizeof (insn_queue)); --- 3304,3311 ---- /* Now HEAD and TAIL are going to become disconnected entirely from the insn chain. */ ! tail = 0; /* Q_SIZE will always be zero here. */ ! q_ptr = 0; clock = 0; bzero (insn_queue, sizeof (insn_queue)); *************** *** 2829,2833 **** while (sched_n_insns < n_insns) { ! q_ptr = NEXT_Q (q_ptr); /* Add all pending insns that can be scheduled without stalls to the --- 3323,3327 ---- while (sched_n_insns < n_insns) { ! q_ptr = NEXT_Q (q_ptr); clock++; /* Add all pending insns that can be scheduled without stalls to the *************** *** 2836,2841 **** { if (file) ! fprintf (file, ";; launching %d before %d with no stalls\n", ! INSN_UID (insn), INSN_UID (last)); ready[new_ready++] = insn; q_size -= 1; --- 3330,3335 ---- { if (file) ! fprintf (file, ";; launching %d before %d with no stalls at T-%d\n", ! INSN_UID (insn), INSN_UID (last), clock); ready[new_ready++] = insn; q_size -= 1; *************** *** 2849,2853 **** register int stalls; ! for (stalls = 1; stalls < Q_SIZE; stalls++) if (insn = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]) { --- 3343,3347 ---- register int stalls; ! for (stalls = 1; stalls < INSN_QUEUE_SIZE; stalls++) if (insn = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]) { *************** *** 2855,2860 **** { if (file) ! fprintf (file, ";; issue insn %d before %d with %d stalls\n", ! INSN_UID (insn), INSN_UID (last), stalls); ready[new_ready++] = insn; q_size -= 1; --- 3349,3354 ---- { if (file) ! fprintf (file, ";; launching %d before %d with %d stalls at T-%d\n", ! INSN_UID (insn), INSN_UID (last), stalls, clock); ready[new_ready++] = insn; q_size -= 1; *************** *** 2864,2872 **** } ! #if 0 ! /* This looks logically correct, but on the SPEC benchmark set on ! the SPARC, I get better code without it. */ ! q_ptr = NEXT_Q_AFTER (q_ptr, stalls); ! #endif } --- 3358,3362 ---- } ! q_ptr = NEXT_Q_AFTER (q_ptr, stalls); clock += stalls; } *************** *** 2875,2886 **** abort (); ! /* Sort the ready list and choose the best insn to schedule. N_READY holds the number of items that were scheduled the last time, minus the one instruction scheduled on the last loop iteration; it is not modified for any other reason in this loop. */ SCHED_SORT (ready, new_ready, n_ready); n_ready = new_ready; last_scheduled_insn = insn = ready[0]; if (DONE_PRIORITY_P (insn)) abort (); --- 3365,3410 ---- abort (); ! if (file) ! { ! fprintf (file, ";; ready list at T-%d:", clock); ! for (i = 0; i < new_ready; i++) ! fprintf (file, " %d (%x)", ! INSN_UID (ready[i]), INSN_PRIORITY (ready[i])); ! } ! ! /* Sort the ready list and choose the best insn to schedule. Select ! which insn should issue in this cycle and queue those that are ! blocked by function unit hazards. ! N_READY holds the number of items that were scheduled the last time, minus the one instruction scheduled on the last loop iteration; it is not modified for any other reason in this loop. */ + SCHED_SORT (ready, new_ready, n_ready); + if (MAX_BLOCKAGE > 1) + { + new_ready = schedule_select (ready, new_ready, clock, file); + if (new_ready == 0) + { + if (file) + fprintf (file, "\n"); + continue; + } + } n_ready = new_ready; last_scheduled_insn = insn = ready[0]; + /* The first insn scheduled becomes the new tail. */ + if (tail == 0) + tail = insn; + + if (file) + { + fprintf (file, ", now"); + for (i = 0; i < n_ready; i++) + fprintf (file, " %d", INSN_UID (ready[i])); + fprintf (file, "\n"); + } + if (DONE_PRIORITY_P (insn)) abort (); *************** *** 2927,2931 **** { register int offset = i / REGSET_ELT_BITS; ! register int bit = 1 << (i % REGSET_ELT_BITS); bb_live_regs[offset] &= ~bit; --- 3451,3456 ---- { register int offset = i / REGSET_ELT_BITS; ! register REGSET_ELT_TYPE bit ! = (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS); bb_live_regs[offset] &= ~bit; *************** *** 2941,2945 **** p = regs_sometimes_live; for (i = 0; i < sometimes_max; i++, p++) ! if (bb_live_regs[p->offset] & (1 << p->bit)) p->calls_crossed += 1; } --- 3466,3471 ---- p = regs_sometimes_live; for (i = 0; i < sometimes_max; i++, p++) ! if (bb_live_regs[p->offset] ! & ((REGSET_ELT_TYPE) 1 << p->bit)) p->calls_crossed += 1; } *************** *** 2952,2956 **** for (i = 0; i < regset_size; i++) { ! int diff = bb_live_regs[i] & ~old_live_regs[i]; if (diff) { --- 3478,3482 ---- for (i = 0; i < regset_size; i++) { ! REGSET_ELT_TYPE diff = bb_live_regs[i] & ~old_live_regs[i]; if (diff) { *************** *** 2958,2962 **** old_live_regs[i] |= diff; for (bit = 0; bit < REGSET_ELT_BITS; bit++) ! if (diff & (1 << bit)) sometimes_max = new_sometimes_live (regs_sometimes_live, i, bit, --- 3484,3488 ---- old_live_regs[i] |= diff; for (bit = 0; bit < REGSET_ELT_BITS; bit++) ! if (diff & ((REGSET_ELT_TYPE) 1 << bit)) sometimes_max = new_sometimes_live (regs_sometimes_live, i, bit, *************** *** 2975,2979 **** p->live_length += 1; ! if ((bb_live_regs[p->offset] & (1 << p->bit)) == 0) { /* This is the end of one of this register's lifetime --- 3501,3506 ---- p->live_length += 1; ! if ((bb_live_regs[p->offset] ! & ((REGSET_ELT_TYPE) 1 << p->bit)) == 0) { /* This is the end of one of this register's lifetime *************** *** 2982,2986 **** sched_reg_live_length[regno] += p->live_length; sched_reg_n_calls_crossed[regno] += p->calls_crossed; ! old_live_regs[p->offset] &= ~(1 << p->bit); /* Delete the reg_sometimes_live entry for this reg by --- 3509,3514 ---- sched_reg_live_length[regno] += p->live_length; sched_reg_n_calls_crossed[regno] += p->calls_crossed; ! old_live_regs[p->offset] ! &= ~((REGSET_ELT_TYPE) 1 << p->bit); /* Delete the reg_sometimes_live entry for this reg by *************** *** 3018,3022 **** priority to -1. */ INSN_PRIORITY (insn) = LAUNCH_PRIORITY; ! new_ready = launch_links (insn, ready, n_ready); INSN_PRIORITY (insn) = DONE_PRIORITY; --- 3546,3550 ---- priority to -1. */ INSN_PRIORITY (insn) = LAUNCH_PRIORITY; ! new_ready = schedule_insn (insn, ready, n_ready, clock); INSN_PRIORITY (insn) = DONE_PRIORITY; *************** *** 3037,3041 **** { insn = PREV_INSN (insn); ! new_ready = launch_links (insn, ready, new_ready); INSN_PRIORITY (insn) = DONE_PRIORITY; --- 3565,3569 ---- { insn = PREV_INSN (insn); ! new_ready = schedule_insn (insn, ready, new_ready, clock); INSN_PRIORITY (insn) = DONE_PRIORITY; *************** *** 3146,3151 **** if (file) { ! fprintf (file, ";; new basic block head = %d\n;; new basic block end = %d\n\n", ! INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b])); } --- 3674,3679 ---- if (file) { ! fprintf (file, ";; total time = %d\n;; new basic block head = %d\n;; new basic block end = %d\n\n", ! clock, INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b])); } *************** *** 3518,3522 **** insn = XEXP (note, 0); ! note = find_reg_note (insn, REG_RETVAL, 0); if (note) XEXP (note, 0) = first; --- 4046,4050 ---- insn = XEXP (note, 0); ! note = find_reg_note (insn, REG_RETVAL, NULL_RTX); if (note) XEXP (note, 0) = first; *************** *** 3530,3534 **** insn = XEXP (note, 0); ! note = find_reg_note (insn, REG_LIBCALL, 0); if (note) XEXP (note, 0) = last; --- 4058,4062 ---- insn = XEXP (note, 0); ! note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); if (note) XEXP (note, 0) = last; *************** *** 3784,3788 **** /* Create an insn here so that we can hang dependencies off of it later. */ ! sched_before_next_call = gen_rtx (INSN, VOIDmode, 0, 0, 0, 0, 0, 0, 0); /* Initialize the unused_*_lists. We can't use the ones left over from --- 4312,4318 ---- /* Create an insn here so that we can hang dependencies off of it later. */ ! sched_before_next_call ! = gen_rtx (INSN, VOIDmode, 0, NULL_RTX, NULL_RTX, ! NULL_RTX, 0, NULL_RTX, 0); /* Initialize the unused_*_lists. We can't use the ones left over from *************** *** 3805,3809 **** --- 4335,4342 ---- insn_luid = (int *) alloca (max_uid * sizeof (int)); insn_priority = (int *) alloca (max_uid * sizeof (int)); + insn_tick = (int *) alloca (max_uid * sizeof (int)); insn_costs = (short *) alloca (max_uid * sizeof (short)); + insn_units = (short *) alloca (max_uid * sizeof (short)); + insn_blockage = (unsigned int *) alloca (max_uid * sizeof (unsigned int)); insn_ref_count = (int *) alloca (max_uid * sizeof (int)); *************** *** 3856,3860 **** --- 4389,4396 ---- bzero (insn_luid, max_uid * sizeof (int)); bzero (insn_priority, max_uid * sizeof (int)); + bzero (insn_tick, max_uid * sizeof (int)); bzero (insn_costs, max_uid * sizeof (short)); + bzero (insn_units, max_uid * sizeof (short)); + bzero (insn_blockage, max_uid * sizeof (unsigned int)); bzero (insn_ref_count, max_uid * sizeof (int)); *************** *** 3949,3952 **** --- 4485,4493 ---- #endif } + + /* Reposition the prologue and epilogue notes in case we moved the + prologue/epilogue insns. */ + if (reload_completed) + reposition_prologue_and_epilogue_notes (get_insns ()); if (write_symbols != NO_DEBUG) diff -rc2N gcc-2.2.2/sdbout.c gcc-2.3.1/sdbout.c *** gcc-2.2.2/sdbout.c Sun May 31 01:03:41 1992 --- gcc-2.3.1/sdbout.c Fri Oct 23 21:18:34 1992 *************** *** 54,58 **** /* Mips systems use the SDB functions to dump out symbols, but do not supply usable syms.h include files. */ ! #if defined(USG) && !defined(MIPS) #include /* Use T_INT if we don't have T_VOID. */ --- 54,58 ---- /* Mips systems use the SDB functions to dump out symbols, but do not supply usable syms.h include files. */ ! #if defined(USG) && !defined(MIPS) && !defined (hpux) #include /* Use T_INT if we don't have T_VOID. */ *************** *** 617,621 **** if (context == current_function_decl) return; ! if (TREE_EXTERNAL (decl)) return; if (GET_CODE (DECL_RTL (decl)) != MEM --- 617,621 ---- if (context == current_function_decl) return; ! if (DECL_EXTERNAL (decl)) return; if (GET_CODE (DECL_RTL (decl)) != MEM *************** *** 647,651 **** /* Don't mention a variable that is external. Let the file that defines it describe it. */ ! if (TREE_EXTERNAL (decl)) return; --- 647,651 ---- /* Don't mention a variable that is external. Let the file that defines it describe it. */ ! if (DECL_EXTERNAL (decl)) return; *************** *** 660,664 **** return; ! value = eliminate_regs (DECL_RTL (decl), 0, 0); /* Don't mention a variable at all --- 660,669 ---- return; ! DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX); ! #ifdef LEAF_REG_REMAP ! if (leaf_function) ! leaf_renumber_regs_insn (DECL_RTL (decl)); ! #endif ! value = DECL_RTL (decl); /* Don't mention a variable at all *************** *** 672,680 **** regno = REGNO (DECL_RTL (decl)); if (regno >= FIRST_PSEUDO_REGISTER) - regno = reg_renumber[REGNO (DECL_RTL (decl))]; - if (regno < 0) return; } ! else if (GET_CODE (DECL_RTL (decl)) == SUBREG) { int offset = 0; --- 677,683 ---- regno = REGNO (DECL_RTL (decl)); if (regno >= FIRST_PSEUDO_REGISTER) return; } ! else if (GET_CODE (value) == SUBREG) { int offset = 0; *************** *** 688,695 **** regno = REGNO (value); if (regno >= FIRST_PSEUDO_REGISTER) ! regno = reg_renumber[REGNO (value)]; ! if (regno >= 0) ! regno += offset; } } --- 691,699 ---- regno = REGNO (value); if (regno >= FIRST_PSEUDO_REGISTER) ! return; ! regno += offset; } + alter_subreg (DECL_RTL (decl)); + value = DECL_RTL (decl); } *************** *** 712,715 **** --- 716,724 ---- return; + /* C++ in 2.3 makes nameless symbols. That will be fixed later. + For now, avoid crashing. */ + if (DECL_NAME (decl) == NULL_TREE) + return; + /* Record the name for, starting a symtab entry. */ name = IDENTIFIER_POINTER (DECL_NAME (decl)); *************** *** 947,951 **** #if 1 /* This is reputed to cause trouble with the following case, ! but perhaps checking TYPE_SIZE above will fix it. /* Here is a test case: --- 956,960 ---- #if 1 /* This is reputed to cause trouble with the following case, ! but perhaps checking TYPE_SIZE above will fix it. */ /* Here is a test case: *************** *** 1126,1131 **** so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) = ! eliminate_regs (DECL_INCOMING_RTL (parms), 0, 0); ! DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, 0); if (PARM_PASSED_IN_MEMORY (parms)) --- 1135,1140 ---- so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) = ! eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX); ! DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX); if (PARM_PASSED_IN_MEMORY (parms)) diff -rc2N gcc-2.2.2/stab.def gcc-2.3.1/stab.def *** gcc-2.2.2/stab.def Sun Jun 14 18:18:05 1992 --- gcc-2.3.1/stab.def Sun Nov 1 03:44:41 1992 *************** *** 31,35 **** __define_stab (N_FUN, 0x24, "FUN") ! /* Data-segment variable with internal linkage. Value is its address. */ __define_stab (N_STSYM, 0x26, "STSYM") --- 31,36 ---- __define_stab (N_FUN, 0x24, "FUN") ! /* Data-segment variable with internal linkage. Value is its address. ! "Static Sym". */ __define_stab (N_STSYM, 0x26, "STSYM") *************** *** 41,89 **** __define_stab (N_MAIN, 0x2a, "MAIN") ! /* Register variable. Value is number of register. */ ! __define_stab (N_RSYM, 0x40, "RSYM") ! ! /* Structure or union element. Value is offset in the structure. */ ! __define_stab (N_SSYM, 0x60, "SSYM") ! /* Parameter variable. Value is offset from argument pointer. ! (On most machines the argument pointer is the same as the frame pointer. */ ! __define_stab (N_PSYM, 0xa0, "PSYM") ! /* Automatic variable in the stack. Value is offset from frame pointer. ! Also used for type descriptions. */ ! __define_stab (N_LSYM, 0x80, "LSYM") ! /* Alternate entry point. Value is its address. */ ! __define_stab (N_ENTRY, 0xa4, "ENTRY") ! /* Name of main source file. ! Value is starting text address of the compilation. */ ! __define_stab (N_SO, 0x64, "SO") ! /* Name of sub-source file. ! Value is starting text address of the compilation. */ ! __define_stab (N_SOL, 0x84, "SOL") /* Line number in text segment. Desc is the line number; value is corresponding address. */ __define_stab (N_SLINE, 0x44, "SLINE") /* Similar, for data segment. */ __define_stab (N_DSLINE, 0x46, "DSLINE") /* Similar, for bss segment. */ __define_stab (N_BSLINE, 0x48, "BSLINE") /* Beginning of an include file. Only Sun uses this. In an object file, only the name is significant. The Sun linker puts data into some of the other fields. */ __define_stab (N_BINCL, 0x82, "BINCL") /* End of an include file. No name. ! These two act as brackets around the file's output. In an object file, there is no significant data in this entry. The Sun linker puts data into some of the fields. */ __define_stab (N_EINCL, 0xa2, "EINCL") ! /* Place holder for deleted include file. ! This appears only in output from the Sun linker. */ ! __define_stab (N_EXCL, 0xc2, "EXCL") /* Beginning of lexical block. --- 42,137 ---- __define_stab (N_MAIN, 0x2a, "MAIN") ! /* Global symbol in Pascal. ! Supposedly the value is its line number; I'm skeptical. */ ! __define_stab (N_PC, 0x30, "PC") ! /* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ ! __define_stab (N_NSYMS, 0x32, "NSYMS") ! /* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ ! __define_stab (N_NOMAP, 0x34, "NOMAP") ! /* New stab from Solaris. I don't know what it means, but it ! don't seem to contain useful information. */ ! __define_stab (N_OBJ, 0x38, "OBJ") ! ! /* New stab from Solaris. I don't know what it means, but it ! don't seem to contain useful information. Possibly related to the ! optimization flags used in this module. */ ! __define_stab (N_OPT, 0x3c, "OPT") ! /* Register variable. Value is number of register. */ ! __define_stab (N_RSYM, 0x40, "RSYM") ! /* Modula-2 compilation unit. Can someone say what info it contains? */ ! __define_stab (N_M2C, 0x42, "M2C") /* Line number in text segment. Desc is the line number; value is corresponding address. */ __define_stab (N_SLINE, 0x44, "SLINE") + /* Similar, for data segment. */ __define_stab (N_DSLINE, 0x46, "DSLINE") + /* Similar, for bss segment. */ __define_stab (N_BSLINE, 0x48, "BSLINE") + /* Sun's source-code browser stabs. ?? Don't know what the fields are. + Supposedly the field is "path to associated .cb file". THIS VALUE + OVERLAPS WITH N_BSLINE! */ + __define_stab (N_BROWS, 0x48, "BROWS") + + /* GNU Modula-2 definition module dependency. Value is the modification time + of the definition file. Other is non-zero if it is imported with the + GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there + are enough empty fields? */ + __define_stab(N_DEFD, 0x4a, "DEFD") + + /* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 + and one is for C++. Still,... */ + /* GNU C++ exception variable. Name is variable name. */ + __define_stab (N_EHDECL, 0x50, "EHDECL") + /* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ + __define_stab (N_MOD2, 0x50, "MOD2") + + /* GNU C++ `catch' clause. Value is its address. Desc is nonzero if + this entry is immediately followed by a CAUGHT stab saying what exception + was caught. Multiple CAUGHT stabs means that multiple exceptions + can be caught here. If Desc is 0, it means all exceptions are caught + here. */ + __define_stab (N_CATCH, 0x54, "CATCH") + + /* Structure or union element. Value is offset in the structure. */ + __define_stab (N_SSYM, 0x60, "SSYM") + + /* Name of main source file. + Value is starting text address of the compilation. */ + __define_stab (N_SO, 0x64, "SO") + + /* Automatic variable in the stack. Value is offset from frame pointer. + Also used for type descriptions. */ + __define_stab (N_LSYM, 0x80, "LSYM") + /* Beginning of an include file. Only Sun uses this. In an object file, only the name is significant. The Sun linker puts data into some of the other fields. */ __define_stab (N_BINCL, 0x82, "BINCL") + + /* Name of sub-source file (#include file). + Value is starting text address of the compilation. */ + __define_stab (N_SOL, 0x84, "SOL") + + /* Parameter variable. Value is offset from argument pointer. + (On most machines the argument pointer is the same as the frame pointer. */ + __define_stab (N_PSYM, 0xa0, "PSYM") + /* End of an include file. No name. ! This and N_BINCL act as brackets around the file's output. In an object file, there is no significant data in this entry. The Sun linker puts data into some of the fields. */ __define_stab (N_EINCL, 0xa2, "EINCL") ! ! /* Alternate entry point. Value is its address. */ ! __define_stab (N_ENTRY, 0xa4, "ENTRY") /* Beginning of lexical block. *************** *** 92,95 **** --- 140,153 ---- The variables declared inside the block *precede* the N_LBRAC symbol. */ __define_stab (N_LBRAC, 0xc0, "LBRAC") + + /* Place holder for deleted include file. Replaces a N_BINCL and everything + up to the corresponding N_EINCL. The Sun linker generates these when + it finds multiple identical copies of the symbols from an include file. + This appears only in output from the Sun linker. */ + __define_stab (N_EXCL, 0xc2, "EXCL") + + /* Modula-2 scope information. Can someone say what info it contains? */ + __define_stab (N_SCOPE, 0xc4, "SCOPE") + /* End of a lexical block. Desc matches the N_LBRAC's desc. The value is the address of the end of the text for the block. */ *************** *** 98,133 **** /* Begin named common block. Only the name is significant. */ __define_stab (N_BCOMM, 0xe2, "BCOMM") ! /* Begin named common block. Only the name is significant (and it should match the N_BCOMM). */ __define_stab (N_ECOMM, 0xe4, "ECOMM") /* End common (local name): value is address. I'm not sure how this is used. */ __define_stab (N_ECOML, 0xe8, "ECOML") /* Second symbol entry containing a length-value for the preceding entry. The value is the length. */ __define_stab (N_LENG, 0xfe, "LENG") - - /* Global symbol in Pascal. - Supposedly the value is its line number; I'm skeptical. */ - __define_stab (N_PC, 0x30, "PC") - - /* Modula-2 compilation unit. Can someone say what info it contains? */ - __define_stab (N_M2C, 0x42, "M2C") - /* Modula-2 scope information. Can someone say what info it contains? */ - __define_stab (N_SCOPE, 0xc4, "SCOPE") - - /* Sun's source-code browser stabs. ?? Don't know what the fields are. - Supposedly the field is "path to associated .cb file". */ - /* This conflicts with the definition of N_BSLINE. */ - __define_stab (N_BROWS, 0x48, "BROWS") - - /* GNU C++ exception stabs. */ - - /* GNU C++ `catch' clause. Value is its address. Desc is nonzero if - this entry is immediately followed by a CAUGHT stab saying what exception - was caught. Multiple CAUGHT stabs means that multiple exceptions - can be caught here. If Desc is 0, it means all exceptions are caught - here. */ - __define_stab (N_CATCH, 0x54, "CATCH") /* The above information, in matrix format. --- 156,180 ---- /* Begin named common block. Only the name is significant. */ __define_stab (N_BCOMM, 0xe2, "BCOMM") ! ! /* End named common block. Only the name is significant (and it should match the N_BCOMM). */ __define_stab (N_ECOMM, 0xe4, "ECOMM") + /* End common (local name): value is address. I'm not sure how this is used. */ __define_stab (N_ECOML, 0xe8, "ECOML") + + /* These STAB's are used on Gould systems for Non-Base register symbols + or something like that. FIXME. I have assigned the values at random + since I don't have a Gould here. Fixups from Gould folk welcome... */ + __define_stab (N_NBTEXT, 0xF0, "NBTEXT") + __define_stab (N_NBDATA, 0xF2, "NBDATA") + __define_stab (N_NBBSS, 0xF4, "NBBSS") + __define_stab (N_NBSTS, 0xF6, "NBSTS") + __define_stab (N_NBLCS, 0xF8, "NBLCS") + /* Second symbol entry containing a length-value for the preceding entry. The value is the length. */ __define_stab (N_LENG, 0xfe, "LENG") /* The above information, in matrix format. *************** *** 136,153 **** _________________________________________________ | 00 - 1F are not dbx stab symbols | ! | Entries with bits 01 set are external symbols | ! | N_UNDEF | N_ABS | N_TEXT | N_DATA | ! | N_BSS | N_COMM | | N_FN | |_______________________________________________| | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | | 28 LCSYM | 2A MAIN | 2C | 2E | ! | 30 PC | 32 | 34 | 36 | ! | 38 | 3A | 3C | 3E | | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | ! | 48 BROWS/BSLINE | 4A | 4C | 4E | ! | 50 EHDECL | 52 | 54 CATCH | 56 | | 58 | 5A | 5C | 5E | ! | 60 SSYM | 62 | 64 SO | 66 | ! | 68 | 6A | 6C | 6E | | 70 | 72 | 74 | 76 | | 78 | 7A | 7C | 7E | --- 183,212 ---- _________________________________________________ | 00 - 1F are not dbx stab symbols | ! | In most cases, the low bit is the EXTernal bit| ! ! | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | ! | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | ! ! | 08 BSS | 0A INDR | 0C FN_SEQ | 0E | ! | 09 |EXT | 0B | 0D | 0F | ! ! | 10 | 12 COMM | 14 SETA | 16 SETT | ! | 11 | 13 | 15 | 17 | ! ! | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| ! | 19 | 1B | 1D | 1F FN | ! |_______________________________________________| + | Debug entries with bit 01 set are unused. | | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | | 28 LCSYM | 2A MAIN | 2C | 2E | ! | 30 PC | 32 NSYMS | 34 NOMAP | 36 | ! | 38 OBJ | 3A | 3C OPT | 3E | | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | ! | 48 BSLINE*| 4A DEFD | 4C | 4E | ! | 50 EHDECL*| 52 | 54 CATCH | 56 | | 58 | 5A | 5C | 5E | ! | 60 SSYM | 62 | 64 SO | 66 | ! | 68 | 6A | 6C | 6E | | 70 | 72 | 74 | 76 | | 78 | 7A | 7C | 7E | *************** *** 169,172 **** | F8 | FA | FC | FE LENG | +-----------------------------------------------+ ! ! */ --- 228,232 ---- | F8 | FA | FC | FE LENG | +-----------------------------------------------+ ! * 50 EHDECL is also MOD2. ! * 48 BSLINE is also BROWS. ! */ diff -rc2N gcc-2.2.2/stmt.c gcc-2.3.1/stmt.c *** gcc-2.2.2/stmt.c Mon May 25 15:53:22 1992 --- gcc-2.3.1/stmt.c Fri Oct 9 12:59:03 1992 *************** *** 55,61 **** struct obstack stmt_obstack; - extern int xmalloc (); - extern void free (); - /* Filename and line number of last line-number note, whether we actually emitted it or not. */ --- 55,58 ---- *************** *** 74,77 **** --- 71,81 ---- static rtx last_expr_value; + /* Each time we expand the end of a binding contour (in `expand_end_bindings') + and we emit a new NOTE_INSN_BLOCK_END note, we save a pointer to it here. + This is used by the `remember_end_note' function to record the endpoint + of each generated block in its associated BLOCK node. */ + + static rtx last_block_end_note; + /* Number of binding contours started so far in this function. */ *************** *** 182,186 **** void free_temp_slots (); static void expand_cleanups (); - static void fixup_cleanups (); static void expand_null_return_1 (); static int tail_recursion_args (); --- 186,189 ---- *************** *** 330,333 **** --- 333,338 ---- struct nesting *block_stack; + /* If any new stacks are added here, add them to POPSTACKS too. */ + /* Chain of all pending binding contours that restore stack levels or have cleanups. */ *************** *** 358,372 **** (struct nesting *) obstack_alloc (&stmt_obstack, sizeof (struct nesting)) ! /* Pop one of the sub-stacks, such as `loop_stack' or `cond_stack'; ! and pop off `nesting_stack' down to the same level. */ #define POPSTACK(STACK) \ ! do { int initial_depth = nesting_stack->depth; \ ! do { struct nesting *this = STACK; \ ! STACK = this->next; \ nesting_stack = this->all; \ - nesting_depth = this->depth; \ obstack_free (&stmt_obstack, this); } \ ! while (nesting_depth > initial_depth); } while (0) /* In some cases it is impossible to generate code for a forward goto --- 363,391 ---- (struct nesting *) obstack_alloc (&stmt_obstack, sizeof (struct nesting)) ! /* Pop the nesting stack element by element until we pop off ! the element which is at the top of STACK. ! Update all the other stacks, popping off elements from them ! as we pop them from nesting_stack. */ #define POPSTACK(STACK) \ ! do { struct nesting *target = STACK; \ ! struct nesting *this; \ ! do { this = nesting_stack; \ ! if (loop_stack == this) \ ! loop_stack = loop_stack->next; \ ! if (cond_stack == this) \ ! cond_stack = cond_stack->next; \ ! if (block_stack == this) \ ! block_stack = block_stack->next; \ ! if (stack_block_stack == this) \ ! stack_block_stack = stack_block_stack->next; \ ! if (case_stack == this) \ ! case_stack = case_stack->next; \ ! if (except_stack == this) \ ! except_stack = except_stack->next; \ ! nesting_depth = nesting_stack->depth - 1; \ nesting_stack = this->all; \ obstack_free (&stmt_obstack, this); } \ ! while (this != target); } while (0) /* In some cases it is impossible to generate code for a forward goto *************** *** 388,391 **** --- 407,412 ---- for break, continue or return. */ tree target; + /* The BLOCK for the place where this goto was found. */ + tree context; /* The CODE_LABEL rtx that this is jumping to. */ rtx target_rtl; *************** *** 535,539 **** tree exp; { ! rtx x = expand_expr (exp, 0, VOIDmode, 0); emit_queue (); emit_indirect_jump (x); --- 556,560 ---- tree exp; { ! rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0); emit_queue (); emit_indirect_jump (x); *************** *** 648,652 **** virtual_stack_vars_rtx, frame_pointer_rtx); ! emit_stack_restore (SAVE_NONLOCAL, addr, 0); /* Put in the static chain register the nonlocal label address. */ --- 669,673 ---- virtual_stack_vars_rtx, frame_pointer_rtx); ! emit_stack_restore (SAVE_NONLOCAL, addr, NULL_RTX); /* Put in the static chain register the nonlocal label address. */ *************** *** 662,666 **** } else ! expand_goto_internal (label, label_rtx (label), 0); } --- 683,687 ---- } else ! expand_goto_internal (label, label_rtx (label), NULL_RTX); } *************** *** 700,704 **** if (block->data.block.cleanups != 0) { ! expand_cleanups (block->data.block.cleanups, 0); do_pending_stack_adjust (); } --- 721,725 ---- if (block->data.block.cleanups != 0) { ! expand_cleanups (block->data.block.cleanups, NULL_TREE); do_pending_stack_adjust (); } *************** *** 711,715 **** clear_pending_stack_adjust (); do_pending_stack_adjust (); ! emit_stack_restore (SAVE_BLOCK, stack_level, 0); } --- 732,736 ---- clear_pending_stack_adjust (); do_pending_stack_adjust (); ! emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX); } *************** *** 738,743 **** after insn LAST_INSN instead of at the current point in the insn stream. ! The fixup will be used later to insert insns at this point ! to restore the stack level as appropriate for the target label. Value is nonzero if a fixup is made. */ --- 759,767 ---- after insn LAST_INSN instead of at the current point in the insn stream. ! The fixup will be used later to insert insns just before the goto. ! Those insns will restore the stack level as appropriate for the ! target label, and will (in the case of C++) also invoke any object ! destructors which have to be invoked when we exit the scopes which ! are exited by the goto. Value is nonzero if a fixup is made. */ *************** *** 816,822 **** if (last_insn == 0) do_pending_stack_adjust (); - fixup->before_jump = last_insn ? last_insn : get_last_insn (); fixup->target = tree_label; fixup->target_rtl = rtl_label; fixup->block_start_count = block_start_count; fixup->stack_level = 0; --- 840,867 ---- if (last_insn == 0) do_pending_stack_adjust (); fixup->target = tree_label; fixup->target_rtl = rtl_label; + + /* Create a BLOCK node and a corresponding matched set of + NOTE_INSN_BEGIN_BLOCK and NOTE_INSN_END_BLOCK notes at + this point. The notes will encapsulate any and all fixup + code which we might later insert at this point in the insn + stream. Also, the BLOCK node will be the parent (i.e. the + `SUPERBLOCK') of any other BLOCK nodes which we might create + later on when we are expanding the fixup code. */ + + { + register rtx original_before_jump + = last_insn ? last_insn : get_last_insn (); + + start_sequence (); + pushlevel (0); + fixup->before_jump = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG); + last_block_end_note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END); + fixup->context = poplevel (1, 0, 0); /* Create the BLOCK node now! */ + end_sequence (); + emit_insns_after (fixup->before_jump, original_before_jump); + } + fixup->block_start_count = block_start_count; fixup->stack_level = 0; *************** *** 828,832 **** ) || block->data.block.cleanups) ! ? tree_cons (0, block->data.block.cleanups, block->data.block.outer_cleanups) : 0); --- 873,877 ---- ) || block->data.block.cleanups) ! ? tree_cons (NULL_TREE, block->data.block.cleanups, block->data.block.outer_cleanups) : 0); *************** *** 879,882 **** --- 924,929 ---- else if (PREV_INSN (f->target_rtl) != 0) { + register rtx cleanup_insns; + /* Get the first non-label after the label this goto jumps to. If that's before this scope begins, *************** *** 899,911 **** || INSN_UID (first_insn) < INSN_UID (after_label)) && INSN_UID (first_insn) > INSN_UID (f->before_jump) ! && ! TREE_REGDECL (f->target)) { error_with_decl (f->target, "label `%s' used before containing binding contour"); /* Prevent multiple errors for one label. */ ! TREE_REGDECL (f->target) = 1; } ! /* Execute cleanups for blocks this jump exits. */ if (f->cleanup_list_list) { --- 946,971 ---- || INSN_UID (first_insn) < INSN_UID (after_label)) && INSN_UID (first_insn) > INSN_UID (f->before_jump) ! && ! DECL_REGISTER (f->target)) { error_with_decl (f->target, "label `%s' used before containing binding contour"); /* Prevent multiple errors for one label. */ ! DECL_REGISTER (f->target) = 1; } ! /* We will expand the cleanups into a sequence of their own and ! then later on we will attach this new sequence to the insn ! stream just ahead of the actual jump insn. */ ! ! start_sequence (); ! ! /* Temporarily restore the lexical context where we will ! logically be inserting the fixup code. We do this for the ! sake of getting the debugging information right. */ ! ! pushlevel (0); ! set_block (f->context); ! ! /* Expand the cleanups for blocks this jump exits. */ if (f->cleanup_list_list) { *************** *** 916,920 **** if (TREE_ADDRESSABLE (lists) && TREE_VALUE (lists) != 0) ! fixup_cleanups (TREE_VALUE (lists), &f->before_jump); } --- 976,985 ---- if (TREE_ADDRESSABLE (lists) && TREE_VALUE (lists) != 0) ! { ! expand_cleanups (TREE_VALUE (lists), 0); ! /* Pop any pushes done in the cleanups, ! in case function is about to return. */ ! do_pending_stack_adjust (); ! } } *************** *** 923,926 **** --- 988,1008 ---- if (f->stack_level) emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump); + + /* Finish up the sequence containing the insns which implement the + necessary cleanups, and then attach that whole sequence to the + insn stream just ahead of the actual jump insn. Attaching it + at that point insures that any cleanups which are in fact + implicit C++ object destructions (which must be executed upon + leaving the block) appear (to the debugger) to be taking place + in an area of the generated code where the object(s) being + destructed are still "in scope". */ + + cleanup_insns = get_insns (); + poplevel (1, 0, 0); + + end_sequence (); + emit_insns_after (cleanup_insns, f->before_jump); + + f->before_jump = 0; } *************** *** 1013,1017 **** { char *regname = TREE_STRING_POINTER (TREE_VALUE (tail)); ! if (decode_reg_name (regname) >= 0) ++nclobbers; } --- 1095,1100 ---- { char *regname = TREE_STRING_POINTER (TREE_VALUE (tail)); ! i = decode_reg_name (regname); ! if (i >= 0 || i == -4) ++nclobbers; } *************** *** 1065,1069 **** TREE_VALUE (tail) = save_expr (TREE_VALUE (tail)); ! output_rtx[i] = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0); } --- 1148,1152 ---- TREE_VALUE (tail) = save_expr (TREE_VALUE (tail)); ! output_rtx[i] = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0); } *************** *** 1116,1120 **** XVECEXP (body, 3, i) /* argvec */ ! = expand_expr (TREE_VALUE (tail), 0, VOIDmode, 0); XVECEXP (body, 4, i) /* constraints */ = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), --- 1199,1203 ---- XVECEXP (body, 3, i) /* argvec */ ! = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0); XVECEXP (body, 4, i) /* constraints */ = gen_rtx (ASM_INPUT, TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), *************** *** 1184,1190 **** if (j < 0) { ! if (j == -3) continue; error ("unknown register name `%s' in `asm'", regname); return; --- 1267,1279 ---- if (j < 0) { ! if (j == -3) /* `cc', which is not a register */ continue; + if (j == -4) /* `memory', don't cache memory across asm */ + { + XVECEXP (body, 0, i++) = gen_rtx (CLOBBER, VOIDmode, const0_rtx); + continue; + } + error ("unknown register name `%s' in `asm'", regname); return; *************** *** 1224,1228 **** last_expr_type = TREE_TYPE (exp); if (! flag_syntax_only) ! last_expr_value = expand_expr (exp, expr_stmts_for_value ? 0 : const0_rtx, VOIDmode, 0); --- 1313,1319 ---- last_expr_type = TREE_TYPE (exp); if (! flag_syntax_only) ! last_expr_value = expand_expr (exp, ! (expr_stmts_for_value ! ? NULL_RTX : const0_rtx), VOIDmode, 0); *************** *** 1241,1245 **** emit_cmp_insn (last_expr_value, last_expr_value, EQ, expand_expr (TYPE_SIZE (last_expr_type), ! 0, VOIDmode, 0), BLKmode, 0, TYPE_ALIGN (last_expr_type) / BITS_PER_UNIT); --- 1332,1336 ---- emit_cmp_insn (last_expr_value, last_expr_value, EQ, expand_expr (TYPE_SIZE (last_expr_type), ! NULL_RTX, VOIDmode, 0), BLKmode, 0, TYPE_ALIGN (last_expr_type) / BITS_PER_UNIT); *************** *** 1438,1441 **** --- 1529,1533 ---- } + */ /* Return nonzero iff in a try block at level LEVEL. */ *************** *** 1536,1540 **** nesting_stack = thishandler; ! do_jump (try_clause, thishandler->data.except_stmt.except_label, NULL); } --- 1628,1632 ---- nesting_stack = thishandler; ! do_jump (try_clause, thishandler->data.except_stmt.except_label, NULL_RTX); } *************** *** 1545,1549 **** { except_stack->data.except_stmt.after_label = gen_label_rtx (); ! expand_goto_internal (NULL, except_stack->data.except_stmt.after_label, 0); } --- 1637,1642 ---- { except_stack->data.except_stmt.after_label = gen_label_rtx (); ! expand_goto_internal (NULL_TREE, except_stack->data.except_stmt.after_label, ! NULL_RTX); } *************** *** 1608,1612 **** if (n->data.except_stmt.escape_label != 0) { ! expand_goto_internal (0, n->data.except_stmt.escape_label, 0); return 1; } --- 1701,1706 ---- if (n->data.except_stmt.escape_label != 0) { ! expand_goto_internal (NULL_TREE, ! n->data.except_stmt.escape_label, NULL_RTX); return 1; } *************** *** 1711,1715 **** if (except_stack == 0 || except_stack->data.except_stmt.after_label == 0) return 0; ! expand_goto_internal (0, except_stack->data.except_stmt.after_label, 0); return 1; } --- 1805,1810 ---- if (except_stack == 0 || except_stack->data.except_stmt.after_label == 0) return 0; ! expand_goto_internal (NULL_TREE, except_stack->data.except_stmt.after_label, ! NULL_RTX); return 1; } *************** *** 1742,1746 **** nesting_stack = thiscond; ! do_jump (cond, thiscond->data.cond.next_label, NULL); } --- 1837,1841 ---- nesting_stack = thiscond; ! do_jump (cond, thiscond->data.cond.next_label, NULL_RTX); } *************** *** 1757,1761 **** emit_label (cond_stack->data.cond.next_label); cond_stack->data.cond.next_label = gen_label_rtx (); ! do_jump (cond, cond_stack->data.cond.next_label, NULL); } --- 1852,1856 ---- emit_label (cond_stack->data.cond.next_label); cond_stack->data.cond.next_label = gen_label_rtx (); ! do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX); } *************** *** 1818,1822 **** do_pending_stack_adjust (); emit_queue (); ! emit_note (0, NOTE_INSN_LOOP_BEG); emit_label (thisloop->data.loop.start_label); --- 1913,1917 ---- do_pending_stack_adjust (); emit_queue (); ! emit_note (NULL_PTR, NOTE_INSN_LOOP_BEG); emit_label (thisloop->data.loop.start_label); *************** *** 1845,1849 **** { do_pending_stack_adjust (); ! emit_note (0, NOTE_INSN_LOOP_CONT); emit_label (loop_stack->data.loop.continue_label); } --- 1940,1944 ---- { do_pending_stack_adjust (); ! emit_note (NULL_PTR, NOTE_INSN_LOOP_CONT); emit_label (loop_stack->data.loop.continue_label); } *************** *** 1949,1953 **** emit_jump (start_label); ! emit_note (0, NOTE_INSN_LOOP_END); emit_label (loop_stack->data.loop.end_label); --- 2044,2048 ---- emit_jump (start_label); ! emit_note (NULL_PTR, NOTE_INSN_LOOP_END); emit_label (loop_stack->data.loop.end_label); *************** *** 1971,1975 **** if (whichloop == 0) return 0; ! expand_goto_internal (0, whichloop->data.loop.continue_label, 0); return 1; } --- 2066,2071 ---- if (whichloop == 0) return 0; ! expand_goto_internal (NULL_TREE, whichloop->data.loop.continue_label, ! NULL_RTX); return 1; } *************** *** 1987,1991 **** if (whichloop == 0) return 0; ! expand_goto_internal (0, whichloop->data.loop.end_label, 0); return 1; } --- 2083,2087 ---- if (whichloop == 0) return 0; ! expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label, NULL_RTX); return 1; } *************** *** 2005,2009 **** if (whichloop == 0) return 0; ! do_jump (cond, whichloop->data.loop.end_label, NULL); return 1; } --- 2101,2105 ---- if (whichloop == 0) return 0; ! do_jump (cond, whichloop->data.loop.end_label, NULL_RTX); return 1; } *************** *** 2052,2056 **** if (n->exit_label != 0) { ! expand_goto_internal (0, n->exit_label, 0); return 1; } --- 2148,2152 ---- if (n->exit_label != 0) { ! expand_goto_internal (NULL_TREE, n->exit_label, NULL_RTX); return 1; } *************** *** 2130,2134 **** if (end_label == 0) end_label = return_label = gen_label_rtx (); ! expand_goto_internal (0, end_label, last_insn); return; } --- 2226,2230 ---- if (end_label == 0) end_label = return_label = gen_label_rtx (); ! expand_goto_internal (NULL_TREE, end_label, last_insn); return; } *************** *** 2146,2150 **** /* Otherwise jump to the epilogue. */ ! expand_goto_internal (0, end_label, last_insn); } --- 2242,2246 ---- /* Otherwise jump to the epilogue. */ ! expand_goto_internal (NULL_TREE, end_label, last_insn); } *************** *** 2174,2178 **** if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE) { ! expand_expr (retval, 0, VOIDmode, 0); expand_null_return (); return; --- 2270,2275 ---- if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE) { ! expand_expr (retval, NULL_RTX, VOIDmode, 0); ! emit_queue (); expand_null_return (); return; *************** *** 2210,2214 **** { rtx label = gen_label_rtx (); ! do_jump (TREE_OPERAND (retval_rhs, 0), label, 0); expand_return (build (MODIFY_EXPR, TREE_TYPE (current_function_decl), DECL_RESULT (current_function_decl), --- 2307,2311 ---- { rtx label = gen_label_rtx (); ! do_jump (TREE_OPERAND (retval_rhs, 0), label, NULL_RTX); expand_return (build (MODIFY_EXPR, TREE_TYPE (current_function_decl), DECL_RESULT (current_function_decl), *************** *** 2242,2246 **** tail_recursion_reentry); } ! expand_goto_internal (0, tail_recursion_label, last_insn); emit_barrier (); return; --- 2339,2344 ---- tail_recursion_reentry); } ! emit_queue (); ! expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn); emit_barrier (); return; *************** *** 2288,2292 **** { /* Calculate the return value into a pseudo reg. */ ! val = expand_expr (retval_rhs, 0, VOIDmode, 0); emit_queue (); /* All temporaries have now been used. */ --- 2386,2390 ---- { /* Calculate the return value into a pseudo reg. */ ! val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0); emit_queue (); /* All temporaries have now been used. */ *************** *** 2299,2303 **** /* No cleanups or no hard reg used; calculate value into hard return reg. */ ! expand_expr (retval, 0, VOIDmode, 0); emit_queue (); free_temp_slots (); --- 2397,2401 ---- /* No cleanups or no hard reg used; calculate value into hard return reg. */ ! expand_expr (retval, NULL_RTX, VOIDmode, 0); emit_queue (); free_temp_slots (); *************** *** 2354,2358 **** for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++) ! argvec[i] = expand_expr (TREE_VALUE (a), 0, VOIDmode, 0); /* Find which actual values refer to current values of previous formals. --- 2452,2456 ---- for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++) ! argvec[i] = expand_expr (TREE_VALUE (a), NULL_RTX, VOIDmode, 0); /* Find which actual values refer to current values of previous formals. *************** *** 2375,2379 **** f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++) { ! if (DECL_MODE (f) == GET_MODE (argvec[i])) emit_move_insn (DECL_RTL (f), argvec[i]); else --- 2473,2477 ---- f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++) { ! if (GET_MODE (DECL_RTL (f)) == GET_MODE (argvec[i])) emit_move_insn (DECL_RTL (f), argvec[i]); else *************** *** 2398,2402 **** struct nesting *thisblock = ALLOC_NESTING (); ! rtx note = emit_note (0, NOTE_INSN_BLOCK_BEG); /* Make an entry on block_stack for the block we are entering. */ --- 2496,2500 ---- struct nesting *thisblock = ALLOC_NESTING (); ! rtx note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_BEG); /* Make an entry on block_stack for the block we are entering. */ *************** *** 2445,2448 **** --- 2543,2558 ---- } + /* Given a pointer to a BLOCK node, save a pointer to the most recently + generated NOTE_INSN_BLOCK_END in the BLOCK_END_NOTE field of the given + BLOCK node. */ + + void + remember_end_note (block) + register tree block; + { + BLOCK_END_NOTE (block) = last_block_end_note; + last_block_end_note = NULL_RTX; + } + /* Generate RTL code to terminate a binding contour. VARS is the chain of VAR_DECL nodes *************** *** 2465,2479 **** if (warn_unused) for (decl = vars; decl; decl = TREE_CHAIN (decl)) ! if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL) warning_with_decl (decl, "unused variable `%s'"); - /* Mark the beginning and end of the scope if requested. */ - - if (mark_ends) - emit_note (0, NOTE_INSN_BLOCK_END); - else - /* Get rid of the beginning-mark if we don't make an end-mark. */ - NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED; - if (thisblock->exit_label) { --- 2575,2582 ---- if (warn_unused) for (decl = vars; decl; decl = TREE_CHAIN (decl)) ! if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL ! && ! DECL_IN_SYSTEM_HEADER (decl)) warning_with_decl (decl, "unused variable `%s'"); if (thisblock->exit_label) { *************** *** 2539,2552 **** if (fixed_regs[ARG_POINTER_REGNUM]) { ! /* Now restore our arg pointer from the address at which it was saved ! in our stack frame. ! If there hasn't be space allocated for it yet, make some now. */ ! if (arg_pointer_save_area == 0) ! arg_pointer_save_area ! = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); ! emit_move_insn (virtual_incoming_args_rtx, ! /* We need a pseudo here, ! or else instantiate_virtual_regs_1 complains. */ ! copy_to_reg (arg_pointer_save_area)); } #endif --- 2642,2674 ---- if (fixed_regs[ARG_POINTER_REGNUM]) { ! #ifdef ELIMINABLE_REGS ! /* If the argument pointer can be eliminated in favor of the ! frame pointer, we don't need to restore it. We assume here ! that if such an elimination is present, it can always be used. ! This is the case on all known machines; if we don't make this ! assumption, we do unnecessary saving on many machines. */ ! static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS; ! int i; ! ! for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++) ! if (elim_regs[i].from == ARG_POINTER_REGNUM ! && elim_regs[i].to == FRAME_POINTER_REGNUM) ! break; ! ! if (i == sizeof elim_regs / sizeof elim_regs [0]) ! #endif ! { ! /* Now restore our arg pointer from the address at which it ! was saved in our stack frame. ! If there hasn't be space allocated for it yet, make ! some now. */ ! if (arg_pointer_save_area == 0) ! arg_pointer_save_area ! = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); ! emit_move_insn (virtual_incoming_args_rtx, ! /* We need a pseudo here, or else ! instantiate_virtual_regs_1 complains. */ ! copy_to_reg (arg_pointer_save_area)); ! } } #endif *************** *** 2610,2614 **** /* Do the cleanups. */ ! expand_cleanups (thisblock->data.block.cleanups, 0); do_pending_stack_adjust (); --- 2732,2736 ---- /* Do the cleanups. */ ! expand_cleanups (thisblock->data.block.cleanups, NULL_TREE); do_pending_stack_adjust (); *************** *** 2622,2628 **** { emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION, ! thisblock->data.block.stack_level, 0); if (nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0); } --- 2744,2751 ---- { emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION, ! thisblock->data.block.stack_level, NULL_RTX); if (nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, ! NULL_RTX); } *************** *** 2637,2640 **** --- 2760,2773 ---- } + /* Mark the beginning and end of the scope if requested. + We do this now, after running cleanups on the variables + just going out of scope, so they are in scope for their cleanups. */ + + if (mark_ends) + last_block_end_note = emit_note (NULL_PTR, NOTE_INSN_BLOCK_END); + else + /* Get rid of the beginning-mark if we don't make an end-mark. */ + NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED; + /* If doing stupid register allocation, make sure lives of all register variables declared here extend thru end of scope. */ *************** *** 2690,2694 **** if (TREE_CODE (decl) != VAR_DECL) return; ! if (TREE_STATIC (decl) || TREE_EXTERNAL (decl)) return; --- 2823,2827 ---- if (TREE_CODE (decl) != VAR_DECL) return; ! if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) return; *************** *** 2715,2722 **** && ! TREE_THIS_VOLATILE (decl) && ! TREE_ADDRESSABLE (decl) ! && (TREE_REGDECL (decl) || ! obey_regdecls)) { /* Automatic variable that can go in a register. */ ! DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl)); if (TREE_CODE (type) == POINTER_TYPE) mark_reg_pointer (DECL_RTL (decl)); --- 2848,2866 ---- && ! TREE_THIS_VOLATILE (decl) && ! TREE_ADDRESSABLE (decl) ! && (DECL_REGISTER (decl) || ! obey_regdecls)) { /* Automatic variable that can go in a register. */ ! enum machine_mode reg_mode = DECL_MODE (decl); ! int unsignedp = TREE_UNSIGNED (type); ! ! if (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE ! || TREE_CODE (type) == BOOLEAN_TYPE || TREE_CODE (type) == CHAR_TYPE ! || TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == POINTER_TYPE ! || TREE_CODE (type) == OFFSET_TYPE) ! { ! PROMOTE_MODE (reg_mode, unsignedp, type); ! } ! ! DECL_RTL (decl) = gen_reg_rtx (reg_mode); if (TREE_CODE (type) == POINTER_TYPE) mark_reg_pointer (DECL_RTL (decl)); *************** *** 2793,2797 **** DECL_SIZE (decl), size_int (BITS_PER_UNIT)), ! 0, VOIDmode, 0); free_temp_slots (); --- 2937,2941 ---- DECL_SIZE (decl), size_int (BITS_PER_UNIT)), ! NULL_RTX, VOIDmode, 0); free_temp_slots (); *************** *** 2800,2807 **** /* Allocate space on the stack for the variable. */ ! address = allocate_dynamic_stack_space (size, 0, DECL_ALIGN (decl)); if (nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0); /* Reference the variable indirect through that rtx. */ --- 2944,2952 ---- /* Allocate space on the stack for the variable. */ ! address = allocate_dynamic_stack_space (size, NULL_RTX, ! DECL_ALIGN (decl)); if (nonlocal_goto_handler_slot != 0) ! emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX); /* Reference the variable indirect through that rtx. */ *************** *** 2995,3025 **** } - /* Expand a list of cleanups for a goto fixup. - The expansion is put into the insn chain after the insn *BEFORE_JUMP - and *BEFORE_JUMP is set to the insn that now comes before the jump. */ - - static void - fixup_cleanups (list, before_jump) - tree list; - rtx *before_jump; - { - rtx beyond_jump = get_last_insn (); - rtx new_before_jump; - - expand_cleanups (list, 0); - /* Pop any pushes done in the cleanups, - in case function is about to return. */ - do_pending_stack_adjust (); - - new_before_jump = get_last_insn (); - - if (beyond_jump != new_before_jump) - { - /* If cleanups expand to nothing, don't reorder. */ - reorder_insns (NEXT_INSN (beyond_jump), new_before_jump, *before_jump); - *before_jump = new_before_jump; - } - } - /* Move all cleanups from the current block_stack to the containing block_stack, where they are assumed to --- 3140,3143 ---- *************** *** 3121,3125 **** need any transformation before expand_end_case. */ if (GET_CODE (get_last_insn ()) != NOTE) ! emit_note (0, NOTE_INSN_DELETED); thiscase->data.case_stmt.start = get_last_insn (); --- 3239,3243 ---- need any transformation before expand_end_case. */ if (GET_CODE (get_last_insn ()) != NOTE) ! emit_note (NULL_PTR, NOTE_INSN_DELETED); thiscase->data.case_stmt.start = get_last_insn (); *************** *** 3438,3445 **** ; ! if (!(n && tree_int_cst_equal (n->low, TREE_VALUE (chain)))) { if (warn_switch) ! warning ("enumerated value `%s' not handled in switch", IDENTIFIER_POINTER (TREE_PURPOSE (chain))); all_values = 0; --- 3556,3563 ---- ; ! if (!n || tree_int_cst_lt (TREE_VALUE (chain), n->low)) { if (warn_switch) ! warning ("enumeration value `%s' not handled in switch", IDENTIFIER_POINTER (TREE_PURPOSE (chain))); all_values = 0; *************** *** 3467,3470 **** --- 3585,3603 ---- ? TYPE_NAME (type) : DECL_NAME (TYPE_NAME (type)))); + if (!tree_int_cst_equal (n->low, n->high)) + { + for (chain = TYPE_VALUES (type); + chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain)); + chain = TREE_CHAIN (chain)) + ; + + if (!chain) + warning ("case value `%d' not in enumerated type `%s'", + TREE_INT_CST_LOW (n->high), + IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type)) + == IDENTIFIER_NODE) + ? TYPE_NAME (type) + : DECL_NAME (TYPE_NAME (type)))); + } } *************** *** 3487,3491 **** /* Terminate a case (Pascal) or switch (C) statement ! in which CASE_INDEX is the expression to be tested. Generate the code to test it and jump to the right place. */ --- 3620,3624 ---- /* Terminate a case (Pascal) or switch (C) statement ! in which ORIG_INDEX is the expression to be tested. Generate the code to test it and jump to the right place. */ *************** *** 3602,3615 **** If the switch-index is a constant, do it this way because we can optimize it. */ ! else if (TREE_INT_CST_HIGH (range) != 0 #ifdef HAVE_casesi ! || (HAVE_casesi ? count < 4 : count < 5) #else ! /* If machine does not have a case insn that compares the ! bounds, this means extra overhead for dispatch tables ! which raises the threshold for using them. */ ! || count < 5 ! #endif ! || (unsigned) (TREE_INT_CST_LOW (range)) > 10 * count || TREE_CODE (index_expr) == INTEGER_CST /* These will reduce to a constant. */ --- 3735,3754 ---- If the switch-index is a constant, do it this way because we can optimize it. */ ! ! #ifndef CASE_VALUES_THRESHOLD #ifdef HAVE_casesi ! #define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5) #else ! /* If machine does not have a case insn that compares the ! bounds, this means extra overhead for dispatch tables ! which raises the threshold for using them. */ ! #define CASE_VALUES_THRESHOLD 5 ! #endif /* HAVE_casesi */ ! #endif /* CASE_VALUES_THRESHOLD */ ! ! else if (TREE_INT_CST_HIGH (range) != 0 ! || count < CASE_VALUES_THRESHOLD ! || ((unsigned HOST_WIDE_INT) (TREE_INT_CST_LOW (range)) ! > 10 * count) || TREE_CODE (index_expr) == INTEGER_CST /* These will reduce to a constant. */ *************** *** 3621,3625 **** && TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST)) { ! index = expand_expr (index_expr, 0, VOIDmode, 0); /* If the index is a short or char that we do not have --- 3760,3764 ---- && TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST)) { ! index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0); /* If the index is a short or char that we do not have *************** *** 3699,3703 **** = (TREE_CODE (TREE_TYPE (orig_index)) != ENUMERAL_TYPE && estimate_case_costs (thiscase->data.case_stmt.case_list)); ! balance_case_nodes (&thiscase->data.case_stmt.case_list, 0); emit_case_nodes (index, thiscase->data.case_stmt.case_list, default_label, TREE_TYPE (index_expr)); --- 3838,3843 ---- = (TREE_CODE (TREE_TYPE (orig_index)) != ENUMERAL_TYPE && estimate_case_costs (thiscase->data.case_stmt.case_list)); ! balance_case_nodes (&thiscase->data.case_stmt.case_list, ! NULL_PTR); emit_case_nodes (index, thiscase->data.case_stmt.case_list, default_label, TREE_TYPE (index_expr)); *************** *** 3719,3723 **** { enum machine_mode omode = TYPE_MODE (TREE_TYPE (index_expr)); ! rtx rangertx = expand_expr (range, 0, VOIDmode, 0); /* We must handle the endpoints in the original mode. */ --- 3859,3863 ---- { enum machine_mode omode = TYPE_MODE (TREE_TYPE (index_expr)); ! rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0); /* We must handle the endpoints in the original mode. */ *************** *** 3725,3730 **** index_expr, minval); minval = integer_zero_node; ! index = expand_expr (index_expr, 0, VOIDmode, 0); ! emit_cmp_insn (rangertx, index, LTU, 0, omode, 0, 0); emit_jump_insn (gen_bltu (default_label)); /* Now we can safely truncate. */ --- 3865,3870 ---- index_expr, minval); minval = integer_zero_node; ! index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0); ! emit_cmp_insn (rangertx, index, LTU, NULL_RTX, omode, 0, 0); emit_jump_insn (gen_bltu (default_label)); /* Now we can safely truncate. */ *************** *** 3736,3740 **** index_expr = convert (type_for_size (index_bits, 0), index_expr); ! index = expand_expr (index_expr, 0, VOIDmode, 0); } emit_queue (); --- 3876,3880 ---- index_expr = convert (type_for_size (index_bits, 0), index_expr); ! index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0); } emit_queue (); *************** *** 3742,3747 **** do_pending_stack_adjust (); ! emit_jump_insn (gen_casesi (index, expand_expr (minval, 0, VOIDmode, 0), ! expand_expr (range, 0, VOIDmode, 0), table_label, default_label)); win = 1; --- 3882,3889 ---- do_pending_stack_adjust (); ! emit_jump_insn (gen_casesi (index, expand_expr (minval, NULL_RTX, ! VOIDmode, 0), ! expand_expr (range, NULL_RTX, ! VOIDmode, 0), table_label, default_label)); win = 1; *************** *** 3755,3759 **** TREE_TYPE (index_expr), index_expr, minval))); ! index = expand_expr (index_expr, 0, VOIDmode, 0); emit_queue (); index = protect_from_queue (index, 0); --- 3897,3901 ---- TREE_TYPE (index_expr), index_expr, minval))); ! index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0); emit_queue (); index = protect_from_queue (index, 0); *************** *** 3761,3765 **** do_tablejump (index, TYPE_MODE (TREE_TYPE (index_expr)), ! expand_expr (range, 0, VOIDmode, 0), table_label, default_label); win = 1; --- 3903,3907 ---- do_tablejump (index, TYPE_MODE (TREE_TYPE (index_expr)), ! expand_expr (range, NULL_RTX, VOIDmode, 0), table_label, default_label); win = 1; *************** *** 3777,3781 **** for (n = thiscase->data.case_stmt.case_list; n; n = n->right) { ! register int i = TREE_INT_CST_LOW (n->low) - TREE_INT_CST_LOW (minval); --- 3919,3923 ---- for (n = thiscase->data.case_stmt.case_list; n; n = n->right) { ! register HOST_WIDE_INT i = TREE_INT_CST_LOW (n->low) - TREE_INT_CST_LOW (minval); *************** *** 3800,3804 **** /* This would be a lot nicer if CASE_VECTOR_PC_RELATIVE ! were an expression, instead of a an #ifdef/#ifndef. */ if ( #ifdef CASE_VECTOR_PC_RELATIVE --- 3942,3946 ---- /* This would be a lot nicer if CASE_VECTOR_PC_RELATIVE ! were an expression, instead of an #ifdef/#ifndef. */ if ( #ifdef CASE_VECTOR_PC_RELATIVE *************** *** 3853,3857 **** if (mode == VOIDmode) mode = GET_MODE (op2); ! emit_cmp_insn (op1, op2, EQ, 0, mode, unsignedp, 0); emit_jump_insn (gen_beq (label)); } --- 3995,3999 ---- if (mode == VOIDmode) mode = GET_MODE (op2); ! emit_cmp_insn (op1, op2, EQ, NULL_RTX, mode, unsignedp, 0); emit_jump_insn (gen_beq (label)); } *************** *** 4234,4238 **** code for out of bound conditions on the current node node. ! We can asume that when control reaches the code generated here, the index value has already been compared with the parents of this node, and determined to be on the same side of each parent --- 4376,4380 ---- code for out of bound conditions on the current node node. ! We can assume that when control reaches the code generated here, the index value has already been compared with the parents of this node, and determined to be on the same side of each parent *************** *** 4268,4272 **** this node and then check our children, if any. */ ! do_jump_if_equal (index, expand_expr (node->low, 0, VOIDmode, 0), label_rtx (node->code_label), unsignedp); --- 4410,4414 ---- this node and then check our children, if any. */ ! do_jump_if_equal (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0), label_rtx (node->code_label), unsignedp); *************** *** 4281,4286 **** if (node_is_bounded (node->right, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! GT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label))); --- 4423,4429 ---- if (node_is_bounded (node->right, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! GT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label))); *************** *** 4290,4296 **** else if (node_is_bounded (node->left, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! LT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (label_rtx (node->left->code_label))); emit_case_nodes (index, node->right, default_label, index_type); --- 4433,4439 ---- else if (node_is_bounded (node->left, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, VOIDmode, 0), ! LT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (label_rtx (node->left->code_label))); emit_case_nodes (index, node->right, default_label, index_type); *************** *** 4306,4312 **** /* See if the value is on the right. */ ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! GT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (label_rtx (test_label))); --- 4449,4455 ---- /* See if the value is on the right. */ ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, VOIDmode, 0), ! GT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (label_rtx (test_label))); *************** *** 4337,4342 **** if (!node_has_low_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! LT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (default_label)); } --- 4480,4486 ---- if (!node_has_low_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! LT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (default_label)); } *************** *** 4349,4353 **** this node's value. So handle node->right explicitly. */ do_jump_if_equal (index, ! expand_expr (node->right->low, 0, VOIDmode, 0), label_rtx (node->right->code_label), unsignedp); } --- 4493,4498 ---- this node's value. So handle node->right explicitly. */ do_jump_if_equal (index, ! expand_expr (node->right->low, NULL_RTX, ! VOIDmode, 0), label_rtx (node->right->code_label), unsignedp); } *************** *** 4375,4380 **** if (!node_has_high_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! GT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (default_label)); } --- 4520,4526 ---- if (!node_has_high_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! GT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (default_label)); } *************** *** 4387,4391 **** this node's value. So handle node->left explicitly. */ do_jump_if_equal (index, ! expand_expr (node->left->low, 0, VOIDmode, 0), label_rtx (node->left->code_label), unsignedp); } --- 4533,4538 ---- this node's value. So handle node->left explicitly. */ do_jump_if_equal (index, ! expand_expr (node->left->low, NULL_RTX, ! VOIDmode, 0), label_rtx (node->left->code_label), unsignedp); } *************** *** 4406,4411 **** tree test_label = 0; ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! GT, 0, mode, unsignedp, 0); if (node_is_bounded (node->right, index_type)) --- 4553,4559 ---- tree test_label = 0; ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! GT, NULL_RTX, mode, unsignedp, 0); if (node_is_bounded (node->right, index_type)) *************** *** 4424,4429 **** /* Value belongs to this node or to the left-hand subtree. */ ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), ! GE, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label))); --- 4572,4577 ---- /* Value belongs to this node or to the left-hand subtree. */ ! emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0), ! GE, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label))); *************** *** 4450,4455 **** if (!node_has_low_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), ! LT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (default_label)); } --- 4598,4604 ---- if (!node_has_low_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, ! VOIDmode, 0), ! LT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (default_label)); } *************** *** 4457,4462 **** /* Value belongs to this node or to the right-hand subtree. */ ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! LE, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_ble_pat) (label_rtx (node->code_label))); --- 4606,4612 ---- /* Value belongs to this node or to the right-hand subtree. */ ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! LE, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_ble_pat) (label_rtx (node->code_label))); *************** *** 4470,4475 **** if (!node_has_high_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! GT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (default_label)); } --- 4620,4626 ---- if (!node_has_high_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! GT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (default_label)); } *************** *** 4477,4482 **** /* Value belongs to this node or to the left-hand subtree. */ ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), ! GE, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label))); --- 4628,4633 ---- /* Value belongs to this node or to the left-hand subtree. */ ! emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0), ! GE, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label))); *************** *** 4492,4497 **** if (!node_has_high_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), ! GT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (default_label)); } --- 4643,4649 ---- if (!node_has_high_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->high, NULL_RTX, ! VOIDmode, 0), ! GT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_bgt_pat) (default_label)); } *************** *** 4499,4504 **** if (!node_has_low_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), ! LT, 0, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (default_label)); } --- 4651,4657 ---- if (!node_has_low_bound (node, index_type)) { ! emit_cmp_insn (index, expand_expr (node->low, NULL_RTX, ! VOIDmode, 0), ! LT, NULL_RTX, mode, unsignedp, 0); emit_jump_insn ((*gen_blt_pat) (default_label)); } *************** *** 4512,4678 **** so that the debugging info will be correct for the unrolled loop. */ ! /* Indexed by loop number, contains pointer to the first block in the loop, ! or zero if none. Only valid if doing loop unrolling and outputting debugger ! info. */ ! ! tree *loop_number_first_block; ! ! /* Indexed by loop number, contains pointer to the last block in the loop, ! only valid if loop_number_first_block is nonzero. */ ! ! tree *loop_number_last_block; ! /* Indexed by loop number, contains nesting level of first block in the ! loop, if any. Only valid if doing loop unrolling and outputting debugger ! info. */ - int *loop_number_block_level; - - /* Scan the function looking for loops, and walk the BLOCK tree at the - same time. Record the first and last BLOCK tree corresponding to each - loop. This function is similar to find_and_verify_loops in loop.c. */ - void ! find_loop_tree_blocks (f) ! rtx f; { ! rtx insn; ! int current_loop = -1; ! int next_loop = -1; ! int loop; ! int block_level, tree_level; ! tree tree_block, parent_tree_block; ! ! tree_block = DECL_INITIAL (current_function_decl); ! parent_tree_block = 0; ! block_level = 0; ! tree_level = -1; ! ! /* Find boundaries of loops, and save the first and last BLOCK tree ! corresponding to each loop. */ ! ! for (insn = f; insn; insn = NEXT_INSN (insn)) ! { ! if (GET_CODE (insn) == NOTE) ! switch (NOTE_LINE_NUMBER (insn)) ! { ! case NOTE_INSN_LOOP_BEG: ! loop_number_block_level[++next_loop] = block_level; ! loop_number_first_block[next_loop] = 0; ! current_loop = next_loop; ! break; ! ! case NOTE_INSN_LOOP_END: ! if (current_loop == -1) ! abort (); ! ! current_loop = loop_outer_loop[current_loop]; ! break; ! ! case NOTE_INSN_BLOCK_BEG: ! if (tree_level < block_level) ! { ! /* We have seen two NOTE_INSN_BLOCK_BEG notes in a row, so ! we must now visit the subtree of the current block. */ ! parent_tree_block = tree_block; ! tree_block = BLOCK_SUBBLOCKS (tree_block); ! tree_level++; ! } ! else if (tree_level > block_level) ! abort (); ! /* Save this block tree here for all nested loops for which ! this is the topmost block. */ ! for (loop = current_loop; ! loop != -1 && block_level == loop_number_block_level[loop]; ! loop = loop_outer_loop[loop]) ! { ! if (loop_number_first_block[loop] == 0) ! loop_number_first_block[loop] = tree_block; ! loop_number_last_block[loop] = tree_block; ! } ! ! block_level++; ! break; ! case NOTE_INSN_BLOCK_END: ! block_level--; ! if (tree_level > block_level) ! { ! /* We have seen two NOTE_INSN_BLOCK_END notes in a row, so ! we must now visit the parent of the current tree. */ ! if (tree_block != 0 || parent_tree_block == 0) ! abort (); ! tree_block = parent_tree_block; ! parent_tree_block = BLOCK_SUPERCONTEXT (parent_tree_block); ! tree_level--; ! } ! tree_block = BLOCK_CHAIN (tree_block); ! break; ! } ! } } - /* This routine will make COPIES-1 copies of all BLOCK trees that correspond - to BLOCK_BEG notes inside the loop LOOP_NUMBER. - - Note that we only copy the topmost level of tree nodes; they will share - pointers to the same subblocks. */ - void ! unroll_block_trees (loop_number, copies) ! int loop_number; ! int copies; { ! int i; ! ! /* First check whether there are any blocks that need to be copied. */ ! if (loop_number_first_block[loop_number]) ! { ! tree first_block = loop_number_first_block[loop_number]; ! tree last_block = loop_number_last_block[loop_number]; ! tree last_block_created = 0; ! ! for (i = 0; i < copies - 1; i++) ! { ! tree block = first_block; ! tree insert_after = last_block; ! tree copied_block; ! ! /* Copy every block between first_block and last_block inclusive, ! inserting the new blocks after last_block. */ ! do ! { ! tree new_block = make_node (BLOCK); ! BLOCK_VARS (new_block) = BLOCK_VARS (block); ! BLOCK_TYPE_TAGS (new_block) = BLOCK_TYPE_TAGS (block); ! BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (block); ! BLOCK_SUPERCONTEXT (new_block) = BLOCK_SUPERCONTEXT (block); ! TREE_USED (new_block) = TREE_USED (block); ! ! /* Insert the new block after the insertion point, and move ! the insertion point to the new block. This ensures that ! the copies are inserted in the right order. */ ! BLOCK_CHAIN (new_block) = BLOCK_CHAIN (insert_after); ! BLOCK_CHAIN (insert_after) = new_block; ! insert_after = new_block; ! ! copied_block = block; ! block = BLOCK_CHAIN (block); ! } ! while (copied_block != last_block); ! ! /* Remember the last block created, so that we can update the ! info in the tables. */ ! if (last_block_created == 0) ! last_block_created = insert_after; ! } ! /* For all nested loops for which LAST_BLOCK was originally the last ! block, update the tables to indicate that LAST_BLOCK_CREATED is ! now the last block in the loop. */ ! for (i = loop_number; last_block == loop_number_last_block[i]; ! i = loop_outer_loop[i]) ! loop_number_last_block[i] = last_block_created; ! } } --- 4665,4690 ---- so that the debugging info will be correct for the unrolled loop. */ ! /* Indexed by block number, contains a pointer to the N'th block node. */ ! static tree *block_vector; void ! find_loop_tree_blocks () { ! tree block = DECL_INITIAL (current_function_decl); ! /* There first block is for the function body, and does not have ! corresponding block notes. Don't include it in the block vector. */ ! block = BLOCK_SUBBLOCKS (block); ! block_vector = identify_blocks (block, get_insns ()); } void ! unroll_block_trees () { ! tree block = DECL_INITIAL (current_function_decl); ! reorder_blocks (block_vector, block, get_insns ()); } + diff -rc2N gcc-2.2.2/stor-layout.c gcc-2.3.1/stor-layout.c *** gcc-2.2.2/stor-layout.c Mon Apr 13 06:56:36 1992 --- gcc-2.3.1/stor-layout.c Sat Sep 5 19:24:35 1992 *************** *** 41,44 **** --- 41,48 ---- tree size_one_node; + /* If nonzero, this is an upper limit on alignment of structure fields. + The value is measured in bits. */ + int maximum_field_alignment; + #define GET_MODE_ALIGNMENT(MODE) \ MIN (BIGGEST_ALIGNMENT, \ *************** *** 83,89 **** if (immediate_size_expand) ! expand_expr (size, 0, VOIDmode, 0); else ! pending_sizes = tree_cons (0, size, pending_sizes); return size; --- 87,93 ---- if (immediate_size_expand) ! expand_expr (size, NULL_PTR, VOIDmode, 0); else ! pending_sizes = tree_cons (NULL_TREE, size, pending_sizes); return size; *************** *** 199,203 **** and occupying a complete byte or bytes on proper boundary. */ if (code == FIELD_DECL) ! DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0; if (DECL_BIT_FIELD (decl) && TYPE_SIZE (type) != 0 --- 203,212 ---- and occupying a complete byte or bytes on proper boundary. */ if (code == FIELD_DECL) ! { ! DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0; ! if (maximum_field_alignment != 0) ! DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment); ! } ! if (DECL_BIT_FIELD (decl) && TYPE_SIZE (type) != 0 *************** *** 272,276 **** if (TREE_STATIC (field)) { ! pending_statics = tree_cons (NULL, field, pending_statics); continue; } --- 281,285 ---- if (TREE_STATIC (field)) { ! pending_statics = tree_cons (NULL_TREE, field, pending_statics); continue; } *************** *** 319,323 **** forces the entire structure to have `int' alignment. */ if (DECL_NAME (field) != 0) ! record_align = MAX (record_align, TYPE_ALIGN (TREE_TYPE (field))); } else --- 328,338 ---- forces the entire structure to have `int' alignment. */ if (DECL_NAME (field) != 0) ! { ! int type_align = TYPE_ALIGN (TREE_TYPE (field)); ! if (maximum_field_alignment != 0) ! type_align = MIN (type_align, maximum_field_alignment); ! ! record_align = MAX (record_align, type_align); ! } } else *************** *** 363,368 **** --- 378,390 ---- int field_size = TREE_INT_CST_LOW (dsize); + if (maximum_field_alignment != 0) + type_align = MIN (type_align, maximum_field_alignment); + /* A bit field may not span the unit of alignment of its type. Advance to next boundary if necessary. */ + /* ??? There is some uncertainty here as to what + should be done if type_align is less than the width of the type. + That can happen because the width exceeds BIGGEST_ALIGNMENT + or because it exceeds maximum_field_alignment. */ if (const_size / type_align != (const_size + field_size - 1) / type_align) *************** *** 385,388 **** --- 407,413 ---- int field_size = TREE_INT_CST_LOW (dsize); + if (maximum_field_alignment != 0) + type_align = MIN (type_align, maximum_field_alignment); + /* A bit field may not span the unit of alignment of its type. Advance to next boundary if necessary. */ *************** *** 422,426 **** register tree dsize = DECL_SIZE (field); ! if (TREE_CODE (dsize) == INTEGER_CST) const_size += TREE_INT_CST_LOW (dsize); else --- 447,456 ---- register tree dsize = DECL_SIZE (field); ! /* This can happen when we have an invalid nested struct definition, ! such as struct j { struct j { int i; } }. The error message is ! printed in finish_struct. */ ! if (dsize == 0) ! /* Do nothing. */; ! else if (TREE_CODE (dsize) == INTEGER_CST) const_size += TREE_INT_CST_LOW (dsize); else *************** *** 808,811 **** --- 838,863 ---- break; + /* Pascal types */ + case BOOLEAN_TYPE: /* store one byte/boolean for now. */ + TYPE_MODE (type) = QImode; + TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); + TYPE_PRECISION (type) = 1; + TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); + break; + + case CHAR_TYPE: + TYPE_MODE (type) = QImode; + TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type))); + TYPE_PRECISION (type) = GET_MODE_BITSIZE (TYPE_MODE (type)); + TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); + break; + + case FILE_TYPE: + /* The size may vary in different languages, so the language front end + should fill in the size. */ + TYPE_ALIGN (type) = BIGGEST_ALIGNMENT; + TYPE_MODE (type) = BLKmode; + break; + default: abort (); *************** *** 865,876 **** TYPE_MIN_VALUE (type) ! = build_int_2 ((precision-HOST_BITS_PER_INT > 0 ? 0 : (-1)<<(precision-1)), ! (-1)<<(precision-HOST_BITS_PER_INT-1 > 0 ! ? precision-HOST_BITS_PER_INT-1 ! : 0)); TYPE_MAX_VALUE (type) ! = build_int_2 ((precision-HOST_BITS_PER_INT > 0 ? -1 : (1<<(precision-1))-1), ! (precision-HOST_BITS_PER_INT-1 > 0 ! ? (1<<(precision-HOST_BITS_PER_INT-1))-1 : 0)); --- 917,932 ---- TYPE_MIN_VALUE (type) ! = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 ! ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)), ! (((HOST_WIDE_INT) (-1) ! << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0 ! ? precision-HOST_BITS_PER_WIDE_INT - 1 ! : 0)))); TYPE_MAX_VALUE (type) ! = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 ! ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1), ! (precision - HOST_BITS_PER_WIDE_INT - 1 > 0 ! ? (((HOST_WIDE_INT) 1 ! << (precision - HOST_BITS_PER_INT - 1)))-1 : 0)); *************** *** 918,921 **** --- 974,1007 ---- /* Set the extreme values of TYPE based on its precision in bits, + the lay it out. Used when make_signed_type won't do + because the tree code is not INTEGER_TYPE. + E.g. for Pascal, when the -fsigned-char option is given. */ + + void + fixup_signed_type (type) + tree type; + { + register int precision = TYPE_PRECISION (type); + + TYPE_MIN_VALUE (type) + = build_int_2 ((precision-BITS_PER_WORD > 0 ? 0 : (-1)<<(precision-1)), + (-1)<<(precision-BITS_PER_WORD-1 > 0 + ? precision-BITS_PER_WORD-1 + : 0)); + TYPE_MAX_VALUE (type) + = build_int_2 ((precision-BITS_PER_WORD > 0 ? -1 : (1<<(precision-1))-1), + (precision-BITS_PER_WORD-1 > 0 + ? (1<<(precision-BITS_PER_WORD-1))-1 + : 0)); + + TREE_TYPE (TYPE_MIN_VALUE (type)) = type; + TREE_TYPE (TYPE_MAX_VALUE (type)) = type; + + /* Lay out the type: set its alignment, size, etc. */ + + layout_type (type); + } + + /* Set the extreme values of TYPE based on its precision in bits, the lay it out. This is used both in `make_unsigned_type' and for enumeral types. */ *************** *** 929,936 **** TYPE_MIN_VALUE (type) = build_int_2 (0, 0); TYPE_MAX_VALUE (type) ! = build_int_2 (precision-HOST_BITS_PER_INT >= 0 ? -1 : (1< 0 ! ? ((unsigned) ~0 ! >> (HOST_BITS_PER_INT - (precision - HOST_BITS_PER_INT))) : 0); TREE_TYPE (TYPE_MIN_VALUE (type)) = type; --- 1015,1024 ---- TYPE_MIN_VALUE (type) = build_int_2 (0, 0); TYPE_MAX_VALUE (type) ! = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0 ! ? -1 : ((HOST_WIDE_INT) 1<< precision) - 1, ! precision - HOST_BITS_PER_WIDE_INT > 0 ! ? ((unsigned HOST_WIDE_INT) ~0 ! >> (HOST_BITS_PER_WIDE_INT ! - (precision - HOST_BITS_PER_WIDE_INT))) : 0); TREE_TYPE (TYPE_MIN_VALUE (type)) = type; *************** *** 953,959 **** mode meeting these conditions. ! Otherwise (VOLATILEP is false and SLOW_BYTE_ACCESS is true), if a mode ! whose size is UNITS_PER_WORD meets all the conditions, it is returned ! instead. */ enum machine_mode --- 1041,1047 ---- mode meeting these conditions. ! Otherwise (VOLATILEP is false and SLOW_BYTE_ACCESS is true), we return ! the largest mode (but a mode no wider than UNITS_PER_WORD) that meets ! all the conditions. */ enum machine_mode *************** *** 988,997 **** return VOIDmode; ! if (SLOW_BYTE_ACCESS ! && ! volatilep ! && BITS_PER_WORD <= MIN (align, BIGGEST_ALIGNMENT) ! && (largest_mode == VOIDmode ! || BITS_PER_WORD <= GET_MODE_BITSIZE (largest_mode))) ! return word_mode; return mode; --- 1076,1098 ---- return VOIDmode; ! if (SLOW_BYTE_ACCESS && ! volatilep) ! { ! enum machine_mode wide_mode = VOIDmode, tmode; ! ! for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); tmode != VOIDmode; ! tmode = GET_MODE_WIDER_MODE (tmode)) ! { ! unit = GET_MODE_BITSIZE (tmode); ! if (bitpos / unit == (bitpos + bitsize - 1) / unit ! && unit <= BITS_PER_WORD ! && unit <= MIN (align, BIGGEST_ALIGNMENT) ! && (largest_mode == VOIDmode ! || unit <= GET_MODE_BITSIZE (largest_mode))) ! wide_mode = tmode; ! } ! ! if (wide_mode != VOIDmode) ! return wide_mode; ! } return mode; diff -rc2N gcc-2.2.2/sys-types.h gcc-2.3.1/sys-types.h *** gcc-2.2.2/sys-types.h Sun Dec 15 01:01:37 1991 --- gcc-2.3.1/sys-types.h Fri Sep 11 21:09:51 1992 *************** *** 87,90 **** --- 87,94 ---- /* #include "sys/types.h" */ + + /* The actual types used here are mostly wrong, + but it is not supposed to matter what types we use here. */ + typedef int dev_t; typedef int pid_t; *************** *** 162,166 **** typedef int uint; ! typedef va_list; typedef int archdr; --- 166,170 ---- typedef int uint; ! typedef int va_list; typedef int archdr; diff -rc2N gcc-2.2.2/syslimits.h gcc-2.3.1/syslimits.h *** gcc-2.2.2/syslimits.h --- gcc-2.3.1/syslimits.h Thu Sep 24 02:58:53 1992 *************** *** 0 **** --- 1,6 ---- + /* syslimits.h stands for the system's own limits.h file. + If we can use it ok unmodified, then we install this text. + If fixincludes fixes it, then the fixed version is installed + instead of this text. */ + + #include_next diff -rc2N gcc-2.2.2/texinfo.tex gcc-2.3.1/texinfo.tex *** gcc-2.2.2/texinfo.tex Sun Jun 14 18:18:08 1992 --- gcc-2.3.1/texinfo.tex Sun Nov 1 03:44:45 1992 *************** *** 1,5 **** %% TeX macros to handle texinfo files ! % Copyright (C) 1985, 1986, 1988, 1990, 1991 Free Software Foundation, Inc. %This texinfo.tex file is free software; you can redistribute it and/or --- 1,5 ---- %% TeX macros to handle texinfo files ! % Copyright (C) 1985, 86, 88, 90, 91, 92 Free Software Foundation, Inc. %This texinfo.tex file is free software; you can redistribute it and/or *************** *** 23,27 **** %what you give them. Help stamp out software-hoarding! ! \def\texinfoversion{2.72} \message{Loading texinfo package [Version \texinfoversion]:} \message{} --- 23,27 ---- %what you give them. Help stamp out software-hoarding! ! \def\texinfoversion{2.88} \message{Loading texinfo package [Version \texinfoversion]:} \message{} *************** *** 55,58 **** --- 55,62 ---- \newlinechar = `^^J + % Ignore a token. + % + \def\gobble#1{} + \hyphenation{ap-pen-dix} \hyphenation{mini-buf-fer mini-buf-fers} *************** *** 161,185 **** {\hrule height\cornerlong depth\cornerthick width\cornerthick}} ! % Parse an argument, then pass it to #1. ! % The argument can be delimited with [...] or with "..." or braces ! % or it can be a whole line. ! % #1 should be a macro which expects ! % an ordinary undelimited TeX argument. ! ! \def\parsearg #1{\let\next=#1\begingroup\obeylines\futurelet\temp\parseargx} \def\parseargx{% ! \ifx \obeyedspace\temp \aftergroup\parseargdiscardspace \else% ! \aftergroup \parseargline % ! \fi \endgroup} {\obeyspaces % ! \gdef\parseargdiscardspace {\begingroup\obeylines\futurelet\temp\parseargx}} ! \gdef\obeyedspace{\ } - \def\parseargline{\begingroup \obeylines \parsearglinex} {\obeylines % ! \gdef\parsearglinex #1^^M{\endgroup \next {#1}}} \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} --- 165,245 ---- {\hrule height\cornerlong depth\cornerthick width\cornerthick}} ! % Parse an argument, then pass it to #1. The argument is the rest of ! % the input line (except we remove a trailing comment). #1 should be a ! % macro which expects an ordinary undelimited TeX argument. ! % ! \def\parsearg#1{% ! \let\next = #1% ! \begingroup ! \obeylines ! \futurelet\temp\parseargx ! } + % If the next token is an obeyed space (from an @example environment or + % the like), remove it and recurse. Otherwise, we're done. \def\parseargx{% ! \ifx\obeyedspace\temp ! \expandafter\parseargdiscardspace ! \else ! \expandafter\parseargline ! \fi ! } + % Remove a single space (as the delimiter token to the macro call). {\obeyspaces % ! \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} ! \def\obeyedspace{\ } {\obeylines % ! \gdef\parseargline#1^^M{% ! \endgroup % End of the group started in \parsearg. ! % ! % First remove any @c comment, then any @comment. ! % Result of each macro is put in \toks0. ! \argremovec #1\c\relax % ! \expandafter\argremovecomment \the\toks0 \comment\relax % ! % ! % Call the caller's macro, saved as \next in \parsearg. ! \expandafter\next\expandafter{\the\toks0}% ! }% ! } ! ! % Since all \c{,omment} does is throw away the argument, we can let TeX ! % do that for us. The \relax here is matched by the \relax in the call ! % in \parseargline; it could be more or less anything, its purpose is ! % just to delimit the argument to the \c. ! \def\argremovec#1\c#2\relax{\toks0 = {#1}} ! \def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} ! ! % \argremovec{,omment} might leave us with trailing spaces, though; e.g., ! % @end itemize @c foo ! % will have two active spaces as part of the argument with the ! % `itemize'. Here we remove all active spaces from #1, and assign the ! % result to \toks0. ! % ! % This loses if there are any *other* active characters besides spaces ! % in the argument -- _ ^ +, for example -- since they get expanded. ! % Fortunately, Texinfo does not define any such commands. (If it ever ! % does, the catcode of the characters in questionwill have to be changed ! % here.) But this means we cannot call \removeactivespaces as part of ! % \argremovec{,omment}, since @c uses \parsearg, and thus the argument ! % that \parsearg gets might well have any character at all in it. ! % ! \def\removeactivespaces#1{% ! \begingroup ! \ignoreactivespaces ! \edef\temp{#1}% ! \global\toks0 = \expandafter{\temp}% ! \endgroup ! } ! ! % Change the active space to expand to nothing. ! % ! \begingroup ! \obeyspaces ! \gdef\ignoreactivespaces{\obeyspaces\let =\empty} ! \endgroup ! \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} *************** *** 193,197 **** % @begin foo is the same as @foo, for now. ! \newhelp\EMsimple{Type to continue} \outer\def\begin{\parsearg\beginxxx} --- 253,257 ---- % @begin foo is the same as @foo, for now. ! \newhelp\EMsimple{Type to continue.} \outer\def\begin{\parsearg\beginxxx} *************** *** 202,218 **** \csname #1\endcsname\fi} ! %% @end foo executes the definition of \Efoo. ! %% foo can be delimited by doublequotes or brackets. ! \def\end{\parsearg\endxxx} - \def\endxxx #1{% ! \expandafter\ifx\csname E#1\endcsname\relax ! \expandafter\ifx\csname #1\endcsname\relax ! \errmessage{Undefined command @end #1}\else ! \errorE{#1}\fi\fi ! \csname E#1\endcsname} ! \def\errorE#1{ ! {\errhelp=\EMsimple \errmessage{@end #1 not within #1 environment}}} % Single-spacing is done by various environments. --- 262,288 ---- \csname #1\endcsname\fi} ! % @end foo executes the definition of \Efoo. ! % \def\end{\parsearg\endxxx} \def\endxxx #1{% ! \removeactivespaces{#1}% ! \edef\endthing{\the\toks0}% ! % ! \expandafter\ifx\csname E\endthing\endcsname\relax ! \expandafter\ifx\csname \endthing\endcsname\relax ! % There's no \foo, i.e., no ``environment'' foo. ! \errhelp = \EMsimple ! \errmessage{Undefined command `@end \endthing'}% ! \else ! % There is an environment foo, but it hasn't been started. ! \errhelp = \EMsimple ! \errmessage{This `@end \endthing' doesn't have a matching `@\endthing'}% ! \fi ! \else ! % Everything's ok; the right environment has been started. ! \csname E\endthing\endcsname ! \fi ! } ! % Single-spacing is done by various environments. *************** *** 231,238 **** \def\@{{\tt \char '100}} ! % Define @` and @' to be the same as ` and ' ! % but suppressing ligatures. ! \def\`{{`}} ! \def\'{{'}} % Used to generate quoted braces. --- 301,310 ---- \def\@{{\tt \char '100}} ! % This is turned off because it was never documented ! % and you can use @w{...} around a quote to suppress ligatures. ! %% Define @` and @' to be the same as ` and ' ! %% but suppressing ligatures. ! %\def\`{{`}} ! %\def\'{{'}} % Used to generate quoted braces. *************** *** 270,275 **** \errmessage{@group invalid in context where filling is enabled}% \fi ! \def\Egroup{\egroup\endgroup}% \vtop\bgroup } % --- 342,364 ---- \errmessage{@group invalid in context where filling is enabled}% \fi ! % ! % The \vtop we start below produces a box with large depth; thus, TeX ! % puts \baselineskip glue before it, and (when the next line of text ! % is done) \lineskip glue after it. (See p.82 of the TeXbook.) But ! % the next line of text also gets us \parskip glue. Final result: ! % space below is slightly more than space above. ! \def\Egroup{% ! \egroup % End the \vtop. ! \endgroup % End the \group. ! }% ! % \vtop\bgroup + % We do @comment here in case we are called inside an environment, + % such as @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment } % *************** *** 420,428 **** } ! \def\ignore{\begingroup\ignoresections ! % Make sure that spaces turn into tokens that match what \ignorexxx wants. ! \catcode32=10 ! \ignorexxx} ! \long\def\ignorexxx #1\end ignore{\endgroup\ignorespaces} \def\direntry{\begingroup\direntryxxx} --- 509,539 ---- } ! % Ignore @ignore ... @end ignore. ! % ! \def\ignore{\doignore{ignore}} ! ! % We ignore @ifinfo text. ! % ! \def\ifinfo{\doignore{ifinfo}} ! ! % Ignore text until a line `@end #1'. ! % ! \def\doignore#1{\begingroup ! % Don't complain about control sequences we have declared \outer. ! \ignoresections ! % ! % Define a command to swallow text until we reach `@end #1'. ! \long\def\doignoretext##1\end #1{\enddoignore}% ! % ! % Make sure that spaces turn into tokens that match what \doignoretext wants. ! \catcode32 = 10 ! % ! % And now expand that command. ! \doignoretext ! } ! ! % What we do to finish off ignored text. ! % ! \def\enddoignore{\endgroup\ignorespaces}% \def\direntry{\begingroup\direntryxxx} *************** *** 434,470 **** \def\ifsetxxx #1{\endgroup ! \expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\ifsetfail \else \let\temp=\relax \fi \temp} \def\Eifset{} ! \def\ifsetfail{\begingroup\ignoresections\ifsetfailxxx} ! \long\def\ifsetfailxxx #1\end ifset{\endgroup\ignorespaces} \def\ifclear{\begingroup\ignoresections\parsearg\ifclearxxx} \def\ifclearxxx #1{\endgroup ! \expandafter\ifx\csname IF#1\endcsname\relax \let\temp=\relax \else \let\temp=\ifclearfail \fi \temp} \def\Eifclear{} ! \def\ifclearfail{\begingroup\ignoresections\ifclearfailxxx} ! \long\def\ifclearfailxxx #1\end ifclear{\endgroup\ignorespaces} ! % @set foo to set the flag named foo. % @clear foo to clear the flag named foo. \def\set{\parsearg\setxxx} - \def\setxxx #1{ - \expandafter\let\csname IF#1\endcsname=\set} \def\clear{\parsearg\clearxxx} \def\clearxxx #1{ ! \expandafter\let\csname IF#1\endcsname=\relax} % Some texinfo constructs that are trivial in tex \def\iftex{} \def\Eiftex{} - \def\ifinfo{\begingroup\ignoresections\ifinfoxxx} - \long\def\ifinfoxxx #1\end ifinfo{\endgroup\ignorespaces} \long\def\menu #1\end menu{} --- 545,590 ---- \def\ifsetxxx #1{\endgroup ! \expandafter\ifx\csname SET#1\endcsname\relax \let\temp=\ifsetfail \else \let\temp=\relax \fi \temp} \def\Eifset{} ! \def\ifsetfail{\doignore{ifset}} \def\ifclear{\begingroup\ignoresections\parsearg\ifclearxxx} \def\ifclearxxx #1{\endgroup ! \expandafter\ifx\csname SET#1\endcsname\relax \let\temp=\relax \else \let\temp=\ifclearfail \fi \temp} \def\Eifclear{} ! \def\ifclearfail{\doignore{ifclear}} ! % @set foo ! % to set the flag named foo to a default value (empty) ! % @set foo REST-OF-LINE ! % to set the flag named foo to a text string REST-OF-LINE % @clear foo to clear the flag named foo. + % @value{foo} to set the text saved in foo + % + % @set command, work macro \setyyy + % + \def\setyyy#1 #2\endsetyyy{\expandafter\xdef\csname SET#1\endcsname{#2\unskip}} + % + \def\setxxx#1{\setyyy#1 \endsetyyy} \def\set{\parsearg\setxxx} \def\clear{\parsearg\clearxxx} \def\clearxxx #1{ ! \expandafter\let\csname SET#1\endcsname=\relax} + \def\value#1{\expandafter + \ifx\csname SET#1\endcsname\relax + {\{No value for ``#1''\}} + \else \csname SET#1\endcsname \fi} + % Some texinfo constructs that are trivial in tex \def\iftex{} \def\Eiftex{} \long\def\menu #1\end menu{} *************** *** 484,487 **** --- 604,611 ---- \def\math#1{\implicitmath #1\implicitmath} + % @bullet and @minus need the same treatment as @math, just above. + \def\bullet{\implicitmath\ptexbullet\implicitmath} + \def\minus{\implicitmath-\implicitmath} + \def\node{\ENVcheck\parsearg\nodezzz} \def\nodezzz#1{\nodexxx [#1,]} *************** *** 1120,1126 **** \let\item=\itemizeitem} - \def\bullet{$\ptexbullet$} - \def\minus{$-$} - % Set sfcode to normal for the chars that usually have another value. % These are `.?!:;,' --- 1244,1247 ---- *************** *** 1520,1535 **** \line{\secbf#1\hfill}\kern 2pt\penalty10000}} \def\entry #1#2{\begingroup - \parfillskip=0in \parskip=0in \parindent=0in % ! % \hangindent is only relevant when the page number and the entry text ! % don't fit on one line. In that case, bob suggests starting the dots ! % pretty far over on the line. ! % \hangafter is reset to 1 at the start of each paragraph. ! \hangindent=.75\hsize \noindent % ! % Don't break the text of the index entry. ! \hbox{#1}% % % If we must, put the page number on a line of its own, and fill out --- 1641,1683 ---- \line{\secbf#1\hfill}\kern 2pt\penalty10000}} + % This typesets a paragraph consisting of #1, dot leaders, and then #2 + % flush to the right margin. It is used for index and table of contents + % entries. The paragraph is indented by \leftskip. + % \def\entry #1#2{\begingroup % ! % Start a new paragraph if necessary, so our assignments below can't ! % affect previous text. ! \par ! % ! % Do not fill out the last line with white space. ! \parfillskip = 0in ! % ! % No extra space above this paragraph. ! \parskip = 0in ! % ! % Do not prefer a separate line ending with a hyphen to fewer lines. ! \finalhyphendemerits = 0 ! % ! % \hangindent is only relevant when the entry text and page number ! % don't both fit on one line. In that case, bob suggests starting the ! % dots pretty far over on the line. Unfortunately, a large ! % indentation looks wrong when the entry text itself is broken across ! % lines. So we use a small indentation and put up with long leaders. ! % ! % \hangafter is reset to 1 (which is the value we want) at the start ! % of each paragraph, so we need not do anything with that. ! \hangindent=2em ! % ! % When the entry text needs to be broken, just fill out the first line ! % with blank space. ! \rightskip = 0pt plus1fil ! % ! % Start a ``paragraph'' for the index entry so the line breaking ! % parameters we've set above will have an effect. \noindent % ! % Insert the text of the index entry. TeX will do line-breaking on it. ! #1% % % If we must, put the page number on a line of its own, and fill out *************** *** 1540,1544 **** % % The `\ ' here is removed by the implicit \unskip that TeX does as ! % part of (the primitive) \par. Without, a spurious underfull \hbox ensues. \ #2% The page number ends the paragraph. \par --- 1688,1693 ---- % % The `\ ' here is removed by the implicit \unskip that TeX does as ! % part of (the primitive) \par. Without it, a spurious underfull ! % \hbox ensues. \ #2% The page number ends the paragraph. \par *************** *** 1560,1577 **** %% Define two-column mode, which is used in indexes. ! %% Adapted from the TeXBook, page 416 \catcode `\@=11 \newbox\partialpage ! \newdimen\doublecolumnhsize \doublecolumnhsize = 3.11in ! \newdimen\doublecolumnvsize \doublecolumnvsize = 19.1in \newdimen\availdimen@ \def\begindoublecolumns{\begingroup ! \output={\global\setbox\partialpage= ! \vbox{\unvbox255\kern -\topskip \kern \baselineskip}}\eject \output={\doublecolumnout}% ! \hsize=\doublecolumnhsize \vsize=\doublecolumnvsize} \def\enddoublecolumns{\output={\balancecolumns}\eject \endgroup \pagegoal=\vsize} --- 1709,1755 ---- %% Define two-column mode, which is used in indexes. ! %% Adapted from the TeXbook, page 416. \catcode `\@=11 \newbox\partialpage ! \newdimen\doublecolumnhsize \newdimen\availdimen@ \def\begindoublecolumns{\begingroup ! % Grab any single-column material above us. ! \output = {\global\setbox\partialpage ! =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}% ! \eject ! % ! % Now switch to the double-column output routine. \output={\doublecolumnout}% ! % ! % Change the page size parameters. We could do this once outside this ! % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 ! % format, but then we repeat the same computation. Repeating a couple ! % of assignments once per index is clearly meaningless for the ! % execution time, so we may as well do it once. ! % ! % First we halve the line length, less a little for the gutter between ! % the columns. We compute the gutter based on the line length, so it ! % changes automatically with the paper format. The magic constant ! % below is chosen so that the gutter has the same value (well, +- < ! % 1pt) as it did when we hard-coded it. ! % ! % We put the result in a separate register, \doublecolumhsize, so we ! % can restore it in \pagesofar, after \hsize itself has (potentially) ! % been clobbered. ! % ! \doublecolumnhsize = \hsize ! \advance\doublecolumnhsize by -.04154\hsize ! \divide\doublecolumnhsize by 2 ! \hsize = \doublecolumnhsize ! % ! % Double the \vsize as well. (We don't need a separate register here, ! % since nobody clobbers \vsize.) ! \vsize = 2\vsize ! } ! \def\enddoublecolumns{\output={\balancecolumns}\eject \endgroup \pagegoal=\vsize} *************** *** 1716,1720 **** \outer\def\unnumbered{\parsearg\unnumberedzzz} \def\unnumberedzzz #1{\seccheck{unnumbered}% ! \secno=0 \subsecno=0 \subsubsecno=0 \message{(#1)} \unnumbchapmacro {#1}% \gdef\thischapter{#1}\gdef\thissection{#1}% --- 1894,1911 ---- \outer\def\unnumbered{\parsearg\unnumberedzzz} \def\unnumberedzzz #1{\seccheck{unnumbered}% ! \secno=0 \subsecno=0 \subsubsecno=0 ! % ! % This used to be simply \message{#1}, but TeX fully expands the ! % argument to \message. Therefore, if #1 contained @-commands, TeX ! % expanded them. For example, in `@unnumbered The @cite{Book}', TeX ! % expanded @cite (which turns out to cause errors because \cite is meant ! % to be executed, not expanded). ! % ! % Anyway, we don't want the fully-expanded definition of @cite to appear ! % as a result of the \message, we just want `@cite' itself. We use ! % \the to achieve this: TeX expands \the only once, ! % simply yielding the contents of the . ! \toks0 = {#1}\message{(\the\toks0)}% ! % \unnumbchapmacro {#1}% \gdef\thischapter{#1}\gdef\thissection{#1}% *************** *** 2030,2038 **** \newskip\contentsrightmargin \contentsrightmargin=1in \def\startcontents#1{% \ifnum \pageno>0 \pageno = -1 % Request roman numbered pages. \fi - \pagealignmacro - \immediate\closeout \contentsfile % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. --- 2221,2229 ---- \newskip\contentsrightmargin \contentsrightmargin=1in \def\startcontents#1{% + \pagealignmacro + \immediate\closeout \contentsfile \ifnum \pageno>0 \pageno = -1 % Request roman numbered pages. \fi % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. *************** *** 2086,2101 **** % See comments in \dochapentry re vbox and related settings \def\shortchapentry#1#2#3{% ! \vbox{\hyphenpenalty=10000\tolerance=5000 ! \parindent=0pt\strut\raggedright ! {#2\labelspace #1}\dotfill\doshortpageno{#3}}% } ! \def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} ! \def\shortunnumberedentry#1#2{% ! \vbox{\hyphenpenalty=10000\tolerance=5000 ! \parindent=0pt\strut\raggedright ! #1\dotfill\doshortpageno{#2}}% } % Sections. \def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} --- 2277,2308 ---- % See comments in \dochapentry re vbox and related settings \def\shortchapentry#1#2#3{% ! \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}% } ! % Typeset the label for a chapter or appendix for the short contents. ! % The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter. ! % We could simplify the code here by writing out an \appendixentry ! % command in the toc file for appendices, instead of using \chapentry ! % for both, but it doesn't seem worth it. ! \setbox0 = \hbox{\shortcontrm Appendix } ! \newdimen\shortappendixwidth \shortappendixwidth = \wd0 ! ! \def\shortchaplabel#1{% ! % We typeset #1 in a box of constant width, regardless of the text of ! % #1, so the chapter titles will come out aligned. ! \setbox0 = \hbox{#1}% ! \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi ! % ! % This space should be plenty, since a single number is .5em, and the ! % widest letter (M) is 1em, at least in the Computer Modern fonts. ! % (This space doesn't include the extra space that gets added after ! % the label; that gets put in in \shortchapentry above.) ! \advance\dimen0 by 1.1em ! \hbox to \dimen0{#1\hfil}% } + \def\unnumbchapentry#1#2{\dochapentry{#1}{#2}} + \def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}} + % Sections. \def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} *************** *** 2122,2159 **** \def\dochapentry#1#2{% \penalty-300 \vskip\baselineskip ! % This \vbox (and similar ones in dosecentry etc.) used to be a ! % \line; changed to permit linebreaks for long headings. See ! % comments above \majorheading. Here we also use \strut to ! % keep the top end of the vbox from jamming up against the previous ! % entry in the table of contents. ! \vbox{\chapentryfonts ! \hyphenpenalty=10000\tolerance=5000 % this line and next introduced ! \parindent=0pt\strut\raggedright % with \line -> \vbox change ! #1\dotfill ! \dopageno{#2}}% \nobreak\vskip .25\baselineskip } ! \def\dosecentry#1#2{% ! \vbox{\secentryfonts \leftskip=\tocindent ! \hyphenpenalty=10000\tolerance=5000 ! \parindent=0pt\strut\raggedright #1\dotfill ! \dopageno{#2}}% ! } ! ! \def\dosubsecentry#1#2{% ! \vbox{\subsecentryfonts \leftskip=2\tocindent ! \hyphenpenalty=10000\tolerance=5000 ! \parindent=0pt\strut\raggedright #1\dotfill ! \dopageno{#2}}% ! } ! ! \def\dosubsubsecentry#1#2{% ! \vbox{\subsubsecentryfonts \leftskip=3\tocindent ! \hyphenpenalty=10000\tolerance=5000 ! \parindent=0pt\strut\raggedright #1\dotfill ! \dopageno{#2}}% ! } % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} --- 2329,2364 ---- \def\dochapentry#1#2{% \penalty-300 \vskip\baselineskip ! \begingroup ! \chapentryfonts ! \tocentry{#1}{\dopageno{#2}}% ! \endgroup \nobreak\vskip .25\baselineskip } ! \def\dosecentry#1#2{\begingroup ! \secentryfonts \leftskip=\tocindent ! \tocentry{#1}{\dopageno{#2}}% ! \endgroup} ! ! \def\dosubsecentry#1#2{\begingroup ! \subsecentryfonts \leftskip=2\tocindent ! \tocentry{#1}{\dopageno{#2}}% ! \endgroup} ! ! \def\dosubsubsecentry#1#2{\begingroup ! \subsubsecentryfonts \leftskip=3\tocindent ! \tocentry{#1}{\dopageno{#2}}% ! \endgroup} + % Final typesetting of a toc entry; we use the same \entry macro as for + % the index entries, but we want to suppress hyphenation here. (We + % can't do that in the \entry macro, since index entries might consist + % of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) + % + \def\tocentry#1#2{\begingroup + \hyphenpenalty = 10000 + \entry{#1}{#2}% + \endgroup} + % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} *************** *** 2264,2275 **** \gdef\sepspaces{\def {\ }}} ! \newskip\aboveenvskipamount \aboveenvskipamount= 0pt ! \def\aboveenvbreak{{\advance\aboveenvskipamount by \parskip ! \endgraf \ifdim\lastskip<\aboveenvskipamount ! \removelastskip \penalty-50 \vskip\aboveenvskipamount \fi}} ! \def\afterenvbreak{\endgraf \ifdim\lastskip<\aboveenvskipamount ! \removelastskip \penalty-50 \vskip\aboveenvskipamount \fi} % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. \let\nonarrowing=\relax --- 2469,2482 ---- \gdef\sepspaces{\def {\ }}} ! % This space is always present above and below environments. ! \newskip\envskipamount \envskipamount = 0pt ! % Make spacing and below environment symmetrical. ! \def\aboveenvbreak{{\advance\envskipamount by \parskip ! \endgraf \ifdim\lastskip<\envskipamount ! \removelastskip \penalty-50 \vskip\envskipamount \fi}} + \let\afterenvbreak = \aboveenvbreak + % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. \let\nonarrowing=\relax *************** *** 2357,2368 **** \parindent=0pt \obeyspaces \obeylines \tt \rawbackslash ! \def\next##1{}\next} ! ! ! \let\example=\lisp ! \def\Eexample{\Elisp} ! \let\smallexample=\lisp ! \def\Esmallexample{\Elisp} % Macro for 9 pt. examples, necessary to print with 5" lines. --- 2564,2578 ---- \parindent=0pt \obeyspaces \obeylines \tt \rawbackslash ! \gobble ! } ! % Define the \E... control sequence only if we are inside the ! % environment, so the error checking in \end will work. ! % ! % We must call \lisp last in the definition, since it reads the ! % return following the @example (or whatever) command. ! % ! \def\example{\begingroup \def\Eexample{\Elisp\endgroup}\lisp} ! \def\smallexample{\begingroup \def\Esmallexample{\Elisp\endgroup}\lisp} % Macro for 9 pt. examples, necessary to print with 5" lines. *************** *** 2503,2507 **** --- 2713,2728 ---- \catcode`\(=\active \catcode`\)=\active \catcode`\&=\active \catcode`\[=\active \catcode`\]=\active} + + % Make control sequences which act like normal parenthesis chars. + \let\lparen = ( \let\rparen = ) + {\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + + % Be sure that we always have a definition for `(', etc. For example, + % if the fn name has parens in it, \boldbrax will not be in effect yet, + % so TeX would otherwise complain about undefined control sequence. + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} *************** *** 2629,2632 **** --- 2850,2888 ---- \begingroup\obeylines\spacesplit{#3{#4}}} + % This is the same as all the others except for the last line. We need + % to parse the arguments differently for @deftp, since the ``attributes'' + % there are optional. + % + \def\deftpparsebody #1#2#3#4 {\begingroup\inENV % + \medbreak % + % Define the end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}% + \parindent=0in + \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent + \exdentamount=\defbodyindent + \begingroup\obeylines\parsetpheaderline{#3{#4}}} + + {\obeylines % + % Parse the type name and any attributes (field names, etc.). + % #1 is the beginning of the macro call that will produce the output, + % i.e., \deftpheader{CLASS}; this is passed from \deftpparsebody. + % #2 is the type name, e.g., `struct termios'. + % #3 is the (possibly empty) attribute list. + % + \gdef\parsetpheaderline#1#2#3^^M{% + \endgroup % Started in \deftpparsebody. + % + % If the attribute list is in fact empty, there will be no space after + % #2; so we can't put a space in our TeX parameter list. But if it + % isn't empty, then #3 will begin with an unwanted space. + \def\theargs{\ignorespaces #3}% + % + % Call the macro to produce the output. + #1{#2}\theargs % + }% + } + \def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV % \medbreak % *************** *** 2886,2890 **** % @deftp Class window height width ... ! \def\deftp{\defvrparsebody\Edeftp\deftpx\deftpheader} \def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% --- 3142,3146 ---- % @deftp Class window height width ... ! \def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} \def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% *************** *** 3081,3084 **** --- 3337,3342 ---- \catcode `\#=\other \catcode `\&=\other + % `\+ does not work, so use 43. + \catcode 43=\other % the aux file uses ' as the escape. % Turn off \ as an escape so we do not lose on *************** *** 3132,3135 **** --- 3390,3447 ---- }%end \catcode `\@=11 + % Set the baselineskip to #1, and the lineskip and strut size + % correspondingly. There is no deep meaning behind these magic numbers + % used as factors; they just match (closely enough) what Knuth defined. + % + \def\lineskipfactor{.1} + \def\strutheightpercent{.71} + \def\strutdepthpercent{.29} + % + \def\setleading#1{% + \baselineskip = #1\relax + \normalbaselineskip = \baselineskip + \lineskip = \lineskipfactor\baselineskip + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% + } + + % @| inserts a changebar to the left of the current line. It should + % surround any changed text. This approach does *not* work if the + % change spans more than two lines of output. To handle that, we would + % have adopt a much more difficult approach (putting marks into the main + % vertical list for the beginning and end of each change). + % + \def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% + } + + % For a final copy, take out the rectangles + % that mark overfull boxes (in case you have decided + % that the text looks ok even though it passes the margin). + % + \def\finalout{\overfullrule=0pt} + + % End of control word definitions. *************** *** 3151,3155 **** \parindent = \defaultparindent \parskip 18pt plus 1pt ! \baselineskip 15pt \advance\topskip by 1.2cm --- 3463,3467 ---- \parindent = \defaultparindent \parskip 18pt plus 1pt ! \setleading{15pt} \advance\topskip by 1.2cm *************** *** 3173,3182 **** % Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) \def\smallbook{ \global\lispnarrowing = 0.3in ! \global\baselineskip 12pt \advance\topskip by -1cm \global\parskip 3pt plus 1pt \global\hsize = 5in - \global\doublecolumnhsize=2.4in \global\doublecolumnvsize=15.0in \global\vsize=7.5in \global\tolerance=700 --- 3485,3499 ---- % Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25) \def\smallbook{ + + % These values for secheadingskip and subsecheadingskip are + % experiments. RJC 7 Aug 1992 + \global\secheadingskip = 17pt plus 6pt minus 3pt + \global\subsecheadingskip = 14pt plus 6pt minus 3pt + \global\lispnarrowing = 0.3in ! \setleading{12pt} \advance\topskip by -1cm \global\parskip 3pt plus 1pt \global\hsize = 5in \global\vsize=7.5in \global\tolerance=700 *************** *** 3196,3200 **** \global\tolerance=700 \global\hfuzz=1pt ! \global\baselineskip=12pt \global\parskip 15pt plus 1pt --- 3513,3517 ---- \global\tolerance=700 \global\hfuzz=1pt ! \setleading{12pt} \global\parskip 15pt plus 1pt *************** *** 3207,3225 **** \global\outervsize=\vsize \global\advance\outervsize by 0.6in - \global\doublecolumnhsize=\hsize - \global\divide\doublecolumnhsize by 2 - \global\advance\doublecolumnhsize by -0.1in - \global\doublecolumnvsize=\vsize - \global\multiply\doublecolumnvsize by 2 - \global\advance\doublecolumnvsize by 0.1in \global\pagewidth=\hsize \global\pageheight=\vsize } - - %% For a final copy, take out the rectangles - %% that mark overfull boxes (in case you have decided - %% that the text looks ok even though it passes the margin). - \def\finalout{\overfullrule=0pt} % Define macros to output various characters with catcode for normal text. --- 3524,3531 ---- diff -rc2N gcc-2.2.2/tm.texi gcc-2.3.1/tm.texi *** gcc-2.2.2/tm.texi Mon Jun 8 18:29:48 1992 --- gcc-2.3.1/tm.texi Fri Oct 23 19:45:36 1992 *************** *** 499,503 **** @item WORDS_BIG_ENDIAN Define this macro to be 1 if, in a multiword object, the most ! significant word has the lowest number. @findex BITS_PER_UNIT --- 499,505 ---- @item WORDS_BIG_ENDIAN Define this macro to be 1 if, in a multiword object, the most ! significant word has the lowest number. This applies to both memory ! locations and registers; GNU CC fundamentally assumes that the order of ! words in memory is the same as the order in registers. @findex BITS_PER_UNIT *************** *** 523,530 **** Width of a pointer, in bits. @findex PARM_BOUNDARY @item PARM_BOUNDARY Normal alignment required for function parameters on the stack, in ! bits. All stack parameters receive least this much alignment regardless of data type. On most machines, this is the same as the size of an integer. --- 525,568 ---- Width of a pointer, in bits. + @findex PROMOTE_MODE + @item PROMOTE_MODE (@var{m}, @var{unsignedp}, @var{type}) + A macro to update @var{m} and @var{unsignedp} when an object whose type + is @var{type} and which has the specified mode and signedness is to be + stored in a register. This macro is only called when @var{type} is a + scalar type. + + On most RISC machines, which only have operations that operate on a full + register, define this macro to set @var{m} to @code{word_mode} if + @var{m} is an integer mode narrower than @code{BITS_PER_WORD}. In most + cases, only integer modes should be widened because wider-precision + floating-point operations are usually more expensive than their narrower + counterparts. + + For most machines, the macro definition does not change @var{unsignedp}. + However, some machines, have instructions that preferentially handle + either signed or unsigned quanities of certain modes. For example, on + the DEC Alpha, 32-bit loads from memory and 32-bit add instructions + sign-extend the result to 64 bits. On such machines, set + @var{unsignedp} according to which kind of extension is more efficient. + + Do not define this macro if it would never modify @var{m}. + + @findex PROMOTE_FUNCTION_ARGS + @item PROMOTE_FUNCTION_ARGS + Define this macro if the promotion described by @code{PROMOTE_MODE} + should also be done for outgoing function arguments. + + @findex PROMOTE_FUNCTION_RETURN + @item PROMOTE_FUNCTION_RETURN + Define this macro if the promotion described by @code{PROMOTE_MODE} + should also be done for the return value of functions. + + If this macro is defined, @code{FUNCTION_VALUE} must perform the same + promotions done by @code{PROMOTE_MODE}. + @findex PARM_BOUNDARY @item PARM_BOUNDARY Normal alignment required for function parameters on the stack, in ! bits. All stack parameters receive at least this much alignment regardless of data type. On most machines, this is the same as the size of an integer. *************** *** 647,650 **** --- 685,718 ---- @code{PCC_BITFIELD_TYPE_MATTERS} to have a nonzero value. + If your aim is to make GNU CC use the same conventions for laying out + bitfields as are used by another compiler, here is how to investigate + what the other compiler does. Compile and run this program: + + @example + struct foo1 + @{ + char x; + char :0; + char y; + @}; + + struct foo2 + @{ + char x; + int :0; + char y; + @}; + + main () + @{ + printf ("Size of foo1 is %d\n", sizeof (struct foo1)); + printf ("Size of foo2 is %d\n", sizeof (struct foo2)); + exit (0); + @} + @end example + + If this prints 2 and 5, then the compiler's behavior is what you would + get from @code{PCC_BITFIELD_TYPE_MATTERS}. + @findex BITFIELD_NBYTES_LIMITED @item BITFIELD_NBYTES_LIMITED *************** *** 1140,1144 **** @cindex leaf functions @cindex functions, leaf ! On some machines, a leaf function (i.e., one which make no calls) can run more efficiently if it does not make its own register window. Often this means it is required to receive its arguments in the registers where they --- 1208,1212 ---- @cindex leaf functions @cindex functions, leaf ! On some machines, a leaf function (i.e., one which makes no calls) can run more efficiently if it does not make its own register window. Often this means it is required to receive its arguments in the registers where they *************** *** 1390,1394 **** @item REGNO_REG_CLASS (@var{regno}) A C expression whose value is a register class containing hard register ! @var{regno}. In general there is more that one such class; choose a class which is @dfn{minimal}, meaning that no smaller class also contains the register. --- 1458,1462 ---- @item REGNO_REG_CLASS (@var{regno}) A C expression whose value is a register class containing hard register ! @var{regno}. In general there is more than one such class; choose a class which is @dfn{minimal}, meaning that no smaller class also contains the register. *************** *** 1464,1467 **** --- 1532,1541 ---- certain kinds of registers. + @findex PREFERRED_OUTPUT_RELOAD_CLASS + @item PREFERRED_OUTPUT_RELOAD_CLASS (@var{x}, @var{class}) + Like @code{PREFERRED_RELOAD_CLASS}, but for output reloads instead of + input reloads. If you don't define this macro, the default is to use + @var{class}, unchanged. + @findex LIMIT_RELOAD_CLASS @item LIMIT_RELOAD_CLASS (@var{mode}, @var{class}) *************** *** 1545,1548 **** --- 1619,1633 ---- general registers. + @findex SECONDARY_MEMORY_NEEDED + @item SECONDARY_MEMORY_NEEDED (@var{class1}, @var{class2}, @var{m}) + Certain machines have the property that some registers cannot be copied + to some other registers without using memory. Define this macro on + those machines to be a C expression that is non-zero if objects of mode + @var{m} in registers of @var{class1} can only be copied to registers of + class @var{class2} by storing a register of @var{class1} into memory + and loading that memory location into a register of @var{class2}. + + Do not define this macro if its value would always be zero. + @findex SMALL_REGISTER_CLASSES @item SMALL_REGISTER_CLASSES *************** *** 1937,1941 **** The value of this macro is the size, in bytes, of the area reserved for ! ! arguments passed in registers for the function represented by @var{fndecl}. This space can either be allocated by the caller or be a part of the --- 2022,2026 ---- The value of this macro is the size, in bytes, of the area reserved for ! arguments passed in registers for the function represented by @var{fndecl}. This space can either be allocated by the caller or be a part of the *************** *** 2228,2231 **** --- 2313,2320 ---- mode).@refill + If @code{PROMOTE_FUNCTION_RETURN} is defined, you must apply the same + promotion rules specified in @code{PROMOTE_MODE} if @var{valtype} is a + scalar type. + If the precise function being called is known, @var{func} is a tree node (@code{FUNCTION_DECL}) for it; otherwise, @var{func} is a null *************** *** 2361,2365 **** the address of a static variable containing the value. GNU CC does not normally use this convention, even if it is the usual one, but does use ! it if @samp{-fpcc-struct-value} is specified. Do not define this if the usual system convention is for the caller to --- 2450,2454 ---- the address of a static variable containing the value. GNU CC does not normally use this convention, even if it is the usual one, but does use ! it if @samp{-fpcc-struct-return} is specified. Do not define this if the usual system convention is for the caller to *************** *** 2522,2530 **** On machines where functions may or may not have frame-pointers, the ! function exit code must vary accordingly. Sometimes the code for ! these two cases is completely different. To determine whether a frame ! pointer is in wanted, the macro can refer to the variable ! @code{frame_pointer_needed}. The variable's value will be 1 at run ! time in a function that needs a frame pointer. Normally, it is necessary for @code{FUNCTION_PROLOGUE} and --- 2611,2619 ---- On machines where functions may or may not have frame-pointers, the ! function exit code must vary accordingly. Sometimes the code for these ! two cases is completely different. To determine whether a frame pointer ! is wanted, the macro can refer to the variable ! @code{frame_pointer_needed}. The variable's value will be 1 at run time ! in a function that needs a frame pointer. Normally, it is necessary for @code{FUNCTION_PROLOGUE} and *************** *** 2999,3002 **** --- 3088,3114 ---- @code{__umoddi3}, a function defined in @file{libgcc.a}. + @findex TARGET_EDOM + @cindex @code{EDOM}, implicit usage + @item TARGET_EDOM + The value of @code{EDOM} on the target machine, as a C integer constant + expression. If you don't define this macro, GNU CC does not attempt to + deposit the value of @code{EDOM} into @code{errno} directly. Look in + @file{/usr/include/errno.h} to find the value of @code{EDOM} on your + system. + + If you do not define @code{TARGET_EDOM}, then compiled code reports + domain errors by calling the library function and letting it report the + error. If mathematical functions on your system use @code{matherr} when + there is an error, then you should leave @code{TARGET_EDOM} undefined so + that @code{matherr} is used normally. + + @findex GEN_ERRNO_RTX + @cindex @code{errno}, implicit usage + @item GEN_ERRNO_RTX + Define this macro as a C expression to create an rtl expression that + refers to the global ``variable'' @code{errno}. (On certain systems, + @code{errno} may not actually be a variable.) If you don't define this + macro, a reasonable default is used. + @findex TARGET_MEM_FUNCTIONS @cindex @code{bcopy}, implicit usage *************** *** 3194,3198 **** the new name in @code{saveable_obstack}. You will have to modify @code{ASM_OUTPUT_LABELREF} to remove and decode the added text and ! output the name accordingly. You can check the information stored here into the @code{symbol_ref} in --- 3306,3311 ---- the new name in @code{saveable_obstack}. You will have to modify @code{ASM_OUTPUT_LABELREF} to remove and decode the added text and ! output the name accordingly, and define @code{STRIP_NAME_ENCODING} to ! access the original name string. You can check the information stored here into the @code{symbol_ref} in *************** *** 3256,3260 **** @var{label};} executed if memory address @var{x} (an RTX) can have different meanings depending on the machine mode of the memory ! reference it is used for. Autoincrement and autodecrement addresses typically have mode-dependent --- 3369,3374 ---- @var{label};} executed if memory address @var{x} (an RTX) can have different meanings depending on the machine mode of the memory ! reference it is used for or if the address is valid for some modes ! but not others. Autoincrement and autodecrement addresses typically have mode-dependent *************** *** 3272,3285 **** @samp{1} is a suitable definition for this macro on machines where anything @code{CONSTANT_P} is valid.@refill - - @findex LEGITIMATE_PIC_OPERAND_P - @item LEGITIMATE_PIC_OPERAND_P (@var{x}) - A C expression that is nonzero if @var{x} is a legitimate immediate - operand on the target machine when generating position independent code. - You can assume that @var{x} satisfies @code{CONSTANT_P}, so you need not - check this. You can also assume @var{flag_pic} is true, so you need not - check it either. You need not define this macro if all constants - (including @code{SYMBOL_REF}) can be immediate operands when generating - position independent code. @end table --- 3386,3389 ---- *************** *** 3377,3392 **** @findex SELECT_CC_MODE ! @item SELECT_CC_MODE (@var{op}, @var{x}) ! Returns a mode from class @code{MODE_CC} to be used when comparison operation ! code @var{op} is applied to rtx @var{x}. For example, on the Sparc, ! @code{SELECT_CC_MODE} is defined as (see @pxref{Jump Patterns} for a ! description of the reason for this definition) @example ! #define SELECT_CC_MODE(OP,X) \ ! (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \ ! : (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ ! || GET_CODE (X) == NEG) \ ! ? CC_NOOVmode : CCmode) @end example --- 3481,3497 ---- @findex SELECT_CC_MODE ! @item SELECT_CC_MODE (@var{op}, @var{x}, @var{y}) ! Returns a mode from class @code{MODE_CC} to be used when comparison ! operation code @var{op} is applied to rtx @var{x} and @var{y}. For ! example, on the Sparc, @code{SELECT_CC_MODE} is defined as (see ! @pxref{Jump Patterns} for a description of the reason for this ! definition) @example ! #define SELECT_CC_MODE(OP,X,Y) \ ! (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ ! ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ ! : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS || GET_CODE (X) == NEG) \ ! ? CC_NOOVmode : CCmode)) @end example *************** *** 3581,3584 **** --- 3686,3698 ---- itself with an explicit address than to call an address kept in a register. + + @findex ADJUST_COST + @item ADJUST_COST (@var{insn}, @var{link}, @var{dep_insn}, @var{cost}) + A C statement (sans semicolon) to update the integer variable @var{cost} + based on the relationship between @var{insn} that is dependent on + @var{dep_insn} through the dependence @var{link}. The default is to + make no adjustment to @var{cost}. This can be used for example to + specify to the scheduler that an output- or anti-dependence does not + incur the same cost as a data-dependence. @end table *************** *** 3600,3623 **** @findex TEXT_SECTION_ASM_OP @item TEXT_SECTION_ASM_OP ! A C string constant for the assembler operation that should precede ! instructions and read-only data. Normally @code{".text"} is right. @findex DATA_SECTION_ASM_OP @item DATA_SECTION_ASM_OP ! A C string constant for the assembler operation to identify the ! following data as writable initialized data. Normally @code{".data"} ! is right. @findex SHARED_SECTION_ASM_OP @item SHARED_SECTION_ASM_OP ! If defined, a C string constant for the assembler operation to identify the ! following data as shared data. If not defined, @code{DATA_SECTION_ASM_OP} ! will be used. @findex INIT_SECTION_ASM_OP @item INIT_SECTION_ASM_OP ! If defined, a C string constant for the assembler operation to identify the ! following data as initialization code. If not defined, GNU CC will ! assume such a section does not exist. @findex EXTRA_SECTIONS --- 3714,3739 ---- @findex TEXT_SECTION_ASM_OP @item TEXT_SECTION_ASM_OP ! A C expression whose value is a string containing the assembler ! operation that should precede instructions and read-only data. Normally ! @code{".text"} is right. @findex DATA_SECTION_ASM_OP @item DATA_SECTION_ASM_OP ! A C expression whose value is a string containing the assembler ! operation to identify the following data as writable initialized data. ! Normally @code{".data"} is right. @findex SHARED_SECTION_ASM_OP @item SHARED_SECTION_ASM_OP ! if defined, a C expression whose value is a string containing the ! assembler operation to identify the following data as shared data. If ! not defined, @code{DATA_SECTION_ASM_OP} will be used. @findex INIT_SECTION_ASM_OP @item INIT_SECTION_ASM_OP ! if defined, a C expression whose value is a string containing the ! assembler operation to identify the following data as initialization ! code. If not defined, GNU CC will assume such a section does not ! exist. @findex EXTRA_SECTIONS *************** *** 3697,3700 **** --- 3813,3822 ---- modified name string in the @code{symbol_ref} (if one bit is not enough information). + + @findex STRIP_NAME_ENCODING + @item STRIP_NAME_ENCODING (@var{var}, @var{sym_name}) + Decode @var{sym_name} and store the real name part in @var{var}, sans + the characters that encode section info. Define this macro if + @code{ENCODE_SECTION_INFO} alters the symbol's name string. @end table *************** *** 3740,3743 **** --- 3862,3874 ---- assembly language.) + @findex LEGITIMATE_PIC_OPERAND_P + @item LEGITIMATE_PIC_OPERAND_P (@var{x}) + A C expression that is nonzero if @var{x} is a legitimate immediate + operand on the target machine when generating position independent code. + You can assume that @var{x} satisfies @code{CONSTANT_P}, so you need not + check this. You can also assume @var{flag_pic} is true, so you need not + check it either. You need not define this macro if all constants + (including @code{SYMBOL_REF}) can be immediate operands when generating + position independent code. @end table *************** *** 3754,3758 **** * Uninitialized Data:: Output of uninitialized variables. * Label Output:: Output and generation of labels. ! * Constructor Output:: Output of initialization and termination routines. * Instruction Output:: Output of actual instructions. * Dispatch Tables:: Output of jump tables. --- 3885,3893 ---- * Uninitialized Data:: Output of uninitialized variables. * Label Output:: Output and generation of labels. ! * Initialization:: General principles of initialization ! and termination routines. ! * Macros for Initialization:: ! Specific macros that control the handling of ! initialization and termination routines. * Instruction Output:: Output of actual instructions. * Dispatch Tables:: Output of jump tables. *************** *** 4211,4216 **** @end table ! @node Constructor Output ! @subsection Output of Initialization Routines @cindex initialization routines @cindex termination routines --- 4346,4351 ---- @end table ! @node Initialization ! @subsection How Initialization Functions Are Handled @cindex initialization routines @cindex termination routines *************** *** 4231,4239 **** must output something in the assembler code to cause those functions to be called at the appropriate time. When you port the compiler to a new ! system, you need to specify what assembler code is needed to do this. ! Here are the two macros you should define if necessary: @table @code @item ASM_OUTPUT_CONSTRUCTOR (@var{stream}, @var{name}) @findex ASM_OUTPUT_CONSTRUCTOR --- 4366,4504 ---- must output something in the assembler code to cause those functions to be called at the appropriate time. When you port the compiler to a new ! system, you need to specify how to do this. ! ! There are two major ways that GCC currently supports the execution of ! initialization and termination functions. Each way has two variants. ! Much of the structure is common to all four variations. ! ! @findex __CTOR_LIST__ ! @findex __DTOR_LIST__ ! The linker must build two lists of these functions---a list of ! initialization functions, called @code{__CTOR_LIST__}, and a list of ! termination functions, called @code{__DTOR_LIST__}. ! ! Each list always begins with an ignored function pointer (which may hold ! 0, @minus{}1, or a count of the function pointers after it, depending on ! the environment). This is followed by a series of zero or more function ! pointers to constructors (or destructors), followed by a function ! pointer containing zero. ! ! Depending on the operating system and its executable file format, either ! @file{crtstuff.c} or @file{libgcc2.c} traverses these lists at startup ! time and exit time. Constructors are called in forward order of the ! list; destructors in reverse order. ! ! The best way to handle static constructors works only for object file ! formats which provide arbitrarily-named sections. A section is set ! aside for a list of constructors, and another for a list of destructors. ! Traditionally these are called @samp{.ctors} and @samp{.dtors}. Each ! object file that defines an initialization function also puts a word in ! the constructor section to point to that function. The linker ! accumulates all these words into one contiguous @samp{.ctors} section. ! Termination functions are handled similarly. ! ! To use this method, you need appropriate definitions of the macros ! @code{ASM_OUTPUT_CONSTRUCTOR} and @code{ASM_OUTPUT_DESTRUCTOR}. Usually ! you can get them by including @file{svr4.h}. ! ! When arbitrary sections are available, there are two variants, depending ! upon how the code in @file{crtstuff.c} is called. On systems that ! support an @dfn{init} section which is executed at program startup, ! parts of @file{crtstuff.c} are compiled into that section. The ! program is linked by the @code{gcc} driver like this: ! @example ! ld -o @var{output_file} crtbegin.o @dots{} crtend.o -lgcc ! @end example ! ! The head of a function (@code{__do_global_ctors}) appears in the init ! section of @file{crtbegin.o}; the remainder of the function appears in ! the init section of @file{crtend.o}. The linker will pull these two ! parts of the section together, making a whole function. If any of the ! user's object files linked into the middle of it contribute code, then that ! code will be executed as part of the body of @code{__do_global_ctors}. ! ! To use this variant, you must define the @code{INIT_SECTION_ASM_OP} ! macro properly. ! ! If no init section is available, do not define ! @code{INIT_SECTION_ASM_OP}. Then @code{__do_global_ctors} is built into ! the text section like all other functions, and resides in ! @file{libgcc.a}. When GCC compiles any function called @code{main}, it ! inserts a procedure call to @code{__main} as the first executable code ! after the function prologue. The @code{__main} function, also defined ! in @file{libgcc2.c}, simply calls @file{__do_global_ctors}. ! ! In file formats that don't support arbitrary sections, there are again ! two variants. In the simplest variant, the GNU linker (GNU @code{ld}) ! and an `a.out' format must be used. In this case, ! @code{ASM_OUTPUT_CONSTRUCTOR} is defined to produce a @code{.stabs} ! entry of type @samp{N_SETT}, referencing the name @code{__CTOR_LIST__}, ! and with the address of the void function containing the initialization ! code as its value. The GNU linker recognizes this as a request to add ! the value to a ``set''; the values are accumulated, and are eventually ! placed in the executable as a vector in the format described above, with ! a leading (ignored) count and a trailing zero element. ! @code{ASM_OUTPUT_DESTRUCTOR} is handled similarly. Since no init ! section is available, the absence of @code{INIT_SECTION_ASM_OP} causes ! the compilation of @code{main} to call @code{__main} as above, starting ! the initialization process. ! ! The last variant uses neither arbitrary sections nor the GNU linker. ! This is preferable when you want to do dynamic linking and when using ! file formats which the GNU linker does not support, such as `ECOFF'. In ! this case, @code{ASM_OUTPUT_CONSTRUCTOR} does not produce an ! @code{N_SETT} symbol; initialization and termination functions are ! recognized simply by their names. This requires an extra program in the ! linkage step, called @code{collect2}. This program pretends to be the ! linker, for use with GNU CC; it does its job by running the ordinary ! linker, but also arranges to include the vectors of initialization and ! termination functions. These functions are called via @code{__main} as ! described above. ! ! Choosing among these configuration options has been simplified by a set ! of operating-system-dependent files in the @file{config} subdirectory. ! These files define all of the relevant parameters. Usually it is ! sufficient to include one into your specific machine-dependent ! configuration file. These files are: ! ! @table @file ! @item aoutos.h ! For operating systems using the `a.out' format. ! ! @item next.h ! For operating systems using the `MachO' format. ! ! @item svr3.h ! For System V Release 3 and similar systems using `COFF' format. ! ! @item svr4.h ! For System V Release 4 and similar systems using `ELF' format. ! ! @item vms.h ! For the VMS operating system. ! @end table ! ! @ifinfo ! The following section describes the specific macros that control and ! customize the handling of initialization and termination functions. ! @end ifinfo ! ! @node Macros for Initialization ! @subsection Macros Controlling Initialization Routines + Here are the macros that control how the compiler handles initialization + and termination functions: + @table @code + @findex INIT_SECTION_ASM_OP + @item INIT_SECTION_ASM_OP + If defined, a C string constant for the assembler operation to identify + the following data as initialization code. If not defined, GNU CC will + assume such a section does not exist. When you are using special + sections for initialization and termination functions, this macro also + controls how @file{crtstuff.c} and @file{libgcc2.c} arrange to run the + initialization functions. + @item ASM_OUTPUT_CONSTRUCTOR (@var{stream}, @var{name}) @findex ASM_OUTPUT_CONSTRUCTOR *************** *** 4250,4256 **** If you don't define this macro, nothing special is output to arrange to call the function. This is correct when the function will be called in ! some other manner---for example, by means of the @code{collect} program, which looks through the symbol table to find these functions by their ! names. If you want to use @code{collect}, then you need to arrange for it to be built and installed and used on your system. --- 4515,4521 ---- If you don't define this macro, nothing special is output to arrange to call the function. This is correct when the function will be called in ! some other manner---for example, by means of the @code{collect2} program, which looks through the symbol table to find these functions by their ! names. If you want to use @code{collect2}, then you need to arrange for it to be built and installed and used on your system. *************** *** 4811,4815 **** for (decl = syms; decl; decl = TREE_CHAIN (decl)) if (TREE_CODE (decl) == TYPE_DECL ! && TREE_CODE (TREE_TYPE (decl)) == INTEGER_CST && TYPE_PRECISION (TREE_TYPE (decl)) == 16 && TYPE_UNSIGNED (TREE_TYPE (decl))) --- 5076,5080 ---- for (decl = syms; decl; decl = TREE_CHAIN (decl)) if (TREE_CODE (decl) == TYPE_DECL ! && TREE_CODE (TREE_TYPE (decl)) == INTEGER_CST && TYPE_PRECISION (TREE_TYPE (decl)) == 16 && TYPE_UNSIGNED (TREE_TYPE (decl))) *************** *** 5066,5077 **** @findex REAL_VALUE_TRUNCATE ! @item REAL_VALUE_TRUNCATE (@var{x}) ! A macro for a C expression which converts the double-precision floating ! point value @var{x} to single-precision. Both @var{x} and the value of the expression have type @code{REAL_VALUE_TYPE} and are in the target machine's floating point representation. However, the value should have an appropriate bit ! pattern to be output properly as a single-precision floating constant. There is no way for this macro to report overflow. --- 5331,5343 ---- @findex REAL_VALUE_TRUNCATE ! @item REAL_VALUE_TRUNCATE (@var{mode}, @var{x}) ! A macro for a C expression which converts the floating point value ! @var{x} to mode @var{mode}. Both @var{x} and the value of the expression have type @code{REAL_VALUE_TYPE} and are in the target machine's floating point representation. However, the value should have an appropriate bit ! pattern to be output properly as a floating constant whose precision ! accords with mode @var{mode}. There is no way for this macro to report overflow. *************** *** 5134,5137 **** --- 5400,5410 ---- actually ignored by the @code{case} insn proper. + @findex CASE_VALUES_THRESHOLD + @item CASE_VALUES_THRESHOLD + Define this to be the smallest number of different values for which it + is best to use a jump-table instead of a tree of conditional branches. + The default is four for machines with a @code{casesi} instruction and + five otherwise. This is best for most machines. + @findex BYTE_LOADS_ZERO_EXTEND @item BYTE_LOADS_ZERO_EXTEND *************** *** 5140,5143 **** --- 5413,5422 ---- register. + @findex BYTE_LOADS_SIGN_EXTEND + @item BYTE_LOADS_SIGN_EXTEND + Define this macro if an instruction to load a value narrower than a + word from memory into a register also sign-extends the value to the whole + register. + @findex IMPLICIT_FIX_EXPR @item IMPLICIT_FIX_EXPR *************** *** 5173,5179 **** shift operation to a width equal to the number of bits needed to represent the size of the object being shifted. On machines that have ! instructions that act on bitfields at variable positions, including `bit ! test' instructions, defining @code{SHIFT_COUNT_TRUNCATED} also causes ! truncation not to be applied to these instructions. If both types of instructions truncate the count (for shifts) and --- 5452,5459 ---- shift operation to a width equal to the number of bits needed to represent the size of the object being shifted. On machines that have ! instructions that act on bitfields at variable positions, which may ! include `bit test' instructions, defining @code{SHIFT_COUNT_TRUNCATED} ! also enables deletion of truncations of the values that serve as ! arguments to bitfield instructions. If both types of instructions truncate the count (for shifts) and *************** *** 5204,5210 **** @item STORE_FLAG_VALUE A C expression describing the value returned by a comparison operator ! and stored by a store-flag instruction (@samp{s@var{cond}}) when the ! condition is true. This description must apply to @emph{all} the ! @samp{s@var{cond}} patterns and all the comparison operators. A value of 1 or -1 means that the instruction implementing the --- 5484,5491 ---- @item STORE_FLAG_VALUE A C expression describing the value returned by a comparison operator ! with an integral mode and stored by a store-flag instruction ! (@samp{s@var{cond}}) when the condition is true. This description must ! apply to @emph{all} the @samp{s@var{cond}} patterns and all the ! comparison operators whose results have a @code{MODE_INT} mode. A value of 1 or -1 means that the instruction implementing the *************** *** 5278,5281 **** --- 5559,5570 ---- You need not define @code{STORE_FLAG_VALUE} if the machine has no store-flag instructions. + + @findex FLOAT_STORE_FLAG_VALUE + @item FLOAT_STORE_FLAG_VALUE + A C expression that gives a non-zero floating point value that is + returned when comparison operators with floating-point results are true. + Define this macro on machine that have comparison operations that return + floating-point values. If there are no such operations, do not define + this macro. @findex Pmode diff -rc2N gcc-2.2.2/toplev.c gcc-2.3.1/toplev.c *** gcc-2.2.2/toplev.c Thu May 28 01:36:37 1992 --- gcc-2.3.1/toplev.c Fri Oct 23 05:50:36 1992 *************** *** 78,82 **** --- 78,84 ---- extern int rtx_equal_function_value_matters; + #if ! (defined (VMS) || defined (OS2)) extern char **environ; + #endif extern char *version_string, *language_string; *************** *** 188,196 **** enum debug_info_level debug_info_level = DINFO_LEVEL_NONE; ! #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) ! /* Nonzero means can use our own extensions to DBX format. ! Relevant only when write_symbols == DBX_DEBUG or XCOFF_DEBUG. */ ! int use_gdb_dbx_extensions = 0; ! #endif /* Nonzero means do optimizations. -O. --- 190,198 ---- enum debug_info_level debug_info_level = DINFO_LEVEL_NONE; ! /* Nonzero means use GNU-only extensions in the generated symbolic ! debugging information. */ ! /* Currently, this only has an effect when write_symbols is set to ! DBX_DEBUG, XCOFF_DEBUG, or DWARF_DEBUG. */ ! int use_gnu_debug_info_extensions = 0; /* Nonzero means do optimizations. -O. *************** *** 494,497 **** --- 496,624 ---- {"gnu-linker", &flag_gnu_linker, 1} }; + + /* Table of language-specific options. */ + + char *lang_options[] = + { + "-ftraditional", + "-traditional", + "-fnotraditional", + "-fno-traditional", + "-fsigned-char", + "-funsigned-char", + "-fno-signed-char", + "-fno-unsigned-char", + "-fsigned-bitfields", + "-funsigned-bitfields", + "-fno-signed-bitfields", + "-fno-unsigned-bitfields", + "-fshort-enums", + "-fno-short-enums", + "-fcond-mismatch", + "-fno-cond-mismatch", + "-fshort-double", + "-fno-short-double", + "-fasm", + "-fno-asm", + "-fbuiltin", + "-fno-builtin", + "-fno-ident", + "-fident", + "-ansi", + "-Wimplicit", + "-Wno-implicit", + "-Wwrite-strings", + "-Wno-write-strings", + "-Wcast-qual", + "-Wno-cast-qual", + "-Wpointer-arith", + "-Wno-pointer-arith", + "-Wstrict-prototypes", + "-Wno-strict-prototypes", + "-Wmissing-prototypes", + "-Wno-missing-prototypes", + "-Wredundant-decls", + "-Wno-redundant-decls", + "-Wnested-externs", + "-Wno-nested-externs", + "-Wtraditional", + "-Wno-traditional", + "-Wformat", + "-Wno-format", + "-Wchar-subscripts", + "-Wno-char-subscripts", + "-Wconversion", + "-Wno-conversion", + "-Wparentheses", + "-Wno-parentheses", + "-Wcomment", + "-Wno-comment", + "-Wcomments", + "-Wno-comments", + "-Wtrigraphs", + "-Wno-trigraphs", + "-Wimport", + "-Wno-import", + "-Wall", + + /* These are for C++. */ + "+e0", + "+e1", + "+e2", + "-fsave-memoized", + "-fno-save-memoized", + "-fSOS", + "-fno-SOS", + "-fcadillac", + "-fno-cadillac", + "-fgc", + "-fno-gc", + "-flabels-ok", + "-fno-labels-ok", + "-fstats", + "-fno-stats", + "-fthis-is-variable", + "-fno-this-is-variable", + "-fstrict-prototype", + "-fno-strict-prototype", + "-fall-virtual", + "-fno-all-virtual", + "-fmemoize-lookups", + "-fno-memoize-lookups", + "-felide-constructors", + "-fno-elide-constructors", + "-finline-debug", + "-fno-inline-debug", + "-fhandle-exceptions", + "-fno-handle-exceptions", + "-fansi-exceptions", + "-fno-ansi-exceptions", + "-fspring-exceptions", + "-fno-spring-exceptions", + "-fdefault-inline", + "-fno-default-inline", + "-fenum-int-equiv", + "-fno-enum-int-equiv", + "-fdossier", + "-fno-dossier", + "-fxref", + "-fno-xref", + "-fnonnull-objects", + "-fno-nonnull-objects", + + "-Wreturn-type", + "-Wno-return-type", + "-Woverloaded-virtual", + "-Wno-overloaded-virtual", + "-Wenum-clash", + "-Wno-enum-clash", + + /* these are for obj c */ + "-lang-objc", + "-gen-decls", + "-Wselector", + "-Wno-selector", + 0 + }; /* Options controlling warnings */ *************** *** 854,864 **** /* Report an error at the current line number. ! S and V are a string and an arg for `printf'. */ void error (s, v, v2) char *s; ! int v; /* @@also used as pointer */ ! int v2; /* @@also used as pointer */ { error_with_file_and_line (input_filename, lineno, s, v, v2); --- 981,994 ---- /* Report an error at the current line number. ! S is a string and V and V2 are args for `printf'. We use HOST_WIDE_INT ! as the type for these args assuming it is wide enough to hold a ! pointer. This isn't terribly portable, but is the best we can do ! without vprintf universally available. */ void error (s, v, v2) char *s; ! HOST_WIDE_INT v; /* Also used as pointer */ ! HOST_WIDE_INT v2; /* Also used as pointer */ { error_with_file_and_line (input_filename, lineno, s, v, v2); *************** *** 873,878 **** int line; char *s; ! int v; ! int v2; { count_error (0); --- 1003,1008 ---- int line; char *s; ! HOST_WIDE_INT v; ! HOST_WIDE_INT v2; { count_error (0); *************** *** 889,893 **** /* Report an error at the declaration DECL. ! S and V are a string and an arg which uses %s to substitute the declaration name. */ void --- 1019,1024 ---- /* Report an error at the declaration DECL. ! S and V are a string and an arg which uses %s to substitute ! the declaration name. */ void *************** *** 895,899 **** tree decl; char *s; ! int v; { char *junk; --- 1026,1030 ---- tree decl; char *s; ! HOST_WIDE_INT v; { char *junk; *************** *** 921,926 **** rtx insn; char *s; ! int v; /* @@also used as pointer */ ! int v2; /* @@also used as pointer */ { char *filename; --- 1052,1057 ---- rtx insn; char *s; ! HOST_WIDE_INT v; /* Also used as pointer */ ! HOST_WIDE_INT v2; /* Also used as pointer */ { char *filename; *************** *** 955,961 **** int line; char *s; ! int v; ! int v2; ! int v3; { if (count_error (1) == 0) --- 1086,1090 ---- int line; char *s; ! HOST_WIDE_INT v, v2, v3; { if (count_error (1) == 0) *************** *** 980,986 **** warning (s, v, v2, v3) char *s; ! int v; /* @@also used as pointer */ ! int v2; ! int v3; { warning_with_file_and_line (input_filename, lineno, s, v, v2, v3); --- 1109,1113 ---- warning (s, v, v2, v3) char *s; ! HOST_WIDE_INT v, v2, v3; /* Also used as pointer */ { warning_with_file_and_line (input_filename, lineno, s, v, v2, v3); *************** *** 995,999 **** tree decl; char *s; ! int v; { char *junk; --- 1122,1126 ---- tree decl; char *s; ! HOST_WIDE_INT v; { char *junk; *************** *** 1024,1029 **** rtx insn; char *s; ! int v; /* @@also used as pointer */ ! int v2; /* @@also used as pointer */ { char *filename; --- 1151,1156 ---- rtx insn; char *s; ! HOST_WIDE_INT v; /* Also used as pointer */ ! HOST_WIDE_INT v2; /* Also used as pointer */ { char *filename; *************** *** 1056,1061 **** pedwarn (s, v, v2) char *s; ! int v; /* @@also used as pointer */ ! int v2; { if (flag_pedantic_errors) --- 1183,1188 ---- pedwarn (s, v, v2) char *s; ! HOST_WIDE_INT v; /* Also used as pointer */ ! HOST_WIDE_INT v2; { if (flag_pedantic_errors) *************** *** 1069,1073 **** tree decl; char *s; ! int v; { if (flag_pedantic_errors) --- 1196,1200 ---- tree decl; char *s; ! HOST_WIDE_INT v; { if (flag_pedantic_errors) *************** *** 1082,1087 **** int line; char *s; ! int v; ! int v2; { if (flag_pedantic_errors) --- 1209,1214 ---- int line; char *s; ! HOST_WIDE_INT v; ! HOST_WIDE_INT v2; { if (flag_pedantic_errors) *************** *** 1097,1101 **** sorry (s, v, v2) char *s; ! int v, v2; { sorrycount++; --- 1224,1228 ---- sorry (s, v, v2) char *s; ! HOST_WIDE_INT v, v2; { sorrycount++; *************** *** 1116,1120 **** really_sorry (s, v, v2) char *s; ! int v, v2; { if (input_filename) --- 1243,1247 ---- really_sorry (s, v, v2) char *s; ! HOST_WIDE_INT v, v2; { if (input_filename) *************** *** 1162,1170 **** /* Same as `malloc' but report error if no memory available. */ ! int xmalloc (size) unsigned size; { ! register int value = (int) malloc (size); if (value == 0) fatal ("virtual memory exhausted"); --- 1289,1297 ---- /* Same as `malloc' but report error if no memory available. */ ! char * xmalloc (size) unsigned size; { ! register char *value = (char *) malloc (size); if (value == 0) fatal ("virtual memory exhausted"); *************** *** 1174,1183 **** /* Same as `realloc' but report error if no memory available. */ ! int xrealloc (ptr, size) char *ptr; int size; { ! int result = realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); --- 1301,1310 ---- /* Same as `realloc' but report error if no memory available. */ ! char * xrealloc (ptr, size) char *ptr; int size; { ! char *result = (char *) realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); *************** *** 1186,1194 **** /* Return the logarithm of X, base 2, considering X unsigned, ! if X is a power of 2. Otherwise, returns -1. */ int ! exact_log2 (x) ! register unsigned int x; { register int log = 0; --- 1313,1323 ---- /* Return the logarithm of X, base 2, considering X unsigned, ! if X is a power of 2. Otherwise, returns -1. ! ! This should be used via the `exact_log2' macro. */ int ! exact_log2_wide (x) ! register unsigned HOST_WIDE_INT x; { register int log = 0; *************** *** 1202,1210 **** /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X. ! If X is 0, return -1. */ int ! floor_log2 (x) ! register unsigned int x; { register int log = -1; --- 1331,1341 ---- /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X. ! If X is 0, return -1. + This should be used via the floor_log2 macro. */ + int ! floor_log2_wide (x) ! register unsigned HOST_WIDE_INT x; { register int log = -1; *************** *** 1230,1233 **** --- 1361,1394 ---- } + /* Specify, in HANDLER, where to longjmp to when a floating arithmetic + error happens, pushing the previous specification into OLD_HANDLER. + Return an indication of whether there was a previous handler in effect. */ + + int + push_float_handler (handler, old_handler) + jmp_buf handler, old_handler; + { + int was_handled = float_handled; + + float_handled = 1; + if (was_handled) + bcopy (float_handler, old_handler, sizeof (float_handler)); + bcopy (handler, float_handler, sizeof (float_handler)); + return was_handled; + } + + /* Restore the previous specification of whether and where to longjmp to + when a floating arithmetic error happens. */ + + void + pop_float_handler (handled, handler) + int handled; + jmp_buf handler; + { + float_handled = handled; + if (handled) + bcopy (handler, float_handler, sizeof (float_handler)); + } + /* Signals actually come here. */ *************** *** 1277,1280 **** --- 1438,1445 ---- else if (len > 3 && ! strcmp (".cc", name + len - 3)) name[len - 3] = 0; + else if (len > 2 && ! strcmp (".C", name + len - 2)) + name[len - 2] = 0; + else if (len > 4 && ! strcmp (".cxx", name + len - 4)) + name[len - 4] = 0; else if (len > 2 && ! strcmp (".f", name + len - 2)) name[len - 2] = 0; *************** *** 1377,1380 **** --- 1542,1546 ---- init_stmt (); init_expmed (); + init_expr_once (); init_loop (); init_reload (); *************** *** 1682,1686 **** || TREE_ADDRESSABLE (decl) || TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl))) ! rest_of_decl_compilation (decl, 0, 1, 1); else /* Cancel the RTL for this decl so that, if debugging info --- 1848,1852 ---- || TREE_ADDRESSABLE (decl) || TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl))) ! rest_of_decl_compilation (decl, NULL_PTR, 1, 1); else /* Cancel the RTL for this decl so that, if debugging info *************** *** 1695,1699 **** && (TREE_ADDRESSABLE (decl) || TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl))) ! && ! TREE_EXTERNAL (decl)) output_inline_function (decl); --- 1861,1865 ---- && (TREE_ADDRESSABLE (decl) || TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl))) ! && ! DECL_EXTERNAL (decl)) output_inline_function (decl); *************** *** 1708,1712 **** && TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) == 0 ! && TREE_EXTERNAL (decl) && ! TREE_PUBLIC (decl)) warning_with_decl (decl, "`%s' declared `static' but never defined"); --- 1874,1878 ---- && TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) == 0 ! && DECL_EXTERNAL (decl) && ! TREE_PUBLIC (decl)) warning_with_decl (decl, "`%s' declared `static' but never defined"); *************** *** 1717,1724 **** && (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) ! && ! TREE_EXTERNAL (decl) && ! TREE_PUBLIC (decl) && ! TREE_USED (decl) ! && ! TREE_INLINE (decl) /* The TREE_USED bit for file-scope decls is kept in the identifier, to handle multiple --- 1883,1891 ---- && (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) ! && ! DECL_IN_SYSTEM_HEADER (decl) ! && ! DECL_EXTERNAL (decl) && ! TREE_PUBLIC (decl) && ! TREE_USED (decl) ! && ! DECL_INLINE (decl) /* The TREE_USED bit for file-scope decls is kept in the identifier, to handle multiple *************** *** 1903,1907 **** /* Forward declarations for nested functions are not "external", but we need to treat them as if they were. */ ! if (TREE_STATIC (decl) || TREE_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) TIMEVAR (varconst_time, --- 2070,2074 ---- /* Forward declarations for nested functions are not "external", but we need to treat them as if they were. */ ! if (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL) TIMEVAR (varconst_time, *************** *** 1922,1926 **** assemble_variable (decl, top_level, at_end); }); ! else if (TREE_REGDECL (decl) && asmspec != 0) { if (decode_reg_name (asmspec) >= 0) --- 2089,2093 ---- assemble_variable (decl, top_level, at_end); }); ! else if (DECL_REGISTER (decl) && asmspec != 0) { if (decode_reg_name (asmspec) >= 0) *************** *** 1978,1981 **** --- 2145,2151 ---- (for use when compiling inline calls to this function). */ tree saved_block_tree = 0; + /* Likewise, for DECL_ARGUMENTS. */ + tree saved_arguments = 0; + int failure = 0; /* If we are reconsidering an inline function *************** *** 1984,1988 **** if (DECL_SAVED_INSNS (decl) == 0) { ! int specd = TREE_INLINE (decl); char *lose; --- 2154,2158 ---- if (DECL_SAVED_INSNS (decl) == 0) { ! int specd = DECL_INLINE (decl); char *lose; *************** *** 1996,2003 **** if (warn_inline && specd) warning_with_decl (decl, lose); ! TREE_INLINE (decl) = 0; } else ! TREE_INLINE (decl) = 1; }); --- 2166,2173 ---- if (warn_inline && specd) warning_with_decl (decl, lose); ! DECL_INLINE (decl) = 0; } else ! DECL_INLINE (decl) = 1; }); *************** *** 2022,2048 **** for those functions that need to be output. */ ! if (TREE_INLINE (decl) && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl) && ! flag_keep_inline_functions) ! || TREE_EXTERNAL (decl))) { TIMEVAR (integration_time, save_for_inline_nocopy (decl)); goto exit_rest_of_compilation; } ! /* If we have to compile the function now, save its rtl so that its compilation will not affect what others get. */ ! if (TREE_INLINE (decl)) { saved_block_tree = DECL_INITIAL (decl); TIMEVAR (integration_time, save_for_inline_copying (decl)); } } - /* Suppress warnings for unused static functions - defined (not just declared) in system headers. */ - if (in_system_header && TREE_STATIC (decl) && !TREE_INLINE (decl)) - TREE_USED (decl) = 1; - TREE_ASM_WRITTEN (decl) = 1; --- 2192,2237 ---- for those functions that need to be output. */ ! if (DECL_INLINE (decl) && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl) && ! flag_keep_inline_functions) ! || DECL_EXTERNAL (decl))) { + #ifdef DWARF_DEBUGGING_INFO + /* Generate the DWARF info for the "abstract" instance + of a function which we may later generate inlined and/or + out-of-line instances of. */ + if (write_symbols == DWARF_DEBUG) + { + set_decl_abstract_flags (decl, 1); + TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0)); + set_decl_abstract_flags (decl, 0); + } + #endif TIMEVAR (integration_time, save_for_inline_nocopy (decl)); goto exit_rest_of_compilation; } ! /* If we have to compile the function now, save its rtl and subdecls so that its compilation will not affect what others get. */ ! if (DECL_INLINE (decl)) { + #ifdef DWARF_DEBUGGING_INFO + /* Generate the DWARF info for the "abstract" instance of + a function which we will generate an out-of-line instance + of almost immediately (and which we may also later generate + various inlined instances of). */ + if (write_symbols == DWARF_DEBUG) + { + set_decl_abstract_flags (decl, 1); + TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0)); + set_decl_abstract_flags (decl, 0); + } + #endif saved_block_tree = DECL_INITIAL (decl); + saved_arguments = DECL_ARGUMENTS (decl); TIMEVAR (integration_time, save_for_inline_copying (decl)); } } TREE_ASM_WRITTEN (decl) = 1; *************** *** 2166,2170 **** TIMEVAR (loop_time, { ! loop_optimize (insns, loop_dump ? loop_dump_file : 0); }); } --- 2355,2359 ---- TIMEVAR (loop_time, { ! loop_optimize (insns, loop_dump_file); }); } *************** *** 2344,2351 **** { if (!obey_regdecls) ! global_alloc (global_reg_dump ? global_reg_dump_file : 0); else ! reload (insns, 0, ! global_reg_dump ? global_reg_dump_file : 0); }); --- 2533,2539 ---- { if (!obey_regdecls) ! failure = global_alloc (global_reg_dump_file); else ! failure = reload (insns, 0, global_reg_dump_file); }); *************** *** 2358,2363 **** --- 2546,2561 ---- }); + if (failure) + goto exit_rest_of_compilation; + reload_completed = 1; + /* On some machines, the prologue and epilogue code, or parts thereof, + can be represented as RTL. Doing so lets us schedule insns between + it and the rest of the code and also allows delayed branch + scheduling to operate in the epilogue. */ + + thread_prologue_and_epilogue_insns (insns); + if (optimize > 0 && flag_schedule_insns_after_reload) { *************** *** 2387,2391 **** leaf_function = 0; if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ()) ! leaf_function = 1; #endif --- 2585,2589 ---- leaf_function = 0; if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ()) ! leaf_function = 1; #endif *************** *** 2506,2513 **** #ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG) ! sdbout_types (0); #endif ! /* Put back the tree of subblocks from before we copied it. Code generation and the output of debugging info may have modified the copy, but the original is unchanged. */ --- 2704,2712 ---- #ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG) ! sdbout_types (NULL_TREE); #endif ! /* Put back the tree of subblocks and list of arguments ! from before we copied them. Code generation and the output of debugging info may have modified the copy, but the original is unchanged. */ *************** *** 2515,2518 **** --- 2714,2719 ---- if (saved_block_tree != 0) DECL_INITIAL (decl) = saved_block_tree; + if (saved_arguments != 0) + DECL_ARGUMENTS (decl) = saved_arguments; reload_completed = 0; *************** *** 2647,2651 **** for (i = 1; i < argc; i++) { ! if (argv[i][0] == '-' && argv[i][1] != 0) { register char *str = argv[i] + 1; --- 2848,2863 ---- for (i = 1; i < argc; i++) { ! int j; ! /* If this is a language-specific option, ! decode it in a language-specific way. */ ! for (j = 0; lang_options[j] != 0; j++) ! if (!strncmp (argv[i], lang_options[j], ! strlen (lang_options[j]))) ! break; ! if (lang_options[j] != 0) ! /* If the option is valid for *some* language, ! treat it as valid even if this language doesn't understand it. */ ! lang_decode_option (argv[i]); ! else if (argv[i][0] == '-' && argv[i][1] != 0) { register char *str = argv[i] + 1; *************** *** 2739,2743 **** else if (str[0] == 'f') { - int j; register char *p = &str[1]; int found = 0; --- 2951,2954 ---- *************** *** 2774,2778 **** else if (!strncmp (p, "call-saved-", 11)) fix_register (&p[11], 0, 0); ! else if (! lang_decode_option (argv[i])) error ("Invalid option `%s'", argv[i]); } --- 2985,2989 ---- else if (!strncmp (p, "call-saved-", 11)) fix_register (&p[11], 0, 0); ! else error ("Invalid option `%s'", argv[i]); } *************** *** 2791,2796 **** else if (!strcmp (str, "pedantic-errors")) flag_pedantic_errors = pedantic = 1; - else if (lang_decode_option (argv[i])) - ; else if (!strcmp (str, "quiet")) quiet_flag = 1; --- 3002,3005 ---- *************** *** 2806,2810 **** else if (str[0] == 'W') { - int j; register char *p = &str[1]; int found = 0; --- 3015,3018 ---- *************** *** 2844,2851 **** endp++; else ! error ("Invalid option `%s'", argv[i]); } warn_id_clash = 1; id_clash_len = atoi (str + 10); } else --- 3052,3063 ---- endp++; else ! { ! error ("Invalid option `%s'", argv[i]); ! goto id_clash_lose; ! } } warn_id_clash = 1; id_clash_len = atoi (str + 10); + id_clash_lose: ; } else *************** *** 2890,2895 **** you must define PREFERRED_DEBUGGING_TYPE to choose a format in a system-dependent way. */ ! #if 1 < (defined (DBX_DEBUGGING_INFO) + defined (SDB_DEBUGGING_INFO) \ ! + defined (DWARF_DEBUGGING_INFO) + defined (XCOFF_DEBUGGING_INFO)) #ifdef PREFERRED_DEBUGGING_TYPE if (!strncmp (str, "ggdb", len)) --- 3102,3107 ---- you must define PREFERRED_DEBUGGING_TYPE to choose a format in a system-dependent way. */ ! /* This is one long line cause VAXC can't handle a \-newline. */ ! #if 1 < (defined (DBX_DEBUGGING_INFO) + defined (SDB_DEBUGGING_INFO) + defined (DWARF_DEBUGGING_INFO) + defined (XCOFF_DEBUGGING_INFO)) #ifdef PREFERRED_DEBUGGING_TYPE if (!strncmp (str, "ggdb", len)) *************** *** 2912,2937 **** if (write_symbols == DBX_DEBUG && !strncmp (str, "ggdb", len) && len >= 2) ! use_gdb_dbx_extensions = 1; else if (write_symbols == DBX_DEBUG && !strcmp (str, "gstabs+")) ! use_gdb_dbx_extensions = 1; else if (write_symbols == DBX_DEBUG && !strncmp (str, "gstabs", len) && len >= 2) ! use_gdb_dbx_extensions = 0; else ! use_gdb_dbx_extensions = DEFAULT_GDB_EXTENSIONS; #endif /* DBX_DEBUGGING_INFO */ #ifdef DWARF_DEBUGGING_INFO if (write_symbols != NO_DEBUG) ; else if (!strncmp (str, "ggdb", len)) write_symbols = DWARF_DEBUG; - /* For orthogonality. */ else if (!strncmp (str, "gdwarf", len)) write_symbols = DWARF_DEBUG; #endif #ifdef SDB_DEBUGGING_INFO if (write_symbols != NO_DEBUG) ; ! else if (!strncmp (str, "ggdb", len)) write_symbols = SDB_DEBUG; else if (!strncmp (str, "gcoff", len)) --- 3124,3166 ---- if (write_symbols == DBX_DEBUG && !strncmp (str, "ggdb", len) && len >= 2) ! use_gnu_debug_info_extensions = 1; else if (write_symbols == DBX_DEBUG && !strcmp (str, "gstabs+")) ! use_gnu_debug_info_extensions = 1; else if (write_symbols == DBX_DEBUG && !strncmp (str, "gstabs", len) && len >= 2) ! use_gnu_debug_info_extensions = 0; else ! use_gnu_debug_info_extensions = DEFAULT_GDB_EXTENSIONS; #endif /* DBX_DEBUGGING_INFO */ #ifdef DWARF_DEBUGGING_INFO if (write_symbols != NO_DEBUG) ; + else if (!strncmp (str, "g", len)) + write_symbols = DWARF_DEBUG; else if (!strncmp (str, "ggdb", len)) write_symbols = DWARF_DEBUG; else if (!strncmp (str, "gdwarf", len)) write_symbols = DWARF_DEBUG; + + /* Always enable extensions for -ggdb or -gdwarf+, + always disable for -gdwarf. + For plain -g, use system-specific default. */ + if (write_symbols == DWARF_DEBUG && !strncmp (str, "ggdb", len) + && len >= 2) + use_gnu_debug_info_extensions = 1; + else if (write_symbols == DWARF_DEBUG && !strcmp (str, "gdwarf+")) + use_gnu_debug_info_extensions = 1; + else if (write_symbols == DWARF_DEBUG + && !strncmp (str, "gdwarf", len) && len >= 2) + use_gnu_debug_info_extensions = 0; + else + use_gnu_debug_info_extensions = DEFAULT_GDB_EXTENSIONS; #endif #ifdef SDB_DEBUGGING_INFO if (write_symbols != NO_DEBUG) ; ! else if (!strncmp (str, "g", len)) ! write_symbols = SDB_DEBUG; ! else if (!strncmp (str, "gdb", len)) write_symbols = SDB_DEBUG; else if (!strncmp (str, "gcoff", len)) *************** *** 2941,2944 **** --- 3170,3175 ---- if (write_symbols != NO_DEBUG) ; + else if (!strncmp (str, "g", len)) + write_symbols = XCOFF_DEBUG; else if (!strncmp (str, "ggdb", len)) write_symbols = XCOFF_DEBUG; *************** *** 2946,2960 **** write_symbols = XCOFF_DEBUG; ! /* Always enable extensions for -ggdb, always disable for -gxcoff. For plain -g, use system-specific default. */ if (write_symbols == XCOFF_DEBUG && !strncmp (str, "ggdb", len) && len >= 2) ! use_gdb_dbx_extensions = 1; else if (write_symbols == XCOFF_DEBUG && !strncmp (str, "gxcoff", len) && len >= 2) ! use_gdb_dbx_extensions = 0; else ! use_gdb_dbx_extensions = DEFAULT_GDB_EXTENSIONS; #endif if (write_symbols == NO_DEBUG) --- 3177,3193 ---- write_symbols = XCOFF_DEBUG; ! /* Always enable extensions for -ggdb or -gxcoff+, always disable for -gxcoff. For plain -g, use system-specific default. */ if (write_symbols == XCOFF_DEBUG && !strncmp (str, "ggdb", len) && len >= 2) ! use_gnu_debug_info_extensions = 1; ! else if (write_symbols == XCOFF_DEBUG && !strcmp (str, "gxcoff+")) ! use_gnu_debug_info_extensions = 1; else if (write_symbols == XCOFF_DEBUG && !strncmp (str, "gxcoff", len) && len >= 2) ! use_gnu_debug_info_extensions = 0; else ! use_gnu_debug_info_extensions = DEFAULT_GDB_EXTENSIONS; #endif if (write_symbols == NO_DEBUG) *************** *** 2983,2992 **** } else if (argv[i][0] == '+') ! { ! if (lang_decode_option (argv[i])) ! ; ! else ! error ("Invalid option `%s'", argv[i]); ! } else filename = argv[i]; --- 3216,3220 ---- } else if (argv[i][0] == '+') ! error ("Invalid option `%s'", argv[i]); else filename = argv[i]; *************** *** 3062,3066 **** fprintf (stderr, "Data size %d.\n", ! (int) lim - (int) &environ); fflush (stderr); --- 3290,3294 ---- fprintf (stderr, "Data size %d.\n", ! lim - (char *) &environ); fflush (stderr); diff -rc2N gcc-2.2.2/tree.c gcc-2.3.1/tree.c *** gcc-2.2.2/tree.c Mon May 11 22:51:10 1992 --- gcc-2.3.1/tree.c Thu Oct 22 08:00:22 1992 *************** *** 34,50 **** #include "config.h" - #include #include "flags.h" - #include "function.h" #include "tree.h" #include "obstack.h" #include "gvarargs.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free - extern int xmalloc (); - extern void free (); - /* Tree nodes of permanent duration are allocated in this obstack. They are the identifier nodes, and everything outside of --- 34,47 ---- #include "config.h" #include "flags.h" #include "tree.h" + #include "function.h" #include "obstack.h" #include "gvarargs.h" + #include #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free /* Tree nodes of permanent duration are allocated in this obstack. They are the identifier nodes, and everything outside of *************** *** 199,212 **** typedef enum { ! d_kind, t_kind, s_kind, r_kind, e_kind, c_kind, ! id_kind, op_id_kind, perm_list_kind, temp_list_kind, ! vec_kind, x_kind, lang_decl, lang_type, all_kinds } tree_node_kind; int tree_node_counts[(int)all_kinds]; int tree_node_sizes[(int)all_kinds]; int id_string_size = 0; ! char *tree_node_kind_names[] = { "decls", "types", "stmts", "refs", "exprs", "constants", ! "identifiers", "op_identifiers", "perm_tree_lists", "temp_tree_lists", ! "vecs", "random kinds", "lang_decl kinds", "lang_type kinds" }; /* Hash table for uniquizing IDENTIFIER_NODEs by name. */ --- 196,238 ---- typedef enum { ! d_kind, ! t_kind, ! b_kind, ! s_kind, ! r_kind, ! e_kind, ! c_kind, ! id_kind, ! op_id_kind, ! perm_list_kind, ! temp_list_kind, ! vec_kind, ! x_kind, ! lang_decl, ! lang_type, ! all_kinds } tree_node_kind; + int tree_node_counts[(int)all_kinds]; int tree_node_sizes[(int)all_kinds]; int id_string_size = 0; ! ! char *tree_node_kind_names[] = { ! "decls", ! "types", ! "blocks", ! "stmts", ! "refs", ! "exprs", ! "constants", ! "identifiers", ! "op_identifiers", ! "perm_tree_lists", ! "temp_tree_lists", ! "vecs", ! "random kinds", ! "lang_decl kinds", ! "lang_type kinds" ! }; /* Hash table for uniquizing IDENTIFIER_NODEs by name. */ *************** *** 218,221 **** --- 244,250 ---- static int do_identifier_warnings; + /* Unique id for next decl created. */ + static int next_decl_uid; + extern char *mode_name[]; *************** *** 538,542 **** char * permalloc (size) ! long size; { return (char *) obstack_alloc (&permanent_obstack, size); --- 567,571 ---- char * permalloc (size) ! int size; { return (char *) obstack_alloc (&permanent_obstack, size); *************** *** 775,778 **** --- 804,817 ---- break; + case 'b': /* a lexical block */ + #ifdef GATHER_STATISTICS + kind = b_kind; + #endif + length = sizeof (struct tree_block); + /* All BLOCK nodes are put where we can preserve them if nec. */ + if (obstack != &permanent_obstack) + obstack = saveable_obstack; + break; + case 's': /* an expression with side effects */ #ifdef GATHER_STATISTICS *************** *** 794,801 **** #endif obstack = expression_obstack; ! /* All BLOCK nodes are put where we can preserve them if nec. ! Also their potential controllers. */ ! if ((code == BLOCK || code == BIND_EXPR) ! && obstack != &permanent_obstack) obstack = saveable_obstack; length = sizeof (struct tree_exp) --- 833,838 ---- #endif obstack = expression_obstack; ! /* All BIND_EXPR nodes are put where we can preserve them if nec. */ ! if (code == BIND_EXPR && obstack != &permanent_obstack) obstack = saveable_obstack; length = sizeof (struct tree_exp) *************** *** 841,850 **** #endif ! TREE_TYPE (t) = 0; ! TREE_CHAIN (t) = 0; ! for (i = (length / sizeof (int)) - 1; ! i >= sizeof (struct tree_common) / sizeof (int) - 1; ! i--) ((int *) t)[i] = 0; TREE_SET_CODE (t, code); --- 878,887 ---- #endif ! /* Clear a word at a time. */ ! for (i = (length / sizeof (int)) - 1; i >= 0; i--) ((int *) t)[i] = 0; + /* Clear any extra bytes. */ + for (i = length / sizeof (int) * sizeof (int); i < length; i++) + ((char *) t)[i] = 0; TREE_SET_CODE (t, code); *************** *** 862,867 **** --- 899,907 ---- if (code != FUNCTION_DECL) DECL_ALIGN (t) = 1; + DECL_IN_SYSTEM_HEADER (t) + = in_system_header && (obstack == &permanent_obstack); DECL_SOURCE_LINE (t) = lineno; DECL_SOURCE_FILE (t) = (input_filename) ? input_filename : ""; + DECL_UID (t) = next_decl_uid++; break; *************** *** 906,911 **** break; case 'r': /* a reference */ ! case 'e': /* a expression */ case 's': /* an expression with side effects */ case '<': /* a comparison expression */ --- 946,955 ---- break; + case 'b': /* a lexical block node */ + length = sizeof (struct tree_block); + break; + case 'r': /* a reference */ ! case 'e': /* an expression */ case 's': /* an expression with side effects */ case '<': /* a comparison expression */ *************** *** 934,941 **** t = (tree) obstack_alloc (current_obstack, length); ! for (i = ((length + sizeof (int) - 1) / sizeof (int)) - 1; ! i >= 0; ! i--) ((int *) t)[i] = ((int *) node)[i]; TREE_CHAIN (t) = 0; --- 978,986 ---- t = (tree) obstack_alloc (current_obstack, length); ! for (i = (length / sizeof (int)) - 1; i >= 0; i--) ((int *) t)[i] = ((int *) node)[i]; + /* Clear any extra bytes. */ + for (i = length / sizeof (int) * sizeof (int); i < length; i++) + ((char *) t)[i] = ((char *) node)[i]; TREE_CHAIN (t) = 0; *************** *** 1059,1067 **** /* Return a newly constructed INTEGER_CST node whose constant value is specified by the two ints LOW and HI. ! The TREE_TYPE is set to `int'. */ tree ! build_int_2 (low, hi) ! int low, hi; { register tree t = make_node (INTEGER_CST); --- 1104,1114 ---- /* Return a newly constructed INTEGER_CST node whose constant value is specified by the two ints LOW and HI. ! The TREE_TYPE is set to `int'. + This function should be used via the `build_int_2' macro. */ + tree ! build_int_2_wide (low, hi) ! HOST_WIDE_INT low, hi; { register tree t = make_node (INTEGER_CST); *************** *** 1106,1123 **** REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i)); #else /* not REAL_ARITHMETIC */ ! if (TREE_INT_CST_HIGH (i) < 0) { d = (double) (~ TREE_INT_CST_HIGH (i)); ! d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) ! * (double) (1 << (HOST_BITS_PER_INT / 2))); ! d += (double) (unsigned) (~ TREE_INT_CST_LOW (i)); d = (- d - 1.0); } else { ! d = (double) TREE_INT_CST_HIGH (i); ! d *= ((double) (1 << (HOST_BITS_PER_INT / 2)) ! * (double) (1 << (HOST_BITS_PER_INT / 2))); ! d += (double) (unsigned) TREE_INT_CST_LOW (i); } #endif /* not REAL_ARITHMETIC */ --- 1153,1170 ---- REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i)); #else /* not REAL_ARITHMETIC */ ! if (TREE_INT_CST_HIGH (i) < 0 && ! TREE_UNSIGNED (TREE_TYPE (i))) { d = (double) (~ TREE_INT_CST_HIGH (i)); ! d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) ! * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); ! d += (double) (unsigned HOST_WIDE_INT) (~ TREE_INT_CST_LOW (i)); d = (- d - 1.0); } else { ! d = (double) (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (i); ! d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)) ! * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))); ! d += (double) (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (i); } #endif /* not REAL_ARITHMETIC */ *************** *** 1139,1143 **** TREE_TYPE (v) = type; ! d = real_value_from_int_cst (i); /* Check for valid float value for this type on this target machine; if not, can print error message and store a valid value in D. */ --- 1186,1190 ---- TREE_TYPE (v) = type; ! d = REAL_VALUE_TRUNCATE (TYPE_MODE (type), real_value_from_int_cst (i)); /* Check for valid float value for this type on this target machine; if not, can print error message and store a valid value in D. */ *************** *** 1199,1208 **** t = (tree) obstack_alloc (obstack, length); ! TREE_TYPE (t) = 0; ! TREE_CHAIN (t) = 0; ! for (i = (length / sizeof (int)) - 1; ! i >= sizeof (struct tree_common) / sizeof (int) - 1; ! i--) ((int *) t)[i] = 0; TREE_SET_CODE (t, TREE_VEC); TREE_VEC_LENGTH (t) = len; --- 1246,1252 ---- t = (tree) obstack_alloc (obstack, length); ! for (i = (length / sizeof (int)) - 1; i >= 0; i--) ((int *) t)[i] = 0; + TREE_SET_CODE (t, TREE_VEC); TREE_VEC_LENGTH (t) = len; *************** *** 1219,1224 **** tree expr; { ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == INTEGER_CST --- 1263,1267 ---- tree expr; { ! STRIP_NOPS (expr); return (TREE_CODE (expr) == INTEGER_CST *************** *** 1233,1238 **** tree expr; { ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == INTEGER_CST --- 1276,1280 ---- tree expr; { ! STRIP_NOPS (expr); return (TREE_CODE (expr) == INTEGER_CST *************** *** 1251,1256 **** register int uns; ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); if (TREE_CODE (expr) != INTEGER_CST) --- 1293,1297 ---- register int uns; ! STRIP_NOPS (expr); if (TREE_CODE (expr) != INTEGER_CST) *************** *** 1262,1280 **** prec = TYPE_PRECISION (TREE_TYPE (expr)); ! if (prec >= HOST_BITS_PER_INT) { int high_value, shift_amount; ! shift_amount = prec - HOST_BITS_PER_INT; ! if (shift_amount > HOST_BITS_PER_INT) /* Can not handle precisions greater than twice the host int size. */ abort (); ! else if (shift_amount == HOST_BITS_PER_INT) /* Shifting by the host word size is undefined according to the ANSI standard, so we must handle this as a special case. */ high_value = -1; else ! high_value = (1 << shift_amount) - 1; return TREE_INT_CST_LOW (expr) == -1 --- 1303,1321 ---- prec = TYPE_PRECISION (TREE_TYPE (expr)); ! if (prec >= HOST_BITS_PER_WIDE_INT) { int high_value, shift_amount; ! shift_amount = prec - HOST_BITS_PER_WIDE_INT; ! if (shift_amount > HOST_BITS_PER_WIDE_INT) /* Can not handle precisions greater than twice the host int size. */ abort (); ! else if (shift_amount == HOST_BITS_PER_WIDE_INT) /* Shifting by the host word size is undefined according to the ANSI standard, so we must handle this as a special case. */ high_value = -1; else ! high_value = ((HOST_WIDE_INT) 1 << shift_amount) - 1; return TREE_INT_CST_LOW (expr) == -1 *************** *** 1282,1286 **** } else ! return TREE_INT_CST_LOW (expr) == (1 << prec) - 1; } --- 1323,1327 ---- } else ! return TREE_INT_CST_LOW (expr) == ((HOST_WIDE_INT) 1 << prec) - 1; } *************** *** 1292,1299 **** tree expr; { ! int high, low; ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); if (TREE_CODE (expr) != INTEGER_CST) --- 1333,1339 ---- tree expr; { ! HOST_WIDE_INT high, low; ! STRIP_NOPS (expr); if (TREE_CODE (expr) != INTEGER_CST) *************** *** 1316,1321 **** tree expr; { ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == REAL_CST --- 1356,1360 ---- tree expr; { ! STRIP_NOPS (expr); return (TREE_CODE (expr) == REAL_CST *************** *** 1329,1334 **** tree expr; { ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == REAL_CST --- 1368,1372 ---- tree expr; { ! STRIP_NOPS (expr); return (TREE_CODE (expr) == REAL_CST *************** *** 1342,1347 **** tree expr; { ! while (TREE_CODE (expr) == NON_LVALUE_EXPR) ! expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == REAL_CST --- 1380,1384 ---- tree expr; { ! STRIP_NOPS (expr); return (TREE_CODE (expr) == REAL_CST *************** *** 1355,1358 **** --- 1392,1396 ---- tree exp; { + /* This is not quite the same as STRIP_NOPS. It does more. */ while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR *************** *** 1457,1460 **** --- 1495,1499 ---- for (t = op1; TREE_CHAIN (t); t = TREE_CHAIN (t)) if (t == op2) abort (); /* Circularity being created */ + if (t == op2) abort (); /* Circularity being created */ TREE_CHAIN (t) = op2; return op1; *************** *** 1563,1571 **** #endif ! ((int *)node)[(sizeof (struct tree_common)/sizeof (int)) - 1] = 0; TREE_SET_CODE (node, TREE_LIST); if (current_obstack == &permanent_obstack) TREE_PERMANENT (node) = 1; - TREE_TYPE (node) = 0; #endif --- 1602,1611 ---- #endif ! for (i = (sizeof (struct tree_common) / sizeof (int)) - 1; i >= 0; i--) ! ((int *) node)[i] = 0; ! TREE_SET_CODE (node, TREE_LIST); if (current_obstack == &permanent_obstack) TREE_PERMANENT (node) = 1; #endif *************** *** 1650,1654 **** if (TYPE_SIZE (type) == 0) { ! incomplete_type_error (0, type); return integer_zero_node; } --- 1690,1694 ---- if (TYPE_SIZE (type) == 0) { ! incomplete_type_error (NULL_TREE, type); return integer_zero_node; } *************** *** 1704,1708 **** case FUNCTION_DECL: case CONSTRUCTOR: ! return TREE_STATIC (arg) || TREE_EXTERNAL (arg); case STRING_CST: --- 1744,1748 ---- case FUNCTION_DECL: case CONSTRUCTOR: ! return TREE_STATIC (arg) || DECL_EXTERNAL (arg); case STRING_CST: *************** *** 1751,1755 **** return t; ! t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL); /* This expression might be placed ahead of a jump to ensure that the --- 1791,1795 ---- return t; ! t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE); /* This expression might be placed ahead of a jump to ensure that the *************** *** 1868,1871 **** --- 1908,1912 ---- case 't': case 'd': + case 'b': case '<': case 's': *************** *** 2005,2015 **** #endif ! TREE_TYPE (t) = type; ! TREE_CHAIN (t) = 0; ! ! for (i = (length / sizeof (int)) - 2; ! i >= sizeof (struct tree_common) / sizeof (int) - 1; ! i--) ((int *) t)[i] = 0; TREE_SET_CODE (t, code); --- 2046,2053 ---- #endif ! for (i = (length / sizeof (int)) - 1; i >= 0; i--) ((int *) t)[i] = 0; + + TREE_TYPE (t) = type; TREE_SET_CODE (t, code); *************** *** 2135,2141 **** /* BLOCK nodes are used to represent the structure of binding contours and declarations, once those contours have been exited and their contents ! compiled. This information is used for outputting debugging info. ! A BLOCK may have a "controller" which is a BIND_EXPR node. ! Then the BLOCK is ignored unless the controller has the TREE_USED flag. */ tree --- 2173,2177 ---- /* BLOCK nodes are used to represent the structure of binding contours and declarations, once those contours have been exited and their contents ! compiled. This information is used for outputting debugging info. */ tree *************** *** 2259,2263 **** /* Here is how primitive or already-canonicalized types' hash codes are made. */ ! #define TYPE_HASH(TYPE) ((int) (TYPE) & 0777777) /* Compute a hash code for a list of types (chain of TREE_LIST nodes --- 2295,2299 ---- /* Here is how primitive or already-canonicalized types' hash codes are made. */ ! #define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777) /* Compute a hash code for a list of types (chain of TREE_LIST nodes *************** *** 2632,2637 **** if (TREE_CODE (maxval) == INTEGER_CST) { ! int maxint = TREE_INT_CST_LOW (maxval); ! return type_hash_canon (maxint > 0 ? maxint : - maxint, itype); } else --- 2668,2673 ---- if (TREE_CODE (maxval) == INTEGER_CST) { ! int maxint = (int) TREE_INT_CST_LOW (maxval); ! return type_hash_canon (maxint < 0 ? ~maxint : maxint, itype); } else *************** *** 2656,2663 **** && (TREE_CODE (highval) == INTEGER_CST)) { ! int highint = TREE_INT_CST_LOW (highval); ! int lowint = TREE_INT_CST_LOW (lowval); ! int maxint = highint - lowint; ! return type_hash_canon (maxint > 0 ? maxint : - maxint, itype); } else --- 2692,2699 ---- && (TREE_CODE (highval) == INTEGER_CST)) { ! HOST_WIDE_INT highint = TREE_INT_CST_LOW (highval); ! HOST_WIDE_INT lowint = TREE_INT_CST_LOW (lowval); ! int maxint = (int) (highint - lowint); ! return type_hash_canon (maxint < 0 ? ~maxint : maxint, itype); } else *************** *** 2822,2826 **** TYPE_ARG_TYPES (t) ! = tree_cons (NULL, build_pointer_type (basetype), TYPE_ARG_TYPES (type)); /* If we already have such a type, use the old one and free this one. */ --- 2858,2863 ---- TYPE_ARG_TYPES (t) ! = tree_cons (NULL_TREE, ! build_pointer_type (basetype), TYPE_ARG_TYPES (type)); /* If we already have such a type, use the old one and free this one. */ *************** *** 3099,3106 **** if (TREE_UNSIGNED (type)) return (!INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c) ! && !INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))); else return (!INT_CST_LT (TYPE_MAX_VALUE (type), c) ! && !INT_CST_LT (c, TYPE_MIN_VALUE (type))); } --- 3136,3145 ---- if (TREE_UNSIGNED (type)) return (!INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c) ! && !INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type)) ! && (TREE_INT_CST_HIGH (c) >= 0 || TREE_UNSIGNED (TREE_TYPE (c)))); else return (!INT_CST_LT (TYPE_MAX_VALUE (type), c) ! && !INT_CST_LT (c, TYPE_MIN_VALUE (type)) ! && (TREE_INT_CST_HIGH (c) >= 0 || !TREE_UNSIGNED (TREE_TYPE (c)))); } diff -rc2N gcc-2.2.2/tree.def gcc-2.3.1/tree.def *** gcc-2.2.2/tree.def Wed May 27 23:43:45 1992 --- gcc-2.3.1/tree.def Tue Aug 4 21:34:39 1992 *************** *** 23,27 **** "x" for an exceptional code (fits no category). "t" for a type object code. ! "c" for codes for constants. "d" for codes for declarations (also serving as variable refs). --- 23,27 ---- "x" for an exceptional code (fits no category). "t" for a type object code. ! "b" for a lexical block. "c" for codes for constants. "d" for codes for declarations (also serving as variable refs). *************** *** 69,76 **** chained through the BLOCK_CHAIN field. BLOCK_SUPERCONTEXT points to the parent block. BLOCK_VARS points to a chain of decl nodes. BLOCK_TYPE_TAGS points to a chain of types which have their own names. ! BLOCK_CHAIN points to the next BLOCK at the same level. */ ! DEFTREECODE (BLOCK, "block", "e", 4) /* Each data type is represented by a tree node whose code is one of --- 69,87 ---- chained through the BLOCK_CHAIN field. BLOCK_SUPERCONTEXT points to the parent block. + For a block which represents the outermost scope of a function, it + points to the FUNCTION_DECL node. BLOCK_VARS points to a chain of decl nodes. BLOCK_TYPE_TAGS points to a chain of types which have their own names. ! BLOCK_CHAIN points to the next BLOCK at the same level. ! BLOCK_ABSTRACT_ORIGIN points to the original (abstract) tree node which ! this block is an instance of, or else is NULL to indicate that this ! block is not an instance of anything else. When non-NULL, the value ! could either point to another BLOCK node or it could point to a ! FUNCTION_DECL node (e.g. in the case of a block representing the ! outermost scope of a particular inlining of a function). ! BLOCK_ABSTRACT is non-zero if the block represents an abstract ! instance of a block (i.e. one which is nested within an abstract ! instance of a inline function. */ ! DEFTREECODE (BLOCK, "block", "b", 0) /* Each data type is represented by a tree node whose code is one of *************** *** 94,106 **** in the case of structs, unions or enums that are known with a tag, or zero for types that have no special name. ! The TYPE_CONTEXT for any sort of type which could have a name (i.e. ! tagged types in C/C++) will point to the node which represents ! the scope of the given type. For most types, this will be a ! BLOCK node or a FUNCTION_DECL node, but it could also be a ! FUNCTION_TYPE node (for types whose scope is limited to the formal parameter list of some function type specification) or it ! could be a RECORD_TYPE or UNION_TYPE node (for C++ "member" types). For non-tagged-types, TYPE_CONTEXT need not be set to anything in ! particular (since an anonymous type doesn't really have a "scope"). */ /* TREE_CHAIN is used for ENUMERAL_TYPE, RECORD_TYPE and UNION_TYPE nodes used as forward-references to names; see below. */ --- 105,120 ---- in the case of structs, unions or enums that are known with a tag, or zero for types that have no special name. ! The TYPE_CONTEXT for any sort of type which could have a name or ! which could have named members (e.g. tagged types in C/C++) will ! point to the node which represents the scope of the given type, or ! will be NULL_TREE if the type has "file scope". For most types, this ! will point to a BLOCK node or a FUNCTION_DECL node, but it could also ! point to a FUNCTION_TYPE node (for types whose scope is limited to the formal parameter list of some function type specification) or it ! could point to a RECORD_TYPE or UNION_TYPE node (for C++ "member" types). For non-tagged-types, TYPE_CONTEXT need not be set to anything in ! particular, since any type which is of some type category (e.g. ! an array type or a function type) which cannot either have a name ! itself or have named members doesn't really have a "scope" per se. */ /* TREE_CHAIN is used for ENUMERAL_TYPE, RECORD_TYPE and UNION_TYPE nodes used as forward-references to names; see below. */ *************** *** 244,250 **** DECL_CONTEXT points to the node representing the context in which this declaration has its scope. For FIELD_DECLs, this is the ! RECORD_TYPE or UNION_TYPE node that the field belongs to; ! for VAR_DECL, PARM_DECL, FUNCTION_DECL and LABEL_DECL, this ! is the FUNCTION_DECL for the containing function, or 0 if global. The TREE_TYPE field holds the data type of the object, when relevant. LABEL_DECLs have no data type. For TYPE_DECL, the TREE_TYPE field --- 258,268 ---- DECL_CONTEXT points to the node representing the context in which this declaration has its scope. For FIELD_DECLs, this is the ! RECORD_TYPE or UNION_TYPE node that the field is a member of. For ! VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, ! this points to the FUNCTION_DECL for the containing function, or else ! yields NULL_TREE if the given decl has "file scope". ! DECL_ABSTRACT_ORIGIN, if non-NULL, points to the original (abstract) ! ..._DECL node of which this decl is an (inlined or template expanded) ! instance. The TREE_TYPE field holds the data type of the object, when relevant. LABEL_DECLs have no data type. For TYPE_DECL, the TREE_TYPE field *************** *** 285,289 **** DECL_SOURCE_FILE holds a filename string and DECL_SOURCE_LINE holds a line number. In some cases these can be the location of ! a reference, if no definition has been seen. */ DEFTREECODE (FUNCTION_DECL, "function_decl", "d", 0) --- 303,311 ---- DECL_SOURCE_FILE holds a filename string and DECL_SOURCE_LINE holds a line number. In some cases these can be the location of ! a reference, if no definition has been seen. ! ! DECL_ABSTRACT is non-zero if the decl represents an abstract instance ! of a decl (i.e. one which is nested within an abstract instance of a ! inline function. */ DEFTREECODE (FUNCTION_DECL, "function_decl", "d", 0) diff -rc2N gcc-2.2.2/tree.h gcc-2.3.1/tree.h *** gcc-2.2.2/tree.h Sun May 17 17:15:14 1992 --- gcc-2.3.1/tree.h Thu Oct 29 01:06:07 1992 *************** *** 78,81 **** --- 78,83 ---- BUILT_IN_STRLEN, BUILT_IN_FSQRT, + BUILT_IN_SIN, + BUILT_IN_COS, BUILT_IN_GETEXP, BUILT_IN_GETMAN, *************** *** 116,121 **** typedef union tree_node *tree; - #define NULL_TREE (tree) NULL - /* Every kind of tree node starts with this structure, so all nodes have these fields. --- 118,121 ---- *************** *** 193,196 **** --- 193,206 ---- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (EXP, 0))))) \ (EXP) = TREE_OPERAND (EXP, 0); + + /* Like STRIP_NOPS, but don't alter the TREE_TYPE either. */ + + #define STRIP_TYPE_NOPS(EXP) \ + while ((TREE_CODE (EXP) == NOP_EXPR \ + || TREE_CODE (EXP) == CONVERT_EXPR \ + || TREE_CODE (EXP) == NON_LVALUE_EXPR) \ + && (TREE_TYPE (EXP) \ + == TREE_TYPE (TREE_OPERAND (EXP, 0)))) \ + (EXP) = TREE_OPERAND (EXP, 0); /* Define many boolean fields that all tree nodes have. */ *************** *** 211,215 **** /* In a VAR_DECL, nonzero means allocate static storage. ! In a FUNCTION_DECL, currently nonzero if function has been defined. In a CONSTRUCTOR, nonzero means allocate static storage. */ #define TREE_STATIC(NODE) ((NODE)->common.static_flag) --- 221,225 ---- /* In a VAR_DECL, nonzero means allocate static storage. ! In a FUNCTION_DECL, nonzero if function has been defined. In a CONSTRUCTOR, nonzero means allocate static storage. */ #define TREE_STATIC(NODE) ((NODE)->common.static_flag) *************** *** 219,224 **** #define TREE_NO_UNUSED_WARNING(NODE) ((NODE)->common.static_flag) ! /* In a NON_LVALUE_EXPR, this means there was overflow in folding. ! The folded constant is inside the NON_LVALUE_EXPR. */ #define TREE_CONSTANT_OVERFLOW(NODE) ((NODE)->common.static_flag) --- 229,233 ---- #define TREE_NO_UNUSED_WARNING(NODE) ((NODE)->common.static_flag) ! /* In an INTEGER_CST, this means there was overflow in folding. */ #define TREE_CONSTANT_OVERFLOW(NODE) ((NODE)->common.static_flag) *************** *** 229,233 **** /* In a VAR_DECL or FUNCTION_DECL, nonzero means name is to be accessible from outside this module. ! In an identifier node, nonzero means a external declaration accessible from outside this module was previously seen for this name in an inner scope. */ --- 238,242 ---- /* In a VAR_DECL or FUNCTION_DECL, nonzero means name is to be accessible from outside this module. ! In an identifier node, nonzero means an external declaration accessible from outside this module was previously seen for this name in an inner scope. */ *************** *** 239,242 **** --- 248,260 ---- #define TREE_VIA_PUBLIC(NODE) ((NODE)->common.public_flag) + /* Ditto, for `private' declarations. */ + #define TREE_VIA_PRIVATE(NODE) ((NODE)->common.private_flag) + + /* Nonzero for TREE_LIST node means that the path to the + base class is via a `protected' declaration, which preserves + protected fields from the base class as protected. + OVERLOADED. */ + #define TREE_VIA_PROTECTED(NODE) ((NODE)->common.protected_flag) + /* In any expression, nonzero means it has side effects or reevaluation of the whole expression could produce a different value. *************** *** 286,290 **** to be compiled separately. Nonzero in a RECORD_TYPE, UNION_TYPE or ENUMERAL_TYPE ! if the sdb debugging info for the type has been written. */ #define TREE_ASM_WRITTEN(NODE) ((NODE)->common.asm_written_flag) --- 304,309 ---- to be compiled separately. Nonzero in a RECORD_TYPE, UNION_TYPE or ENUMERAL_TYPE ! if the sdb debugging info for the type has been written. ! In a BLOCK node, nonzero if reorder_blocks has already seen this block. */ #define TREE_ASM_WRITTEN(NODE) ((NODE)->common.asm_written_flag) *************** *** 299,306 **** #define TREE_RAISES(NODE) ((NODE)->common.raises_flag) ! /* These are currently used in classes in C++. */ #define TREE_PRIVATE(NODE) ((NODE)->common.private_flag) #define TREE_PROTECTED(NODE) ((NODE)->common.protected_flag) #define TREE_LANG_FLAG_0(NODE) ((NODE)->common.lang_flag_0) #define TREE_LANG_FLAG_1(NODE) ((NODE)->common.lang_flag_1) --- 318,328 ---- #define TREE_RAISES(NODE) ((NODE)->common.raises_flag) ! /* Used in classes in C++. */ #define TREE_PRIVATE(NODE) ((NODE)->common.private_flag) + /* Used in classes in C++. + In a BLOCK node, this is BLOCK_HANDLER_BLOCK. */ #define TREE_PROTECTED(NODE) ((NODE)->common.protected_flag) + /* These flags are available for each language front end to use internally. */ #define TREE_LANG_FLAG_0(NODE) ((NODE)->common.lang_flag_0) #define TREE_LANG_FLAG_1(NODE) ((NODE)->common.lang_flag_1) *************** *** 313,320 **** /* Define additional fields and accessors for nodes representing constants. */ ! /* In an INTEGER_CST node. These two together make a 64 bit integer. ! If the data type is signed, the value is sign-extended to 64 bits even though not all of them may really be in use. ! In an unsigned constant shorter than 64 bits, the extra bits are 0. */ #define TREE_INT_CST_LOW(NODE) ((NODE)->int_cst.int_cst_low) #define TREE_INT_CST_HIGH(NODE) ((NODE)->int_cst.int_cst_high) --- 335,342 ---- /* Define additional fields and accessors for nodes representing constants. */ ! /* In an INTEGER_CST node. These two together make a 2-word integer. ! If the data type is signed, the value is sign-extended to 2 words even though not all of them may really be in use. ! In an unsigned constant shorter than 2 words, the extra bits are 0. */ #define TREE_INT_CST_LOW(NODE) ((NODE)->int_cst.int_cst_low) #define TREE_INT_CST_HIGH(NODE) ((NODE)->int_cst.int_cst_high) *************** *** 323,338 **** (TREE_INT_CST_HIGH (A) < TREE_INT_CST_HIGH (B) \ || (TREE_INT_CST_HIGH (A) == TREE_INT_CST_HIGH (B) \ ! && ((unsigned) TREE_INT_CST_LOW (A) < (unsigned) TREE_INT_CST_LOW (B)))) #define INT_CST_LT_UNSIGNED(A, B) \ ! ((unsigned) TREE_INT_CST_HIGH (A) < (unsigned) TREE_INT_CST_HIGH (B) \ ! || ((unsigned) TREE_INT_CST_HIGH (A) == (unsigned) TREE_INT_CST_HIGH (B) \ ! && ((unsigned) TREE_INT_CST_LOW (A) < (unsigned) TREE_INT_CST_LOW (B)))) struct tree_int_cst { char common[sizeof (struct tree_common)]; ! long int_cst_low; ! long int_cst_high; }; --- 345,364 ---- (TREE_INT_CST_HIGH (A) < TREE_INT_CST_HIGH (B) \ || (TREE_INT_CST_HIGH (A) == TREE_INT_CST_HIGH (B) \ ! && ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (A) \ ! < (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (B)))) #define INT_CST_LT_UNSIGNED(A, B) \ ! (((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (A) \ ! < (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (B)) \ ! || (((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (A) \ ! == (unsigned HOST_WIDE_INT ) TREE_INT_CST_HIGH (B)) \ ! && (((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (A) \ ! < (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (B))))) struct tree_int_cst { char common[sizeof (struct tree_common)]; ! HOST_WIDE_INT int_cst_low; ! HOST_WIDE_INT int_cst_high; }; *************** *** 390,394 **** #define IDENTIFIER_LENGTH(NODE) ((NODE)->identifier.length) #define IDENTIFIER_POINTER(NODE) ((NODE)->identifier.pointer) - #define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE) struct tree_identifier --- 416,419 ---- *************** *** 438,463 **** #define CONSTRUCTOR_ELTS(NODE) TREE_OPERAND (NODE, 1) /* In a BLOCK node. */ ! #define BLOCK_VARS(NODE) ((NODE)->exp.operands[0]) ! #define BLOCK_TYPE_TAGS(NODE) ((NODE)->exp.operands[1]) ! #define BLOCK_SUBBLOCKS(NODE) ((NODE)->exp.operands[2]) ! #define BLOCK_SUPERCONTEXT(NODE) ((NODE)->exp.operands[3]) /* Note: when changing this, make sure to find the places that use chainon or nreverse. */ #define BLOCK_CHAIN(NODE) TREE_CHAIN (NODE) /* Nonzero means that this block is prepared to handle exceptions listed in the BLOCK_VARS slot. */ ! #define BLOCK_HANDLER_BLOCK(NODE) TREE_PROTECTED(NODE) ! /* In ordinary expression nodes. */ ! #define TREE_OPERAND(NODE, I) ((NODE)->exp.operands[I]) ! #define TREE_COMPLEXITY(NODE) ((NODE)->exp.complexity) ! ! struct tree_exp { char common[sizeof (struct tree_common)]; ! int complexity; ! union tree_node *operands[1]; }; --- 463,506 ---- #define CONSTRUCTOR_ELTS(NODE) TREE_OPERAND (NODE, 1) + /* In ordinary expression nodes. */ + #define TREE_OPERAND(NODE, I) ((NODE)->exp.operands[I]) + #define TREE_COMPLEXITY(NODE) ((NODE)->exp.complexity) + + struct tree_exp + { + char common[sizeof (struct tree_common)]; + int complexity; + union tree_node *operands[1]; + }; + /* In a BLOCK node. */ ! #define BLOCK_VARS(NODE) ((NODE)->block.vars) ! #define BLOCK_TYPE_TAGS(NODE) ((NODE)->block.type_tags) ! #define BLOCK_SUBBLOCKS(NODE) ((NODE)->block.subblocks) ! #define BLOCK_SUPERCONTEXT(NODE) ((NODE)->block.supercontext) /* Note: when changing this, make sure to find the places that use chainon or nreverse. */ #define BLOCK_CHAIN(NODE) TREE_CHAIN (NODE) + #define BLOCK_ABSTRACT_ORIGIN(NODE) ((NODE)->block.abstract_origin) + #define BLOCK_ABSTRACT(NODE) ((NODE)->block.abstract_flag) + #define BLOCK_END_NOTE(NODE) ((NODE)->block.end_note) /* Nonzero means that this block is prepared to handle exceptions listed in the BLOCK_VARS slot. */ ! #define BLOCK_HANDLER_BLOCK(NODE) ((NODE)->block.handler_block_flag) ! struct tree_block { char common[sizeof (struct tree_common)]; ! ! unsigned handler_block_flag : 1; ! unsigned abstract_flag : 1; ! ! union tree_node *vars; ! union tree_node *type_tags; ! union tree_node *subblocks; ! union tree_node *supercontext; ! union tree_node *abstract_origin; ! struct rtx_def *end_note; }; *************** *** 509,512 **** --- 552,556 ---- #define TYPE_READONLY(NODE) ((NODE)->common.readonly_flag) + /* These flags are available for each language front end to use internally. */ #define TYPE_LANG_FLAG_0(NODE) ((NODE)->type.lang_flag_0) #define TYPE_LANG_FLAG_1(NODE) ((NODE)->type.lang_flag_1) *************** *** 529,533 **** enum machine_mode mode : 8; #endif - unsigned char align; unsigned char precision; --- 573,576 ---- *************** *** 541,544 **** --- 584,588 ---- unsigned lang_flag_6 : 1; + unsigned int align; union tree_node *pointer_to; union tree_node *reference_to; *************** *** 611,614 **** --- 655,664 ---- #define TYPE_BINFO_BASETYPES(NODE) TREE_VEC_ELT (TYPE_BINFO (NODE), 4) + /* For a BINFO record describing an inheritance, this yields a pointer + to the artificial FIELD_DECL node which contains the "virtual base + class pointer" for the given inheritance. */ + + #define BINFO_VPTR_FIELD(NODE) TREE_VEC_ELT ((NODE), 5) + /* Accessor macro to get to the Nth basetype of this basetype. */ #define BINFO_BASETYPE(NODE,N) TREE_VEC_ELT (BINFO_BASETYPES (NODE), (N)) *************** *** 640,645 **** It is an IDENTIFIER_NODE. */ #define DECL_ASSEMBLER_NAME(NODE) ((NODE)->decl.assembler_name) ! /* The containing binding context; either a BINDING ! or a RECORD_TYPE or UNION_TYPE. */ #define DECL_CONTEXT(NODE) ((NODE)->decl.context) #define DECL_FIELD_CONTEXT(NODE) ((NODE)->decl.context) --- 690,698 ---- It is an IDENTIFIER_NODE. */ #define DECL_ASSEMBLER_NAME(NODE) ((NODE)->decl.assembler_name) ! /* For FIELD_DECLs, this is the ! RECORD_TYPE or UNION_TYPE node that the field is a member of. For ! VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, ! this points to the FUNCTION_DECL for the containing function, or else ! yields NULL_TREE if the given decl has "file scope". */ #define DECL_CONTEXT(NODE) ((NODE)->decl.context) #define DECL_FIELD_CONTEXT(NODE) ((NODE)->decl.context) *************** *** 676,682 **** /* Holds the alignment required for the datum. */ #define DECL_ALIGN(NODE) ((NODE)->decl.frame_size) ! /* Holds the machine mode of a variable or field. */ #define DECL_MODE(NODE) ((NODE)->decl.mode) ! /* Holds the RTL expression for the value of a variable or function. */ #define DECL_RTL(NODE) ((NODE)->decl.rtl) /* For PARM_DECL, holds an RTL for the stack slot or register --- 729,741 ---- /* Holds the alignment required for the datum. */ #define DECL_ALIGN(NODE) ((NODE)->decl.frame_size) ! /* Holds the machine mode corresponding to the declaration of a variable or ! field. Always equal to TYPE_MODE (TREE_TYPE (decl)) except for a ! FIELD_DECL. */ #define DECL_MODE(NODE) ((NODE)->decl.mode) ! /* Holds the RTL expression for the value of a variable or function. If ! PROMOTED_MODE is defined, the mode of this expression may not be same ! as DECL_MODE. In that case, DECL_MODE contains the mode corresponding ! to the variable's data type, while the mode ! of DECL_RTL is the mode actually used to contain the data. */ #define DECL_RTL(NODE) ((NODE)->decl.rtl) /* For PARM_DECL, holds an RTL for the stack slot or register *************** *** 685,696 **** /* For FUNCTION_DECL, if it is inline, holds the saved insn chain. */ #define DECL_SAVED_INSNS(NODE) ((NODE)->decl.saved_insns.r) ! /* For FUNCTION_DECL for built-in function. */ #define DECL_FUNCTION_CODE(NODE) \ ((enum built_in_function) (NODE)->decl.frame_size) #define DECL_SET_FUNCTION_CODE(NODE,VAL) \ ((NODE)->decl.frame_size = (int) (VAL)) - /* For FUNCTION_DECL, if it is inline, - holds the size of the stack frame, as an integer. */ - #define DECL_FRAME_SIZE(NODE) ((NODE)->decl.frame_size) /* For a FIELD_DECL, holds the size of the member as an integer. */ #define DECL_FIELD_SIZE(NODE) ((NODE)->decl.saved_insns.i) --- 744,756 ---- /* For FUNCTION_DECL, if it is inline, holds the saved insn chain. */ #define DECL_SAVED_INSNS(NODE) ((NODE)->decl.saved_insns.r) ! /* For FUNCTION_DECL, if it is inline, ! holds the size of the stack frame, as an integer. */ ! #define DECL_FRAME_SIZE(NODE) ((NODE)->decl.frame_size) ! /* For FUNCTION_DECL, if it is built-in, ! this identifies which built-in operation it is. */ #define DECL_FUNCTION_CODE(NODE) \ ((enum built_in_function) (NODE)->decl.frame_size) #define DECL_SET_FUNCTION_CODE(NODE,VAL) \ ((NODE)->decl.frame_size = (int) (VAL)) /* For a FIELD_DECL, holds the size of the member as an integer. */ #define DECL_FIELD_SIZE(NODE) ((NODE)->decl.saved_insns.i) *************** *** 709,715 **** #define DECL_FCONTEXT(NODE) ((NODE)->decl.vindex) ! /* Nonzero in a VAR_DECL or PARM_DECL means this decl was made by inlining; suppress any warnings about shadowing some other variable. */ ! #define DECL_FROM_INLINE(NODE) ((NODE)->decl.from_inline_flag) /* Nonzero if a _DECL means that the name of this decl should be ignored --- 769,784 ---- #define DECL_FCONTEXT(NODE) ((NODE)->decl.vindex) ! /* Every ..._DECL node gets a unique number. */ ! #define DECL_UID(NODE) ((NODE)->decl.uid) ! ! /* For any sort of a ..._DECL node, this points to the original (abstract) ! decl node which this decl is an instance of, or else it is NULL indicating ! that this decl is not an instance of some other decl. */ ! #define DECL_ABSTRACT_ORIGIN(NODE) ((NODE)->decl.abstract_origin) ! ! /* Nonzero for any sort of ..._DECL node means this decl node represents ! an inline instance of some original (abstract) decl from an inline function; suppress any warnings about shadowing some other variable. */ ! #define DECL_FROM_INLINE(NODE) (DECL_ABSTRACT_ORIGIN (NODE) != (tree) 0) /* Nonzero if a _DECL means that the name of this decl should be ignored *************** *** 717,720 **** --- 786,802 ---- #define DECL_IGNORED_P(NODE) ((NODE)->decl.ignored_flag) + /* Nonzero for a given ..._DECL node means that this node represents an + "abstract instance" of the given declaration (e.g. in the original + declaration of an inline function). When generating symbolic debugging + information, we musn't try to generate any address information for nodes + marked as "abstract instances" because we don't actually generate + any code or allocate any data space for such instances. */ + #define DECL_ABSTRACT(NODE) ((NODE)->decl.abstract_flag) + + /* Nonzero if a _DECL means that no warnings should be generated just + because this decl is unused. */ + #define DECL_IN_SYSTEM_HEADER(NODE) ((NODE)->decl.in_system_header_flag) + + /* Language-specific decl information. */ #define DECL_LANG_SPECIFIC(NODE) ((NODE)->decl.lang_specific) *************** *** 722,731 **** nonzero means external reference: do not allocate storage, and refer to a definition elsewhere. */ ! #define TREE_EXTERNAL(NODE) ((NODE)->decl.external_flag) /* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'. In LABEL_DECL nodes, nonzero means that an error message about jumping into such a binding contour has been printed for this label. */ ! #define TREE_REGDECL(NODE) ((NODE)->decl.regdecl_flag) /* Nonzero in a ..._DECL means this variable is ref'd from a nested function. --- 804,815 ---- nonzero means external reference: do not allocate storage, and refer to a definition elsewhere. */ ! #define DECL_EXTERNAL(NODE) ((NODE)->decl.external_flag) /* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'. In LABEL_DECL nodes, nonzero means that an error message about jumping into such a binding contour has been printed for this label. */ ! #define DECL_REGISTER(NODE) ((NODE)->decl.regdecl_flag) ! /* In a FIELD_DECL, indicates this field should be bit-packed. */ ! #define DECL_PACKED(NODE) ((NODE)->decl.regdecl_flag) /* Nonzero in a ..._DECL means this variable is ref'd from a nested function. *************** *** 736,744 **** Also set in some languages for variables, etc., outside the normal lexical scope, such as class instance variables. */ ! #define TREE_NONLOCAL(NODE) ((NODE)->decl.nonlocal_flag) /* Nonzero in a FUNCTION_DECL means this function can be substituted where it is called. */ ! #define TREE_INLINE(NODE) ((NODE)->decl.inline_flag) /* Nonzero in a FUNCTION_DECL means this is a built-in function --- 820,828 ---- Also set in some languages for variables, etc., outside the normal lexical scope, such as class instance variables. */ ! #define DECL_NONLOCAL(NODE) ((NODE)->decl.nonlocal_flag) /* Nonzero in a FUNCTION_DECL means this function can be substituted where it is called. */ ! #define DECL_INLINE(NODE) ((NODE)->decl.inline_flag) /* Nonzero in a FUNCTION_DECL means this is a built-in function *************** *** 756,764 **** #define DECL_BUILT_IN(NODE) ((NODE)->decl.bit_field_flag) ! /* In a FUNCTION_DECL, indicates a method ! for which each instance has a pointer. */ #define DECL_VIRTUAL_P(NODE) ((NODE)->decl.virtual_flag) - /* In a FIELD_DECL, indicates this field should be bit-packed. */ - #define DECL_PACKED(NODE) ((NODE)->decl.virtual_flag) /* Additional flags for language-specific uses. */ --- 840,846 ---- #define DECL_BUILT_IN(NODE) ((NODE)->decl.bit_field_flag) ! /* Used in VAR_DECLs to indicate that the variable is a vtable. ! It is also used in FIELD_DECLs for vtable pointers. */ #define DECL_VIRTUAL_P(NODE) ((NODE)->decl.virtual_flag) /* Additional flags for language-specific uses. */ *************** *** 778,781 **** --- 860,864 ---- int linenum; union tree_node *size; + unsigned int uid; #ifdef ONLY_INT_FIELDS int mode : 8; *************** *** 790,795 **** unsigned bit_field_flag : 1; unsigned virtual_flag : 1; - unsigned from_inline_flag : 1; unsigned ignored_flag : 1; unsigned lang_flag_0 : 1; --- 873,881 ---- unsigned bit_field_flag : 1; unsigned virtual_flag : 1; unsigned ignored_flag : 1; + unsigned abstract_flag : 1; + + unsigned in_system_header_flag : 1; + /* room for seven more */ unsigned lang_flag_0 : 1; *************** *** 807,810 **** --- 893,897 ---- union tree_node *result; union tree_node *initial; + union tree_node *abstract_origin; /* The PRINT_NAME field is marked for death. */ char *print_name; *************** *** 813,817 **** (rtl) info */ /* For a FUNCTION_DECL, if inline, this is the size of frame needed. ! If built-in, this is the code for which built-in function. */ int frame_size; /* For FUNCTION_DECLs: points to insn that constitutes its definition --- 900,905 ---- (rtl) info */ /* For a FUNCTION_DECL, if inline, this is the size of frame needed. ! If built-in, this is the code for which built-in function. ! For other kinds of decls, this is DECL_ALIGN. */ int frame_size; /* For FUNCTION_DECLs: points to insn that constitutes its definition *************** *** 844,849 **** --- 932,968 ---- struct tree_vec vec; struct tree_exp exp; + struct tree_block block; }; + /* Add prototype support. */ + #ifndef PROTO + #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) + #define PROTO(ARGS) ARGS + #else + #define PROTO(ARGS) () + #endif + #endif + + + #define NULL_TREE (tree) NULL + + /* Define a generic NULL if one hasn't already been defined. */ + + #ifndef NULL + #define NULL 0 + #endif + + #ifndef GENERIC_PTR + #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) + #define GENERIC_PTR void * + #else + #define GENERIC_PTR char * + #endif + #endif + + #ifndef NULL_PTR + #define NULL_PTR ((GENERIC_PTR)0) + #endif + /* Format for global names of constructor and destructor functions. */ #ifndef NO_DOLLAR_IN_LABEL *************** *** 853,865 **** #endif ! extern char *oballoc (); ! extern char *permalloc (); ! extern char *savealloc (); /* Lowest level primitive for allocating a node. The TREE_CODE is the only argument. Contents are initialized to zero except for a few of the common fields. */ ! extern tree make_node (); /* Make a copy of a node, with all the same contents except --- 972,1004 ---- #endif ! /* The following functions accept a wide integer argument. Rather than ! having to cast on every function call, we use a macro instead, that is ! defined here and in rtl.h. */ ! ! #ifndef exact_log2 ! #define exact_log2(N) exact_log2_wide ((HOST_WIDE_INT) (N)) ! #define floor_log2(N) floor_log2_wide ((HOST_WIDE_INT) (N)) ! #endif + #if 0 + /* At present, don't prototype xrealloc, since all of the callers don't + cast their pointers to char *, and all of the xrealloc's don't use + void * yet. */ + extern char *xrealloc PROTO((void *, unsigned)); + #else + extern char *xrealloc (); + #endif + + extern char *oballoc PROTO((int)); + extern char *permalloc PROTO((int)); + extern char *savealloc PROTO((int)); + extern char *xmalloc PROTO((unsigned)); + extern void free PROTO((void *)); + /* Lowest level primitive for allocating a node. The TREE_CODE is the only argument. Contents are initialized to zero except for a few of the common fields. */ ! extern tree make_node PROTO((enum tree_code)); /* Make a copy of a node, with all the same contents except *************** *** 867,921 **** iff nodes being made now are permanent.) */ ! extern tree copy_node (); /* Make a copy of a chain of TREE_LIST nodes. */ ! extern tree copy_list (); /* Make a TREE_VEC. */ ! extern tree make_tree_vec (); /* Return the (unique) IDENTIFIER_NODE node for a given name. The name is supplied as a char *. */ ! extern tree get_identifier (); /* Construct various types of nodes. */ ! extern tree build_int_2 (); ! extern tree build_real (); ! extern tree build_real_from_string (); ! extern tree build_real_from_int_cst (); ! extern tree build_complex (); ! extern tree build_string (); ! extern tree build (), build1 (); ! extern tree build_nt (), build_parse_node (); ! extern tree build_tree_list (), build_decl_list (); ! extern tree build_op_identifier (); ! extern tree build_decl (); ! extern tree build_block (); ! /* Construct various nodes representing data types. */ ! extern tree make_signed_type (); ! extern tree make_unsigned_type (); ! extern tree signed_or_unsigned_type (); ! extern void fixup_unsigned_type (); ! extern tree build_pointer_type (); ! extern tree build_reference_type (); ! extern tree build_index_type (), build_index_2_type (); ! extern tree build_array_type (); ! extern tree build_function_type (); ! extern tree build_method_type (); ! extern tree build_offset_type (); ! extern tree build_complex_type (); ! extern tree array_type_nelts (); ! /* Construct expressions, performing type checking. */ extern tree build_binary_op (); extern tree build_indirect_ref (); ! extern tree build_unary_op (); /* Given a type node TYPE, and CONSTP and VOLATILEP, return a type --- 1006,1084 ---- iff nodes being made now are permanent.) */ ! extern tree copy_node PROTO((tree)); /* Make a copy of a chain of TREE_LIST nodes. */ ! extern tree copy_list PROTO((tree)); /* Make a TREE_VEC. */ ! extern tree make_tree_vec PROTO((int)); /* Return the (unique) IDENTIFIER_NODE node for a given name. The name is supplied as a char *. */ ! extern tree get_identifier PROTO((char *)); /* Construct various types of nodes. */ ! #define build_int_2(LO,HI) \ ! build_int_2_wide ((HOST_WIDE_INT) (LO), (HOST_WIDE_INT) (HI)) ! #if 0 ! /* We cannot define prototypes for the variable argument functions, ! since they have not been ANSI-fied, and an ANSI compiler would ! complain when compiling the definition of these functions. */ ! ! extern tree build PROTO((enum tree_code, tree, ...)); ! extern tree build_nt PROTO((enum tree_code, ...)); ! extern tree build_parse_node PROTO((enum tree_code, ...)); ! #else ! extern tree build (); ! extern tree build_nt (); ! extern tree build_parse_node (); ! #endif ! ! extern tree build_int_2_wide PROTO((HOST_WIDE_INT, HOST_WIDE_INT)); ! extern tree build_real PROTO((tree, REAL_VALUE_TYPE)); ! extern tree build_real_from_int_cst PROTO((tree, tree)); ! extern tree build_complex PROTO((tree, tree)); ! extern tree build_string PROTO((int, char *)); ! extern tree build1 PROTO((enum tree_code, tree, tree)); ! extern tree build_tree_list PROTO((tree, tree)); ! extern tree build_decl_list PROTO((tree, tree)); ! extern tree build_decl PROTO((enum tree_code, tree, tree)); ! extern tree build_block PROTO((tree, tree, tree, tree, tree)); ! /* Construct various nodes representing data types. */ ! extern tree make_signed_type PROTO((int)); ! extern tree make_unsigned_type PROTO((int)); ! extern tree signed_or_unsigned_type PROTO((int, tree)); ! extern void fixup_unsigned_type PROTO((tree)); ! extern tree build_pointer_type PROTO((tree)); ! extern tree build_reference_type PROTO((tree)); ! extern tree build_index_type PROTO((tree)); ! extern tree build_index_2_type PROTO((tree, tree)); ! extern tree build_array_type PROTO((tree, tree)); ! extern tree build_function_type PROTO((tree, tree)); ! extern tree build_method_type PROTO((tree, tree)); ! extern tree build_offset_type PROTO((tree, tree)); ! extern tree build_complex_type PROTO((tree)); ! extern tree array_type_nelts PROTO((tree)); ! ! /* Construct expressions, performing type checking. ! GCC and G++ use different calling sequences for build_binary_op, ! and build_indirect_ref, so don't include a prototype here. */ extern tree build_binary_op (); extern tree build_indirect_ref (); ! extern tree build_unary_op PROTO((enum tree_code, tree, int)); ! ! /* From expmed.c. Since rtl.h is included after tree.h, we can't ! put the prototype here. Rtl.h does declare the prototype if ! tree.h had been included. */ ! ! extern tree make_tree (); /* Given a type node TYPE, and CONSTP and VOLATILEP, return a type *************** *** 926,934 **** Only main variants should ever appear as types of expressions. */ ! extern tree build_type_variant (); /* Make a copy of a type node. */ ! extern tree build_type_copy (); /* Given a ..._TYPE node, calculate the TYPE_SIZE, TYPE_SIZE_UNIT, --- 1089,1097 ---- Only main variants should ever appear as types of expressions. */ ! extern tree build_type_variant PROTO((tree, int, int)); /* Make a copy of a type node. */ ! extern tree build_type_copy PROTO((tree)); /* Given a ..._TYPE node, calculate the TYPE_SIZE, TYPE_SIZE_UNIT, *************** *** 937,941 **** for the first time. */ ! extern void layout_type (); /* Given a hashcode and a ..._TYPE node (for which the hashcode was made), --- 1100,1104 ---- for the first time. */ ! extern void layout_type PROTO((tree)); /* Given a hashcode and a ..._TYPE node (for which the hashcode was made), *************** *** 944,948 **** callers that could hash identical-looking type nodes agree. */ ! extern tree type_hash_canon (); /* Given a VAR_DECL, PARM_DECL, RESULT_DECL or FIELD_DECL node, --- 1107,1111 ---- callers that could hash identical-looking type nodes agree. */ ! extern tree type_hash_canon PROTO((int, tree)); /* Given a VAR_DECL, PARM_DECL, RESULT_DECL or FIELD_DECL node, *************** *** 954,958 **** on any boundary that may be needed. */ ! extern void layout_decl (); /* Fold constants as much as possible in an expression. --- 1117,1121 ---- on any boundary that may be needed. */ ! extern void layout_decl PROTO((tree, unsigned)); /* Fold constants as much as possible in an expression. *************** *** 962,978 **** subexpressions are not changed. */ ! extern tree fold (); /* Return an expr equal to X but certainly not valid as an lvalue. */ ! extern tree non_lvalue (); ! extern tree convert (); ! extern tree size_in_bytes (); ! extern tree size_binop (); ! extern tree size_int (); ! extern tree round_up (); ! extern tree get_pending_sizes (); ! extern tree get_permanent_types (), get_temporary_types (); /* Type for sizes of data-type. */ --- 1125,1141 ---- subexpressions are not changed. */ ! extern tree fold PROTO((tree)); /* Return an expr equal to X but certainly not valid as an lvalue. */ ! extern tree non_lvalue PROTO((tree)); ! extern tree convert PROTO((tree, tree)); ! extern tree size_in_bytes PROTO((tree)); ! extern int int_size_in_bytes PROTO((tree)); ! extern tree size_binop PROTO((enum tree_code, tree, tree)); ! extern tree size_int PROTO((unsigned)); ! extern tree round_up PROTO((tree, int)); ! extern tree get_pending_sizes PROTO((void)); /* Type for sizes of data-type. */ *************** *** 984,1045 **** Returns X, except if X is 0 returns Y. */ ! extern tree chainon (); /* Make a new TREE_LIST node from specified PURPOSE, VALUE and CHAIN. */ ! extern tree tree_cons (), perm_tree_cons (), temp_tree_cons (); ! extern tree saveable_tree_cons (), decl_tree_cons (); /* Return the last tree node in a chain. */ ! extern tree tree_last (); /* Reverse the order of elements in a chain, and return the new head. */ ! extern tree nreverse (); ! ! /* Make a copy of a chain of tree nodes. */ - extern tree copy_chain (); - /* Returns the length of a chain of nodes (number of chain pointers to follow before reaching a null pointer). */ ! extern int list_length (); /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0 */ ! extern int integer_zerop (); /* integer_onep (tree x) is nonzero if X is an integer constant of value 1 */ ! extern int integer_onep (); /* integer_all_onesp (tree x) is nonzero if X is an integer constant all of whose significant bits are 1. */ ! extern int integer_all_onesp (); /* integer_pow2p (tree x) is nonzero is X is an integer constant with exactly one bit 1. */ ! extern int integer_pow2p (); ! ! /* type_unsigned_p (tree x) is nonzero if the type X is an unsigned type ! (all of its possible values are >= 0). ! If X is a pointer type, the value is 1. ! If X is a real type, the value is 0. */ - extern int type_unsigned_p (); - /* staticp (tree x) is nonzero if X is a reference to data allocated at a fixed address in memory. */ ! extern int staticp (); /* Gets an error if argument X is not an lvalue. Also returns 1 if X is an lvalue, 0 if not. */ ! extern int lvalue_or_else (); /* save_expr (EXP) returns an expression equivalent to EXP --- 1147,1200 ---- Returns X, except if X is 0 returns Y. */ ! extern tree chainon PROTO((tree, tree)); /* Make a new TREE_LIST node from specified PURPOSE, VALUE and CHAIN. */ ! extern tree tree_cons PROTO((tree, tree, tree)); ! extern tree perm_tree_cons PROTO((tree, tree, tree)); ! extern tree temp_tree_cons PROTO((tree, tree, tree)); ! extern tree saveable_tree_cons PROTO((tree, tree, tree)); ! extern tree decl_tree_cons PROTO((tree, tree, tree)); /* Return the last tree node in a chain. */ ! extern tree tree_last PROTO((tree)); /* Reverse the order of elements in a chain, and return the new head. */ ! extern tree nreverse PROTO((tree)); /* Returns the length of a chain of nodes (number of chain pointers to follow before reaching a null pointer). */ ! extern int list_length PROTO((tree)); /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0 */ ! extern int integer_zerop PROTO((tree)); /* integer_onep (tree x) is nonzero if X is an integer constant of value 1 */ ! extern int integer_onep PROTO((tree)); /* integer_all_onesp (tree x) is nonzero if X is an integer constant all of whose significant bits are 1. */ ! extern int integer_all_onesp PROTO((tree)); /* integer_pow2p (tree x) is nonzero is X is an integer constant with exactly one bit 1. */ ! extern int integer_pow2p PROTO((tree)); /* staticp (tree x) is nonzero if X is a reference to data allocated at a fixed address in memory. */ ! extern int staticp PROTO((tree)); /* Gets an error if argument X is not an lvalue. Also returns 1 if X is an lvalue, 0 if not. */ ! extern int lvalue_or_else PROTO((tree, char *)); /* save_expr (EXP) returns an expression equivalent to EXP *************** *** 1047,1051 **** and only evaluate EXP once. */ ! extern tree save_expr (); /* variable_size (EXP) is like save_expr (EXP) except that it --- 1202,1206 ---- and only evaluate EXP once. */ ! extern tree save_expr PROTO((tree)); /* variable_size (EXP) is like save_expr (EXP) except that it *************** *** 1055,1059 **** belongs to a function parameter. */ ! extern tree variable_size (); /* stabilize_reference (EXP) returns an reference equivalent to EXP --- 1210,1214 ---- belongs to a function parameter. */ ! extern tree variable_size PROTO((tree)); /* stabilize_reference (EXP) returns an reference equivalent to EXP *************** *** 1061,1065 **** and only evaluate the subexpressions once. */ ! extern tree stabilize_reference (); /* Return EXP, stripped of any conversions to wider types --- 1216,1220 ---- and only evaluate the subexpressions once. */ ! extern tree stabilize_reference PROTO((tree)); /* Return EXP, stripped of any conversions to wider types *************** *** 1068,1072 **** If FOR_TYPE is 0, it signifies EXP's type. */ ! extern tree get_unwidened (); /* Return OP or a simpler expression for a narrower value --- 1223,1227 ---- If FOR_TYPE is 0, it signifies EXP's type. */ ! extern tree get_unwidened PROTO((tree, tree)); /* Return OP or a simpler expression for a narrower value *************** *** 1075,1079 **** or 0 if the value should be sign-extended. */ ! extern tree get_narrower (); /* Given MODE and UNSIGNEDP, return a suitable type-tree --- 1230,1234 ---- or 0 if the value should be sign-extended. */ ! extern tree get_narrower PROTO((tree, int *)); /* Given MODE and UNSIGNEDP, return a suitable type-tree *************** *** 1082,1086 **** as the repertoire of available types may vary. */ ! extern tree type_for_mode (); /* Given PRECISION and UNSIGNEDP, return a suitable type-tree --- 1237,1241 ---- as the repertoire of available types may vary. */ ! extern tree type_for_mode PROTO((enum machine_mode, int)); /* Given PRECISION and UNSIGNEDP, return a suitable type-tree *************** *** 1089,1093 **** as the repertoire of available types may vary. */ ! extern tree type_for_size (); /* Given an integer type T, return a type like T but unsigned. --- 1244,1248 ---- as the repertoire of available types may vary. */ ! extern tree type_for_size PROTO((unsigned, int)); /* Given an integer type T, return a type like T but unsigned. *************** *** 1096,1100 **** as the repertoire of available types may vary. */ ! extern tree unsigned_type (); /* Given an integer type T, return a type like T but signed. --- 1251,1255 ---- as the repertoire of available types may vary. */ ! extern tree unsigned_type PROTO((tree)); /* Given an integer type T, return a type like T but signed. *************** *** 1103,1107 **** as the repertoire of available types may vary. */ ! extern tree signed_type (); /* This function must be defined in the language-specific files. --- 1258,1262 ---- as the repertoire of available types may vary. */ ! extern tree signed_type PROTO((tree)); /* This function must be defined in the language-specific files. *************** *** 1109,1117 **** This is defined in a language-specific file. */ ! extern tree maybe_build_cleanup (); ! ! /* Return the floating type node for a given floating machine mode. */ ! ! extern tree get_floating_type (); /* Given an expression EXP that may be a COMPONENT_REF or an ARRAY_REF, --- 1264,1268 ---- This is defined in a language-specific file. */ ! extern tree maybe_build_cleanup PROTO((tree)); /* Given an expression EXP that may be a COMPONENT_REF or an ARRAY_REF, *************** *** 1119,1131 **** and find the ultimate containing object, which is returned. */ ! extern tree get_inner_reference (); /* Return the FUNCTION_DECL which provides this _DECL with its context, or zero if none. */ ! extern tree decl_function_context (); /* Return the RECORD_TYPE or UNION_TYPE which provides this _DECL with its context, or zero if none. */ ! extern tree decl_type_context (); /* Given the FUNCTION_DECL for the current function, --- 1270,1282 ---- and find the ultimate containing object, which is returned. */ ! extern tree get_inner_reference PROTO((tree, int *, int *, tree *, enum machine_mode *, int *, int *)); /* Return the FUNCTION_DECL which provides this _DECL with its context, or zero if none. */ ! extern tree decl_function_context PROTO((tree)); /* Return the RECORD_TYPE or UNION_TYPE which provides this _DECL with its context, or zero if none. */ ! extern tree decl_type_context PROTO((tree)); /* Given the FUNCTION_DECL for the current function, *************** *** 1134,1138 **** for the function's name. */ ! extern char *function_cannot_inline_p (); /* Declare commonly used variables for tree structure. */ --- 1285,1289 ---- for the function's name. */ ! extern char *function_cannot_inline_p PROTO((tree)); /* Declare commonly used variables for tree structure. */ *************** *** 1204,1264 **** extern char *(*decl_printable_name) (); - /* In expmed.c */ - extern tree make_tree (); - /* In stmt.c */ ! extern tree expand_start_stmt_expr (); ! extern tree expand_end_stmt_expr (); ! extern void expand_expr_stmt (), clear_last_expr (); ! extern void expand_label (), expand_goto (), expand_asm (); ! extern void expand_start_cond (), expand_end_cond (); ! extern void expand_start_else (), expand_start_elseif (); ! extern struct nesting *expand_start_loop (); ! extern struct nesting *expand_start_loop_continue_elsewhere (); ! extern void expand_loop_continue_here (); ! extern void expand_end_loop (); ! extern int expand_continue_loop (); ! extern int expand_exit_loop (), expand_exit_loop_if_false (); ! extern int expand_exit_something (); ! ! extern void expand_start_delayed_expr (); ! extern tree expand_end_delayed_expr (); ! extern void expand_emit_delayed_expr (); ! ! extern void expand_null_return (), expand_return (); ! extern void expand_start_bindings (), expand_end_bindings (); ! extern tree last_cleanup_this_contour (); ! extern void expand_start_case (), expand_end_case (); ! extern int pushcase (), pushcase_range (); ! extern void expand_start_function (), expand_end_function (); /* In fold-const.c */ ! extern tree invert_truthvalue (); /* The language front-end must define these functions. */ /* Function of no arguments for initializing lexical scanning. */ ! extern void init_lex (); /* Function of no arguments for initializing the symbol table. */ ! extern void init_decl_processing (); /* Functions called with no arguments at the beginning and end or processing the input source file. */ ! extern void lang_init (); ! extern void lang_finish (); /* Function called with no arguments to parse and compile the input. */ ! extern int yyparse (); /* Function called with option as argument to decode options starting with -f or -W or +. It should return nonzero if it handles the option. */ ! extern int lang_decode_option (); /* Functions for processing symbol declarations. */ /* Function to enter a new lexical scope. Takes one argument: always zero when called from outside the front end. */ ! extern void pushlevel (); /* Function to exit a lexical scope. It returns a BINDING for that scope. Takes three arguments: --- 1355,1417 ---- extern char *(*decl_printable_name) (); /* In stmt.c */ ! extern tree expand_start_stmt_expr PROTO((void)); ! extern tree expand_end_stmt_expr PROTO((tree)); ! extern void expand_expr_stmt PROTO((tree)); ! extern void clear_last_expr PROTO((void)); ! extern void expand_label PROTO((tree)); ! extern void expand_goto PROTO((tree)); ! extern void expand_asm PROTO((tree)); ! extern void expand_start_cond PROTO((tree, int)); ! extern void expand_end_cond PROTO((void)); ! extern void expand_start_else PROTO((void)); ! extern void expand_start_elseif PROTO((tree)); ! extern struct nesting *expand_start_loop PROTO((int)); ! extern struct nesting *expand_start_loop_continue_elsewhere PROTO((int)); ! extern void expand_loop_continue_here PROTO((void)); ! extern void expand_end_loop PROTO((void)); ! extern int expand_continue_loop PROTO((struct nesting *)); ! extern int expand_exit_loop PROTO((struct nesting *)); ! extern int expand_exit_loop_if_false PROTO((struct nesting *, tree)); ! extern int expand_exit_something PROTO((void)); ! ! extern void expand_null_return PROTO((void)); ! extern void expand_return PROTO((tree)); ! extern void expand_start_bindings PROTO((int)); ! extern void expand_end_bindings PROTO((tree, int, int)); ! extern tree last_cleanup_this_contour PROTO((void)); ! extern void expand_start_case PROTO((int, tree, tree, char *)); ! extern void expand_end_case PROTO((tree)); ! extern int pushcase PROTO((tree, tree, tree *)); ! extern int pushcase_range PROTO((tree, tree, tree, tree *)); /* In fold-const.c */ ! extern tree invert_truthvalue PROTO((tree)); /* The language front-end must define these functions. */ /* Function of no arguments for initializing lexical scanning. */ ! extern void init_lex PROTO((void)); /* Function of no arguments for initializing the symbol table. */ ! extern void init_decl_processing PROTO((void)); /* Functions called with no arguments at the beginning and end or processing the input source file. */ ! extern void lang_init PROTO((void)); ! extern void lang_finish PROTO((void)); /* Function called with no arguments to parse and compile the input. */ ! extern int yyparse PROTO((void)); /* Function called with option as argument to decode options starting with -f or -W or +. It should return nonzero if it handles the option. */ ! extern int lang_decode_option PROTO((char *)); /* Functions for processing symbol declarations. */ /* Function to enter a new lexical scope. Takes one argument: always zero when called from outside the front end. */ ! extern void pushlevel PROTO((int)); /* Function to exit a lexical scope. It returns a BINDING for that scope. Takes three arguments: *************** *** 1266,1277 **** REVERSE -- reverse the order of decls before returning them. FUNCTIONBODY -- nonzero if this level is the body of a function. */ ! extern tree poplevel (); /* Function to add a decl to the current scope level. Takes one argument, a decl to add. Returns that decl, or, if the same symbol is already declared, may return a different decl for that name. */ ! extern tree pushdecl (); /* Function to return the chain of decls so far in the current scope level. */ ! extern tree getdecls (); /* Function to return the chain of structure tags in the current scope level. */ ! extern tree gettags (); --- 1419,1432 ---- REVERSE -- reverse the order of decls before returning them. FUNCTIONBODY -- nonzero if this level is the body of a function. */ ! extern tree poplevel PROTO((int, int, int)); ! /* Set the BLOCK node for the current scope level. */ ! extern void set_block PROTO((tree)); /* Function to add a decl to the current scope level. Takes one argument, a decl to add. Returns that decl, or, if the same symbol is already declared, may return a different decl for that name. */ ! extern tree pushdecl PROTO((tree)); /* Function to return the chain of decls so far in the current scope level. */ ! extern tree getdecls PROTO((void)); /* Function to return the chain of structure tags in the current scope level. */ ! extern tree gettags PROTO((void)); diff -rc2N gcc-2.2.2/unroll.c gcc-2.3.1/unroll.c *** gcc-2.2.2/unroll.c Wed May 27 18:10:02 1992 --- gcc-2.3.1/unroll.c Tue Oct 6 20:19:34 1992 *************** *** 784,788 **** diff = expand_binop (mode, sub_optab, copy_rtx (final_value), ! copy_rtx (initial_value), 0, 0, OPTAB_LIB_WIDEN); --- 784,788 ---- diff = expand_binop (mode, sub_optab, copy_rtx (final_value), ! copy_rtx (initial_value), NULL_RTX, 0, OPTAB_LIB_WIDEN); *************** *** 790,796 **** and instruction. */ diff = expand_binop (GET_MODE (diff), and_optab, diff, ! gen_rtx (CONST_INT, VOIDmode, ! unroll_number * abs_inc - 1), ! 0, 0, OPTAB_LIB_WIDEN); /* Now emit a sequence of branches to jump to the proper precond --- 790,795 ---- and instruction. */ diff = expand_binop (GET_MODE (diff), and_optab, diff, ! GEN_INT (unroll_number * abs_inc - 1), ! NULL_RTX, 0, OPTAB_LIB_WIDEN); /* Now emit a sequence of branches to jump to the proper precond *************** *** 827,833 **** cmp_const = i; ! emit_cmp_insn (diff, gen_rtx (CONST_INT, VOIDmode, ! abs_inc * cmp_const), ! EQ, 0, mode, 0, 0); if (i == 0) --- 826,831 ---- cmp_const = i; ! emit_cmp_insn (diff, GEN_INT (abs_inc * cmp_const), ! EQ, NULL_RTX, mode, 0, 0); if (i == 0) *************** *** 859,864 **** cmp_const = abs_inc * (unroll_number - 1) + 1; ! emit_cmp_insn (diff, gen_rtx (CONST_INT, VOIDmode, cmp_const), ! EQ, 0, mode, 0, 0); if (neg_inc) --- 857,862 ---- cmp_const = abs_inc * (unroll_number - 1) + 1; ! emit_cmp_insn (diff, GEN_INT (cmp_const), EQ, NULL_RTX, ! mode, 0, 0); if (neg_inc) *************** *** 1138,1154 **** if (exit_label) emit_label_after (exit_label, loop_end); - - /* If debugging, we must replicate the tree nodes corresponding to the blocks - inside the loop, so that the original one to one mapping will remain. */ - - if (write_symbols != NO_DEBUG) - { - int copies = unroll_number; - - if (loop_preconditioned) - copies += unroll_number - 1; - - unroll_block_trees (uid_loop_num[INSN_UID (loop_start)], copies); - } } --- 1136,1139 ---- *************** *** 1179,1183 **** *initial_value = const0_rtx; *increment = const1_rtx; ! *final_value = gen_rtx (CONST_INT, VOIDmode, loop_n_iterations); if (loop_dump_stream) --- 1164,1168 ---- *initial_value = const0_rtx; *increment = const1_rtx; ! *final_value = GEN_INT (loop_n_iterations); if (loop_dump_stream) *************** *** 1389,1392 **** --- 1374,1378 ---- rtx copy_start, copy_end; struct inline_remap *map; + rtx exit_label; int last_iteration; enum unroll_types unroll_type; *************** *** 1584,1589 **** splittable_regs[regno] ! = gen_rtx (CONST_INT, VOIDmode, ! INTVAL (giv_inc) + INTVAL (splittable_regs[regno])); giv_inc = splittable_regs[regno]; --- 1570,1574 ---- splittable_regs[regno] ! = GEN_INT (INTVAL (giv_inc) + INTVAL (splittable_regs[regno])); giv_inc = splittable_regs[regno]; *************** *** 1675,1704 **** case to be a branch past the end of the loop, and the original jump label case to fall_through. */ - - int fall_through; - /* Never map the label in this case. */ pattern = copy_rtx (PATTERN (insn)); ! ! /* Assume a conditional branch, since the code above ! does not let unconditional branches be copied. */ ! if (! condjump_p (insn)) ! abort (); ! fall_through ! = (XEXP (SET_SRC (PATTERN (insn)), 2) == pc_rtx) + 1; ! /* Set the fall through case to the exit label. Must ! create a new label_ref since they can't be shared. */ ! XEXP (SET_SRC (pattern), fall_through) ! = gen_rtx (LABEL_REF, VOIDmode, exit_label); ! ! /* Set the original branch case to fall through. */ ! XEXP (SET_SRC (pattern), 3 - fall_through) ! = pc_rtx; } else ! pattern = copy_rtx_and_substitute (PATTERN (insn), map); ! ! copy = emit_jump_insn (pattern); #ifdef HAVE_cc0 --- 1660,1678 ---- case to be a branch past the end of the loop, and the original jump label case to fall_through. */ /* Never map the label in this case. */ + pattern = copy_rtx (PATTERN (insn)); ! copy = emit_jump_insn (pattern); ! if (! invert_exp (pattern, copy) ! || ! redirect_exp (&pattern, JUMP_LABEL (insn), ! exit_label, copy)) ! abort (); } else ! { ! pattern = copy_rtx_and_substitute (PATTERN (insn), map); ! copy = emit_jump_insn (pattern); ! } #ifdef HAVE_cc0 *************** *** 1713,1716 **** --- 1687,1692 ---- if (JUMP_LABEL (insn)) { + rtx label = 0; + /* Can't use the label_map for every insn, since this may be the backward branch, and hence the label was not mapped. */ *************** *** 1719,1733 **** tem = SET_SRC (pattern); if (GET_CODE (tem) == LABEL_REF) ! JUMP_LABEL (copy) = XEXP (tem, 0); else if (GET_CODE (tem) == IF_THEN_ELSE) { if (XEXP (tem, 1) != pc_rtx) ! JUMP_LABEL (copy) = XEXP (XEXP (tem, 1), 0); else ! JUMP_LABEL (copy) = XEXP (XEXP (tem, 2), 0); } - else - abort (); } else { --- 1695,1710 ---- tem = SET_SRC (pattern); if (GET_CODE (tem) == LABEL_REF) ! label = XEXP (tem, 0); else if (GET_CODE (tem) == IF_THEN_ELSE) { if (XEXP (tem, 1) != pc_rtx) ! label = XEXP (XEXP (tem, 1), 0); else ! label = XEXP (XEXP (tem, 2), 0); } } + + if (label && GET_CODE (label) == CODE_LABEL) + JUMP_LABEL (copy) = label; else { *************** *** 1811,1815 **** case NOTE: ! if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED) copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn)); --- 1788,1797 ---- case NOTE: ! /* VTOP notes are valid only before the loop exit test. If placed ! anywhere else, loop may generate bad code. */ ! ! if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED ! && (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP ! || (last_iteration && unroll_type != UNROLL_COMPLETELY))) copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn)); *************** *** 2195,2198 **** --- 2177,2181 ---- { struct iv_class *bl; + struct induction *v; rtx increment, tem; rtx biv_final_value; *************** *** 2232,2235 **** --- 2215,2227 ---- biv_splittable = 0; + /* If any of the insns setting the BIV don't do so with a simple + PLUS, we don't know how to split it. */ + for (v = bl->biv; biv_splittable && v; v = v->next_iv) + if ((tem = single_set (v->insn)) == 0 + || GET_CODE (SET_DEST (tem)) != REG + || REGNO (SET_DEST (tem)) != bl->regno + || GET_CODE (SET_SRC (tem)) != PLUS) + biv_splittable = 0; + /* If final value is non-zero, then must emit an instruction which sets the value of the biv to the proper value. This is done after *************** *** 2392,2396 **** sequence, in which case the first insn setting the pseudo is the first insn of the shift/add sequence. */ ! && (! (tem = find_reg_note (v->insn, REG_RETVAL, 0)) || (regno_first_uid[REGNO (v->dest_reg)] != INSN_UID (XEXP (tem, 0))))) --- 2384,2388 ---- sequence, in which case the first insn setting the pseudo is the first insn of the shift/add sequence. */ ! && (! (tem = find_reg_note (v->insn, REG_RETVAL, NULL_RTX)) || (regno_first_uid[REGNO (v->dest_reg)] != INSN_UID (XEXP (tem, 0))))) *************** *** 2431,2439 **** if (unroll_type == UNROLL_COMPLETELY) ! /* It is not safe to use bl->initial_value here, because it may not ! be invariant. It is safe to use the initial value stored in ! the splittable_regs array. */ ! value = fold_rtx_mult_add (v->mult_val, splittable_regs[bl->regno], ! v->add_val, v->mode); else value = const0_rtx; --- 2423,2451 ---- if (unroll_type == UNROLL_COMPLETELY) ! { ! /* It is not safe to use bl->initial_value here, because it may not ! be invariant. It is safe to use the initial value stored in ! the splittable_regs array if it is set. In rare cases, it won't ! be set, so then we do exactly the same thing as ! find_splittable_regs does to get a safe value. */ ! rtx biv_initial_value; ! ! if (splittable_regs[bl->regno]) ! biv_initial_value = splittable_regs[bl->regno]; ! else if (GET_CODE (bl->initial_value) != REG ! || (REGNO (bl->initial_value) != bl->regno ! && REGNO (bl->initial_value) >= FIRST_PSEUDO_REGISTER)) ! biv_initial_value = bl->initial_value; ! else ! { ! rtx tem = gen_reg_rtx (bl->biv->mode); ! ! emit_insn_before (gen_move_insn (tem, bl->biv->src_reg), ! loop_start); ! biv_initial_value = tem; ! } ! value = fold_rtx_mult_add (v->mult_val, biv_initial_value, ! v->add_val, v->mode); ! } else value = const0_rtx; *************** *** 2517,2522 **** address resulting from loop unrolling, if one fails, then can't do const elim here. */ ! if (memory_address_p (v->mode, v->dest_reg) ! && memory_address_p (v->mode, plus_constant (v->dest_reg, INTVAL (giv_inc) --- 2529,2534 ---- address resulting from loop unrolling, if one fails, then can't do const elim here. */ ! if (memory_address_p (v->mem_mode, v->dest_reg) ! && memory_address_p (v->mem_mode, plus_constant (v->dest_reg, INTVAL (giv_inc) *************** *** 2544,2549 **** unrolled copy of the address is not a valid address. */ if (v->dest_reg == tem ! && (! memory_address_p (v->mode, v->dest_reg) ! || ! memory_address_p (v->mode, plus_constant (v->dest_reg, INTVAL (giv_inc) --- 2556,2561 ---- unrolled copy of the address is not a valid address. */ if (v->dest_reg == tem ! && (! memory_address_p (v->mem_mode, v->dest_reg) ! || ! memory_address_p (v->mem_mode, plus_constant (v->dest_reg, INTVAL (giv_inc) *************** *** 2565,2569 **** copy_rtx (v->new_reg)), loop_start); ! if (! recog_memoized (PREV_INSN (loop_start))) { delete_insn (PREV_INSN (loop_start)); --- 2577,2581 ---- copy_rtx (v->new_reg)), loop_start); ! if (recog_memoized (PREV_INSN (loop_start)) < 0) { delete_insn (PREV_INSN (loop_start)); *************** *** 2581,2586 **** /* Check the resulting address for validity, and fail if the resulting address would be illegal. */ ! if (! memory_address_p (v->mode, v->dest_reg) ! || ! memory_address_p (v->mode, plus_constant (v->dest_reg, INTVAL (giv_inc) * --- 2593,2598 ---- /* Check the resulting address for validity, and fail if the resulting address would be illegal. */ ! if (! memory_address_p (v->mem_mode, v->dest_reg) ! || ! memory_address_p (v->mem_mode, plus_constant (v->dest_reg, INTVAL (giv_inc) * *************** *** 2786,2791 **** tem = gen_reg_rtx (bl->biv->mode); ! emit_iv_add_mult (increment, ! gen_rtx (CONST_INT, VOIDmode, loop_n_iterations), bl->initial_value, tem, NEXT_INSN (loop_end)); --- 2798,2802 ---- tem = gen_reg_rtx (bl->biv->mode); ! emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), bl->initial_value, tem, NEXT_INSN (loop_end)); *************** *** 2821,2825 **** { struct iv_class *bl; ! rtx reg, insn, pattern; rtx increment, tem; enum rtx_code code; --- 2832,2836 ---- { struct iv_class *bl; ! rtx insn; rtx increment, tem; enum rtx_code code; *************** *** 2878,2883 **** /* Put the final biv value in tem. */ tem = gen_reg_rtx (bl->biv->mode); ! emit_iv_add_mult (increment, ! gen_rtx (CONST_INT, VOIDmode, loop_n_iterations), bl->initial_value, tem, insert_before); --- 2889,2893 ---- /* Put the final biv value in tem. */ tem = gen_reg_rtx (bl->biv->mode); ! emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), bl->initial_value, tem, insert_before); *************** *** 2886,2914 **** insn = NEXT_INSN (insn)) { ! if (GET_CODE (insn) == INSN ! && GET_CODE (PATTERN (insn)) == SET ! && SET_DEST (PATTERN (insn)) == v->src_reg) ! { ! pattern = PATTERN (insn); ! if (GET_CODE (SET_SRC (pattern)) != PLUS) ! { ! /* Sometimes a biv is computed in a temp reg, ! and then copied into the biv reg. */ ! pattern = PATTERN (PREV_INSN (insn)); ! if (GET_CODE (SET_SRC (pattern)) != PLUS) ! abort (); ! } ! if (GET_CODE (XEXP (SET_SRC (pattern), 0)) != REG ! || REGNO (XEXP (SET_SRC (pattern), 0)) != bl->regno) ! abort (); ! ! start_sequence (); ! tem = expand_binop (GET_MODE (tem), sub_optab, tem, ! XEXP (SET_SRC (pattern), 1), 0, 0, ! OPTAB_LIB_WIDEN); ! seq = gen_sequence (); ! end_sequence (); ! emit_insn_before (seq, insert_before); ! } } --- 2896,2912 ---- insn = NEXT_INSN (insn)) { ! struct induction *biv; ! ! for (biv = bl->biv; biv; biv = biv->next_iv) ! if (biv->insn == insn) ! { ! start_sequence (); ! tem = expand_binop (GET_MODE (tem), sub_optab, tem, ! biv->add_val, NULL_RTX, 0, ! OPTAB_LIB_WIDEN); ! seq = gen_sequence (); ! end_sequence (); ! emit_insn_before (seq, insert_before); ! } } *************** *** 2948,2952 **** iterations if it can be calculated, otherwise returns zero. */ ! unsigned long loop_iterations (loop_start, loop_end) rtx loop_start, loop_end; --- 2946,2950 ---- iterations if it can be calculated, otherwise returns zero. */ ! unsigned HOST_WIDE_INT loop_iterations (loop_start, loop_end) rtx loop_start, loop_end; *************** *** 2955,2959 **** rtx iteration_var, initial_value, increment, final_value; enum rtx_code comparison_code; ! int i, increment_dir; int unsigned_compare, compare_dir, final_larger; unsigned long tempu; --- 2953,2958 ---- rtx iteration_var, initial_value, increment, final_value; enum rtx_code comparison_code; ! HOST_WIDE_INT i; ! int increment_dir; int unsigned_compare, compare_dir, final_larger; unsigned long tempu; *************** *** 3045,3049 **** && (SET_DEST (set) == comparison_value)) { ! rtx note = find_reg_note (insn, REG_EQUAL, 0); if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST) --- 3044,3048 ---- && (SET_DEST (set) == comparison_value)) { ! rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX); if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST) *************** *** 3095,3103 **** if (unsigned_compare) final_larger ! = ((unsigned) INTVAL (final_value) > (unsigned) INTVAL (initial_value)) - ! ((unsigned) INTVAL (final_value) < (unsigned) INTVAL (initial_value)); else ! final_larger = (INTVAL (final_value) > INTVAL (initial_value)) - ! (INTVAL (final_value) < INTVAL (initial_value)); if (INTVAL (increment) > 0) --- 3094,3104 ---- if (unsigned_compare) final_larger ! = ((unsigned HOST_WIDE_INT) INTVAL (final_value) ! > (unsigned HOST_WIDE_INT) INTVAL (initial_value)) ! - ((unsigned HOST_WIDE_INT) INTVAL (final_value) ! < (unsigned HOST_WIDE_INT) INTVAL (initial_value)); else ! final_larger = (INTVAL (final_value) > INTVAL (initial_value)) ! - (INTVAL (final_value) < INTVAL (initial_value)); if (INTVAL (increment) > 0) diff -rc2N gcc-2.2.2/va-alpha.h gcc-2.3.1/va-alpha.h *** gcc-2.2.2/va-alpha.h --- gcc-2.3.1/va-alpha.h Fri Oct 9 07:27:31 1992 *************** *** 0 **** --- 1,186 ---- + /* GNU C varargs and stdargs support for the DEC Alpha. */ + + /* Note: We must use the name __builtin_savregs. GCC attaches special + significance to that name. In particular, regardless of where in a + function __builtin_saveregs is called, GCC moves the call up to the + very start of the function. */ + + /* Define __gnuc_va_list. */ + + #ifndef __GNUC_VA_LIST + #define __GNUC_VA_LIST + + typedef struct { + long __va_arg; /* Current argument number. */ + long *__va_stack; /* Start of arguments on stack */ + long *__va_iregs; /* Integer parameter registers ($16-$21) */ + long *__va_fregs; /* FP parameter registers ($f16-$f21) */ + } __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 va_list __gnuc_va_list + #define _VA_LIST + #define _VA_LIST_ + + #if !defined(_STDARG_H) + + /* varargs support */ + #define va_alist __builtin_va_alist + #define va_dcl + #define va_start(pvar) ((pvar) = * (__gnuc_va_list *) __builtin_saveregs ()) + + #else /* STDARG.H */ + + /* ANSI alternative. */ + + #define va_start(pvar, firstarg) \ + ((pvar) = *(__gnuc_va_list *) __builtin_saveregs ()) + + #endif /* _STDARG_H */ + + #define va_end(__va) + + /* Values returned by __builtin_classify_type. */ + + enum { + __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 + }; + + /* Note that parameters are always aligned at least to a word boundary + (when passed) regardless of what GCC's __alignof__ operator says. */ + + /* Avoid errors if compiling GCC v2 with GCC v1. */ + #if __GNUC__ == 1 + #define __extension__ + #endif + + /* Get the rounded number of words of a type. */ + + #define __va_nwords(__type) \ + ((sizeof (__type) + sizeof (long) - 1) / sizeof (long)) + + #define va_arg(__va, __type) \ + __extension__ \ + (* (__type *) \ + ({ \ + register void *__rv; /* result value */ \ + switch (__builtin_classify_type (* (__type *) 0)) \ + { \ + case __real_type_class: \ + \ + /* Get a pointer to the value. If we want a float instead of \ + a double, we have to make one and point to it instead. */ \ + \ + __rv = (void *) & ((__va).__va_arg < 6 \ + ? (__va).__va_fregs[(__va).__va_arg] \ + : (__va).__va_stack[(__va).__va_arg - 6]); \ + \ + if (sizeof (__type) == sizeof (float)) \ + { \ + float __rf = * ((double *) __rv); \ + \ + __rv = (void *) &__rf; \ + } \ + \ + break; \ + \ + case __void_type_class: \ + case __integer_type_class: \ + case __char_type_class: \ + case __enumeral_type_class: \ + case __boolean_type_class: \ + case __pointer_type_class: \ + case __reference_type_class: \ + case __offset_type_class: \ + case __record_type_class: \ + case __union_type_class: \ + \ + /* Force this on the stack if it's alignment isn't right. */ \ + \ + if ((__va).__va_arg < 6) \ + switch (sizeof (__type)) \ + { \ + case sizeof (char): \ + break; \ + case sizeof (short): \ + if (__alignof__ (__type) < sizeof (short)) \ + (__va).__va_arg = 6; \ + break; \ + case 3: \ + case sizeof (int): \ + if (__alignof__ (__type) < sizeof (int)) \ + (__va).__va_arg = 6; \ + break; \ + default: \ + if (__alignof__ (__type) < sizeof (long)) \ + (__va).__va_arg = 6; \ + break; \ + } \ + \ + /* If this object is only one word long, just get it. If it is \ + longer, we need to worry about the possibility that it is \ + passed both in registers and in memory. */ \ + \ + if (sizeof (__type) <= sizeof (long) \ + || (__va).__va_arg >= 6 \ + || (__va).__va_arg + __va_nwords (__type) < 6) \ + __rv = (void *) & ((__va).__va_arg < 6 \ + ? (__va).__va_iregs[(__va).__va_arg] \ + : (__va).__va_stack[(__va).__va_arg - 6]); \ + else \ + { \ + long __obj[__va_nwords (__type)]; \ + int __i; \ + \ + for (__i = 0; __i < __va_nwords (__type); __i++) \ + __obj[__i] = ((__va).__va_arg < 6 \ + ? (__va).__va_iregs[(__va).__va_arg] \ + : (__va).__va_stack[(__va).__va_arg - 6]); \ + \ + __rv = (void *) &__obj[0]; \ + } \ + break; \ + \ + case __complex_type_class: \ + case __function_type_class: \ + case __method_type_class: \ + case __array_type_class: \ + case __string_type_class: \ + case __set_type_class: \ + case __file_type_class: \ + case __lang_type_class: \ + case __no_type_class: \ + default: \ + abort (); \ + } \ + \ + (__va).__va_arg += __va_nwords (__type); \ + \ + __rv; \ + })) + + #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ + diff -rc2N gcc-2.2.2/va-i860.h gcc-2.3.1/va-i860.h *** gcc-2.2.2/va-i860.h Fri Jan 31 01:51:09 1992 --- gcc-2.3.1/va-i860.h Thu Oct 8 14:22:01 1992 *************** *** 4,29 **** very start of the function. */ - #if !defined(_STDARG_H) - - /* varargs support */ - - #define va_alist __builtin_va_alist - - #define va_dcl - - #define va_start(pvar) ((pvar) = * (va_list *) __builtin_saveregs ()) ! #else /* ANSI stdarg.h */ ! /* Note that CUMULATIVE_ARGS elements are measured in bytes on the i860, ! so we divide by 4 to get # of registers. */ ! #define va_start(pvar, firstarg) \ ! ((pvar) = *(va_list *) __builtin_saveregs (), \ ! (pvar).__ireg_used = __builtin_args_info (0) / 4, \ ! (pvar).__freg_used = __builtin_args_info (1) / 4, \ ! (pvar).__mem_ptr = __builtin_next_arg ()) ! #endif /* !defined(_STDARG_H) ... varargs support */ - typedef union { float __freg[8]; --- 4,13 ---- very start of the function. */ ! /* Define __gnuc_va_list. */ ! #ifndef __GNUC_VA_LIST ! #define __GNUC_VA_LIST typedef union { float __freg[8]; *************** *** 32,36 **** typedef struct { ! #ifdef __SVR4__ __f_regs __float_regs; long __ireg[12]; #else /* pre-SVR4 */ --- 16,20 ---- typedef struct { ! #if defined (__SVR4__) || defined (__svr4__) || defined (__alliant__) __f_regs __float_regs; long __ireg[12]; #else /* pre-SVR4 */ *************** *** 39,48 **** } __va_saved_regs; - #ifndef _VA_LIST - #define _VA_LIST - #define __GNU_VA_LIST /* Field names were properly prefixed with `__'. */ - typedef struct { ! #ifdef __SVR4__ unsigned __ireg_used; /* How many int regs consumed 'til now? */ unsigned __freg_used; /* How many flt regs consumed 'til now? */ --- 23,28 ---- } __va_saved_regs; typedef struct { ! #if defined(__SVR4__) || defined(__alliant__) unsigned __ireg_used; /* How many int regs consumed 'til now? */ unsigned __freg_used; /* How many flt regs consumed 'til now? */ *************** *** 55,62 **** unsigned __freg_used; /* How many flt regs consumed 'til now? */ #endif ! } va_list; ! #endif /* !defined(_VA_LIST) */ #define va_end(__va) --- 35,66 ---- unsigned __freg_used; /* How many flt regs consumed 'til now? */ #endif ! } __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) + #if !defined(_STDARG_H) + + /* varargs support */ + #define va_alist __builtin_va_alist + #define va_dcl + #define va_start(pvar) ((pvar) = * (__gnuc_va_list *) __builtin_saveregs ()) + + #else /* STDARG.H */ + + /* ANSI alternative. */ + /* Note that CUMULATIVE_ARGS elements are measured in bytes on the i860, + so we divide by 4 to get # of registers. */ + #define va_start(pvar, firstarg) \ + ((pvar) = *(__gnuc_va_list *) __builtin_saveregs (), \ + (pvar).__ireg_used = __builtin_args_info (0) / 4, \ + (pvar).__freg_used = __builtin_args_info (1) / 4, \ + (pvar).__mem_ptr = __builtin_next_arg ()) + + #endif /* _STDARG_H */ + + void va_end (__gnuc_va_list); /* Defined in libgcc.a */ #define va_end(__va) *************** *** 89,93 **** #define __NUM_PARM_IREGS 12 ! #define __savereg(__va) ((__va_saved_regs *) (__va.__reg_base)) /* This macro works both for SVR4 and pre-SVR4 environments. */ --- 93,97 ---- #define __NUM_PARM_IREGS 12 ! #define __savereg(__va) ((__va_saved_regs *) ((__va).__reg_base)) /* This macro works both for SVR4 and pre-SVR4 environments. */ *************** *** 98,101 **** --- 102,106 ---- /* Make allowances here for adding 128-bit (long double) floats someday. */ + #if 0 /* What was this for? */ #ifndef __GNU_VA_LIST #define __ireg_used ireg_used *************** *** 104,107 **** --- 109,113 ---- #define __reg_base reg_base #endif + #endif /* 0 */ /* Avoid errors if compiling GCC v2 with GCC v1. */ *************** *** 123,139 **** case sizeof (float): \ case sizeof (double): \ ! if (__va.__freg_used < __NUM_PARM_FREGS - 1) \ { \ ! if ((__va.__freg_used & 1) != 0) \ ! __va.__freg_used++; /* skip odd */ \ ! __rv = &__savereg(__va)->__float_regs.__freg[__va.__freg_used];\ ! __va.__freg_used += 2; \ } \ else \ { \ ! if ((((unsigned) __va.__mem_ptr) & (sizeof(double)-1)) != 0) \ ! __va.__mem_ptr++; /* skip odd */ \ ! __rv = __va.__mem_ptr; \ ! __va.__mem_ptr += 2; \ } \ if (sizeof (__type) == sizeof (float)) \ --- 129,145 ---- case sizeof (float): \ case sizeof (double): \ ! if ((__va).__freg_used < __NUM_PARM_FREGS - 1) \ { \ ! if (((__va).__freg_used & 1) != 0) \ ! (__va).__freg_used++; /* skip odd */ \ ! __rv = &__savereg((__va))->__float_regs.__freg[(__va).__freg_used];\ ! (__va).__freg_used += 2; \ } \ else \ { \ ! if ((((unsigned) (__va).__mem_ptr) & (sizeof(double)-1)) != 0) \ ! (__va).__mem_ptr++; /* skip odd */ \ ! __rv = (__va).__mem_ptr; \ ! (__va).__mem_ptr += 2; \ } \ if (sizeof (__type) == sizeof (float)) \ *************** *** 157,169 **** if (sizeof (__type) <= 4) \ { \ ! __rv = (__va.__ireg_used < __NUM_PARM_IREGS \ ! ? (&__savereg(__va)->__ireg[__va.__ireg_used++]) \ ! : __va.__mem_ptr++); \ break; \ } \ ! else if (__va.__ireg_used + sizeof (__type) / 4 <= __NUM_PARM_IREGS) \ { \ ! __rv = &__savereg(__va)->__ireg[__va.__ireg_used]; \ ! __va.__ireg_used += sizeof (__type) / 4; \ break; \ } \ --- 163,175 ---- if (sizeof (__type) <= 4) \ { \ ! __rv = ((__va).__ireg_used < __NUM_PARM_IREGS \ ! ? (&__savereg((__va))->__ireg[(__va).__ireg_used++]) \ ! : (__va).__mem_ptr++); \ break; \ } \ ! else if ((__va).__ireg_used + sizeof (__type) / 4 <= __NUM_PARM_IREGS) \ { \ ! __rv = &__savereg((__va))->__ireg[(__va).__ireg_used]; \ ! (__va).__ireg_used += sizeof (__type) / 4; \ break; \ } \ *************** *** 174,182 **** ? sizeof (long) \ : __alignof__ (__type)); \ ! __va.__mem_ptr \ = (long *) \ ! ((((unsigned) __va.__mem_ptr) + (__align-1)) & ~(__align-1)); \ ! __rv = __va.__mem_ptr; \ ! __va.__mem_ptr \ += ((sizeof (__type) + sizeof (long) - 1) / sizeof (long)); \ break; \ --- 180,188 ---- ? sizeof (long) \ : __alignof__ (__type)); \ ! (__va).__mem_ptr \ = (long *) \ ! ((((unsigned) (__va).__mem_ptr) + (__align-1)) & ~(__align-1)); \ ! __rv = (__va).__mem_ptr; \ ! (__va).__mem_ptr \ += ((sizeof (__type) + sizeof (long) - 1) / sizeof (long)); \ break; \ *************** *** 195,197 **** --- 201,205 ---- __rv; \ })) + + #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff -rc2N gcc-2.2.2/va-i960.h gcc-2.3.1/va-i960.h *** gcc-2.2.2/va-i960.h Tue May 26 00:05:00 1992 --- gcc-2.3.1/va-i960.h Fri Sep 25 01:41:00 1992 *************** *** 1,4 **** --- 1,17 ---- /* GNU C varargs support for the Intel 80960. */ + /* Define __gnuc_va_list. */ + + #ifndef __GNUC_VA_LIST + #define __GNUC_VA_LIST + /* The first element is the address of the first argument. + The second element is the number of bytes skipped past so far. */ + typedef unsigned __gnuc_va_list[2]; + #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. */ *************** *** 10,17 **** #endif - /* The first element is the address of the first argument. - The second element is the number of bytes skipped past so far. */ - typedef unsigned va_list[2]; - /* The stack size of the type t. */ #define __vsiz(T) (((sizeof (T) + 3) / 4) * 4) --- 23,26 ---- *************** *** 23,28 **** #ifdef _STDARG_H ! #define va_start(AP, LASTARG) ((AP)[1] = 0, \ ! *(AP) = (unsigned) __builtin_next_arg ()) #else --- 32,39 ---- #ifdef _STDARG_H ! #define va_start(AP, LASTARG) \ ! __extension__ \ ! ({ __asm__ ("st g14,%0" : "=m" (*(AP))); \ ! (AP)[1] = (unsigned) __builtin_next_arg () - *AP; }) #else *************** *** 32,35 **** --- 43,48 ---- #endif + /* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ #define va_arg(AP, T) \ ( \ *************** *** 40,45 **** ), \ \ ! *((T *) ((char *) *(AP) + (AP)[1] - __vsiz (T))) \ ) #define va_end(AP) --- 53,62 ---- ), \ \ ! *((T *) (void *) ((char *) *(AP) + (AP)[1] - __vsiz (T))) \ ) + void va_end (__gnuc_va_list); /* Defined in libgcc.a */ #define va_end(AP) + + #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ + diff -rc2N gcc-2.2.2/va-m88k.h gcc-2.3.1/va-m88k.h *** gcc-2.2.2/va-m88k.h Mon Dec 23 22:42:25 1991 --- gcc-2.3.1/va-m88k.h Tue Sep 15 01:03:39 1992 *************** *** 1,8 **** - /* This file contains changes made by Data General, December 1989. */ /* GNU C varargs support for the Motorola 88100 */ ! #ifndef __INT_VARARGS_H /* Prevent multiple inclusions of this file */ ! #define __INT_VARARGS_H /* and _int_varargs.h under DG/UX */ typedef struct { --- 1,9 ---- /* GNU C varargs support for the Motorola 88100 */ ! /* Define __gnuc_va_list. */ + #ifndef __GNUC_VA_LIST + #define __GNUC_VA_LIST + typedef struct { *************** *** 10,24 **** int *__va_stk; /* start of args passed on stack */ int *__va_reg; /* start of args passed in regs */ ! } va_list; ! #else ! #undef __va_size ! #undef __va_reg_p ! #endif /* __INT_VARARGS_H */ #ifdef _STDARG_H /* stdarg.h support */ #if __GNUC__ > 1 /* GCC 2.0 and beyond */ ! #define va_start(AP,LASTARG) ((AP) = *(va_list *)__builtin_saveregs()) #else #define va_start(AP,LASTARG) \ --- 11,25 ---- int *__va_stk; /* start of args passed on stack */ int *__va_reg; /* start of args passed in regs */ ! } __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 /* stdarg.h support */ #if __GNUC__ > 1 /* GCC 2.0 and beyond */ ! #define va_start(AP,LASTARG) ((AP) = *(__gnuc_va_list *)__builtin_saveregs()) #else #define va_start(AP,LASTARG) \ *************** *** 31,35 **** #if __GNUC__ > 1 /* GCC 2.0 and beyond */ ! #define va_start(AP) ((AP) = *(va_list *)__builtin_saveregs()) #else #define va_start(AP) \ --- 32,36 ---- #if __GNUC__ > 1 /* GCC 2.0 and beyond */ ! #define va_start(AP) ((AP) = *(__gnuc_va_list *)__builtin_saveregs()) #else #define va_start(AP) \ *************** *** 43,46 **** --- 44,61 ---- #endif /* _STDARG_H */ + /* Avoid trouble between this file and _int_varargs.h under DG/UX. This file + can be included by and others and provides definitions of + __va_size and __va_reg_p and a va_list typedef. Avoid defining va_list + again with _VA_LIST. */ + #ifdef __INT_VARARGS_H + #undef __va_size + #undef __va_reg_p + #define __gnuc_va_list va_list + #define _VA_LIST + #else + /* Similarly, if this gets included first, do nothing in _int_varargs.h. */ + #define __INT_VARARGS_H + #endif + #define __va_reg_p(TYPE) \ (__builtin_classify_type(*(TYPE *)0) < 12 \ *************** *** 49,59 **** #define __va_size(TYPE) ((sizeof(TYPE) + 3) >> 2) ! #define va_arg(AP,TYPE) \ ( (AP).__va_arg = (((AP).__va_arg + (1 << (__alignof__(TYPE) >> 3)) - 1) \ ! & ~((1 << (__alignof__(TYPE) >> 3)) - 1)) \ ! + __va_size(TYPE), \ ! *((TYPE *) ((__va_reg_p(TYPE) && (AP).__va_arg < 8 + __va_size(TYPE) \ ! ? (AP).__va_reg : (AP).__va_stk) \ ! + ((AP).__va_arg - __va_size(TYPE))))) #define va_end(AP) --- 64,79 ---- #define __va_size(TYPE) ((sizeof(TYPE) + 3) >> 2) ! /* We cast to void * and then to TYPE * because this avoids ! a warning about increasing the alignment requirement. */ ! #define va_arg(AP,TYPE) \ ( (AP).__va_arg = (((AP).__va_arg + (1 << (__alignof__(TYPE) >> 3)) - 1) \ ! & ~((1 << (__alignof__(TYPE) >> 3)) - 1)) \ ! + __va_size(TYPE), \ ! *((TYPE *) (void *) ((__va_reg_p(TYPE) \ ! && (AP).__va_arg < 8 + __va_size(TYPE) \ ! ? (AP).__va_reg : (AP).__va_stk) \ ! + ((AP).__va_arg - __va_size(TYPE))))) #define va_end(AP) + + #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff -rc2N gcc-2.2.2/va-mips.h gcc-2.3.1/va-mips.h *** gcc-2.2.2/va-mips.h Tue May 26 00:03:51 1992 --- gcc-2.3.1/va-mips.h Tue Sep 15 01:04:29 1992 *************** *** 8,14 **** ! /* These macros implement traditional (non-ANSI) varargs ! for GNU C. */ /* 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. */ --- 8,24 ---- ! /* These macros implement varargs for GNU C--either traditional or ANSU. */ + /* Define __gnuc_va_list. */ + + #ifndef __GNUC_VA_LIST + #define __GNUC_VA_LIST + typedef char * __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. */ *************** *** 20,52 **** #endif ! #ifndef _VA_LIST_ ! #define _VA_LIST_ ! /* Make this a macro rather than a typedef, so we can undef any other defn. */ ! #define va_list __va___list ! typedef char * __va___list; ! #endif ! ! #define __va_rounded_size(TYPE) \ ! (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) #ifdef _STDARG_H ! #define va_start(AP, LASTARG) \ ! (AP = ((char *) &(LASTARG) + __va_rounded_size (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 ! #define va_end(AP) #ifdef lint /* complains about constant in conditional context */ ! #define va_arg(list, mode) ((mode *)(list += sizeof(mode)))[-1] #else /* !lint */ ! #define va_arg(AP, mode) \ ! ((mode *)(AP = (char *) (__alignof(mode) > 4 \ ! ? ((int)AP + 2*8 - 1) & -8 \ ! : ((int)AP + 2*4 - 1) & -4)))[-1] #endif /* lint */ --- 30,61 ---- #endif ! #define __va_rounded_size(__TYPE) \ ! (((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) #ifdef _STDARG_H ! #define va_start(__AP, __LASTARG) \ ! (__AP = ((char *) &(__LASTARG) + __va_rounded_size (__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 ! void va_end (__gnuc_va_list); /* Defined in libgcc.a */ ! #define va_end(__AP) #ifdef lint /* complains about constant in conditional context */ ! #define va_arg(list, mode) ((mode *)(list += __va_rounded_size(mode)))[-1] #else /* !lint */ ! /* We cast to void * and then to TYPE * because this avoids ! a warning about increasing the alignment requirement. */ ! #define va_arg(__AP, __type) \ ! ((__type *) (void *) (__AP = (char *) ((__alignof(__type) > 4 \ ! ? ((int)__AP + 8 - 1) & -8 \ ! : ((int)__AP + 4 - 1) & -4) \ ! + __va_rounded_size(__type))))[-1] #endif /* lint */ + #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff -rc2N gcc-2.2.2/va-pa.h gcc-2.3.1/va-pa.h *** gcc-2.2.2/va-pa.h Mon Mar 16 14:02:51 1992 --- gcc-2.3.1/va-pa.h Wed Oct 14 10:50:04 1992 *************** *** 1,86 **** - #if __GNUC__ > 1 - - typedef struct - { - char *__va_stack_start; /* Real start of stack args. */ - char *__va_int; /* Pointer to the general register */ - /* args and stack. */ - char *__va_float; /* Pointer to the fp register args. */ - char *__va_double; - } va_list; - - #ifdef _STDARG_H - #define va_start(AP,LASTARG) ((AP) = *(va_list *)__builtin_saveregs()) - #else - #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) = *(va_list *)__builtin_saveregs()) - #endif /* _STDARG_H */ - - /* Handle pass by invisible reference and voids left by aligned */ - /* doubles. */ - - #define __va_rounded_size(TYPE) \ - (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) - - #define va_arg(AP, TYPE) \ - (((__va_rounded_size(TYPE) <= 8) \ - ? ((AP).__va_int -= __va_rounded_size (TYPE), \ - (AP).__va_float -= __va_rounded_size (TYPE), \ - (AP).__va_double -= __va_rounded_size (TYPE), \ - (__alignof__ (TYPE) > 4 ? ((int)(AP).__va_int &= ~(0x7), \ - (int)(AP).__va_float &= ~(0x7), \ - (int)(AP).__va_double &= ~(0x7)) : 0))\ - : (int)((AP).__va_int -= sizeof (TYPE *), \ - (AP).__va_float -= sizeof (TYPE *), \ - (AP).__va_double -= sizeof (TYPE *))), \ - (((AP).__va_int < (AP).__va_stack_start \ - || __builtin_classify_type (* (TYPE *) 0) != 8) \ - ? ((__va_rounded_size(TYPE) <= 8) ? *(TYPE *)(AP).__va_int \ - : **(TYPE **)(AP).__va_int) \ - : ((__va_rounded_size(TYPE) <= 4) ? *(TYPE *)(AP).__va_float \ - : ((__va_rounded_size(TYPE) <= 8) ? *(TYPE *)(AP).__va_double \ - : **(TYPE **)(AP).__va_int)))) ! ! void va_end (va_list); /* Defined in libgcc.a */ ! #define va_end(AP) ! #else /* __GNUCC__ > 1 */ ! typedef char *va_list; ! /* __builtin_saveregs () tickles a bug in the pa-risc gcc 1.39 port, */ ! /* so don't use it for varargs. Obviously the stdarg stuff doesn't */ ! /* work very well. */ #ifdef _STDARG_H ! #define va_start(AP,LASTARG) \ ! (__builtin_saveregs(), (AP) = __builtin_next_arg ()) ! ! /* gcc1 doesn't implement pass by invisible reference */ ! #define __va_rounded_size(TYPE) \ ! (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) ! ! #define va_arg(AP,TYPE) \ ! ((AP) -= __va_rounded_size (TYPE), (__alignof__ (TYPE) > 4 ? \ ! (int)AP &= ~(0x7) : 0), \ ! *(TYPE *)(AP)) - void va_end (va_list); /* Defined in libgcc.a */ #define va_end(AP) - #else /* _STDARG_H */ - #define va_alist __va_a__, __va_b__, __va_c__, __va_d__ - #define va_dcl int __va_a__, __va_b__, __va_c__, __va_d__; - #define va_start(list) list = (char *) &__va_a__, &__va_b__, &__va_c__, \ - &__va_d__ - - # define va_arg(list,mode) *(mode *) ((int) (list = (char *) \ - (((int) list + sizeof(int /*__va_a__*/) - sizeof(mode)) & ~(sizeof(mode)-1)) \ - - sizeof(int /*__va_a__*/)) + sizeof(int /*__va_a__*/)) - - #define va_end(list) ! #endif /* _STDARG_H */ ! #endif /* __GNUCC__ > 1 */ --- 1,43 ---- ! /* Define __gnuc_va_list. */ ! #ifndef __GNUC_VA_LIST ! #define __GNUC_VA_LIST ! typedef double *__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) ! #if __GNUC__ > 1 ! #define __va_ellipsis ... ! #define __gnuc_va_start(AP) ((AP) = (va_list)__builtin_saveregs()) ! #else ! #define va_alist __va_a__, __va_b__, __va_c__, __va_d__ ! #define __va_ellipsis ! #define __gnuc_va_start(AP)\ ! (AP) = (double *) &__va_a__, &__va_b__, &__va_c__, &__va_d__, \ ! (AP) = (double *)((char *)(AP) + 4) ! #endif /* __GNUC__ > 1 */ #ifdef _STDARG_H ! #define va_start(AP,LASTARG) __gnuc_va_start (AP) ! #else ! /* The ... causes current_function_varargs to be set in cc1. */ ! #define va_dcl long va_alist; __va_ellipsis ! #define va_start(AP) __gnuc_va_start (AP) ! #endif ! ! #define va_arg(AP,TYPE) \ ! (sizeof(TYPE) > 8 ? \ ! ((AP = (__gnuc_va_list) ((char *)AP - sizeof (int))), \ ! (*((TYPE *) (void *) (*((int *) (AP)))))) \ ! :((AP = \ ! (__gnuc_va_list) ((long)((char *)AP - sizeof (TYPE)) \ ! & (sizeof(TYPE) > 4 ? ~0x7 : ~0x3))), \ ! (*((TYPE *) (void *) ((char *)AP + ((8 - sizeof(TYPE)) % 4)))))) #define va_end(AP) ! #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff -rc2N gcc-2.2.2/va-pyr.h gcc-2.3.1/va-pyr.h *** gcc-2.2.2/va-pyr.h Thu May 7 02:38:26 1992 --- gcc-2.3.1/va-pyr.h Tue Sep 15 01:05:46 1992 *************** *** 45,48 **** --- 45,53 ---- */ + /* Define __gnuc_va_list. */ + + #ifndef __GNUC_VA_LIST + #define __GNUC_VA_LIST + typedef void *__voidptr; #if 1 *************** *** 64,67 **** --- 69,80 ---- #endif + typedef __va_buf __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. */ *************** *** 80,85 **** #define va_dcl __voidptr va_alist; __va_ellipsis - typedef __va_buf va_list; - /* __asm ("rcsp %0" : "=r" ( _AP [0]));*/ --- 93,96 ---- *************** *** 97,100 **** --- 108,113 ---- #endif + /* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ #define va_arg(_AP, _MODE) \ __extension__ \ *************** *** 109,114 **** if (__onstack==0 || (int)(__ap[2])==11) \ __ap[2]+= (__size >> 2); \ ! *(( _MODE *)__param_addr); \ }) #define va_end(_X) --- 122,130 ---- if (__onstack==0 || (int)(__ap[2])==11) \ __ap[2]+= (__size >> 2); \ ! *(( _MODE *) (void *) __param_addr); \ }) + void va_end (__gnuc_va_list); /* Defined in libgcc.a */ #define va_end(_X) + + #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff -rc2N gcc-2.2.2/va-sparc.h gcc-2.3.1/va-sparc.h *** gcc-2.2.2/va-sparc.h Sat Jun 13 02:51:07 1992 --- gcc-2.3.1/va-sparc.h Fri Sep 25 01:47:08 1992 *************** *** 2,16 **** except for differences described below. */ ! /* Make this a macro rather than a typedef, so we can undef any other defn. */ ! #define va_list __va___list #ifndef __svr4__ /* This has to be a char * to be compatible with Sun. i.e., we have to pass a `va_list' to vsprintf. */ ! typedef char * __va___list; #else /* This has to be a void * to be compatible with Sun svr4. i.e., we have to pass a `va_list' to vsprintf. */ ! typedef void * __va___list; #endif /* In GCC version 2, we want an ellipsis at the end of the declaration --- 2,24 ---- except for differences described below. */ ! /* Define __gnuc_va_list. */ ! ! #ifndef __GNUC_VA_LIST ! #define __GNUC_VA_LIST ! #ifndef __svr4__ /* This has to be a char * to be compatible with Sun. i.e., we have to pass a `va_list' to vsprintf. */ ! typedef char * __gnuc_va_list; #else /* This has to be a void * to be compatible with Sun svr4. i.e., we have to pass a `va_list' to vsprintf. */ ! typedef void * __gnuc_va_list; #endif + #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 *************** *** 35,38 **** --- 43,47 ---- #endif + void va_end (__gnuc_va_list); /* Defined in libgcc.a */ #define va_end(pvar) *************** *** 49,52 **** --- 58,65 ---- 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. */ + /* We don't declare the union member `d' to have type TYPE + because that would lose in C++ if TYPE has a constructor. */ + /* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ #define va_arg(pvar,TYPE) \ __extension__ \ *************** *** 54,64 **** ((__builtin_classify_type (__va_temp) >= 12) \ ? ((pvar) += __va_rounded_size (TYPE *), \ ! **(TYPE **) ((pvar) - __va_rounded_size (TYPE *))) \ : __va_rounded_size (TYPE) == 8 \ ! ? ({ union {TYPE d; int i[2];} u; \ ! u.i[0] = ((int *) (pvar))[0]; \ ! u.i[1] = ((int *) (pvar))[1]; \ (pvar) += 8; \ ! u.d; }) \ : ((pvar) += __va_rounded_size (TYPE), \ ! *((TYPE *) ((pvar) - __va_rounded_size (TYPE)))));}) --- 67,80 ---- ((__builtin_classify_type (__va_temp) >= 12) \ ? ((pvar) += __va_rounded_size (TYPE *), \ ! **(TYPE **) (void *) ((pvar) - __va_rounded_size (TYPE *))) \ : __va_rounded_size (TYPE) == 8 \ ! ? ({ union {char __d[sizeof (TYPE)]; int __i[2];} __u; \ ! __u.__i[0] = ((int *) (void *) (pvar))[0]; \ ! __u.__i[1] = ((int *) (void *) (pvar))[1]; \ (pvar) += 8; \ ! *(TYPE *) (void *) __u.__d; }) \ : ((pvar) += __va_rounded_size (TYPE), \ ! *((TYPE *) (void *) ((pvar) - __va_rounded_size (TYPE)))));}) ! ! #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ ! diff -rc2N gcc-2.2.2/varasm.c gcc-2.3.1/varasm.c *** gcc-2.2.2/varasm.c Thu May 21 14:24:40 1992 --- gcc-2.3.1/varasm.c Thu Oct 29 17:29:57 1992 *************** *** 33,40 **** --- 33,42 ---- #include "tree.h" #include "flags.h" + #include "function.h" #include "expr.h" #include "hard-reg-set.h" #include "regs.h" #include "defaults.h" + #include "real.h" #include "obstack.h" *************** *** 48,51 **** --- 50,61 ---- #endif + /* This macro gets just the user-specified name + out of the string in a SYMBOL_REF. On most machines, + we discard the * if any and that's all. */ + #ifndef STRIP_NAME_ENCODING + #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ + (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*')) + #endif + /* File in which assembler code is being written. */ *************** *** 59,63 **** extern struct obstack permanent_obstack; #define obstack_chunk_alloc xmalloc - extern int xmalloc (); /* Number for making the label on the next --- 69,72 ---- *************** *** 83,86 **** --- 92,97 ---- void output_constant (); void output_constructor (); + void text_section (); + void readonly_data_section (); void data_section (); *************** *** 213,218 **** /* Decode an `asm' spec for a declaration as a register name. Return the register number, or -1 if nothing specified, ! or -2 if the ASMSPEC is not `cc' and is not recognized, ! or -3 if ASMSPEC is `cc' and is not recognized. Accept an exact spelling or a decimal number. Prefixes such as % are optional. */ --- 224,230 ---- /* Decode an `asm' spec for a declaration as a register name. Return the register number, or -1 if nothing specified, ! or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized, ! or -3 if ASMSPEC is `cc' and is not recognized, ! or -4 if ASMSPEC is `memory' and is not recognized. Accept an exact spelling or a decimal number. Prefixes such as % are optional. */ *************** *** 258,261 **** --- 270,276 ---- #endif /* ADDITIONAL_REGISTER_NAMES */ + if (!strcmp (asmspec, "memory")) + return -4; + if (!strcmp (asmspec, "cc")) return -3; *************** *** 306,324 **** /* First detect errors in declaring global registers. */ ! if (TREE_REGDECL (decl) && reg_number == -1) error_with_decl (decl, "register name not specified for `%s'"); ! else if (TREE_REGDECL (decl) && reg_number < 0) error_with_decl (decl, "invalid register name for `%s'"); ! else if ((reg_number >= 0 || reg_number == -3) && ! TREE_REGDECL (decl)) error_with_decl (decl, "register name given for non-register variable `%s'"); ! else if (TREE_REGDECL (decl) && TREE_CODE (decl) == FUNCTION_DECL) error ("function declared `register'"); ! else if (TREE_REGDECL (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode) error_with_decl (decl, "data type of `%s' isn't suitable for a register"); /* Now handle properly declared static register variables. */ ! else if (TREE_REGDECL (decl)) { int nregs; --- 321,339 ---- /* First detect errors in declaring global registers. */ ! if (DECL_REGISTER (decl) && reg_number == -1) error_with_decl (decl, "register name not specified for `%s'"); ! else if (DECL_REGISTER (decl) && reg_number < 0) error_with_decl (decl, "invalid register name for `%s'"); ! else if ((reg_number >= 0 || reg_number == -3) && ! DECL_REGISTER (decl)) error_with_decl (decl, "register name given for non-register variable `%s'"); ! else if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL) error ("function declared `register'"); ! else if (DECL_REGISTER (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode) error_with_decl (decl, "data type of `%s' isn't suitable for a register"); /* Now handle properly declared static register variables. */ ! else if (DECL_REGISTER (decl)) { int nregs; *************** *** 357,361 **** whose scope is less than the whole file. Concatenate a distinguishing number. */ ! if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0) { char *label; --- 372,376 ---- whose scope is less than the whole file. Concatenate a distinguishing number. */ ! if (!top_level && !DECL_EXTERNAL (decl) && asmspec == 0) { char *label; *************** *** 389,392 **** --- 404,419 ---- } } + + /* Make the rtl for variable VAR be volatile. + Use this only for static variables. */ + + make_var_volatile (var) + tree var; + { + if (GET_CODE (DECL_RTL (var)) != MEM) + abort (); + + MEM_VOLATILE_P (DECL_RTL (var)) = 1; + } /* Output a string of literal assembler code *************** *** 405,413 **** } ! /* Tiemann: please get rid of this conditional and put appropriate ! definitions in each of the files that should have them. ! The type of debugging format is not the right parameter to ! control how some other aspect of assembler output is done. */ ! #if !(defined(DBX_DEBUGGING_INFO) && !defined(FASCIST_ASSEMBLER)) #ifndef ASM_OUTPUT_CONSTRUCTOR --- 432,439 ---- } ! #if 0 /* This should no longer be needed, because ! flag_gnu_linker should be 0 on these systems, ! which should prevent any output ! if ASM_OUTPUT_CONSTRUCTOR and ASM_OUTPUT_DESTRUCTOR are absent. */ #if !(defined(DBX_DEBUGGING_INFO) && !defined(FASCIST_ASSEMBLER)) #ifndef ASM_OUTPUT_CONSTRUCTOR *************** *** 418,421 **** --- 444,448 ---- #endif #endif + #endif /* 0 */ /* Record an element in the table of global destructors. *************** *** 531,535 **** { if (!first_global_object_name) ! first_global_object_name = fnname + (fnname[0] == '*'); ASM_GLOBALIZE_LABEL (asm_out_file, fnname); } --- 558,562 ---- { if (!first_global_object_name) ! STRIP_NAME_ENCODING (first_global_object_name, fnname); ASM_GLOBALIZE_LABEL (asm_out_file, fnname); } *************** *** 680,684 **** since assembler considers all undefined symbols external. */ ! if (TREE_EXTERNAL (decl)) return; --- 707,711 ---- since assembler considers all undefined symbols external. */ ! if (DECL_EXTERNAL (decl)) return; *************** *** 702,706 **** error_with_file_and_line (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), ! "storage size of static var `%s' isn't known", IDENTIFIER_POINTER (DECL_NAME (decl))); return; --- 729,733 ---- error_with_file_and_line (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), ! "storage size of `%s' isn't known", IDENTIFIER_POINTER (DECL_NAME (decl))); return; *************** *** 821,825 **** { if (!first_global_object_name) ! first_global_object_name = name + (name[0] == '*'); ASM_GLOBALIZE_LABEL (asm_out_file, name); } --- 848,852 ---- { if (!first_global_object_name) ! STRIP_NAME_ENCODING(first_global_object_name, name); ASM_GLOBALIZE_LABEL (asm_out_file, name); } *************** *** 931,935 **** #ifdef ASM_OUTPUT_EXTERNAL if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd' ! && TREE_EXTERNAL (decl) && TREE_PUBLIC (decl)) { rtx rtl = DECL_RTL (decl); --- 958,962 ---- #ifdef ASM_OUTPUT_EXTERNAL if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd' ! && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) { rtx rtl = DECL_RTL (decl); *************** *** 1201,1205 **** } ! set_float_handler (0); } --- 1228,1232 ---- } ! set_float_handler (NULL_PTR); } *************** *** 1211,1216 **** A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain. In that case, CONST_DOUBLE_MEM is either a MEM, ! or const0_rtx if no MEM has been made for this CONST_DOUBLE yet. */ static rtx const_double_chain; --- 1238,1246 ---- A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain. In that case, CONST_DOUBLE_MEM is either a MEM, ! or const0_rtx if no MEM has been made for this CONST_DOUBLE yet. + (CONST_DOUBLE_MEM is used only for top-level functions. + See force_const_mem for explanation.) */ + static rtx const_double_chain; *************** *** 1222,1226 **** rtx immed_double_const (i0, i1, mode) ! int i0, i1; enum machine_mode mode; { --- 1252,1256 ---- rtx immed_double_const (i0, i1, mode) ! HOST_WIDE_INT i0, i1; enum machine_mode mode; { *************** *** 1234,1253 **** or a reasonable unsigned value for this mode. */ int width = GET_MODE_BITSIZE (mode); ! if (width < HOST_BITS_PER_INT ! && ((i0 & ((-1) << (width - 1))) != ((-1) << (width - 1)))) ! i0 &= (1 << width) - 1, i1 = 0; ! else if (width == HOST_BITS_PER_INT && ! (i1 == ~0 && i0 < 0)) i1 = 0; ! else if (width > 2 * HOST_BITS_PER_INT) /* We cannot represent this value as a constant. */ abort (); ! /* If MODE fits within HOST_BITS_PER_INT, always use a CONST_INT. ??? Strictly speaking, this is wrong if we create a CONST_INT for a large unsigned constant with the size of MODE being ! HOST_BITS_PER_INT and later try to interpret that constant in a wider ! mode. In that case we will mis-interpret it as a negative number. Unfortunately, the only alternative is to make a CONST_DOUBLE --- 1264,1285 ---- or a reasonable unsigned value for this mode. */ int width = GET_MODE_BITSIZE (mode); ! if (width < HOST_BITS_PER_WIDE_INT ! && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1))) ! != ((HOST_WIDE_INT) (-1) << (width - 1)))) ! i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0; ! else if (width == HOST_BITS_PER_WIDE_INT && ! (i1 == ~0 && i0 < 0)) i1 = 0; ! else if (width > 2 * HOST_BITS_PER_WIDE_INT) /* We cannot represent this value as a constant. */ abort (); ! /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT. ??? Strictly speaking, this is wrong if we create a CONST_INT for a large unsigned constant with the size of MODE being ! HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a ! wider mode. In that case we will mis-interpret it as a negative ! number. Unfortunately, the only alternative is to make a CONST_DOUBLE *************** *** 1260,1264 **** is being broken. */ ! if (width <= HOST_BITS_PER_INT) i1 = (i0 < 0) ? ~0 : 0; --- 1292,1296 ---- is being broken. */ ! if (width <= HOST_BITS_PER_WIDE_INT) i1 = (i0 < 0) ? ~0 : 0; *************** *** 1266,1270 **** if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) ! return gen_rtx (CONST_INT, VOIDmode, i0); /* We use VOIDmode for integers. */ --- 1298,1302 ---- if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) ! return GEN_INT (i0); /* We use VOIDmode for integers. */ *************** *** 1329,1333 **** return CONST1_RTX (mode); ! if (sizeof u == 2 * sizeof (int)) return immed_double_const (u.i[0], u.i[1], mode); --- 1361,1365 ---- return CONST1_RTX (mode); ! if (sizeof u == 2 * sizeof (HOST_WIDE_INT)) return immed_double_const (u.i[0], u.i[1], mode); *************** *** 1390,1393 **** --- 1422,1430 ---- register rtx r, next; + /* Don't touch CONST_DOUBLE_MEM for nested functions. + See force_const_mem for explanation. */ + if (outer_function_chain != 0) + return; + for (r = const_double_chain; r; r = next) { *************** *** 1407,1411 **** { rtx base; ! int offset; }; --- 1444,1448 ---- { rtx base; ! HOST_WIDE_INT offset; }; *************** *** 1530,1534 **** be shorter. */ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) ! hi = ((int) TREE_TYPE (exp) & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE; else hi = ((5 + int_size_in_bytes (TREE_TYPE (exp))) --- 1567,1572 ---- be shorter. */ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) ! hi = ((HOST_WIDE_INT) TREE_TYPE (exp) & ((1 << HASHBITS) - 1)) ! % MAX_HASH_TABLE; else hi = ((5 + int_size_in_bytes (TREE_TYPE (exp))) *************** *** 1536,1540 **** for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) ! hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE; return hi; --- 1574,1579 ---- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) ! if (TREE_VALUE (link)) ! hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE; return hi; *************** *** 1672,1677 **** for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) ! if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0) ! return 0; return p; } --- 1711,1730 ---- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) ! { ! if (TREE_VALUE (link)) ! { ! if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0) ! return 0; ! } ! else ! { ! tree zero = 0; ! ! if (bcmp (&zero, p, sizeof zero)) ! return 0; ! p += sizeof zero; ! } ! } ! return p; } *************** *** 1793,1797 **** for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) ! record_constant_1 (TREE_VALUE (link)); return; } --- 1846,1860 ---- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) ! { ! if (TREE_VALUE (link)) ! record_constant_1 (TREE_VALUE (link)); ! else ! { ! tree zero = 0; ! ! obstack_grow (&permanent_obstack, (char *) &zero, sizeof zero); ! } ! } ! return; } *************** *** 1962,1966 **** #define MAX_RTX_HASH_TABLE 61 ! static struct constant_descriptor *const_rtx_hash_table[MAX_RTX_HASH_TABLE]; /* Structure to represent sufficient information about a constant so that --- 2025,2029 ---- #define MAX_RTX_HASH_TABLE 61 ! static struct constant_descriptor **const_rtx_hash_table; /* Structure to represent sufficient information about a constant so that *************** *** 1999,2003 **** }; ! static struct pool_sym *const_rtx_sym_hash_table[MAX_RTX_HASH_TABLE]; /* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true. --- 2062,2066 ---- }; ! static struct pool_sym **const_rtx_sym_hash_table; /* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true. *************** *** 2005,2009 **** #define SYMHASH(LABEL) \ ! ((((int) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE) /* Initialize constant pool hashing for next function. */ --- 2068,2072 ---- #define SYMHASH(LABEL) \ ! ((((HOST_WIDE_INT) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE) /* Initialize constant pool hashing for next function. */ *************** *** 2012,2017 **** init_const_rtx_hash_table () { ! bzero (const_rtx_hash_table, sizeof const_rtx_hash_table); ! bzero (const_rtx_sym_hash_table, sizeof const_rtx_sym_hash_table); first_pool = last_pool = 0; --- 2075,2088 ---- init_const_rtx_hash_table () { ! const_rtx_hash_table ! = ((struct constant_descriptor **) ! oballoc (MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *))); ! const_rtx_sym_hash_table ! = ((struct pool_sym **) ! oballoc (MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *))); ! bzero (const_rtx_hash_table, ! MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *)); ! bzero (const_rtx_sym_hash_table, ! MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *)); first_pool = last_pool = 0; *************** *** 2019,2022 **** --- 2090,2117 ---- } + /* Save and restore it for a nested function. */ + + void + save_varasm_status (p) + struct function *p; + { + p->const_rtx_hash_table = const_rtx_hash_table; + p->const_rtx_sym_hash_table = const_rtx_sym_hash_table; + p->first_pool = first_pool; + p->last_pool = last_pool; + p->pool_offset = pool_offset; + } + + void + restore_varasm_status (p) + struct function *p; + { + const_rtx_hash_table = p->const_rtx_hash_table; + const_rtx_sym_hash_table = p->const_rtx_sym_hash_table; + first_pool = p->first_pool; + last_pool = p->last_pool; + pool_offset = p->pool_offset; + } + enum kind { RTX_DOUBLE, RTX_INT }; *************** *** 2111,2114 **** --- 2206,2226 ---- } + /* Given a MINUS expression, simplify it if both sides + include the same symbol. */ + + rtx + simplify_subtraction (x) + rtx x; + { + struct rtx_const val0, val1; + + decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0); + decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1); + + if (val0.un.addr.base == val1.un.addr.base) + return GEN_INT (val0.un.addr.offset - val1.un.addr.offset); + return x; + } + /* Compute a hash code for a constant RTL expression. */ *************** *** 2204,2211 **** memory locations, but this should be extremely rare. */ ! if (GET_CODE (x) == CONST_DOUBLE ! && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM ! && GET_MODE (CONST_DOUBLE_MEM (x)) == mode) ! return CONST_DOUBLE_MEM (x); /* Compute hash code of X. Search the descriptors for that hash code --- 2316,2328 ---- memory locations, but this should be extremely rare. */ ! /* Don't use CONST_DOUBLE_MEM in a nested function. ! Nested functions have their own constant pools, ! so they can't share the same values in CONST_DOUBLE_MEM ! with the containing function. */ ! if (outer_function_chain == 0) ! if (GET_CODE (x) == CONST_DOUBLE ! && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM ! && GET_MODE (CONST_DOUBLE_MEM (x)) == mode) ! return CONST_DOUBLE_MEM (x); /* Compute hash code of X. Search the descriptors for that hash code *************** *** 2290,2302 **** current_function_uses_const_pool = 1; ! if (GET_CODE (x) == CONST_DOUBLE) ! { ! if (CONST_DOUBLE_MEM (x) == cc0_rtx) ! { ! CONST_DOUBLE_CHAIN (x) = const_double_chain; ! const_double_chain = x; ! } ! CONST_DOUBLE_MEM (x) = def; ! } return def; --- 2407,2420 ---- current_function_uses_const_pool = 1; ! if (outer_function_chain == 0) ! if (GET_CODE (x) == CONST_DOUBLE) ! { ! if (CONST_DOUBLE_MEM (x) == cc0_rtx) ! { ! CONST_DOUBLE_CHAIN (x) = const_double_chain; ! const_double_chain = x; ! } ! CONST_DOUBLE_MEM (x) = def; ! } return def; *************** *** 2377,2385 **** whose CODE_LABEL has been deleted. This can occur if a jump table is eliminated by optimization. If so, write a constant of zero ! instead. */ ! if ((GET_CODE (x) == LABEL_REF && INSN_DELETED_P (XEXP (x, 0))) || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF ! && INSN_DELETED_P (XEXP (XEXP (XEXP (x, 0), 0), 0)))) x = const0_rtx; --- 2495,2507 ---- whose CODE_LABEL has been deleted. This can occur if a jump table is eliminated by optimization. If so, write a constant of zero ! instead. Note that this can also happen by turning the ! CODE_LABEL into a NOTE. */ ! if (((GET_CODE (x) == LABEL_REF ! && (INSN_DELETED_P (XEXP (x, 0)) ! || GET_CODE (XEXP (x, 0)) == NOTE))) || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF ! && (INSN_DELETED_P (XEXP (XEXP (XEXP (x, 0), 0), 0)) ! || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == NOTE))) x = const0_rtx; *************** *** 2466,2469 **** --- 2588,2592 ---- case NOP_EXPR: case CONVERT_EXPR: + case NON_LVALUE_EXPR: reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); break; *************** *** 2515,2520 **** /* Allow a constructor with no elements for any data type. This means to fill the space with zeros. */ ! if (TREE_CODE (exp) == CONSTRUCTOR ! && TREE_OPERAND (exp, 1) == 0) { assemble_zeros (size); --- 2638,2642 ---- /* Allow a constructor with no elements for any data type. This means to fill the space with zeros. */ ! if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0) { assemble_zeros (size); *************** *** 2539,2543 **** exp = TREE_OPERAND (exp, 0); ! if (! assemble_integer (expand_expr (exp, 0, VOIDmode, EXPAND_INITIALIZER), size, 0)) --- 2661,2665 ---- exp = TREE_OPERAND (exp, 0); ! if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER), size, 0)) *************** *** 2614,2618 **** register int byte; ! if (HOST_BITS_PER_INT < BITS_PER_UNIT) abort (); --- 2736,2740 ---- register int byte; ! if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT) abort (); *************** *** 2636,2641 **** /* Eliminate the marker that makes a cast not be an lvalue. */ ! if (val != 0 && TREE_CODE (val) == NON_LVALUE_EXPR) ! val = TREE_OPERAND (val, 0); if (field == 0 || !DECL_BIT_FIELD (field)) --- 2758,2763 ---- /* Eliminate the marker that makes a cast not be an lvalue. */ ! if (val != 0) ! STRIP_NOPS (val); if (field == 0 || !DECL_BIT_FIELD (field)) *************** *** 2769,2792 **** /* Don't try to take a bunch of bits that cross the word boundary in the INTEGER_CST. */ ! if (shift < HOST_BITS_PER_INT ! && shift + this_time > HOST_BITS_PER_INT) { ! this_time -= (HOST_BITS_PER_INT - shift); ! shift = HOST_BITS_PER_INT; } /* Now get the bits from the appropriate constant word. */ ! if (shift < HOST_BITS_PER_INT) { value = TREE_INT_CST_LOW (val); } ! else if (shift < 2 * HOST_BITS_PER_INT) { value = TREE_INT_CST_HIGH (val); ! shift -= HOST_BITS_PER_INT; } else abort (); ! byte |= (((value >> shift) & ((1 << this_time) - 1)) << (BITS_PER_UNIT - this_time - next_bit)); #else --- 2891,2915 ---- /* Don't try to take a bunch of bits that cross the word boundary in the INTEGER_CST. */ ! if (shift < HOST_BITS_PER_WIDE_INT ! && shift + this_time > HOST_BITS_PER_WIDE_INT) { ! this_time -= (HOST_BITS_PER_WIDE_INT - shift); ! shift = HOST_BITS_PER_WIDE_INT; } /* Now get the bits from the appropriate constant word. */ ! if (shift < HOST_BITS_PER_WIDE_INT) { value = TREE_INT_CST_LOW (val); } ! else if (shift < 2 * HOST_BITS_PER_WIDE_INT) { value = TREE_INT_CST_HIGH (val); ! shift -= HOST_BITS_PER_WIDE_INT; } else abort (); ! byte |= (((value >> shift) ! & (((HOST_WIDE_INT) 1 << this_time) - 1)) << (BITS_PER_UNIT - this_time - next_bit)); #else *************** *** 2799,2807 **** /* Don't try to take a bunch of bits that cross the word boundary in the INTEGER_CST. */ ! if (shift < HOST_BITS_PER_INT ! && shift + this_time > HOST_BITS_PER_INT) { ! this_time -= (HOST_BITS_PER_INT - shift); ! shift = HOST_BITS_PER_INT; } --- 2922,2930 ---- /* Don't try to take a bunch of bits that cross the word boundary in the INTEGER_CST. */ ! if (shift < HOST_BITS_PER_WIDE_INT ! && shift + this_time > HOST_BITS_PER_WIDE_INT) { ! this_time -= (HOST_BITS_PER_WIDE_INT - shift); ! shift = HOST_BITS_PER_WIDE_INT; } *************** *** 2809,2820 **** if (shift < HOST_BITS_PER_INT) value = TREE_INT_CST_LOW (val); ! else if (shift < 2 * HOST_BITS_PER_INT) { value = TREE_INT_CST_HIGH (val); ! shift -= HOST_BITS_PER_INT; } else abort (); ! byte |= ((value >> shift) & ((1 << this_time) - 1)) << next_bit; #endif next_offset += this_time; --- 2932,2944 ---- if (shift < HOST_BITS_PER_INT) value = TREE_INT_CST_LOW (val); ! else if (shift < 2 * HOST_BITS_PER_WIDE_INT) { value = TREE_INT_CST_HIGH (val); ! shift -= HOST_BITS_PER_WIDE_INT; } else abort (); ! byte |= ((value >> shift) ! & (((HOST_WIDE_INT) 1 << this_time) - 1)) << next_bit; #endif next_offset += this_time; diff -rc2N gcc-2.2.2/version.c gcc-2.3.1/version.c *** gcc-2.2.2/version.c Sun Jun 14 17:39:10 1992 --- gcc-2.3.1/version.c Sun Nov 1 01:55:36 1992 *************** *** 1 **** ! char *version_string = "2.2.2"; --- 1 ---- ! char *version_string = "2.3.1"; diff -rc2N gcc-2.2.2/vmsconfig.com gcc-2.3.1/vmsconfig.com *** gcc-2.2.2/vmsconfig.com Thu May 21 13:45:16 1992 --- gcc-2.3.1/vmsconfig.com Tue Oct 13 00:21:40 1992 *************** *** 1,4 **** $ ! ! $ ! Set up to compile GCC on VMS $ ! $! Set the def dir to proper place for use in batch. Works for interactive too. --- 1,4 ---- $ ! ! $ ! Set up to compile GCC on VAX/VMS $ ! $! Set the def dir to proper place for use in batch. Works for interactive too. *************** *** 11,20 **** $ ! $ if f$search("config.h") .nes. "" then delete config.h.* ! $ copy [.config]xm-vms.h []config.h ! $ echo "Linked `config.h' to `[.config]xm-vms.h'. $ ! $ if f$search("tm.h") .nes. "" then delete tm.h.* ! $ copy [.config]vms.h []tm.h ! $ echo "Linked `tm.h' to `[.config]vms.h'. $ ! $ if f$search("md.") .nes. "" then delete md..* --- 11,36 ---- $ ! $ if f$search("config.h") .nes. "" then delete config.h.* ! $ copy [.config]xm-vax-vms.h []config.h ! $ echo "Linked `config.h' to `[.config]xm-vax-vms.h'. $ ! + $ if f$search("tconfig.h") .nes. "" then delete tconfig.h.* + $ create []tconfig.h + $DECK + /* tconfig.h == config.h :: target and host configurations are the same */ + #include "config.h" + $EOD + $ echo "Created `tconfig.h'. + $ ! + $ if f$search("hconfig.h") .nes. "" then delete hconfig.h.* + $ create []hconfig.h + $DECK + /* hconfig.h == config.h :: target and host configurations are the same */ + #include "config.h" + $EOD + $ echo "Created `hconfig.h'. + $ ! $ if f$search("tm.h") .nes. "" then delete tm.h.* ! $ copy [.config]vax-vms.h []tm.h ! $ echo "Linked `tm.h' to `[.config]vax-vms.h'. $ ! $ if f$search("md.") .nes. "" then delete md..* *************** *** 34,38 **** $read ifile$ line $close ifile$ ! $delete/nolog t.tmp; $ijk=f$locate("""",line)+1 $line=f$extract(ijk,f$length(line)-ijk,line) --- 50,54 ---- $read ifile$ line $close ifile$ ! $delete t.tmp; $ijk=f$locate("""",line)+1 $line=f$extract(ijk,f$length(line)-ijk,line) *************** *** 58,62 **** $write ifile$ "ident="+""""+elm+"""" $close ifile$ ! $pur version.opt/nolog $! $! --- 74,78 ---- $write ifile$ "ident="+""""+elm+"""" $close ifile$ ! $purge version.opt $! $! *************** *** 87,91 **** position (beginning_of (newbuffer)); LOOP ! range1:=search_quietly("," & ((SPAN(" ") & LINE_END) | LINE_END), FORWARD, EXACT); exitif range1 = 0; position (beginning_of (range1)); --- 103,108 ---- position (beginning_of (newbuffer)); LOOP ! range1 := search_quietly("," & ((SPAN(" ") & LINE_END) | LINE_END), ! FORWARD, EXACT); exitif range1 = 0; position (beginning_of (range1)); *************** *** 120,125 **** position (beginning_of (current_buffer)) ; LOOP ! range1 := search_quietly ("$(" & ! SPAN("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ#~0123456789") & ")", FORWARD, EXACT) ; EXITIF range1 = 0; position (beginning_of (range1)); --- 137,143 ---- position (beginning_of (current_buffer)) ; LOOP ! range1 := search_quietly ("$(" & ! SPAN("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ#~0123456789") ! & ")", FORWARD, EXACT) ; EXITIF range1 = 0; position (beginning_of (range1)); *************** *** 230,235 **** SET(OUTPUT_FILE, compiler_list, "compilers.list"); write_file (compiler_list); ! generate_option_file(LINE_BEGIN & "OBJS" & ((SPAN(" ") & "=") | "="),"independent.opt"); ! generate_option_file(LINE_BEGIN & "LIB2FUNCS" & ((SPAN(" ") & "=") | "="),"libgcc2.list"); ! ! Now change OBJS in the Makefile, so each language specific options file --- 248,255 ---- SET(OUTPUT_FILE, compiler_list, "compilers.list"); write_file (compiler_list); ! generate_option_file(LINE_BEGIN & "OBJS" & ((SPAN(" ") & "=") | "="), ! "independent.opt"); ! generate_option_file(LINE_BEGIN & "LIB2FUNCS" & ((SPAN(" ") & "=") | "="), ! "libgcc2.list"); ! ! Now change OBJS in the Makefile, so each language specific options file *************** *** 237,241 **** ! position (beginning_of (mainbuffer)); ! range1 := search_quietly (LINE_BEGIN & "OBJS" & ((SPAN(" ") & "=") | "="), FORWARD, EXACT) ; position (end_of (range1)); split_line; --- 257,262 ---- ! position (beginning_of (mainbuffer)); ! range1 := search_quietly (LINE_BEGIN & "OBJS" & ((SPAN(" ") & "=") | "="), ! FORWARD, EXACT) ; position (end_of (range1)); split_line; *************** *** 246,250 **** message(current_line); generate_option_file(LINE_BEGIN & Current_line & ((SPAN(" ") & ":") | ":"), ! current_line+"-objs.opt"); position (cmark); move_vertical(1); --- 267,271 ---- message(current_line); generate_option_file(LINE_BEGIN & Current_line & ((SPAN(" ") & ":") | ":"), ! current_line+"-objs.opt"); position (cmark); move_vertical(1); *************** *** 253,260 **** $ echo "" $! ! $! Remove excessive versions of the options file... $! ! $purge/nolog *.opt ! $purge/nolog compilers.list $! $! --- 274,281 ---- $ echo "" $! ! $! Remove excessive versions of the option files... $! ! $ purge *.opt ! $ purge compilers.list,libgcc2.list $! $! diff -rc2N gcc-2.2.2/xcoffout.c gcc-2.3.1/xcoffout.c *** gcc-2.2.2/xcoffout.c Fri May 22 06:32:55 1992 --- gcc-2.3.1/xcoffout.c Tue Aug 18 21:37:21 1992 *************** *** 135,139 **** for (decl = syms; decl; decl = TREE_CHAIN (decl)) ! if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), name)) { TREE_ASM_WRITTEN (decl) = 1; --- 135,140 ---- for (decl = syms; decl; decl = TREE_CHAIN (decl)) ! if (DECL_NAME (decl) ! && strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), name) == 0) { TREE_ASM_WRITTEN (decl) = 1; *************** *** 360,364 **** /* Output the subblocks. */ ! xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, 0); } block = BLOCK_CHAIN (block); --- 361,365 ---- /* Output the subblocks. */ ! xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE); } block = BLOCK_CHAIN (block); *************** *** 416,420 **** if (name[i] == '[') { ! n = alloca (i + 1); strncpy (n, name, i); n[i] = '\0'; --- 417,421 ---- if (name[i] == '[') { ! n = (char *) alloca (i + 1); strncpy (n, name, i); n[i] = '\0';