This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[c] fold offsetof by hand


This changes the C front end to fold offsetof to a number by hand,
rather than relying on build_unary_op of ADDR_EXPR to generate a
constant, rather than the address of a COMPONENT_REF.

This is currently redundant with pinskia's TREE_CONSTANT hack in
build_unary_op, which I don't like.

The C++ front end is considerably more wily.  I don't have the
proper placement for that yet.  But I expect to be able to use
fold_offsetof once templates get resolved properly, etc, etc, so
that's why fold_offsetof is in c-common.c.

Tested on i686-linux.


r~


        * c-typeck.c (build_offsetof): Remove.
        * c-tree.h (build_offsetof): Remove.
        * c-common.c (fold_offsetof_1, fold_offsetof): New.
        * c-common.h (fold_offsetof): Declare.
        * c-parse.in (offsetof_base): New.
        (offsetof_member_designator): Use it.  Build references, not just
        a tree list.
        (primary): Use fold_offsetof, not build_offsetof.

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.560
diff -c -p -d -r1.560 c-common.c
*** c-common.c	27 Aug 2004 00:27:21 -0000	1.560
--- c-common.c	27 Aug 2004 00:34:17 -0000
*************** c_warn_unused_result (tree *top_p)
*** 5436,5439 ****
--- 5436,5504 ----
      }
  }
  
+ /* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
+    component references, with an INDIRECT_REF at the bottom; much like
+    the traditional rendering of offsetof as a macro.  Returns the folded
+    and properly cast result.  */
+ 
+ static tree
+ fold_offsetof_1 (tree expr)
+ {
+   enum tree_code code = PLUS_EXPR;
+   tree base, off, t;
+ 
+   switch (TREE_CODE (expr))
+     {
+     case ERROR_MARK:
+       return expr;
+ 
+     case INDIRECT_REF:
+       return size_zero_node;
+ 
+     case COMPONENT_REF:
+       base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+       if (base == error_mark_node)
+ 	return base;
+ 
+       t = TREE_OPERAND (expr, 1);
+       if (DECL_C_BIT_FIELD (t))
+ 	{
+ 	  error ("attempt to take address of bit-field structure "
+ 		 "member `%s'", IDENTIFIER_POINTER (DECL_NAME (t)));
+ 	  return error_mark_node;
+ 	}
+       off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ 			size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
+ 				  / BITS_PER_UNIT));
+       break;
+ 
+     case ARRAY_REF:
+       base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+       if (base == error_mark_node)
+ 	return base;
+ 
+       t = TREE_OPERAND (expr, 1);
+       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
+ 	{
+ 	  code = MINUS_EXPR;
+ 	  t = fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t));
+ 	}
+       t = convert (sizetype, t);
+       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   return size_binop (code, base, off);
+ }
+ 
+ tree
+ fold_offsetof (tree expr)
+ {
+   /* Convert back from the internal sizetype to size_t.  */
+   return convert (size_type_node, fold_offsetof_1 (expr));
+ }
+ 
  #include "gt-c-common.h"
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.257
diff -c -p -d -r1.257 c-common.h
*** c-common.h	27 Aug 2004 00:27:23 -0000	1.257
--- c-common.h	27 Aug 2004 00:34:17 -0000
*************** extern void c_warn_unused_result (tree *
*** 870,875 ****
--- 870,877 ----
  
  extern void verify_sequence_points (tree);
  
+ extern tree fold_offsetof (tree);
+ 
  /* In c-gimplify.c  */
  extern void c_genericize (tree);
  extern int c_gimplify_expr (tree *, tree *, tree *);
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.230
diff -c -p -d -r1.230 c-parse.in
*** c-parse.in	26 Aug 2004 20:55:24 -0000	1.230
--- c-parse.in	27 Aug 2004 00:34:17 -0000
*************** static GTY(()) tree all_prefix_attribute
*** 275,280 ****
--- 275,283 ----
     all_prefix_attributes.  */
  static GTY(()) tree declspec_stack;
  
+ /* INDIRECT_REF with a TREE_TYPE of the type being queried for offsetof.  */
+ static tree offsetof_base;
+ 
  /* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
     should be called from the productions making use of setspecs.  */
  #define PUSH_DECLSPEC_STACK						 \
*************** primary:
*** 681,688 ****
  		{ $$.value = build_va_arg ($3.value, groktypename ($5));
  		  $$.original_code = ERROR_MARK; }
  
! 	| OFFSETOF '(' typename ',' offsetof_member_designator ')'
! 		{ $$.value = build_offsetof (groktypename ($3), $5);
  		  $$.original_code = ERROR_MARK; }
  	| OFFSETOF '(' error ')'
  		{ $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
--- 684,698 ----
  		{ $$.value = build_va_arg ($3.value, groktypename ($5));
  		  $$.original_code = ERROR_MARK; }
  
! 	| OFFSETOF '(' typename ','
! 		{ tree type = groktypename ($3);
! 		  if (type == error_mark_node)
! 		    offsetof_base = error_mark_node;
! 		  else
! 		    offsetof_base = build1 (INDIRECT_REF, type, NULL);
! 		}
! 	  offsetof_member_designator ')'
! 		{ $$.value = fold_offsetof ($6);
  		  $$.original_code = ERROR_MARK; }
  	| OFFSETOF '(' error ')'
  		{ $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
*************** primary:
*** 753,769 ****
  
  /* This is the second argument to __builtin_offsetof.  We must have one
     identifier, and beyond that we want to accept sub structure and sub
!    array references.  We return tree list where each element has
!    PURPOSE set for component refs or VALUE set for array refs.  We'll
!    turn this into something real inside build_offsetof.  */
  
  offsetof_member_designator:
  	  identifier
! 		{ $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
  	| offsetof_member_designator '.' identifier
! 		{ $$ = tree_cons ($3, NULL_TREE, $1); }
  	| offsetof_member_designator '[' expr ']'
! 		{ $$ = tree_cons (NULL_TREE, $3.value, $1); }
  	;
  
  old_style_parm_decls:
--- 763,777 ----
  
  /* This is the second argument to __builtin_offsetof.  We must have one
     identifier, and beyond that we want to accept sub structure and sub
!    array references.  */
  
  offsetof_member_designator:
  	  identifier
! 		{ $$ = build_component_ref (offsetof_base, $1); }
  	| offsetof_member_designator '.' identifier
! 		{ $$ = build_component_ref ($1, $3); }
  	| offsetof_member_designator '[' expr ']'
! 		{ $$ = build_array_ref ($1, $3.value); }
  	;
  
  old_style_parm_decls:
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.169
diff -c -p -d -r1.169 c-tree.h
*** c-tree.h	25 Aug 2004 23:39:11 -0000	1.169
--- c-tree.h	27 Aug 2004 00:34:17 -0000
*************** extern tree c_finish_return (tree);
*** 277,283 ****
  extern tree c_finish_bc_stmt (tree *, bool);
  extern tree c_finish_goto_label (tree);
  extern tree c_finish_goto_ptr (tree);
- extern tree build_offsetof (tree, tree);
  
  /* Set to 0 at beginning of a function definition, set to 1 if
     a return statement that specifies a return value is seen.  */
--- 277,282 ----
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.362
diff -c -p -d -r1.362 c-typeck.c
*** c-typeck.c	25 Aug 2004 20:38:51 -0000	1.362
--- c-typeck.c	27 Aug 2004 00:34:18 -0000
*************** build_binary_op (enum tree_code code, tr
*** 7583,7613 ****
      return result;
    }
  }
- 
- /* Build the result of __builtin_offsetof.  TYPE is the first argument to
-    offsetof, i.e. a type.  LIST is a tree_list that encodes component and
-    array references; PURPOSE is set for the former and VALUE is set for
-    the later.  */
- 
- tree
- build_offsetof (tree type, tree list)
- {
-   tree t;
- 
-   /* Build "*(type *)0".  */
-   t = convert (build_pointer_type (type), null_pointer_node);
-   t = build_indirect_ref (t, "");
- 
-   /* Build COMPONENT and ARRAY_REF expressions as needed.  */
-   for (list = nreverse (list); list ; list = TREE_CHAIN (list))
-     if (TREE_PURPOSE (list))
-       t = build_component_ref (t, TREE_PURPOSE (list));
-     else
-       t = build_array_ref (t, TREE_VALUE (list));
- 
-   /* Finalize the offsetof expression.  For now all we need to do is take
-      the address of the expression we created, and cast that to an integer
-      type; this mirrors the traditional macro implementation of offsetof.  */
-   t = build_unary_op (ADDR_EXPR, t, 0);
-   return convert (size_type_node, t);
- }
--- 7583,7585 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]