+Wed May 3 11:43:53 2000 Jim Wilson <wilson@cygnus.com>
+
+ * config/ia64/ia64.c (ia64_encode_section_info): Add check for
+ TREE_ASM_WRITTEN.
+
+2000-05-03 David Mosberger <davidm@hpl.hp.com>
+
+ * config/ia64/ia64.c (ia64_override_options): Force -mconstant-gp
+ if -mauto-pic is on.
+ (ia64_epilogue_uses): Mark "gp" (r1) as used by the epilogue if
+ -mconstant-gp is in effect and function-descriptors are being used
+ to make indirect calls.
+ * config/ia64/ia64.h (MASK_CONST_GP): New macro.
+ (MASK_AUTO_PIC): Ditto.
+ (TARGET_CONST_GP): Ditto.
+ (TARGET_AUTO_PIC): Ditto.
+ (TARGET_SWITCHES): Add -mconstant-gp and -mauto-pic options.
+ (ASM_OUTPUT_DOUBLE_INT): Don't generate @fptr() if -mauto-pic or
+ -mno-pic is in effect.
+ (ASM_OUTPUT_XDATA_DOUBLE_INT): Ditto.
+ * config/ia64/ia64.md (movdi): Use gen_load_gprel64() if
+ -mauto-pic is in effect.
+ (gprel64_offset): New pattern.
+ (load_gprel64): Ditto.
+ (call): Handle -mauto-pic like -mno-pic (don't use fptr). If
+ -mconstant-gp is in effect, no need to preserve gp around direct
+ calls.
+ (call_value): Ditto.
+ * config/ia64/linux.h (PROFILE_BEFORE_PROLOGUE): Define.
+ (FUNCTION_PROFILER): Define.
+ * config/ia64/sysv4.h (ASM_OUTPUT_CONSTRUCTOR): Don't generate
+ @fptr() directive when -mno-pic or -mauto-pic is in effect.
+ (ASM_OUTPUT_DESTRUCTOR): Ditto.
+
2000-05-03 Richard Henderson <rth@cygnus.com>
* Makefile.in (STAGESTUFF): Add libgcc libgcc.mk.
void
ia64_override_options ()
{
+ if (TARGET_AUTO_PIC)
+ target_flags |= MASK_CONST_GP;
+
if (ia64_fixed_range_string)
fix_range (ia64_fixed_range_string);
ia64_epilogue_uses (regno)
int regno;
{
+ /* When a function makes a call through a function descriptor, we
+ will write a (potentially) new value to "gp". After returning
+ from such a call, we need to make sure the function restores the
+ original gp-value, even if the function itself does not use the
+ gp anymore. */
+ if (regno == R_GR(1) && TARGET_CONST_GP && !(TARGET_AUTO_PIC || TARGET_NO_PIC))
+ return 1;
+
/* For functions defined with the syscall_linkage attribute, all input
registers are marked as live at all function exits. This prevents the
register allocator from using the input registers, which in turn makes it
|| ! strcmp (str, "__DTOR_END__"))
;
+ /* If the variable has already been defined in the output file, then it
+ is too late to put it in sdata if it wasn't put there in the first
+ place. The test is here rather than above, because if it is already
+ in sdata, then it can stay there. */
+
+ else if (TREE_ASM_WRITTEN (decl))
+ ;
+
/* If this is an incomplete type with size 0, then we can't put it in
sdata because it might be too big when completed. */
else if (size > 0 && size <= ia64_section_threshold
#define MASK_NO_SDATA 0x00000080 /* Disable sdata/scommon/sbss. */
+#define MASK_CONST_GP 0x00000100 /* treat gp as program-wide constant */
+
+#define MASK_AUTO_PIC 0x00000200 /* generate automatically PIC */
+
#define MASK_DWARF2_ASM 0x40000000 /* test dwarf2 line info via gas. */
#define TARGET_BIG_ENDIAN (target_flags & MASK_BIG_ENDIAN)
#define TARGET_NO_SDATA (target_flags & MASK_NO_SDATA)
+#define TARGET_CONST_GP (target_flags & MASK_CONST_GP)
+
+#define TARGET_AUTO_PIC (target_flags & MASK_AUTO_PIC)
+
#define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM)
/* This macro defines names of command options to set and clear bits in
`target_flags'. Its definition is an initializer with a subgrouping for
each command option. */
-#define TARGET_SWITCHES \
+#define TARGET_SWITCHES \
{ \
{ "big-endian", MASK_BIG_ENDIAN, \
"Generate big endian code" }, \
"Disable use of sdata/scommon/sbss"}, \
{ "sdata", -MASK_NO_SDATA, \
"Enable use of sdata/scommon/sbss"}, \
+ { "constant-gp", MASK_CONST_GP, \
+ "gp is constant (but save/restore gp on indirect calls)" }, \
+ { "auto-pic", MASK_AUTO_PIC, \
+ "Generate self-relocatable code" }, \
{ "dwarf2-asm", MASK_DWARF2_ASM, \
"Enable Dwarf 2 line debug info via GNU as"}, \
{ "no-dwarf2-asm", -MASK_DWARF2_ASM, \
#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE) \
do { \
fprintf (FILE, "\tdata8\t"); \
- if (SYMBOL_REF_FLAG (VALUE)) \
+ if (!(TARGET_NO_PIC || TARGET_AUTO_PIC) && SYMBOL_REF_FLAG (VALUE)) \
fprintf (FILE, "@fptr("); \
output_addr_const (FILE, (VALUE)); \
- if (SYMBOL_REF_FLAG (VALUE)) \
+ if (!(TARGET_NO_PIC || TARGET_AUTO_PIC) && SYMBOL_REF_FLAG (VALUE)) \
fprintf (FILE, ")"); \
fprintf (FILE, "\n"); \
} while (0)
#define ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, SECTION, VALUE) \
do { \
+ int need_closing_paren = 0; \
fprintf (FILE, "\t.xdata8\t\"%s\", ", SECTION); \
- if (GET_CODE (VALUE) == SYMBOL_REF) \
+ if (!(TARGET_NO_PIC || TARGET_AUTO_PIC) \
+ && GET_CODE (VALUE) == SYMBOL_REF) \
{ \
- if (SYMBOL_REF_FLAG (VALUE)) \
- fprintf (FILE, "@fptr("); \
- else \
- fprintf (FILE, "@segrel("); \
+ fprintf (FILE, SYMBOL_REF_FLAG (VALUE) ? "@fptr(" : "@segrel("); \
+ need_closing_paren = 1; \
} \
- output_addr_const (FILE, (VALUE)); \
- if (GET_CODE (VALUE) == SYMBOL_REF) \
+ output_addr_const (FILE, VALUE); \
+ if (need_closing_paren) \
fprintf (FILE, ")"); \
fprintf (FILE, "\n"); \
} while (0)
else
temp = operands[0];
- if (GET_CODE (operands[1]) == SYMBOL_REF && SYMBOL_REF_FLAG (operands[1]))
+ if (TARGET_AUTO_PIC)
+ emit_insn (gen_load_gprel64 (temp, operands[1]));
+ else if (GET_CODE (operands[1]) == SYMBOL_REF
+ && SYMBOL_REF_FLAG (operands[1]))
emit_insn (gen_load_fptr (temp, operands[1]));
else if (sdata_symbolic_operand (operands[1], DImode))
emit_insn (gen_load_gprel (temp, operands[1]));
"addl %0 = @gprel(%1), gp"
[(set_attr "type" "A")])
+(define_insn "gprel64_offset"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))]
+ ""
+ "movl %0 = @gprel(%1)"
+ [(set_attr "type" "L")])
+
+(define_expand "load_gprel64"
+ [(set (match_dup 2)
+ (minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))
+ (set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (reg:DI 1) (match_dup 2)))]
+ ""
+ "{
+ if (reload_in_progress)
+ operands[2] = operands[0];
+ else
+ operands[2] = gen_reg_rtx (DImode);
+}")
+
(define_expand "load_symptr"
[(set (match_dup 2)
(plus:DI (reg:DI 1) (match_operand:DI 1 "symbolic_operand" "")))
rtx addr = XEXP (operands[0], 0);
enum machine_mode mode = GET_MODE (addr);
- if (TARGET_NO_PIC)
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC)
emit_call_insn (gen_call_internal (addr, operands[1],
gen_rtx_REG (DImode, R_BR (0))));
/* If this is an indirect call, then we have the address of a descriptor. */
else if (! symbolic_operand (addr, mode))
emit_insn (gen_indirect_call_pic (addr, operands[1]));
+ else if (TARGET_CONST_GP)
+ emit_call_insn (gen_call_internal (addr, operands[1],
+ gen_rtx_REG (DImode, R_BR (0))));
/* ??? This is an unsatisfying solution. Should rethink. */
else if (setjmp_operand (addr, mode))
emit_insn (gen_setjmp_call_pic (addr, operands[1]));
rtx addr = XEXP (operands[1], 0);
enum machine_mode mode = GET_MODE (addr);
- if (TARGET_NO_PIC)
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC)
emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
gen_rtx_REG (DImode, R_BR (0))));
emit_insn (gen_indirect_call_value_pic (operands[0], addr,
operands[2]));
}
+ else if (TARGET_CONST_GP)
+ emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
+ gen_rtx_REG (DImode, R_BR (0))));
/* ??? This is an unsatisfying solution. Should rethink. */
else if (setjmp_operand (addr, mode))
emit_insn (gen_setjmp_call_value_pic (operands[0], addr, operands[2]));
#define DONT_USE_BUILTIN_SETJMP
#define JMP_BUF_SIZE (8 * 76)
+
+/* Output any profiling code before the prologue. */
+
+#undef PROFILE_BEFORE_PROLOGUE
+#define PROFILE_BEFORE_PROLOGUE 1
+
+/* A C statement or compound statement to output to FILE some assembler code to
+ call the profiling subroutine `mcount'. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+do { \
+ char buf[20]; \
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", LABELNO); \
+ fputs ("\talloc out0 = ar.pfs, 8, 0, 4, 0\n", FILE); \
+ if (TARGET_AUTO_PIC) \
+ fputs ("\tmovl out3 = @gprel(", FILE); \
+ else \
+ fputs ("\taddl out3 = @ltoff(", FILE); \
+ assemble_name (FILE, buf); \
+ if (TARGET_AUTO_PIC) \
+ fputs (");;\n", FILE); \
+ else \
+ fputs ("), r1;;\n", FILE); \
+ fputs ("\tmov out1 = r1\n", FILE); \
+ fputs ("\tmov out2 = b0\n", FILE); \
+ fputs ("\tbr.call.sptk.many b0 = _mcount;;\n", FILE); \
+} while (0)
+
/* End of linux.h */
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctors_section (); \
- fputs ("\tdata8\t @fptr(", FILE); \
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC) \
+ fputs ("\tdata8\t ", FILE); \
+ else \
+ fputs ("\tdata8\t @fptr(", FILE); \
assemble_name (FILE, NAME); \
- fputs (")\n", FILE); \
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC) \
+ fputs ("\n", FILE); \
+ else \
+ fputs (")\n", FILE); \
} while (0)
/* A C statement (sans semicolon) to output an element in the table of
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtors_section (); \
- fputs ("\tdata8\t @fptr(", FILE); \
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC) \
+ fputs ("\tdata8\t ", FILE); \
+ else \
+ fputs ("\tdata8\t @fptr(", FILE); \
assemble_name (FILE, NAME); \
- fputs (")\n", FILE); \
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC) \
+ fputs ("\n", FILE); \
+ else \
+ fputs (")\n", FILE); \
} while (0)
/* svr4.h undefines this, so we need to define it here. */