Various changes for PIC code on ARM...

Scott Bambrough scottb@corelcomputer.com
Wed Feb 24 06:03:00 GMT 1999


Good day,

The following patches are Corel's changes to get PIC code generation for ELF on
ARMLinux.  These should be used with patches submitted earlier by Phil Blundell.

Scott

1999-02-16  Scott Bambrough <scottb@corelcomputer.com>

        * gcc/config/arm/arm.c: Various changes for PIC code generation. 
Modified
        generated calls to abort to be PLT based if PIC compilation.

        * gcc/config/arm/arm.h: Added SYMBOL_REF_LOCAL.  Needed to distinguish 
        between cases which require GOT or GOTOFF relocs.  Modified macro 
        OUTPUT_INST_ADDR_CONST to use GOT and GOTOFF relocs during PIC
compilation.

        * gcc/config/arm/arm.md: Added wrapper around constant pool generation
        (bMakingConstTable).  Need to know, in order to generate GOT or GOTOFF
        references to the data.  Other changes to generate PLT based calls to 
        symbols when compiling PIC code.
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/arm/arm.c,v
retrieving revision 1.26
diff -u -p -r1.26 arm.c
--- arm.c	1999/02/13 05:41:15	1.26
+++ arm.c	1999/02/16 15:53:24
@@ -68,6 +68,9 @@ static void emit_multi_reg_push PROTO ((
 static void emit_sfm PROTO ((int, int));
 static enum arm_cond_code get_arm_condition_code PROTO ((rtx));
 
+/* help with managing pic data labels. */
+int bMakingConstTable = 0;
+
 /*  Define the information needed to generate branch insns.  This is
    stored from the compare operation. */
 
@@ -1254,7 +1257,7 @@ legitimize_pic_address (orig, mode, reg)
      enum machine_mode mode;
      rtx reg;
 {
-  if (GET_CODE (orig) == SYMBOL_REF)
+  if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
     {
       rtx pic_ref, address;
       rtx insn;
@@ -1282,10 +1285,14 @@ legitimize_pic_address (orig, mode, reg)
 	address = reg;
 
       emit_insn (gen_pic_load_addr (address, orig));
+      
+      /* calculate the address */
+      pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
+      
+      /* for global data (GOT based), we need to dereference this. */
+      if (!SYMBOL_REF_LOCAL(orig) && GET_CODE(orig) != LABEL_REF)
+        pic_ref = gen_rtx_MEM (Pmode, pic_ref);
 
-      pic_ref = gen_rtx_MEM (Pmode,
-			     gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
-					   address));
       RTX_UNCHANGING_P (pic_ref) = 1;
       insn = emit_move_insn (reg, pic_ref);
 #endif
@@ -1347,8 +1354,6 @@ legitimize_pic_address (orig, mode, reg)
 
       return gen_rtx_PLUS (Pmode, base, offset);
     }
-  else if (GET_CODE (orig) == LABEL_REF)
-    current_function_uses_pic_offset_table = 1;
 
   return orig;
 }
@@ -1385,8 +1390,7 @@ arm_finalize_pic ()
      instruction, so the offset is only 'dot'+4.  */
   pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1),
 			   GEN_INT (4));
-  pic_tmp2 = gen_rtx_CONST (VOIDmode,
-			    gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
+  pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
 
   pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
 
@@ -4877,7 +4881,10 @@ output_return_instruction (operand, real
 
       /* Otherwise, trap an attempted return by aborting. */
       ops[0] = operand;
-      ops[1] = gen_rtx_SYMBOL_REF (Pmode, "abort");
+      if (flag_pic)
+      	ops[1] = gen_rtx_SYMBOL_REF (Pmode, "abort(PLT)");
+      else
+      	ops[1] = gen_rtx_SYMBOL_REF (Pmode, "abort");
       assemble_external_libcall (ops[1]);
       output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
       return "";
@@ -5086,7 +5093,11 @@ output_func_epilogue (f, frame_size)
   /* A volatile function should never return.  Call abort.  */
   if (TARGET_ABORT_NORETURN && volatile_func)
     {
-      rtx op = gen_rtx_SYMBOL_REF (Pmode, "abort");
+      rtx op;
+      if (flag_pic)
+        op = gen_rtx_SYMBOL_REF (Pmode, "abort(PLT)");
+      else
+        op = gen_rtx_SYMBOL_REF (Pmode, "abort");
       assemble_external_libcall (op);
       output_asm_insn ("bl\t%a0", &op);
       goto epilogue_done;
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/arm/arm.h,v
retrieving revision 1.22
diff -u -p -r1.22 arm.h
--- arm.h	1999/02/13 05:41:18	1.22
+++ arm.h	1999/02/16 15:53:26
@@ -711,6 +711,13 @@ extern char * structure_size_string;
   1,1,1			     \
 }
 
+/* If compiling PIC, and if SYMBOL_REF is global, we need to mark it for 
+   inclusion in the GOT.  This is the default.  If the SYMBOL_REF is 
+   pointing to static data or a function, we can refer to it without a 
+   GOT entry; this possibility is marked by setting the rtx->jump bit
+   (using the SYMBOL_REF_LOCAL macro). */
+#define SYMBOL_REF_LOCAL (X)	((X)->jump)
+
 /* If doing stupid life analysis, avoid a bug causing a return value r0 to be
    trampled.  This effectively reduces the number of available registers by 1.
    XXX It is a hack, I know.
@@ -1345,25 +1352,37 @@ do {									\
    On the ARM, allow any integer (invalid ones are removed later by insn
    patterns), nice doubles and symbol_refs which refer to the function's
    constant pool XXX.  */
-#define LEGITIMATE_CONSTANT_P(X)	(! label_mentioned_p (X))
+#define LEGITIMATE_CONSTANT_P(X)	(flag_pic || ! label_mentioned_p (X))
 
 /* Symbols in the text segment can be accessed without indirecting via the
    constant pool; it may take an extra binary operation, but this is still
    faster than indirecting via memory.  Don't do this when not optimizing,
    since we won't be calculating al of the offsets necessary to do this
-   simplification.  */
+   simplification.
+   
+   In addition for PIC, we try to determine early whether the symbol is
+   global or static.  A global symbol needs a GOT entry, while the static
+   symbol can be referenced using an offset from the GOT (GOTOFF reloc).
+   Such static symbols are marked with SYMBOL_REF_LOCAL().  */
+   
 /* This doesn't work with AOF syntax, since the string table may be in
    a different AREA.  */
 #ifndef AOF_ASSEMBLER
 #define ENCODE_SECTION_INFO(decl)					\
 {									\
+  rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')			\
+            ? TREE_CST_RTL (decl) : DECL_RTL (decl));			\
   if (optimize > 0 && TREE_CONSTANT (decl)				\
       && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))	\
     {									\
-      rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'		\
-                 ? TREE_CST_RTL (decl) : DECL_RTL (decl));		\
       SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;				\
     }									\
+  if (flag_pic)								\
+    {									\
+      SYMBOL_REF_LOCAL (XEXP (rtl, 0))					\
+        = (TREE_CODE_CLASS( TREE_CODE (decl) != 'd'			\
+        		    || ! TREE_PUBLIC (decl));			\
+    }									\
 }
 #endif
 
@@ -1782,12 +1801,16 @@ extern int arm_pic_register;
 /* We can't directly access anything that contains a symbol, nor can
    we indirect via the constant pool */
 #define LEGITIMATE_PIC_OPERAND_P(X)				\
-	(! symbol_mentioned_p (X)				\
+	(! symbol_mentioned_p (X) && ! label_mentioned_p (X)	\
 	 && (! CONSTANT_POOL_ADDRESS_P (X)			\
 	     || ! symbol_mentioned_p (get_pool_constant (X))))
  
+#define SYMBOLIC_CONST(x)					\	
+	(GET_CODE(x) == SYMBOL_REF(x)				\
+	|| GET_CODE(x) == LABEL_REF				\
+	|| symbol_mentioned_p(x)				\
+	|| label_mentioned_p(x))				
 
-
 /* Condition code information. */
 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
    return the mode to be used for the comparison. 
@@ -2010,7 +2033,26 @@ extern int arm_compare_fp;
   else output_addr_const(STREAM, X);					\
 }
 
-/* Handles PIC addr specially */
+/* We need to know when we are making a constant pool; this data
+   needs to be in the GOT or referenced via a GOT offset. */
+extern in bMakingConstTable;
+
+/* Handles PIC addr specially
+
+   This code was inspired by the i386 version.  
+   
+   Note: We only do GOT dereferencing for pointer/symbols in the 
+   	 .text segment.
+   	 
+   The first "if" statement handles the _GLOBAL_OFFSET_TABLE_ entry.
+   The second "if" statement handles any symbols which need to be in 
+   the GOT (GOT) or referenced via an offset from the GOT (GOTOFF).
+   
+   Note: PatB <patb@corelcomputer.com>
+   Think the 16th/17th line of the macro about CONSTANT_POOL_ADDRESS 
+   will never trigger, as our arm.md will never generate SYMBOL_REF
+   int_addr which points into the CONSTANT_POOL. */
+
 #define OUTPUT_INT_ADDR_CONST(STREAM,X) \
   {									\
     if (flag_pic && GET_CODE(X) == CONST && is_pic(X))			\
@@ -2021,6 +2063,21 @@ extern int arm_compare_fp;
 	fputs(")", STREAM);						\
       }									\
     else output_addr_const(STREAM, X);					\
+ 									\
+    /* Mark symbols as position independent.  We only do this in the	\
+      .text segment, not in the .data segment. */			\
+    if (flag_pic && bMakingConstTable &&				\
+    	GET_CODE(X) == SYMBOL_REF || GET_CODE(X) == LABEL_REF))		\
+      {									\
+        if (GET_CODE(X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P(X)	\
+          fprintf(STREAM,"(GOTOFF)");					\
+        else if (GET_CODE(X) == LABEL_REF)				\
+          fprintf(STREAM,"(GOTOFF)");					\
+        else if (SYMBOL_REF_LOCAL(X))					\
+          fprintf(STREAM,"(GOTOFF)");					\
+        else								\
+          fprintf(STREAM,"(GOT)");					\
+     }									\
   }
 
 /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Index: gcc/config/arm/arm.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/arm/arm.md,v
retrieving revision 1.15
diff -u -p -r1.15 arm.md
--- arm.md	1999/02/13 05:41:17	1.15
+++ arm.md	1999/02/16 15:53:42
@@ -2637,7 +2637,9 @@
 			   : preserve_subexpressions_p ()));
       DONE;
     }
-  if (CONSTANT_P (operands[1]) && flag_pic)
+  /* In PIC code, process anything involving a SYMBOL_REF or
+     a LABEL_REF. */
+  if (flag_pic && SYMBOLIC_CONST (operands[1]))
     operands[1] = legitimize_pic_address (operands[1], SImode,
 					  ((reload_in_progress
 					    || reload_completed)
@@ -4273,7 +4275,13 @@
 	 (match_operand:SI 1 "general_operand" "g"))
    (clobber (reg:SI 14))]
   "GET_CODE (operands[0]) == SYMBOL_REF"
-  "bl%?\\t%a0"
+  "*
+  {
+    if (flag_pic)
+      return \"bl%?\\t%a0(PLT)\";
+    else
+      return \"bl%?\\t%a0\";
+  }"
 [(set_attr "type" "call")])
 
 (define_insn "*call_value_symbol"
@@ -4282,7 +4290,13 @@
 	(match_operand:SI 2 "general_operand" "g")))
    (clobber (reg:SI 14))]
   "GET_CODE(operands[1]) == SYMBOL_REF"
-  "bl%?\\t%a1"
+  "*
+  {
+    if (flag_pic)
+      return \"bl%?\\t%a1(PLT)\";
+    else
+      return \"bl%?\\t%a1\";
+  }"
 [(set_attr "type" "call")])
 
 ;; Often the return insn will be the same as loading from memory, so set attr
@@ -6012,7 +6026,10 @@
   }
 
   output_return_instruction (NULL, FALSE, FALSE);
-  return \"b%?\\t%a0\";
+  if (flag_pic)
+    return \"b%?\\t%a0(PLT)\";
+  else
+    return \"b%?\\t%a0\";
 }"
 [(set_attr "type" "call")
  (set_attr "length" "8")])
@@ -6040,7 +6057,10 @@
   }
 
   output_return_instruction (NULL, FALSE, FALSE);
-  return \"b%?\\t%a1\";
+  if (flag_pic)
+    return \"b%?\\t%a1(PLT)\";
+  else
+    return \"b%?\\t%a1\";
 }"
 [(set_attr "type" "call")
  (set_attr "length" "8")])
@@ -6239,6 +6259,7 @@
   ""
   "*
 {
+  bMakingConstTable = TRUE;
   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
     {
     case MODE_FLOAT:
@@ -6261,6 +6282,7 @@
   ""
   "*
 {
+  bMakingConstTable = TRUE;
   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
     {
     case MODE_FLOAT:
@@ -6282,7 +6304,7 @@
   [(unspec_volatile [(const_int 0)] 4)]
   ""
   "*
-  /* Nothing to do (currently).  */
+  bMakingConstTable = FALSE;
   return \"\";
 ")
 


More information about the Gcc-patches mailing list