Commit 64094f6a by Richard Henderson Committed by Richard Henderson

c-typeck.c (build_asm_stmt): New, broken out from ...

        * c-typeck.c (build_asm_stmt): New, broken out from ...
        (c_expand_asm_operands): ... here.  Just do rtl expansion.
        (c_expand_return): Return the new stmt node.
        (c_start_case, do_case): Likewise.
        * c-common.c (c_expand_expr_stmt): Likewise.
        * c-common.h: Update declarations.
        * c-tree.h: Likewise.
        * c-semantics.c (build_stmt): Use STMT_LINENO not TREE_COMPLEXITY.
        * c-parse.in (fndef): Set DECL_SOURCE_LINE to the open brace.
        (nested_function, notype_nested_function): Likewise.
        (compstmt): Return the compound statement not the binding level.
        (lineno_labeled_stmt): Simplify.
        (lineno_stmt, lineno_label): Set STMT_LINENO.
        (stmt, label): Return the new stmt node.

From-SVN: r38402
parent 3e4d04a1
2000-12-20 Richard Henderson <rth@redhat.com>
* c-typeck.c (build_asm_stmt): New, broken out from ...
(c_expand_asm_operands): ... here. Just do rtl expansion.
(c_expand_return): Return the new stmt node.
(c_start_case, do_case): Likewise.
* c-common.c (c_expand_expr_stmt): Likewise.
* c-common.h: Update declarations.
* c-tree.h: Likewise.
* c-semantics.c (build_stmt): Use STMT_LINENO not TREE_COMPLEXITY.
* c-parse.in (fndef): Set DECL_SOURCE_LINE to the open brace.
(nested_function, notype_nested_function): Likewise.
(compstmt): Return the compound statement not the binding level.
(lineno_labeled_stmt): Simplify.
(lineno_stmt, lineno_label): Set STMT_LINENO.
(stmt, label): Return the new stmt node.
2000-12-20 Bernd Schmidt <bernds@redhat.com> 2000-12-20 Bernd Schmidt <bernds@redhat.com>
* Makefile.in (OBJS): Add sched-ebb.o. * Makefile.in (OBJS): Add sched-ebb.o.
......
...@@ -3950,7 +3950,7 @@ verify_sequence_points (expr) ...@@ -3950,7 +3950,7 @@ verify_sequence_points (expr)
obstack_free (&tlist_obstack, tlist_firstobj); obstack_free (&tlist_obstack, tlist_firstobj);
} }
void tree
c_expand_expr_stmt (expr) c_expand_expr_stmt (expr)
tree expr; tree expr;
{ {
...@@ -3969,7 +3969,7 @@ c_expand_expr_stmt (expr) ...@@ -3969,7 +3969,7 @@ c_expand_expr_stmt (expr)
error ("expression statement has incomplete type"); error ("expression statement has incomplete type");
last_expr_type = TREE_TYPE (expr); last_expr_type = TREE_TYPE (expr);
add_stmt (build_stmt (EXPR_STMT, expr)); return add_stmt (build_stmt (EXPR_STMT, expr));
} }
/* Validate the expression after `case' and apply default promotions. */ /* Validate the expression after `case' and apply default promotions. */
......
...@@ -467,7 +467,7 @@ extern void c_apply_type_quals_to_decl PARAMS ((int, tree)); ...@@ -467,7 +467,7 @@ extern void c_apply_type_quals_to_decl PARAMS ((int, tree));
/* Print an error message for invalid operands to arith operation CODE. /* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */ NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PARAMS ((enum tree_code)); extern void binary_op_error PARAMS ((enum tree_code));
extern void c_expand_expr_stmt PARAMS ((tree)); extern tree c_expand_expr_stmt PARAMS ((tree));
extern void c_expand_start_cond PARAMS ((tree, int)); extern void c_expand_start_cond PARAMS ((tree, int));
extern void c_finish_then PARAMS ((void)); extern void c_finish_then PARAMS ((void));
extern void c_expand_start_else PARAMS ((void)); extern void c_expand_start_else PARAMS ((void));
...@@ -713,8 +713,8 @@ extern int anon_aggr_type_p PARAMS ((tree)); ...@@ -713,8 +713,8 @@ extern int anon_aggr_type_p PARAMS ((tree));
extern void emit_local_var PARAMS ((tree)); extern void emit_local_var PARAMS ((tree));
extern void make_rtl_for_local_static PARAMS ((tree)); extern void make_rtl_for_local_static PARAMS ((tree));
extern tree expand_cond PARAMS ((tree)); extern tree expand_cond PARAMS ((tree));
extern void c_expand_return PARAMS ((tree)); extern tree c_expand_return PARAMS ((tree));
extern void do_case PARAMS ((tree, tree)); extern tree do_case PARAMS ((tree, tree));
extern tree build_stmt PARAMS ((enum tree_code, ...)); extern tree build_stmt PARAMS ((enum tree_code, ...));
extern tree build_case_label PARAMS ((tree, tree, tree)); extern tree build_case_label PARAMS ((tree, tree, tree));
extern tree build_continue_stmt PARAMS ((void)); extern tree build_continue_stmt PARAMS ((void));
......
...@@ -177,7 +177,7 @@ end ifc ...@@ -177,7 +177,7 @@ end ifc
%type <ttype> any_word extension %type <ttype> any_word extension
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start %type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
%type <ttype> do_stmt_start poplevel %type <ttype> do_stmt_start poplevel stmt label
%type <ttype> c99_block_start c99_block_end %type <ttype> c99_block_start c99_block_end
%type <ttype> declarator %type <ttype> declarator
...@@ -365,8 +365,10 @@ fndef: ...@@ -365,8 +365,10 @@ fndef:
} }
old_style_parm_decls old_style_parm_decls
{ store_parm_decls (); } { store_parm_decls (); }
compstmt_or_error save_filename save_lineno compstmt_or_error
{ finish_function (0); { DECL_SOURCE_FILE (current_function_decl) = $7;
DECL_SOURCE_LINE (current_function_decl) = $8;
finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack); current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); } declspec_stack = TREE_CHAIN (declspec_stack); }
...@@ -381,8 +383,10 @@ fndef: ...@@ -381,8 +383,10 @@ fndef:
} }
old_style_parm_decls old_style_parm_decls
{ store_parm_decls (); } { store_parm_decls (); }
compstmt_or_error save_filename save_lineno compstmt_or_error
{ finish_function (0); { DECL_SOURCE_FILE (current_function_decl) = $7;
DECL_SOURCE_LINE (current_function_decl) = $8;
finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack); current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); } declspec_stack = TREE_CHAIN (declspec_stack); }
...@@ -397,8 +401,10 @@ fndef: ...@@ -397,8 +401,10 @@ fndef:
} }
old_style_parm_decls old_style_parm_decls
{ store_parm_decls (); } { store_parm_decls (); }
compstmt_or_error save_filename save_lineno compstmt_or_error
{ finish_function (0); { DECL_SOURCE_FILE (current_function_decl) = $6;
DECL_SOURCE_LINE (current_function_decl) = $7;
finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack); current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack); prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); } declspec_stack = TREE_CHAIN (declspec_stack); }
...@@ -1192,8 +1198,10 @@ nested_function: ...@@ -1192,8 +1198,10 @@ nested_function:
which then was handled by compstmt_or_error. which then was handled by compstmt_or_error.
There followed a repeated execution of that same rule, There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt save_filename save_lineno compstmt
{ tree decl = current_function_decl; { tree decl = current_function_decl;
DECL_SOURCE_FILE (decl) = $5;
DECL_SOURCE_LINE (decl) = $6;
finish_function (1); finish_function (1);
pop_function_context (); pop_function_context ();
add_decl_stmt (decl); } add_decl_stmt (decl); }
...@@ -1220,8 +1228,10 @@ notype_nested_function: ...@@ -1220,8 +1228,10 @@ notype_nested_function:
which then was handled by compstmt_or_error. which then was handled by compstmt_or_error.
There followed a repeated execution of that same rule, There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt save_filename save_lineno compstmt
{ tree decl = current_function_decl; { tree decl = current_function_decl;
DECL_SOURCE_FILE (decl) = $5;
DECL_SOURCE_LINE (decl) = $6;
finish_function (1); finish_function (1);
pop_function_context (); pop_function_context ();
add_decl_stmt (decl); } add_decl_stmt (decl); }
...@@ -1750,7 +1760,7 @@ compstmt_primary_start: ...@@ -1750,7 +1760,7 @@ compstmt_primary_start:
compstmt: compstmt_start compstmt_nostart compstmt: compstmt_start compstmt_nostart
{ RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); { RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
$$ = $2; } $$ = $1; }
; ;
/* Value is number of statements counted as of the closeparen. */ /* Value is number of statements counted as of the closeparen. */
...@@ -1808,13 +1818,8 @@ save_lineno: ...@@ -1808,13 +1818,8 @@ save_lineno:
; ;
lineno_labeled_stmt: lineno_labeled_stmt:
save_filename save_lineno stmt lineno_stmt
{ } | lineno_label lineno_labeled_stmt
/* | save_filename save_lineno error
{ }
*/
| save_filename save_lineno label lineno_labeled_stmt
{ }
; ;
/* Like lineno_labeled_stmt, but a block in C99. */ /* Like lineno_labeled_stmt, but a block in C99. */
...@@ -1826,12 +1831,25 @@ c99_block_lineno_labeled_stmt: ...@@ -1826,12 +1831,25 @@ c99_block_lineno_labeled_stmt:
lineno_stmt: lineno_stmt:
save_filename save_lineno stmt save_filename save_lineno stmt
{ } { if ($3)
{
STMT_LINENO ($3) = $2;
/* ??? We currently have no way of recording
the filename for a statement. This probably
matters little in practice at the moment,
but I suspect that problems will ocurr when
doing inlining at the tree level. */
}
}
; ;
lineno_label: lineno_label:
save_filename save_lineno label save_filename save_lineno label
{ } { if ($3)
{
STMT_LINENO ($3) = $2;
}
}
; ;
select_or_iter_stmt: select_or_iter_stmt:
...@@ -1900,25 +1918,26 @@ for_init_stmt: ...@@ -1900,25 +1918,26 @@ for_init_stmt:
/* Parse a single real statement, not including any labels. */ /* Parse a single real statement, not including any labels. */
stmt: stmt:
compstmt compstmt
{ stmt_count++; } { stmt_count++; $$ = $1; }
| expr ';' | expr ';'
{ stmt_count++; { stmt_count++;
c_expand_expr_stmt ($1); } $$ = c_expand_expr_stmt ($1); }
| c99_block_start select_or_iter_stmt c99_block_end | c99_block_start select_or_iter_stmt c99_block_end
{ if (flag_isoc99) { if (flag_isoc99)
RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); } RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
$$ = NULL_TREE; }
| BREAK ';' | BREAK ';'
{ stmt_count++; { stmt_count++;
add_stmt (build_break_stmt ()); } $$ = add_stmt (build_break_stmt ()); }
| CONTINUE ';' | CONTINUE ';'
{ stmt_count++; { stmt_count++;
add_stmt (build_continue_stmt ()); } $$ = add_stmt (build_continue_stmt ()); }
| RETURN ';' | RETURN ';'
{ stmt_count++; { stmt_count++;
c_expand_return (NULL_TREE); } $$ = c_expand_return (NULL_TREE); }
| RETURN expr ';' | RETURN expr ';'
{ stmt_count++; { stmt_count++;
c_expand_return ($2); } $$ = c_expand_return ($2); }
| ASM_KEYWORD maybe_type_qual '(' expr ')' ';' | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
{ stmt_count++; { stmt_count++;
STRIP_NOPS ($4); STRIP_NOPS ($4);
...@@ -1930,30 +1949,30 @@ stmt: ...@@ -1930,30 +1949,30 @@ stmt:
$4 = TREE_OPERAND ($4, 0); $4 = TREE_OPERAND ($4, 0);
if (TREE_CHAIN ($4)) if (TREE_CHAIN ($4))
$4 = combine_strings ($4); $4 = combine_strings ($4);
add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4, $$ = add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4,
NULL_TREE, NULL_TREE, NULL_TREE)); NULL_TREE, NULL_TREE,
NULL_TREE));
} }
else else
error ("argument of `asm' is not a constant string"); } {
error ("argument of `asm' is not a constant string");
$$ = NULL_TREE;
}
}
/* This is the case with just output operands. */ /* This is the case with just output operands. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';' | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
{ stmt_count++; { stmt_count++;
c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE, $$ = build_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
$2 == ridpointers[(int)RID_VOLATILE],
input_filename, lineno); }
/* This is the case with input operands as well. */ /* This is the case with input operands as well. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' asm_operands ')' ';' | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
asm_operands ')' ';'
{ stmt_count++; { stmt_count++;
c_expand_asm_operands ($4, $6, $8, NULL_TREE, $$ = build_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
$2 == ridpointers[(int)RID_VOLATILE],
input_filename, lineno); }
/* This is the case with clobbered registers as well. */ /* This is the case with clobbered registers as well. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';' asm_operands ':' asm_clobbers ')' ';'
{ stmt_count++; { stmt_count++;
c_expand_asm_operands ($4, $6, $8, $10, $$ = build_asm_stmt ($2, $4, $6, $8, $10); }
$2 == ridpointers[(int)RID_VOLATILE],
input_filename, lineno); }
| GOTO identifier ';' | GOTO identifier ';'
{ tree decl; { tree decl;
stmt_count++; stmt_count++;
...@@ -1961,16 +1980,19 @@ stmt: ...@@ -1961,16 +1980,19 @@ stmt:
if (decl != 0) if (decl != 0)
{ {
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
add_stmt (build_stmt (GOTO_STMT, decl)); $$ = add_stmt (build_stmt (GOTO_STMT, decl));
} }
else
$$ = NULL_TREE;
} }
| GOTO '*' expr ';' | GOTO '*' expr ';'
{ if (pedantic) { if (pedantic)
pedwarn ("ISO C forbids `goto *expr;'"); pedwarn ("ISO C forbids `goto *expr;'");
stmt_count++; stmt_count++;
$3 = convert (ptr_type_node, $3); $3 = convert (ptr_type_node, $3);
add_stmt (build_stmt (GOTO_STMT, $3)); } $$ = add_stmt (build_stmt (GOTO_STMT, $3)); }
| ';' | ';'
{ $$ = NULL_TREE; }
; ;
/* Any kind of label, including jump labels and case labels. /* Any kind of label, including jump labels and case labels.
...@@ -1979,21 +2001,23 @@ stmt: ...@@ -1979,21 +2001,23 @@ stmt:
label: CASE expr_no_commas ':' label: CASE expr_no_commas ':'
{ stmt_count++; { stmt_count++;
do_case ($2, NULL_TREE); } $$ = do_case ($2, NULL_TREE); }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':' | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
{ stmt_count++; { stmt_count++;
do_case ($2, $4); } $$ = do_case ($2, $4); }
| DEFAULT ':' | DEFAULT ':'
{ stmt_count++; { stmt_count++;
do_case (NULL_TREE, NULL_TREE); } $$ = do_case (NULL_TREE, NULL_TREE); }
| identifier save_filename save_lineno ':' maybe_attribute | identifier save_filename save_lineno ':' maybe_attribute
{ tree label = define_label ($2, $3, $1); { tree label = define_label ($2, $3, $1);
stmt_count++; stmt_count++;
if (label) if (label)
{ {
decl_attributes (label, $5, NULL_TREE); decl_attributes (label, $5, NULL_TREE);
add_stmt (build_stmt (LABEL_STMT, label)); $$ = add_stmt (build_stmt (LABEL_STMT, label));
} }
else
$$ = NULL_TREE;
} }
; ;
......
...@@ -220,7 +220,9 @@ finish_stmt_tree (t) ...@@ -220,7 +220,9 @@ finish_stmt_tree (t)
/* Build a generic statement based on the given type of node and /* Build a generic statement based on the given type of node and
arguments. Similar to `build_nt', except that we set arguments. Similar to `build_nt', except that we set
TREE_COMPLEXITY to be the current line number. */ STMT_LINENO to be the current line number. */
/* ??? This should be obsolete with the lineno_stmt productions
in the grammar. */
tree tree
build_stmt VPARAMS ((enum tree_code code, ...)) build_stmt VPARAMS ((enum tree_code code, ...))
...@@ -241,7 +243,7 @@ build_stmt VPARAMS ((enum tree_code code, ...)) ...@@ -241,7 +243,7 @@ build_stmt VPARAMS ((enum tree_code code, ...))
t = make_node (code); t = make_node (code);
length = TREE_CODE_LENGTH (code); length = TREE_CODE_LENGTH (code);
TREE_COMPLEXITY (t) = lineno; STMT_LINENO (t) = lineno;
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
TREE_OPERAND (t, i) = va_arg (p, tree); TREE_OPERAND (t, i) = va_arg (p, tree);
......
...@@ -275,6 +275,8 @@ extern void pedwarn_c99 PARAMS ((const char *, ...)) ...@@ -275,6 +275,8 @@ extern void pedwarn_c99 PARAMS ((const char *, ...))
ATTRIBUTE_PRINTF_1; ATTRIBUTE_PRINTF_1;
extern tree c_start_case PARAMS ((tree)); extern tree c_start_case PARAMS ((tree));
extern void c_finish_case PARAMS ((void)); extern void c_finish_case PARAMS ((void));
extern tree build_asm_stmt PARAMS ((tree, tree, tree,
tree, tree));
/* Set to 0 at beginning of a function definition, set to 1 if /* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */ a return statement that specifies a return value is seen. */
......
...@@ -6303,41 +6303,43 @@ process_init_element (value) ...@@ -6303,41 +6303,43 @@ process_init_element (value)
} }
} }
/* Expand an ASM statement with operands, handling output operands /* Build an asm-statement, whose components are a CV_QUALIFIER, a
that are not variables or INDIRECT_REFS by transforming such STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */
cases into cases that expand_asm_operands can handle.
Arguments are same as for expand_asm_operands. */
void tree
c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers)
tree string, outputs, inputs, clobbers; tree cv_qualifier;
int vol; tree string;
const char *filename; tree outputs;
int line; tree inputs;
tree clobbers;
{ {
int noutputs = list_length (outputs); tree tail;
register int i;
/* o[I] is the place that output number I should be written. */
register tree *o = (tree *) alloca (noutputs * sizeof (tree));
register tree tail;
if (TREE_CODE (string) == ADDR_EXPR) if (TREE_CHAIN (string))
string = TREE_OPERAND (string, 0); string = combine_strings (string);
if (last_tree && TREE_CODE (string) != STRING_CST) if (TREE_CODE (string) != STRING_CST)
{ {
error ("asm template is not a string constant"); error ("asm template is not a string constant");
return; return NULL_TREE;
} }
/* Record the contents of OUTPUTS before it is modified. */ if (cv_qualifier != NULL_TREE
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) && cv_qualifier != ridpointers[(int) RID_VOLATILE])
{
warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
cv_qualifier = NULL_TREE;
}
/* We can remove output conversions that change the type,
but not the mode. */
for (tail = outputs; tail; tail = TREE_CHAIN (tail))
{ {
tree output = TREE_VALUE (tail); tree output = TREE_VALUE (tail);
/* We can remove conversions that just change the type, not the mode. */
STRIP_NOPS (output); STRIP_NOPS (output);
o[i] = output; TREE_VALUE (tail) = output;
/* Allow conversions as LHS here. build_modify_expr as called below /* Allow conversions as LHS here. build_modify_expr as called below
will do the right thing with them. */ will do the right thing with them. */
...@@ -6350,29 +6352,54 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) ...@@ -6350,29 +6352,54 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| TREE_CODE (output) == FIX_CEIL_EXPR) || TREE_CODE (output) == FIX_CEIL_EXPR)
output = TREE_OPERAND (output, 0); output = TREE_OPERAND (output, 0);
if (last_tree) lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement");
lvalue_or_else (o[i], "invalid lvalue in asm statement"); }
/* Remove output conversions that change the type but not the mode. */
for (tail = outputs; tail; tail = TREE_CHAIN (tail))
{
tree output = TREE_VALUE (tail);
STRIP_NOPS (output);
TREE_VALUE (tail) = output;
} }
/* Perform default conversions on array and function inputs. */ /* Perform default conversions on array and function inputs.
/* Don't do this for other types-- Don't do this for other types as it would screw up operands
it would screw up operands expected to be in memory. */ expected to be in memory. */
for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++) for (tail = inputs; tail; tail = TREE_CHAIN (tail))
if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE) || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail)); TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
if (last_tree) return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
{ outputs, inputs, clobbers));
add_stmt (build_stmt (ASM_STMT, }
vol ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
string, outputs, inputs, clobbers)); /* Expand an ASM statement with operands, handling output operands
return; that are not variables or INDIRECT_REFS by transforming such
} cases into cases that expand_asm_operands can handle.
Arguments are same as for expand_asm_operands. */
void
c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
tree string, outputs, inputs, clobbers;
int vol;
const char *filename;
int line;
{
int noutputs = list_length (outputs);
register int i;
/* o[I] is the place that output number I should be written. */
register tree *o = (tree *) alloca (noutputs * sizeof (tree));
register tree tail;
/* Record the contents of OUTPUTS before it is modified. */
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
o[i] = TREE_VALUE (tail);
/* Generate the ASM_OPERANDS insn; /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
store into the TREE_VALUEs of OUTPUTS some trees for OUTPUTS some trees for where the values were actually stored. */
where the values were actually stored. */
expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line); expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
/* Copy all the intermediate outputs into the specified outputs. */ /* Copy all the intermediate outputs into the specified outputs. */
...@@ -6410,7 +6437,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) ...@@ -6410,7 +6437,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
RETVAL is the expression for what to return, RETVAL is the expression for what to return,
or a null pointer for `return;' with no value. */ or a null pointer for `return;' with no value. */
void tree
c_expand_return (retval) c_expand_return (retval)
tree retval; tree retval;
{ {
...@@ -6440,7 +6467,7 @@ c_expand_return (retval) ...@@ -6440,7 +6467,7 @@ c_expand_return (retval)
tree inner; tree inner;
if (t == error_mark_node) if (t == error_mark_node)
return; return NULL_TREE;
inner = t = convert (TREE_TYPE (res), t); inner = t = convert (TREE_TYPE (res), t);
...@@ -6499,7 +6526,7 @@ c_expand_return (retval) ...@@ -6499,7 +6526,7 @@ c_expand_return (retval)
current_function_returns_value = 1; current_function_returns_value = 1;
} }
add_stmt (build_return_stmt (retval)); return add_stmt (build_return_stmt (retval));
} }
struct c_switch { struct c_switch {
...@@ -6581,20 +6608,27 @@ c_start_case (exp) ...@@ -6581,20 +6608,27 @@ c_start_case (exp)
/* Process a case label. */ /* Process a case label. */
void tree
do_case (low_value, high_value) do_case (low_value, high_value)
tree low_value; tree low_value;
tree high_value; tree high_value;
{ {
tree label = NULL_TREE;
if (switch_stack) if (switch_stack)
c_add_case_label (switch_stack->cases, {
SWITCH_COND (switch_stack->switch_stmt), label = c_add_case_label (switch_stack->cases,
low_value, SWITCH_COND (switch_stack->switch_stmt),
high_value); low_value, high_value);
if (label == error_mark_node)
label = NULL_TREE;
}
else if (low_value) else if (low_value)
error ("case label not within a switch statement"); error ("case label not within a switch statement");
else else
error ("`default' label not within a switch statement"); error ("`default' label not within a switch statement");
return label;
} }
/* Finish the switch statement. */ /* Finish the switch statement. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment