Patchwork remove build_function_call_expr

login
register
mail settings
Submitter Nathan Froyd
Date July 6, 2010, 1:50 a.m.
Message ID <20100706015036.GN17877@codesourcery.com>
Download mbox | patch
Permalink /patch/57962/
State New
Headers show

Comments

Nathan Froyd - July 6, 2010, 1:50 a.m.
The patch below continues the TREE_LIST removal by eliminating
build_function_call_expr calls and using array-ish interfaces instead.
We now have an even more dizzying array of ways to build CALL_EXPRs and
more confusing-named ways (quick, what's the difference between
build_call_expr and build_call_list?) but I don't see a better way.
Suggestions welcome.  (I'm pretty sure most of the call sites I modified
never actually get folded, so they could just as well use the
build_call_* functions in tree.c, but I'm not sure how to test for
that...)

Tested on x86_64-unknown-linux-gnu (all languages + Ada, libgomp, etc.).
There are some Fortran-specific pieces I need approval for.  OK to
commit?

-Nathan

gcc/
	* tree.h (build_function_call_expr): Delete.
	(build_call_expr_loc_array): New function.
	(build_call_expr_loc_vec): New function.
	* tree-flow.h (struct omp_region): Change type of ws_args field
	to a VEC.
	* builtins.c (build_function_call_expr): Delete.
	(build_call_expr_loc_array): New function.
	(build_call_expr_loc): Call it.  Use XALLOCAVEC.
	(build_call_expr): Likewise.
	(build_call_expr_loc_vec): New function.
	* cgraphunit.c (build_cdtor): Call build_call_expr instead of
	build_function_call_expr.
	* expr.c (emutls_var_address): Likewise.
	* varasm.c (emutls_common_1): Likewise.
	* omp-low.c (expand_omp_atomic_mutex): Likewise.
	(expand_omp_taskreg): Adjust for new type of region->ws_args.
	(get_ws_args_for): Return a VEC instead of a tree.
	(expand_parallel_call): Call build_call_expr_loc_vec instead of
	build_function_call_expr.
	* stor-layout.c (self_referential_size): Likewise.

gcc/fortran/
	* trans-decl.c (build_entry_thunks): Call build_call_expr_loc_vec
	instead of build_function_call_expr.
	* trans-intrinsic.c (gfc_conv_intrinsic_sr_kind): Likewise.
Diego Novillo - July 9, 2010, 8:26 p.m.
On Mon, Jul 5, 2010 at 21:50, Nathan Froyd <froydnj@codesourcery.com> wrote:

> gcc/
>        * tree.h (build_function_call_expr): Delete.
>        (build_call_expr_loc_array): New function.
>        (build_call_expr_loc_vec): New function.
>        * tree-flow.h (struct omp_region): Change type of ws_args field
>        to a VEC.
>        * builtins.c (build_function_call_expr): Delete.
>        (build_call_expr_loc_array): New function.
>        (build_call_expr_loc): Call it.  Use XALLOCAVEC.
>        (build_call_expr): Likewise.
>        (build_call_expr_loc_vec): New function.
>        * cgraphunit.c (build_cdtor): Call build_call_expr instead of
>        build_function_call_expr.
>        * expr.c (emutls_var_address): Likewise.
>        * varasm.c (emutls_common_1): Likewise.
>        * omp-low.c (expand_omp_atomic_mutex): Likewise.
>        (expand_omp_taskreg): Adjust for new type of region->ws_args.
>        (get_ws_args_for): Return a VEC instead of a tree.
>        (expand_parallel_call): Call build_call_expr_loc_vec instead of
>        build_function_call_expr.
>        * stor-layout.c (self_referential_size): Likewise.
>
> gcc/fortran/
>        * trans-decl.c (build_entry_thunks): Call build_call_expr_loc_vec
>        instead of build_function_call_expr.
>        * trans-intrinsic.c (gfc_conv_intrinsic_sr_kind): Likewise.

OK.


Diego.

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 046593e..0bb9383 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -10676,23 +10676,31 @@  fold_call_expr (location_t loc, tree exp, bool ignore)
 }
 
 /* Conveniently construct a function call expression.  FNDECL names the
-    function to be called and ARGLIST is a TREE_LIST of arguments.  */
+   function to be called and N arguments are passed in the array
+   ARGARRAY.  */
 
 tree
-build_function_call_expr (location_t loc, tree fndecl, tree arglist)
+build_call_expr_loc_array (location_t loc, tree fndecl, int n, tree *argarray)
 {
   tree fntype = TREE_TYPE (fndecl);
   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
-  int n = list_length (arglist);
-  tree *argarray = (tree *) alloca (n * sizeof (tree));
-  int i;
-
-  for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
-    argarray[i] = TREE_VALUE (arglist);
+ 
   return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
 }
 
 /* Conveniently construct a function call expression.  FNDECL names the
+   function to be called and the arguments are passed in the vector
+   VEC.  */
+
+tree
+build_call_expr_loc_vec (location_t loc, tree fndecl, VEC(tree,gc) *vec)
+{
+  return build_call_expr_loc_array (loc, fndecl, VEC_length (tree, vec),
+				    VEC_address (tree, vec));
+}
+
+
+/* Conveniently construct a function call expression.  FNDECL names the
    function to be called, N is the number of arguments, and the "..."
    parameters are the argument expressions.  */
 
@@ -10700,16 +10708,14 @@  tree
 build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
 {
   va_list ap;
-  tree fntype = TREE_TYPE (fndecl);
-  tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
-  tree *argarray = (tree *) alloca (n * sizeof (tree));
+  tree *argarray = XALLOCAVEC (tree, n);
   int i;
 
   va_start (ap, n);
   for (i = 0; i < n; i++)
     argarray[i] = va_arg (ap, tree);
   va_end (ap);
-  return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
+  return build_call_expr_loc_array (loc, fndecl, n, argarray);
 }
 
 /* Like build_call_expr_loc (UNKNOWN_LOCATION, ...).  Duplicated because
@@ -10719,17 +10725,14 @@  tree
 build_call_expr (tree fndecl, int n, ...)
 {
   va_list ap;
-  tree fntype = TREE_TYPE (fndecl);
-  tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
-  tree *argarray = (tree *) alloca (n * sizeof (tree));
+  tree *argarray = XALLOCAVEC (tree, n);
   int i;
 
   va_start (ap, n);
   for (i = 0; i < n; i++)
     argarray[i] = va_arg (ap, tree);
   va_end (ap);
-  return fold_builtin_call_array (UNKNOWN_LOCATION, TREE_TYPE (fntype),
-				  fn, n, argarray);
+  return build_call_expr_loc_array (UNKNOWN_LOCATION, fndecl, n, argarray);
 }
 
 /* Construct a CALL_EXPR with type TYPE with FN as the function expression.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 2988f1c..64f2798 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -210,15 +210,15 @@  build_cdtor (bool ctor_p, tree *cdtors, size_t len)
       do
 	{
 	  priority_type p;
+	  tree call;
 	  fn = cdtors[i];
 	  p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
 	  if (!body)
 	    priority = p;
 	  else if (p != priority)
 	    break;
-	  append_to_statement_list (build_function_call_expr (UNKNOWN_LOCATION,
-							      fn, 0),
-				    &body);
+	  call = build_call_expr (fn, 0);
+	  append_to_statement_list (call, &body);
 	  ++i;
 	}
       while (i < len);
diff --git a/gcc/expr.c b/gcc/expr.c
index a43d708..d7144d3 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6837,8 +6837,7 @@  emutls_var_address (tree var)
   tree emuvar = emutls_decl (var);
   tree fn = built_in_decls [BUILT_IN_EMUTLS_GET_ADDRESS];
   tree arg = build_fold_addr_expr_with_type (emuvar, ptr_type_node);
-  tree arglist = build_tree_list (NULL_TREE, arg);
-  tree call = build_function_call_expr (UNKNOWN_LOCATION, fn, arglist);
+  tree call = build_call_expr (fn, 1, arg);
   return fold_convert (build_pointer_type (TREE_TYPE (var)), call);
 }
 
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 1c7226c..447a73e 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1980,8 +1980,6 @@  build_entry_thunks (gfc_namespace * ns)
   gfc_symbol *thunk_sym;
   stmtblock_t body;
   tree thunk_fndecl;
-  tree args;
-  tree string_args;
   tree tmp;
   locus old_loc;
 
@@ -1991,6 +1989,9 @@  build_entry_thunks (gfc_namespace * ns)
   gfc_get_backend_locus (&old_loc);
   for (el = ns->entries; el; el = el->next)
     {
+      VEC(tree,gc) *args = NULL;
+      VEC(tree,gc) *string_args = NULL;
+
       thunk_sym = el->sym;
       
       build_function_decl (thunk_sym);
@@ -2004,18 +2005,16 @@  build_entry_thunks (gfc_namespace * ns)
 
       /* Pass extra parameter identifying this entry point.  */
       tmp = build_int_cst (gfc_array_index_type, el->id);
-      args = tree_cons (NULL_TREE, tmp, NULL_TREE);
-      string_args = NULL_TREE;
+      VEC_safe_push (tree, gc, args, tmp);
 
       if (thunk_sym->attr.function)
 	{
 	  if (gfc_return_by_reference (ns->proc_name))
 	    {
 	      tree ref = DECL_ARGUMENTS (current_function_decl);
-	      args = tree_cons (NULL_TREE, ref, args);
+	      VEC_safe_push (tree, gc, args, ref);
 	      if (ns->proc_name->ts.type == BT_CHARACTER)
-		args = tree_cons (NULL_TREE, TREE_CHAIN (ref),
-				  args);
+		VEC_safe_push (tree, gc, args, TREE_CHAIN (ref));
 	    }
 	}
 
@@ -2039,31 +2038,29 @@  build_entry_thunks (gfc_namespace * ns)
 	    {
 	      /* Pass the argument.  */
 	      DECL_ARTIFICIAL (thunk_formal->sym->backend_decl) = 1;
-	      args = tree_cons (NULL_TREE, thunk_formal->sym->backend_decl,
-				args);
+	      VEC_safe_push (tree, gc, args, thunk_formal->sym->backend_decl);
 	      if (formal->sym->ts.type == BT_CHARACTER)
 		{
 		  tmp = thunk_formal->sym->ts.u.cl->backend_decl;
-		  string_args = tree_cons (NULL_TREE, tmp, string_args);
+		  VEC_safe_push (tree, gc, string_args, tmp);
 		}
 	    }
 	  else
 	    {
 	      /* Pass NULL for a missing argument.  */
-	      args = tree_cons (NULL_TREE, null_pointer_node, args);
+	      VEC_safe_push (tree, gc, args, null_pointer_node);
 	      if (formal->sym->ts.type == BT_CHARACTER)
 		{
 		  tmp = build_int_cst (gfc_charlen_type_node, 0);
-		  string_args = tree_cons (NULL_TREE, tmp, string_args);
+		  VEC_safe_push (tree, gc, string_args, tmp);
 		}
 	    }
 	}
 
       /* Call the master function.  */
-      args = nreverse (args);
-      args = chainon (args, nreverse (string_args));
+      VEC_safe_splice (tree, gc, args, string_args);
       tmp = ns->proc_name->backend_decl;
-      tmp = build_function_call_expr (input_location, tmp, args);
+      tmp = build_call_expr_loc_vec (input_location, tmp, args);
       if (ns->proc_name->attr.mixed_entry_master)
 	{
 	  tree union_decl, field;
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 7f583da..6938bcc 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -4567,10 +4567,10 @@  static void
 gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
 {
   gfc_actual_arglist *actual;
-  tree args, type;
+  tree type;
   gfc_se argse;
+  VEC(tree,gc) *args = NULL;
 
-  args = NULL_TREE;
   for (actual = expr->value.function.actual; actual; actual = actual->next)
     {
       gfc_init_se (&argse, se);
@@ -4595,13 +4595,13 @@  gfc_conv_intrinsic_sr_kind (gfc_se *se, gfc_expr *expr)
 
       gfc_add_block_to_block (&se->pre, &argse.pre);
       gfc_add_block_to_block (&se->post, &argse.post);
-      args = gfc_chainon_list (args, argse.expr);
+      VEC_safe_push (tree, gc, args, argse.expr);
     }
 
   /* Convert it to the required type.  */
   type = gfc_typenode_for_spec (&expr->ts);
-  se->expr = build_function_call_expr (input_location,
-				       gfor_fndecl_sr_kind, args);
+  se->expr = build_call_expr_loc_vec (input_location,
+				      gfor_fndecl_sr_kind, args);
   se->expr = fold_convert (type, se->expr);
 }
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index eca27c8..cd5faf6 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -555,34 +555,35 @@  workshare_safe_to_combine_p (basic_block ws_entry_bb)
    parallel+workshare call.  WS_STMT is the workshare directive being
    expanded.  */
 
-static tree
+static VEC(tree,gc) *
 get_ws_args_for (gimple ws_stmt)
 {
   tree t;
   location_t loc = gimple_location (ws_stmt);
+  VEC(tree,gc) *ws_args;
 
   if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
     {
       struct omp_for_data fd;
-      tree ws_args;
 
       extract_omp_for_data (ws_stmt, &fd, NULL);
 
-      ws_args = NULL_TREE;
-      if (fd.chunk_size)
-	{
-	  t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
-	  ws_args = tree_cons (NULL, t, ws_args);
-	}
+      ws_args = VEC_alloc (tree, gc, 3 + (fd.chunk_size != 0));
 
-      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
-      ws_args = tree_cons (NULL, t, ws_args);
+      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
+      VEC_quick_push (tree, ws_args, t);
 
       t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
-      ws_args = tree_cons (NULL, t, ws_args);
+      VEC_quick_push (tree, ws_args, t);
 
-      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
-      ws_args = tree_cons (NULL, t, ws_args);
+      t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
+      VEC_quick_push (tree, ws_args, t);
+
+      if (fd.chunk_size)
+	{
+	  t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
+	  VEC_quick_push (tree, ws_args, t);
+	}
 
       return ws_args;
     }
@@ -593,8 +594,9 @@  get_ws_args_for (gimple ws_stmt)
 	 the exit of the sections region.  */
       basic_block bb = single_succ (gimple_bb (ws_stmt));
       t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
-      t = tree_cons (NULL, t, NULL);
-      return t;
+      ws_args = VEC_alloc (tree, gc, 1);
+      VEC_quick_push (tree, ws_args, t);
+      return ws_args;
     }
 
   gcc_unreachable ();
@@ -2899,13 +2901,14 @@  gimple_build_cond_empty (tree cond)
 
 static void
 expand_parallel_call (struct omp_region *region, basic_block bb,
-		      gimple entry_stmt, tree ws_args)
+		      gimple entry_stmt, VEC(tree,gc) *ws_args)
 {
   tree t, t1, t2, val, cond, c, clauses;
   gimple_stmt_iterator gsi;
   gimple stmt;
   int start_ix;
   location_t clause_loc;
+  VEC(tree,gc) *args;
 
   clauses = gimple_omp_parallel_clauses (entry_stmt);
 
@@ -3036,16 +3039,14 @@  expand_parallel_call (struct omp_region *region, basic_block bb,
     t1 = build_fold_addr_expr (t);
   t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
 
-  if (ws_args)
-    {
-      tree args = tree_cons (NULL, t2,
-			     tree_cons (NULL, t1,
-					tree_cons (NULL, val, ws_args)));
-      t = build_function_call_expr (UNKNOWN_LOCATION,
-				    built_in_decls[start_ix], args);
-    }
-  else
-    t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val);
+  args = VEC_alloc (tree, gc, 3 + VEC_length (tree, ws_args));
+  VEC_quick_push (tree, args, t2);
+  VEC_quick_push (tree, args, t1);
+  VEC_quick_push (tree, args, val);
+  VEC_splice (tree, args, ws_args);
+
+  t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
+			       built_in_decls[start_ix], args);
 
   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
 			    false, GSI_CONTINUE_LINKING);
@@ -3334,11 +3335,12 @@  expand_omp_taskreg (struct omp_region *region)
 {
   basic_block entry_bb, exit_bb, new_bb;
   struct function *child_cfun;
-  tree child_fn, block, t, ws_args, *tp;
+  tree child_fn, block, t, *tp;
   tree save_current;
   gimple_stmt_iterator gsi;
   gimple entry_stmt, stmt;
   edge e;
+  VEC(tree,gc) *ws_args;
 
   entry_stmt = last_stmt (region->entry);
   child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
@@ -3353,7 +3355,7 @@  expand_omp_taskreg (struct omp_region *region)
   if (is_combined_parallel (region))
     ws_args = region->ws_args;
   else
-    ws_args = NULL_TREE;
+    ws_args = NULL;
 
   if (child_cfun->cfg)
     {
@@ -5225,7 +5227,7 @@  expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
 
   t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
-  t = build_function_call_expr (UNKNOWN_LOCATION, t, 0);
+  t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
 
   stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
@@ -5240,7 +5242,7 @@  expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
 
   t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
-  t = build_function_call_expr (UNKNOWN_LOCATION, t, 0);
+  t = build_call_expr (t, 0);
   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 89f5fa9..a9acf1e 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -233,10 +233,11 @@  self_referential_size (tree size)
 {
   static unsigned HOST_WIDE_INT fnno = 0;
   VEC (tree, heap) *self_refs = NULL;
-  tree param_type_list = NULL, param_decl_list = NULL, arg_list = NULL;
+  tree param_type_list = NULL, param_decl_list = NULL;
   tree t, ref, return_type, fntype, fnname, fndecl;
   unsigned int i;
   char buf[128];
+  VEC(tree,gc) *args = NULL;
 
   /* Do not factor out simple operations.  */
   t = skip_simple_arithmetic (size);
@@ -255,6 +256,7 @@  self_referential_size (tree size)
 
   /* Build the parameter and argument lists in parallel; also
      substitute the former for the latter in the expression.  */
+  args = VEC_alloc (tree, gc, VEC_length (tree, self_refs));
   for (i = 0; VEC_iterate (tree, self_refs, i, ref); i++)
     {
       tree subst, param_name, param_type, param_decl;
@@ -290,7 +292,7 @@  self_referential_size (tree size)
 
       param_type_list = tree_cons (NULL_TREE, param_type, param_type_list);
       param_decl_list = chainon (param_decl, param_decl_list);
-      arg_list = tree_cons (NULL_TREE, ref, arg_list);
+      VEC_quick_push (tree, args, ref);
     }
 
   VEC_free (tree, heap, self_refs);
@@ -301,7 +303,6 @@  self_referential_size (tree size)
   /* The 3 lists have been created in reverse order.  */
   param_type_list = nreverse (param_type_list);
   param_decl_list = nreverse (param_decl_list);
-  arg_list = nreverse (arg_list);
 
   /* Build the function type.  */
   return_type = TREE_TYPE (size);
@@ -342,7 +343,7 @@  self_referential_size (tree size)
   VEC_safe_push (tree, gc, size_functions, fndecl);
 
   /* Replace the original expression with a call to the size function.  */
-  return build_function_call_expr (UNKNOWN_LOCATION, fndecl, arg_list);
+  return build_call_expr_loc_vec (input_location, fndecl, args);
 }
 
 /* Take, queue and compile all the size functions.  It is essential that
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index fd9a542..6b12d08 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -368,7 +368,7 @@  struct omp_region
   /* If this is a combined parallel+workshare region, this is a list
      of additional arguments needed by the combined parallel+workshare
      library call.  */
-  tree ws_args;
+  VEC(tree,gc) *ws_args;
 
   /* The code for the omp directive of this region.  */
   enum gimple_code type;
diff --git a/gcc/tree.h b/gcc/tree.h
index 59f6b3a..1b1c3f2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5018,8 +5018,9 @@  extern tree fold_builtin_strncpy_chk (location_t, tree, tree, tree, tree, tree);
 extern tree fold_builtin_snprintf_chk (location_t, tree, tree, enum built_in_function);
 extern bool fold_builtin_next_arg (tree, bool);
 extern enum built_in_function builtin_mathfn_code (const_tree);
-extern tree build_function_call_expr (location_t, tree, tree);
 extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
+extern tree build_call_expr_loc_array (location_t, tree, int, tree *);
+extern tree build_call_expr_loc_vec (location_t, tree, VEC(tree,gc) *);
 extern tree build_call_expr_loc (location_t, tree, int, ...);
 extern tree build_call_expr (tree, int, ...);
 extern tree mathfn_built_in (tree, enum built_in_function fn);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index f9a9d97..280e748 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -428,7 +428,7 @@  static int
 emutls_common_1 (void **loc, void *xstmts)
 {
   struct tree_map *h = *(struct tree_map **) loc;
-  tree args, x, *pstmts = (tree *) xstmts;
+  tree x, *pstmts = (tree *) xstmts;
   tree word_type_node;
 
   if (! DECL_COMMON (h->base.from)
@@ -442,17 +442,14 @@  emutls_common_1 (void **loc, void *xstmts)
      do this and there is an initializer, -fanchor_section loses,
      because it would be too late to ensure the template is
      output.  */
-  x = null_pointer_node;
-  args = tree_cons (NULL, x, NULL);
-  x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->base.from));
-  args = tree_cons (NULL, x, args);
-  x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->base.from));
-  args = tree_cons (NULL, x, args);
-  x = build_fold_addr_expr (h->to);
-  args = tree_cons (NULL, x, args);
-
   x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON];
-  x = build_function_call_expr (UNKNOWN_LOCATION, x, args);
+  x = build_call_expr (x, 4,
+		       build_fold_addr_expr (h->to),
+		       fold_convert (word_type_node,
+				     DECL_SIZE_UNIT (h->base.from)),
+		       build_int_cst (word_type_node,
+				      DECL_ALIGN_UNIT (h->base.from)),
+		       null_pointer_node);
 
   append_to_statement_list (x, pstmts);
   return 1;