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]

Re: allow certain kinds of inputs to top level asm()-s


On Tue, Jul 6, 2010 at 9:39 AM, Jan Beulich <JBeulich@novell.com> wrote:
> This is so that use of symbols referenced in these asm()-s can be
> properly tracked by the compiler, just like is the case for all other
> asm()-s. I'm particularly looking forward to use this in the Linux
> kernel.

Can you split up the patch please?  The LTO parts look like a useful
cleanup not related to the core patch.

Thanks,
Richard.

> gcc/
> 2010-07-06 ?Jan Beulich ?<jbeulich@novell.com>
>
> ? ? ? ?* c-parser.c: New second parameter of
> ? ? ? ?c_parser_simple_asm_expr().
> ? ? ? ?Change c_parser_asm_operands()' second parameter's type to
> ? ? ? ?'int'.
> ? ? ? ?(c_parser_declaration_or_fndef): Adjust call to
> ? ? ? ?c_parser_simple_asm_expr().
> ? ? ? ?(c_parser_asm_definition): Obtain and pass inputs.
> ? ? ? ?(c_parser_simple_asm_expr): Adjust simple-asm-expr definition.
> ? ? ? ?New second parameter. Handle optional inputs if requested.
> ? ? ? ?(c_parser_asm_statement): Adjust calls to
> ? ? ? ?c_parser_asm_operands().
> ? ? ? ?(c_parser_asm_statement): Adjust comment. Change second
> ? ? ? ?parameter's type to 'int'. Call c_parser_expr_no_commas()
> ? ? ? ?instead of c_parser_expression() when 'mode' is negative.
> ? ? ? ?* cgraph.c (cgraph_add_asm_node): New parameters 'inputs' and
> ? ? ? ?'loc'. Call check_unique_operand_names(). Initialize new fields
> ? ? ? ?of 'node'.
> ? ? ? ?* cgraph.h (struct cgraph_asm_node): New members 'inputs' and
> ? ? ? ?'loc'.
> ? ? ? ?(cgraph_add_asm_node): New parameters 'inputs' and 'loc'.
> ? ? ? ?* cgraphunit.c (cgraph_output_pending_asms): Adjust call to
> ? ? ? ?assemble_asm().
> ? ? ? ?(process_function_and_variable_attributes): Process inputs of
> ? ? ? ?all asm nodes.
> ? ? ? ?(cgraph_output_in_order): Adjust call to assemble_asm().
> ? ? ? ?* lto-cgraph.c (output_cgraph): Call lto_output_toplevel_asms()
> ? ? ? ?instead of emitting top level asm-s here.
> ? ? ? ?(input_cgraph_1): Call lto_input_toplevel_asms() instead of
> ? ? ? ?reading in top level asm-s here.
> ? ? ? ?* lto-section-in.c (lto_section_name): Add name for asm-s'
> ? ? ? ?section.
> ? ? ? ?* lto-streamer-in.c (lto_input_toplevel_asms): New.
> ? ? ? ?* lto-streamer-out.c (lto_output_toplevel_asms): New.
> ? ? ? ?* lto-streamer.c (lto_get_section_name): Handle
> ? ? ? ?LTO_section_asm.
> ? ? ? ?* lto-streamer.h (LTO_minor_version): Bump.
> ? ? ? ?(enum lto_section_type): Add LTO_section_asm.
> ? ? ? ?(struct lto_asm_header): New.
> ? ? ? ?(lto_input_toplevel_asms): Declare.
> ? ? ? ?(lto_output_toplevel_asms): Declare.
> ? ? ? ?* output.h (assemble_asm): New second and third parameter.
> ? ? ? ?* stmt.c (check_unique_operand_names): No longer static.
> ? ? ? ?* tree.h (check_unique_operand_names): Declare.
> ? ? ? ?* varasm.c: Include pretty-print.h.
> ? ? ? ?(assemble_asm): New parameters 'inputs' and 'loc'. Handle
> ? ? ? ?inputs.
>
> gcc/cp/
> 2010-07-06 ?Jan Beulich ?<jbeulich@novell.com>
>
> ? ? ? ?* parser.c (cp_parser_asm_definition): Correct a comment.
> ? ? ? ?Process optional inputs.
>
> gcc/testsuite/
> 2010-07-06 ?Jan Beulich ?<jbeulich@novell.com>
>
> ? ? ? ?* g++.dg/ext/asm-static-1.C: New.
> ? ? ? ?* gcc.dg/asm-static-1.c: New.
> ? ? ? ?* gcc.dg/asm-static-2.c: New.
> ? ? ? ?* gcc.dg/asm-static-3.c: New.
> ? ? ? ?* gcc.dg/asm-static-4.c: New.
>
> --- 2010-06-30/gcc/c-parser.c ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/c-parser.c ? 2010-07-02 15:33:45.000000000 +0200
> @@ -926,7 +926,7 @@ static struct c_declarator *c_parser_dir
> ?static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree);
> ?static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree);
> ?static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
> -static tree c_parser_simple_asm_expr (c_parser *);
> +static tree c_parser_simple_asm_expr (c_parser *, tree *);
> ?static tree c_parser_attributes (c_parser *);
> ?static struct c_type_name *c_parser_type_name (c_parser *);
> ?static struct c_expr c_parser_initializer (c_parser *);
> @@ -945,7 +945,7 @@ static void c_parser_while_statement (c_
> ?static void c_parser_do_statement (c_parser *);
> ?static void c_parser_for_statement (c_parser *);
> ?static tree c_parser_asm_statement (c_parser *);
> -static tree c_parser_asm_operands (c_parser *, bool);
> +static tree c_parser_asm_operands (c_parser *, int);
> ?static tree c_parser_asm_goto_operands (c_parser *);
> ?static tree c_parser_asm_clobbers (c_parser *);
> ?static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
> @@ -1273,7 +1273,7 @@ c_parser_declaration_or_fndef (c_parser
> ? ? ? ? ? ? function definition. ?*/
> ? ? ? ? ?fndef_ok = false;
> ? ? ? ? ?if (c_parser_next_token_is_keyword (parser, RID_ASM))
> - ? ? ? ? ? asm_name = c_parser_simple_asm_expr (parser);
> + ? ? ? ? ? asm_name = c_parser_simple_asm_expr (parser, NULL);
> ? ? ? ? ?if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
> ? ? ? ? ? ?postfix_attrs = c_parser_attributes (parser);
> ? ? ? ? ?if (c_parser_next_token_is (parser, CPP_EQ))
> @@ -1406,9 +1406,12 @@ c_parser_declaration_or_fndef (c_parser
> ?static void
> ?c_parser_asm_definition (c_parser *parser)
> ?{
> - ?tree asm_str = c_parser_simple_asm_expr (parser);
> + ?location_t loc = c_parser_peek_token (parser)->location;
> + ?tree inputs = NULL_TREE;
> + ?tree asm_str = c_parser_simple_asm_expr (parser, &inputs);
> +
> ? if (asm_str)
> - ? ?cgraph_add_asm_node (asm_str);
> + ? ?cgraph_add_asm_node (asm_str, inputs, loc);
> ? c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
> ?}
>
> @@ -2910,10 +2913,11 @@ c_parser_asm_string_literal (c_parser *p
>
> ? ?simple-asm-expr:
> ? ? ?asm ( asm-string-literal )
> + ? ? asm ( asm-string-literal : asm-operands )
> ?*/
>
> ?static tree
> -c_parser_simple_asm_expr (c_parser *parser)
> +c_parser_simple_asm_expr (c_parser *parser, tree *inputsp)
> ?{
> ? tree str;
> ? gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
> @@ -2927,6 +2931,9 @@ c_parser_simple_asm_expr (c_parser *pars
> ? ? ? return NULL_TREE;
> ? ? }
> ? str = c_parser_asm_string_literal (parser);
> + ?if (inputsp && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN)
> + ? ? ?&& c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
> + ? ? ?*inputsp = c_parser_asm_operands (parser, -1);
> ? parser->lex_untranslated_string = false;
> ? if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
> ? ? {
> @@ -4513,10 +4520,10 @@ c_parser_asm_statement (c_parser *parser
> ? ? ? ? ? ?/* For asm goto, we don't allow output operands, but reserve
> ? ? ? ? ? ? ? the slot for a future extension that does allow them. ?*/
> ? ? ? ? ? ?if (!is_goto)
> - ? ? ? ? ? ? outputs = c_parser_asm_operands (parser, false);
> + ? ? ? ? ? ? outputs = c_parser_asm_operands (parser, 0);
> ? ? ? ? ? ?break;
> ? ? ? ? ?case 1:
> - ? ? ? ? ? inputs = c_parser_asm_operands (parser, true);
> + ? ? ? ? ? inputs = c_parser_asm_operands (parser, 1);
> ? ? ? ? ? ?break;
> ? ? ? ? ?case 2:
> ? ? ? ? ? ?clobbers = c_parser_asm_clobbers (parser);
> @@ -4554,9 +4561,10 @@ c_parser_asm_statement (c_parser *parser
> ? goto error;
> ?}
>
> -/* Parse asm operands, a GNU extension. ?If CONVERT_P (for inputs but
> - ? not outputs), apply the default conversion of functions and arrays
> - ? to pointers.
> +/* Parse asm operands, a GNU extension. ?If MODE is non-zero (for inputs
> + ? but not outputs), apply the default conversion of functions and arrays
> + ? to pointers. ?If MODE is negative (for inputs of asm definitions),
> + ? don't allow comma expressions.
>
> ? ?asm-operands:
> ? ? ?asm-operand
> @@ -4568,7 +4576,7 @@ c_parser_asm_statement (c_parser *parser
> ?*/
>
> ?static tree
> -c_parser_asm_operands (c_parser *parser, bool convert_p)
> +c_parser_asm_operands (c_parser *parser, int mode)
> ?{
> ? tree list = NULL_TREE;
> ? location_t loc;
> @@ -4607,9 +4615,12 @@ c_parser_asm_operands (c_parser *parser,
> ? ? ? ? ?return NULL_TREE;
> ? ? ? ?}
> ? ? ? loc = c_parser_peek_token (parser)->location;
> - ? ? ?expr = c_parser_expression (parser);
> + ? ? ?if (mode >= 0)
> + ? ? ? expr = c_parser_expression (parser);
> + ? ? ?else
> + ? ? ? expr = c_parser_expr_no_commas(parser, NULL);
> ? ? ? mark_exp_read (expr.value);
> - ? ? ?if (convert_p)
> + ? ? ?if (mode)
> ? ? ? ?expr = default_function_array_conversion (loc, expr);
> ? ? ? expr.value = c_fully_fold (expr.value, false, NULL);
> ? ? ? parser->lex_untranslated_string = true;
> --- 2010-06-30/gcc/cgraph.c ? ? 2010-06-30 08:40:00.000000000 +0200
> +++ 2010-06-30/gcc/cgraph.c ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -1971,12 +1971,15 @@ change_decl_assembler_name (tree decl, t
> ?/* Add a top-level asm statement to the list. ?*/
>
> ?struct cgraph_asm_node *
> -cgraph_add_asm_node (tree asm_str)
> +cgraph_add_asm_node (tree asm_str, tree inputs, location_t loc)
> ?{
> ? struct cgraph_asm_node *node;
>
> ? node = ggc_alloc_cleared_cgraph_asm_node ();
> ? node->asm_str = asm_str;
> + ?node->inputs = check_unique_operand_names (NULL_TREE, inputs, NULL_TREE)
> + ? ? ? ? ? ? ? ?? inputs : NULL_TREE;
> + ?node->loc = loc;
> ? node->order = cgraph_order++;
> ? node->next = NULL;
> ? if (cgraph_asm_nodes == NULL)
> --- 2010-06-30/gcc/cgraph.h ? ? 2010-06-30 08:40:00.000000000 +0200
> +++ 2010-06-30/gcc/cgraph.h ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -508,6 +508,10 @@ struct GTY(()) cgraph_asm_node {
> ? struct cgraph_asm_node *next;
> ? /* String for this asm node. ?*/
> ? tree asm_str;
> + ?/* Inputs for this asm node (optional). ?*/
> + ?tree inputs;
> + ?/* Source location of the asm(). ?*/
> + ?location_t loc;
> ? /* Ordering of all cgraph nodes. ?*/
> ? int order;
> ?};
> @@ -582,7 +586,7 @@ struct cgraph_node * cgraph_clone_node (
> ?void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
> ?void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
>
> -struct cgraph_asm_node *cgraph_add_asm_node (tree);
> +struct cgraph_asm_node *cgraph_add_asm_node (tree, tree, location_t);
>
> ?bool cgraph_function_possibly_inlined_p (tree);
> ?void cgraph_unnest_node (struct cgraph_node *);
> --- 2010-06-30/gcc/cgraphunit.c 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/cgraphunit.c 2010-07-02 15:33:45.000000000 +0200
> @@ -903,7 +903,7 @@ cgraph_output_pending_asms (void)
> ? ? return;
>
> ? for (can = cgraph_asm_nodes; can; can = can->next)
> - ? ?assemble_asm (can->asm_str);
> + ? ?assemble_asm (can->asm_str, can->inputs, can->loc);
> ? cgraph_asm_nodes = NULL;
> ?}
>
> @@ -964,6 +964,7 @@ process_function_and_variable_attributes
> ?{
> ? struct cgraph_node *node;
> ? struct varpool_node *vnode;
> + ?struct cgraph_asm_node *anode;
>
> ? for (node = cgraph_nodes; node != first; node = node->next)
> ? ? {
> @@ -999,6 +1000,47 @@ process_function_and_variable_attributes
> ? ? ? ? ? ?varpool_mark_needed_node (vnode);
> ? ? ? ?}
> ? ? }
> + ?for (anode = cgraph_asm_nodes; anode; anode = anode->next)
> + ? ?if (anode->inputs)
> + ? ? ?{
> + ? ? ? tree node = anode->inputs;
> +
> + ? ? ? for (; node && node != error_mark_node; node = TREE_CHAIN (node))
> + ? ? ? ? {
> + ? ? ? ? ? tree value = TREE_VALUE (node);
> +
> + ? ? ? ? ? while (value && value != error_mark_node)
> + ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? switch (TREE_CODE (value))
> + ? ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? ? case INTEGER_CST:
> + ? ? ? ? ? ? ? ? ? ? value = NULL_TREE;
> + ? ? ? ? ? ? ? ? ? ? break;
> +
> + ? ? ? ? ? ? ? ? ? CASE_CONVERT:
> + ? ? ? ? ? ? ? ? ? case ADDR_EXPR:
> + ? ? ? ? ? ? ? ? ? case FDESC_EXPR:
> + ? ? ? ? ? ? ? ? ? case POINTER_PLUS_EXPR:
> + ? ? ? ? ? ? ? ? ? case COMPONENT_REF:
> + ? ? ? ? ? ? ? ? ? ? value = TREE_OPERAND (value, 0);
> + ? ? ? ? ? ? ? ? ? ? break;
> +
> + ? ? ? ? ? ? ? ? ? case FUNCTION_DECL:
> + ? ? ? ? ? ? ? ? ? case VAR_DECL:
> + ? ? ? ? ? ? ? ? ? ? mark_decl_referenced (value);
> + ? ? ? ? ? ? ? ? ? ? value = NULL_TREE;
> + ? ? ? ? ? ? ? ? ? ? break;
> +
> + ? ? ? ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ? ? ? error_at (EXPR_LOCATION (value),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "expression not supported as file scope"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " asm() input");
> + ? ? ? ? ? ? ? ? ? ? value = NULL_TREE;
> + ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? }
> + ? ? ? ? }
> + ? ? ?}
> ?}
>
> ?/* Process CGRAPH_NODES_NEEDED queue, analyze each function (and transitively
> @@ -1810,7 +1852,8 @@ cgraph_output_in_order (void)
> ? ? ? ? ?break;
>
> ? ? ? ?case ORDER_ASM:
> - ? ? ? ? assemble_asm (nodes[i].u.a->asm_str);
> + ? ? ? ? assemble_asm (nodes[i].u.a->asm_str, nodes[i].u.a->inputs,
> + ? ? ? ? ? ? ? ? ? ? ? nodes[i].u.a->loc);
> ? ? ? ? ?break;
>
> ? ? ? ?case ORDER_UNDEFINED:
> --- 2010-06-30/gcc/cp/parser.c ?2010-06-30 08:39:35.000000000 +0200
> +++ 2010-06-30/gcc/cp/parser.c ?2010-07-02 15:33:45.000000000 +0200
> @@ -13537,6 +13537,7 @@ cp_parser_asm_definition (cp_parser* par
> ? bool invalid_inputs_p = false;
> ? bool invalid_outputs_p = false;
> ? bool goto_p = false;
> + ?location_t loc = cp_lexer_peek_token (parser->lexer)->location;
> ? required_token missing = RT_NONE;
>
> ? /* Look for the `asm' keyword. ?*/
> @@ -13618,7 +13619,7 @@ cp_parser_asm_definition (cp_parser* par
> ? ? ? ?{
> ? ? ? ? ?/* Consume the `:' or `::'. ?*/
> ? ? ? ? ?cp_lexer_consume_token (parser->lexer);
> - ? ? ? ? /* Parse the output-operands. ?*/
> + ? ? ? ? /* Parse the input-operands. ?*/
> ? ? ? ? ?if (cp_lexer_next_token_is_not (parser->lexer,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CPP_COLON)
> ? ? ? ? ? ? ?&& cp_lexer_next_token_is_not (parser->lexer,
> @@ -13669,6 +13670,19 @@ cp_parser_asm_definition (cp_parser* par
> ? ? }
> ? else if (goto_p)
> ? ? missing = RT_COLON_SCOPE;
> + ?else if (cp_parser_allow_gnu_extensions_p (parser)
> + ? ? ? ? ?&& ! parser->in_function_body
> + ? ? ? ? ?&& cp_lexer_next_token_is (parser->lexer, CPP_COLON))
> + ? ?{
> + ? ? ?/* Consume the `:'. ?*/
> + ? ? ?cp_lexer_consume_token (parser->lexer);
> +
> + ? ? ?/* Parse the input-operands. ?*/
> + ? ? ?inputs = cp_parser_asm_operand_list (parser);
> +
> + ? ? ?if (inputs == error_mark_node)
> + ? ? ? invalid_inputs_p = true;
> + ? ?}
>
> ? /* Look for the closing `)'. ?*/
> ? if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN,
> @@ -13695,7 +13709,33 @@ cp_parser_asm_definition (cp_parser* par
> ? ? ? ? ? ?}
> ? ? ? ?}
> ? ? ? else
> - ? ? ? cgraph_add_asm_node (string);
> + ? ? ? {
> + ? ? ? ? tree input = inputs;
> +
> + ? ? ? ? while (input && input != error_mark_node)
> + ? ? ? ? ? {
> + ? ? ? ? ? ? tree operand = decay_conversion (TREE_VALUE (input));
> +
> + ? ? ? ? ? ? /* If the type of the operand hasn't been determined (e.g.,
> + ? ? ? ? ? ? ? ?because it involves an overloaded function), then issue
> + ? ? ? ? ? ? ? ?an error message. ?There's no context available to
> + ? ? ? ? ? ? ? ?resolve the overloading. ?*/
> + ? ? ? ? ? ? if (TREE_TYPE (operand) == unknown_type_node)
> + ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? error ("type of asm operand %qE could not be determined",
> + ? ? ? ? ? ? ? ? ? ? ? ?TREE_VALUE (input));
> + ? ? ? ? ? ? ? ? operand = error_mark_node;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? if (!cxx_mark_addressable (operand))
> + ? ? ? ? ? ? ? operand = error_mark_node;
> +
> + ? ? ? ? ? ? TREE_VALUE (input) = operand;
> +
> + ? ? ? ? ? ? input = TREE_CHAIN (input);
> + ? ? ? ? ? }
> + ? ? ? ? cgraph_add_asm_node (string, inputs, loc);
> + ? ? ? }
> ? ? }
> ?}
>
> --- 2010-06-30/gcc/lto-cgraph.c 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/lto-cgraph.c 2010-07-02 15:33:45.000000000 +0200
> @@ -840,7 +840,6 @@ output_cgraph (cgraph_node_set set, varp
> ? int i, n_nodes;
> ? lto_cgraph_encoder_t encoder;
> ? lto_varpool_encoder_t varpool_encoder;
> - ?struct cgraph_asm_node *can;
>
> ? if (flag_wpa)
> ? ? output_cgraph_opt_summary ();
> @@ -876,19 +875,8 @@ output_cgraph (cgraph_node_set set, varp
>
> ? lto_output_uleb128_stream (ob->main_stream, 0);
>
> - ?/* Emit toplevel asms. ?*/
> - ?for (can = cgraph_asm_nodes; can; can = can->next)
> - ? ?{
> - ? ? ?int len = TREE_STRING_LENGTH (can->asm_str);
> - ? ? ?lto_output_uleb128_stream (ob->main_stream, len);
> - ? ? ?for (i = 0; i < len; ++i)
> - ? ? ? lto_output_1_stream (ob->main_stream,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ?TREE_STRING_POINTER (can->asm_str)[i]);
> - ? ?}
> -
> - ?lto_output_uleb128_stream (ob->main_stream, 0);
> -
> ? lto_destroy_simple_output_block (ob);
> + ?lto_output_toplevel_asms ();
> ? output_varpool (set, vset);
> ? output_refs (set, vset, encoder, varpool_encoder);
> ?}
> @@ -1229,7 +1217,6 @@ input_cgraph_1 (struct lto_file_decl_dat
> ? VEC(cgraph_node_ptr, heap) *nodes = NULL;
> ? struct cgraph_node *node;
> ? unsigned i;
> - ?unsigned HOST_WIDE_INT len;
>
> ? tag = (enum LTO_cgraph_tags) lto_input_uleb128 (ib);
> ? while (tag)
> @@ -1250,18 +1237,7 @@ input_cgraph_1 (struct lto_file_decl_dat
> ? ? ? tag = (enum LTO_cgraph_tags) lto_input_uleb128 (ib);
> ? ? }
>
> - ?/* Input toplevel asms. ?*/
> - ?len = lto_input_uleb128 (ib);
> - ?while (len)
> - ? ?{
> - ? ? ?char *str = (char *)xmalloc (len + 1);
> - ? ? ?for (i = 0; i < len; ++i)
> - ? ? ? str[i] = lto_input_1_unsigned (ib);
> - ? ? ?cgraph_add_asm_node (build_string (len, str));
> - ? ? ?free (str);
> -
> - ? ? ?len = lto_input_uleb128 (ib);
> - ? ?}
> + ?lto_input_toplevel_asms (file_data);
>
> ? for (i = 0; VEC_iterate (cgraph_node_ptr, nodes, i, node); i++)
> ? ? {
> --- 2010-06-30/gcc/lto-section-in.c ? ? 2010-06-08 17:20:08.000000000 +0200
> +++ 2010-06-30/gcc/lto-section-in.c ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -52,6 +52,7 @@ const char *lto_section_name[LTO_N_SECTI
> ? "function_body",
> ? "static_initializer",
> ? "cgraph",
> + ?"asm",
> ? "varpool",
> ? "refs",
> ? "jump_funcs"
> --- 2010-06-30/gcc/lto-streamer-in.c ? ?2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/lto-streamer-in.c ? ?2010-07-02 15:33:45.000000000 +0200
> @@ -2731,6 +2731,52 @@ lto_input_tree (struct lto_input_block *
> ?}
>
>
> +/* Input toplevel asms. ?*/
> +
> +void
> +lto_input_toplevel_asms (struct lto_file_decl_data *file_data)
> +{
> + ?size_t len;
> + ?const char *data = lto_get_section_data (file_data, LTO_section_asm,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, &len);
> + ?const struct lto_asm_header *header = (const struct lto_asm_header *) data;
> + ?int32_t string_offset;
> + ?struct data_in *data_in;
> + ?struct lto_input_block ib;
> + ?tree str;
> +
> + ?if (! data)
> + ? ?return;
> +
> + ?string_offset = sizeof (*header) + header->main_size;
> +
> + ?LTO_INIT_INPUT_BLOCK (ib,
> + ? ? ? ? ? ? ? ? ? ? ? data + sizeof (*header),
> + ? ? ? ? ? ? ? ? ? ? ? 0,
> + ? ? ? ? ? ? ? ? ? ? ? header->main_size);
> +
> + ?data_in = lto_data_in_create (file_data, data + string_offset,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? header->string_size, NULL);
> +
> + ?/* Make sure the file was generated by the exact same compiler. ?*/
> + ?lto_check_version (header->lto_header.major_version,
> + ? ? ? ? ? ? ? ? ? ?header->lto_header.minor_version);
> +
> + ?while ((str = input_string_cst (data_in, &ib)))
> + ? ?{
> + ? ? ?tree inputs = lto_input_tree (&ib, data_in);
> + ? ? ?location_t loc = lto_input_location (&ib, data_in);
> +
> + ? ? ?cgraph_add_asm_node (str, inputs, loc);
> + ? ?}
> +
> + ?clear_line_info (data_in);
> + ?lto_data_in_delete (data_in);
> +
> + ?lto_free_section_data (file_data, LTO_section_asm, NULL, data, len);
> +}
> +
> +
> ?/* Initialization for the LTO reader. ?*/
>
> ?void
> --- 2010-06-30/gcc/lto-streamer-out.c ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/lto-streamer-out.c ? 2010-07-02 15:33:45.000000000 +0200
> @@ -2006,6 +2006,65 @@ output_unreferenced_globals (cgraph_node
> ?}
>
>
> +/* Emit toplevel asms. ?*/
> +
> +void
> +lto_output_toplevel_asms (void)
> +{
> + ?struct output_block *ob;
> + ?struct cgraph_asm_node *can;
> + ?char *section_name;
> + ?struct lto_output_stream *header_stream;
> + ?struct lto_asm_header header;
> +
> + ?if (! cgraph_asm_nodes)
> + ? ?return;
> +
> + ?ob = create_output_block (LTO_section_asm);
> +
> + ?/* Make string 0 be a NULL string. ?*/
> + ?lto_output_1_stream (ob->string_stream, 0);
> +
> + ?for (can = cgraph_asm_nodes; can; can = can->next)
> + ? ?{
> + ? ? ?output_string_cst (ob, ob->main_stream, can->asm_str);
> + ? ? ?lto_output_tree (ob, can->inputs, false);
> + ? ? ?lto_output_location (ob, can->loc);
> + ? ?}
> +
> + ?lto_output_uleb128_stream (ob->main_stream, 0);
> +
> + ?section_name = lto_get_section_name (LTO_section_asm, NULL);
> + ?lto_begin_section (section_name, !flag_wpa);
> + ?free (section_name);
> +
> + ?/* The entire header stream is computed here. ?*/
> + ?memset (&header, 0, sizeof (struct lto_function_header));
> +
> + ?/* Write the header. ?*/
> + ?header.lto_header.major_version = LTO_major_version;
> + ?header.lto_header.minor_version = LTO_minor_version;
> + ?header.lto_header.section_type = LTO_section_asm;
> +
> + ?header.main_size = ob->main_stream->total_size;
> + ?header.string_size = ob->string_stream->total_size;
> +
> + ?header_stream = XCNEW (struct lto_output_stream);
> + ?lto_output_data_stream (header_stream, &header, sizeof (header));
> + ?lto_write_stream (header_stream);
> + ?free (header_stream);
> +
> + ?/* Put all of the gimple and the string table out the asm file as a
> + ? ? block of text. ?*/
> + ?lto_write_stream (ob->main_stream);
> + ?lto_write_stream (ob->string_stream);
> +
> + ?lto_end_section ();
> +
> + ?destroy_output_block (ob);
> +}
> +
> +
> ?/* Copy the function body of NODE without deserializing. */
>
> ?static void
> --- 2010-06-30/gcc/lto-streamer.c ? ? ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/lto-streamer.c ? ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -160,6 +160,9 @@ lto_get_section_name (int section_type,
> ? ? case LTO_section_cgraph:
> ? ? ? return concat (LTO_SECTION_NAME_PREFIX, ".cgraph", NULL);
>
> + ? ?case LTO_section_asm:
> + ? ? ?return concat (LTO_SECTION_NAME_PREFIX, ".asm", NULL);
> +
> ? ? case LTO_section_varpool:
> ? ? ? return concat (LTO_SECTION_NAME_PREFIX, ".vars", NULL);
>
> --- 2010-06-30/gcc/lto-streamer.h ? ? ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/lto-streamer.h ? ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -140,7 +140,7 @@ along with GCC; see the file COPYING3.
> ?#define LTO_SECTION_NAME_PREFIX ? ? ? ? ".gnu.lto_"
>
> ?#define LTO_major_version 1
> -#define LTO_minor_version 0
> +#define LTO_minor_version 1
>
> ?typedef unsigned char ?lto_decl_flags_t;
>
> @@ -254,6 +254,7 @@ enum lto_section_type
> ? LTO_section_function_body,
> ? LTO_section_static_initializer,
> ? LTO_section_cgraph,
> + ?LTO_section_asm,
> ? LTO_section_varpool,
> ? LTO_section_refs,
> ? LTO_section_jump_functions,
> @@ -440,6 +441,23 @@ struct lto_decl_header
> ?};
>
>
> +/* Structure describing top level asm()s. ?*/
> +struct lto_asm_header
> +{
> + ?/* The header for all types of sections. */
> + ?struct lto_header lto_header;
> +
> + ?/* Size compressed or 0 if not compressed. ?*/
> + ?int32_t compressed_size;
> +
> + ?/* Size of region for expressions, decls, types, etc. */
> + ?int32_t main_size;
> +
> + ?/* Size of the string table. ?*/
> + ?int32_t string_size;
> +};
> +
> +
> ?/* Statistics gathered during LTO, WPA and LTRANS. ?*/
> ?struct lto_stats_d
> ?{
> @@ -844,6 +862,7 @@ extern void lto_input_function_body (str
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char *);
> ?extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *);
> +extern void lto_input_toplevel_asms (struct lto_file_decl_data *);
> ?extern void lto_init_reader (void);
> ?extern struct data_in *lto_data_in_create (struct lto_file_decl_data *,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *, unsigned,
> @@ -856,6 +875,7 @@ extern void lto_register_decl_definition
> ?extern struct output_block *create_output_block (enum lto_section_type);
> ?extern void destroy_output_block (struct output_block *);
> ?extern void lto_output_tree (struct output_block *, tree, bool);
> +extern void lto_output_toplevel_asms (void);
> ?extern void produce_asm (struct output_block *ob, tree fn);
>
>
> --- 2010-06-30/gcc/output.h ? ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/output.h ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -186,7 +186,7 @@ extern void default_assemble_visibility
>
> ?/* Output a string of literal assembler code
> ? ?for an `asm' keyword used between functions. ?*/
> -extern void assemble_asm (tree);
> +extern void assemble_asm (tree, tree, location_t);
>
> ?/* Output assembler code for the constant pool of a function and associated
> ? ?with defining the name of the function. ?DECL describes the function.
> --- 2010-06-30/gcc/stmt.c ? ? ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/stmt.c ? ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -112,7 +112,6 @@ static int n_occurrences (int, const cha
> ?static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
> ?static void expand_nl_goto_receiver (void);
> ?static bool check_operand_nalternatives (tree, tree);
> -static bool check_unique_operand_names (tree, tree, tree);
> ?static char *resolve_operand_name_1 (char *, tree, tree, tree);
> ?static void expand_null_return_1 (void);
> ?static void expand_value_return (rtx);
> @@ -1227,7 +1226,7 @@ check_operand_nalternatives (tree output
> ? ?are identifiers, and so have been canonicalized by get_identifier,
> ? ?so all we need are pointer comparisons. ?*/
>
> -static bool
> +bool
> ?check_unique_operand_names (tree outputs, tree inputs, tree labels)
> ?{
> ? tree i, j;
> --- 2010-06-30/gcc/testsuite/g++.dg/ext/asm-static-1.C ?1970-01-01 01:00:00.000000000 +0100
> +++ 2010-06-30/gcc/testsuite/g++.dg/ext/asm-static-1.C ?2010-07-02 15:33:45.000000000 +0200
> @@ -0,0 +1,21 @@
> +/* Check compilation of file scope asm() with input oprand(s). */
> +/* { dg-do compile } */
> +
> +extern int a[];
> +extern void f(int*);
> +extern struct s {
> + ? ? ? int i, a[2];
> +} s;
> +static inline void inl(void)
> +{
> + ? ? ? f(a);
> +}
> +
> +__asm__ (".long %c0" : "i" (f));
> +__asm__ (".long %c0" : "i" (a));
> +__asm__ (".long %c0" : "i" (inl));
> +__asm__ (".long %c0" : "i" (&s.i));
> +__asm__ (".long %c0" : "i" (s.a));
> +__asm__ (".long %c0, %c1, %c2" : "i" (-1), "i" ((long)f), "i" (a + 1));
> +__asm__ (".long %c[arr], %c[cnst], %c[fn]"
> + ? ? ? ?: [cnst] "i" (-1), [fn] "i" ((long)f), [arr] "i" (a + 1));
> --- 2010-06-30/gcc/testsuite/gcc.dg/asm-static-1.c ? ? ?1970-01-01 01:00:00.000000000 +0100
> +++ 2010-06-30/gcc/testsuite/gcc.dg/asm-static-1.c ? ? ?2010-07-02 15:33:45.000000000 +0200
> @@ -0,0 +1,21 @@
> +/* Check compilation of file scope asm() with input oprand(s). */
> +/* { dg-do compile } */
> +
> +extern int a[];
> +extern void f(int*);
> +extern struct s {
> + ? ? ? int i, a[2];
> +} s;
> +static __inline__ void inl(void)
> +{
> + ? ? ? f(a);
> +}
> +
> +__asm__ (".long %c0" : "i" (f));
> +__asm__ (".long %c0" : "i" (a));
> +__asm__ (".long %c0" : "i" (inl));
> +__asm__ (".long %c0" : "i" (&s.i));
> +__asm__ (".long %c0" : "i" (s.a));
> +__asm__ (".long %c0, %c1, %c2" : "i" (-1), "i" ((long)f), "i" (a + 1));
> +__asm__ (".long %c[arr], %c[cnst], %c[fn]"
> + ? ? ? ?: [cnst] "i" (-1), [fn] "i" ((long)f), [arr] "i" (a + 1));
> --- 2010-06-30/gcc/testsuite/gcc.dg/asm-static-2.c ? ? ?1970-01-01 01:00:00.000000000 +0100
> +++ 2010-06-30/gcc/testsuite/gcc.dg/asm-static-2.c ? ? ?2010-07-02 15:33:45.000000000 +0200
> @@ -0,0 +1,8 @@
> +/* Check for parse time errors. */
> +/* { dg-do compile } */
> +
> +extern int a[];
> +
> +__asm__ (".long %c0" :: "i" (0)); /* { dg-error "expected string literal" } */
> +__asm__ (".long %c0" : "=g" (a[0]): "0" (0)); /* { dg-error "expected .?\\)" } */
> +__asm__ (".long %c[n]" : [n] "i" (0), [n] "i" (0)); /* { dg-error "duplicate.*operand name" } */
> --- 2010-06-30/gcc/testsuite/gcc.dg/asm-static-3.c ? ? ?1970-01-01 01:00:00.000000000 +0100
> +++ 2010-06-30/gcc/testsuite/gcc.dg/asm-static-3.c ? ? ?2010-07-02 15:33:45.000000000 +0200
> @@ -0,0 +1,7 @@
> +/* Check for errors detected before code generation. */
> +/* { dg-do compile } */
> +
> +extern int a[];
> +extern void f(int*);
> +
> +__asm__ (".long %c0" : "i" ((long)a - (long)f)); /* { dg-error "expression not supported" } */
> --- 2010-06-30/gcc/testsuite/gcc.dg/asm-static-4.c ? ? ?1970-01-01 01:00:00.000000000 +0100
> +++ 2010-06-30/gcc/testsuite/gcc.dg/asm-static-4.c ? ? ?2010-07-02 15:33:45.000000000 +0200
> @@ -0,0 +1,8 @@
> +/* Check for errors detected during code generation. */
> +/* { dg-do compile } */
> +
> +__asm__ (".long %0" : "r" (0)); /* { dg-warning "invalid.*constraint ignored" } */
> +__asm__ (".long %c1" : "i" (0)); /* { dg-error "operand number out of range" } */
> +__asm__ (".long %!0" : "i" (0)); /* { dg-error "invalid.*%-code" } */
> +__asm__ (".long %c[n" : "i" (0)); /* { dg-error "missing close brace" } */
> +__asm__ (".long %c[n]" : "i" (0)); /* { dg-error "undefined named.*operand" } */
> --- 2010-06-30/gcc/tree.h ? ? ? 2010-06-30 13:19:57.000000000 +0200
> +++ 2010-06-30/gcc/tree.h ? ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -5258,6 +5258,7 @@ extern bool parse_input_constraint (cons
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char * const *, bool *, bool *);
> ?extern void expand_asm_stmt (gimple);
> ?extern tree resolve_asm_operand_names (tree, tree, tree, tree);
> +extern bool check_unique_operand_names (tree, tree, tree);
> ?extern void expand_case (gimple);
> ?extern void expand_decl (tree);
> ?#ifdef HARD_CONST
> --- 2010-06-30/gcc/varasm.c ? ? 2010-06-30 08:40:05.000000000 +0200
> +++ 2010-06-30/gcc/varasm.c ? ? 2010-07-02 15:33:45.000000000 +0200
> @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.
> ?#include "cfglayout.h"
> ?#include "basic-block.h"
> ?#include "tree-iterator.h"
> +#include "pretty-print.h"
>
> ?#ifdef XCOFF_DEBUGGING_INFO
> ?#include "xcoffout.h" ? ? ? ? ?/* Needed for external data
> @@ -1557,14 +1558,111 @@ make_decl_rtl_for_debug (tree decl)
> ? ?for an `asm' keyword used between functions. ?*/
>
> ?void
> -assemble_asm (tree string)
> +assemble_asm (tree string, tree inputs, location_t loc)
> ?{
> ? app_enable ();
>
> ? if (TREE_CODE (string) == ADDR_EXPR)
> ? ? string = TREE_OPERAND (string, 0);
>
> - ?fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
> + ?if (inputs)
> + ? ?{
> + ? ? ?const char *p = TREE_STRING_POINTER (string);
> + ? ? ?char c;
> +
> + ? ? ?putc ('\t', asm_out_file);
> +
> + ? ? ?while ((c = *p++))
> + ? ? ? {
> + ? ? ? ? tree node;
> +
> + ? ? ? ? if (c != '%')
> + ? ? ? ? ? {
> + ? ? ? ? ? ? putc (c, asm_out_file);
> + ? ? ? ? ? ? continue;
> + ? ? ? ? ? }
> +
> + ? ? ? ? c = *p;
> + ? ? ? ? if (!ISDIGIT(c))
> + ? ? ? ? ? switch (c)
> + ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? case 'c': case 'a':
> + ? ? ? ? ? ? ? ? /* For now simply ignore (but also don't require) these. ?*/
> + ? ? ? ? ? ? ? ? c = *++p;
> + ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? case '%':
> + ? ? ? ? ? ? ? ? ++p;
> + ? ? ? ? ? ? ? ? putc ('%', asm_out_file);
> + ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? }
> + ? ? ? ? if (c == '[')
> + ? ? ? ? ? {
> + ? ? ? ? ? ? const char *end = strchr (++p, ']');
> + ? ? ? ? ? ? char *q;
> +
> + ? ? ? ? ? ? if (! end)
> + ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? error_at (loc,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? "missing close brace for named asm() operand");
> + ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? q = xstrndup (p, end - p);
> +
> + ? ? ? ? ? ? for (node = inputs; node && node != error_mark_node; )
> + ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? tree name = TREE_PURPOSE (TREE_PURPOSE (node));
> +
> + ? ? ? ? ? ? ? ? if (name && ! strcmp (TREE_STRING_POINTER (name), q))
> + ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? node = TREE_CHAIN (node);
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? if (! node)
> + ? ? ? ? ? ? ? error_at (loc, "undefined named asm() operand %qs",
> + ? ? ? ? ? ? ? ? ? ? ? ? identifier_to_locale (q));
> + ? ? ? ? ? ? free (q);
> + ? ? ? ? ? ? p = end + 1;
> + ? ? ? ? ? }
> + ? ? ? ? else if (ISDIGIT(c))
> + ? ? ? ? ? {
> + ? ? ? ? ? ? char *endp;
> + ? ? ? ? ? ? unsigned long opnum = strtoul (p, &endp, 10);
> +
> + ? ? ? ? ? ? for (node = inputs; opnum-- && node && node != error_mark_node; )
> + ? ? ? ? ? ? ? node = TREE_CHAIN (node);
> +
> + ? ? ? ? ? ? if (! node)
> + ? ? ? ? ? ? ? error_at (loc, "asm() operand number out of range");
> + ? ? ? ? ? ? p = endp;
> + ? ? ? ? ? }
> + ? ? ? ? else
> + ? ? ? ? ? {
> + ? ? ? ? ? ? error_at (loc,
> + ? ? ? ? ? ? ? ? ? ? ? "unsupported or invalid asm() %%-code"
> + ? ? ? ? ? ? ? ? ? ? ? " in this context");
> + ? ? ? ? ? ? break;
> + ? ? ? ? ? }
> +
> + ? ? ? ? if (node && node != error_mark_node)
> + ? ? ? ? ? {
> + ? ? ? ? ? ? tree val = TREE_VALUE (node);
> +
> + ? ? ? ? ? ? string = TREE_VALUE (TREE_PURPOSE (node));
> + ? ? ? ? ? ? gcc_assert (TREE_CODE (string) == STRING_CST);
> + ? ? ? ? ? ? if (strcmp (TREE_STRING_POINTER (string), "i"))
> + ? ? ? ? ? ? ? warning_at (loc, 0,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? "unsupported or invalid asm() constraint"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? " ignored - \"i\" assumed");
> +
> + ? ? ? ? ? ? output_addr_const (asm_out_file,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?expand_expr (val, NULL_RTX, VOIDmode,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? EXPAND_INITIALIZER));
> + ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ?putc ('\n', asm_out_file);
> + ? ?}
> + ?else
> + ? ?fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
> ?}
>
> ?/* Record an element in the table of global destructors. ?SYMBOL is
>
>
>


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