Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
f54d331e
Commit
f54d331e
authored
Apr 15, 2011
by
Ian Lance Taylor
Committed by
Ian Lance Taylor
Apr 15, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use the backend interface for select statements.
From-SVN: r172468
parent
7427a368
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
209 additions
and
139 deletions
+209
-139
gcc/go/ChangeLog
+4
-0
gcc/go/go-gcc.cc
+4
-0
gcc/go/gofrontend/backend.h
+6
-0
gcc/go/gofrontend/expressions.cc
+4
-3
gcc/go/gofrontend/runtime.cc
+9
-0
gcc/go/gofrontend/runtime.h
+9
-0
gcc/go/gofrontend/statements.cc
+164
-129
gcc/go/gofrontend/statements.h
+9
-7
No files found.
gcc/go/ChangeLog
View file @
f54d331e
2011-04-14 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Backend::error_statement): New function.
2011-04-13 Ian Lance Taylor <iant@google.com>
* Make-lang.in (go/gogo-tree.o): depend on $(GO_RUNTIME_H).
...
...
gcc/go/go-gcc.cc
View file @
f54d331e
...
...
@@ -167,6 +167,10 @@ class Gcc_backend : public Backend
// Statements.
Bstatement
*
error_statement
()
{
return
this
->
make_statement
(
error_mark_node
);
}
Bstatement
*
expression_statement
(
Bexpression
*
);
Bstatement
*
...
...
gcc/go/gofrontend/backend.h
View file @
f54d331e
...
...
@@ -107,6 +107,12 @@ class Backend
// Statements.
// Create an error statement. This is used for cases which should
// not occur in a correct program, in order to keep the compilation
// going without crashing.
virtual
Bstatement
*
error_statement
()
=
0
;
// Create an expression statement.
virtual
Bstatement
*
expression_statement
(
Bexpression
*
)
=
0
;
...
...
gcc/go/gofrontend/expressions.cc
View file @
f54d331e
...
...
@@ -3603,10 +3603,11 @@ Unsafe_type_conversion_expression::do_get_tree(Translate_context* context)
else
if
(
t
->
channel_type
()
!=
NULL
)
gcc_assert
(
et
->
channel_type
()
!=
NULL
);
else
if
(
t
->
points_to
()
!=
NULL
&&
t
->
points_to
()
->
channel_type
()
!=
NULL
)
gcc_assert
(
et
->
points_to
()
!=
NULL
&&
et
->
points_to
()
->
channel_type
()
!=
NULL
);
gcc_assert
((
et
->
points_to
()
!=
NULL
&&
et
->
points_to
()
->
channel_type
()
!=
NULL
)
||
et
->
is_nil_type
());
else
if
(
t
->
is_unsafe_pointer_type
())
gcc_assert
(
et
->
points_to
()
!=
NULL
);
gcc_assert
(
et
->
points_to
()
!=
NULL
||
et
->
is_nil_type
()
);
else
if
(
et
->
is_unsafe_pointer_type
())
gcc_assert
(
t
->
points_to
()
!=
NULL
);
else
if
(
t
->
interface_type
()
!=
NULL
&&
!
t
->
interface_type
()
->
is_empty
())
...
...
gcc/go/gofrontend/runtime.cc
View file @
f54d331e
...
...
@@ -381,3 +381,12 @@ Runtime::map_iteration_type()
return
Type
::
make_array_type
(
runtime_function_type
(
RFT_POINTER
),
iexpr
);
}
// Return the type used to pass a list of general channels to the
// select runtime function.
Type
*
Runtime
::
chanptr_type
()
{
return
runtime_function_type
(
RFT_CHANPTR
);
}
gcc/go/gofrontend/runtime.h
View file @
f54d331e
...
...
@@ -30,15 +30,24 @@ class Runtime
NUMBER_OF_FUNCTIONS
};
// Make a call to a runtime function.
static
Call_expression
*
make_call
(
Function
,
source_location
,
int
,
...);
// Convert all the types used by runtime functions to the backend
// representation.
static
void
convert_types
(
Gogo
*
);
// Return the type used for iterations over maps.
static
Type
*
map_iteration_type
();
// Return the type used to pass a list of general channels to the
// select runtime function.
static
Type
*
chanptr_type
();
private
:
static
Named_object
*
runtime_declaration
(
Function
);
...
...
gcc/go/gofrontend/statements.cc
View file @
f54d331e
...
...
@@ -3974,12 +3974,13 @@ Select_clauses::Select_clause::may_fall_through() const
// Return a tree for the statements to execute.
tree
Select_clauses
::
Select_clause
::
get_statements_tree
(
Translate_context
*
context
)
Bstatement
*
Select_clauses
::
Select_clause
::
get_statements_backend
(
Translate_context
*
context
)
{
if
(
this
->
statements_
==
NULL
)
return
NULL
_TREE
;
return
t
his
->
statements_
->
get_tree
(
context
);
return
NULL
;
return
t
ree_to_stat
(
this
->
statements_
->
get_tree
(
context
)
);
}
// Class Select_clauses.
...
...
@@ -4037,7 +4038,7 @@ Select_clauses::may_fall_through() const
return
false
;
}
//
Return a tree
. We build a call to
//
Convert to the backend representation
. We build a call to
// size_t __go_select(size_t count, _Bool has_default,
// channel* channels, _Bool* is_send)
//
...
...
@@ -4051,20 +4052,24 @@ Select_clauses::may_fall_through() const
// FIXME: This doesn't handle channels which send interface types
// where the receiver has a static type which matches that interface.
tree
Select_clauses
::
get_
tree
(
Translate_context
*
context
,
Unnamed_label
*
break_label
,
source_location
location
)
Bstatement
*
Select_clauses
::
get_
backend
(
Translate_context
*
context
,
Unnamed_label
*
break_label
,
source_location
location
)
{
size_t
count
=
this
->
clauses_
.
size
();
VEC
(
constructor_elt
,
gc
)
*
chan_init
=
VEC_alloc
(
constructor_elt
,
gc
,
count
);
VEC
(
constructor_elt
,
gc
)
*
is_send_init
=
VEC_alloc
(
constructor_elt
,
gc
,
count
);
Select_clause
*
default_clause
=
NULL
;
tree
final_stmt_list
=
NULL_TREE
;
tree
channel_type_tree
=
NULL_TREE
;
size_t
i
=
0
;
Expression_list
*
chan_init
=
new
Expression_list
();
chan_init
->
reserve
(
count
);
Expression_list
*
is_send_init
=
new
Expression_list
();
is_send_init
->
reserve
(
count
);
Select_clause
*
default_clause
=
NULL
;
Type
*
runtime_chanptr_type
=
Runtime
::
chanptr_type
();
Type
*
runtime_chan_type
=
runtime_chanptr_type
->
points_to
();
for
(
Clauses
::
iterator
p
=
this
->
clauses_
.
begin
();
p
!=
this
->
clauses_
.
end
();
++
p
)
...
...
@@ -4081,153 +4086,182 @@ Select_clauses::get_tree(Translate_context* context,
// We should have given an error in the send or receive
// statement we created via lowering.
gcc_assert
(
saw_errors
());
return
error_mark_node
;
return
context
->
backend
()
->
error_statement
()
;
}
tree
channel_tree
=
p
->
channel
()
->
get_tree
(
context
);
if
(
channel_tree
==
error_mark_node
)
return
error_mark_node
;
channel_type_tree
=
TREE_TYPE
(
channel_tree
);
constructor_elt
*
elt
=
VEC_quick_push
(
constructor_elt
,
chan_init
,
NULL
);
elt
->
index
=
build_int_cstu
(
sizetype
,
i
);
elt
->
value
=
channel_tree
;
elt
=
VEC_quick_push
(
constructor_elt
,
is_send_init
,
NULL
);
elt
->
index
=
build_int_cstu
(
sizetype
,
i
);
elt
->
value
=
p
->
is_send
()
?
boolean_true_node
:
boolean_false_node
;
Expression
*
c
=
p
->
channel
();
c
=
Expression
::
make_unsafe_cast
(
runtime_chan_type
,
c
,
p
->
location
());
chan_init
->
push_back
(
c
);
++
i
;
is_send_init
->
push_back
(
Expression
::
make_boolean
(
p
->
is_send
(),
p
->
location
()));
}
gcc_assert
(
i
==
count
);
if
(
i
==
0
&&
default_clause
!=
NULL
)
if
(
chan_init
->
empty
()
)
{
// There is only a default clause.
gcc_assert
(
final_stmt_list
==
NULL_TREE
);
tree
stmt_list
=
NULL_TREE
;
append_to_statement_list
(
default_clause
->
get_statements_tree
(
context
),
&
stmt_list
);
gcc_assert
(
count
==
0
);
Bstatement
*
s
;
Bstatement
*
ldef
=
break_label
->
get_definition
(
context
);
append_to_statement_list
(
stat_to_tree
(
ldef
),
&
stmt_list
);
return
stmt_list
;
if
(
default_clause
!=
NULL
)
{
// There is a default clause and no cases. Just execute the
// default clause.
s
=
default_clause
->
get_statements_backend
(
context
);
}
else
{
// There isn't even a default clause. In this case select
// pauses forever. Call the runtime function with nils.
mpz_t
zval
;
mpz_init_set_ui
(
zval
,
0
);
Expression
*
zero
=
Expression
::
make_integer
(
&
zval
,
NULL
,
location
);
mpz_clear
(
zval
);
Expression
*
default_arg
=
Expression
::
make_boolean
(
false
,
location
);
Expression
*
nil1
=
Expression
::
make_nil
(
location
);
Expression
*
nil2
=
nil1
->
copy
();
Expression
*
call
=
Runtime
::
make_call
(
Runtime
::
SELECT
,
location
,
4
,
zero
,
default_arg
,
nil1
,
nil2
);
context
->
gogo
()
->
lower_expression
(
context
->
function
(),
&
call
);
Bexpression
*
bcall
=
tree_to_expr
(
call
->
get_tree
(
context
));
s
=
context
->
backend
()
->
expression_statement
(
bcall
);
}
if
(
s
==
NULL
)
return
ldef
;
std
::
vector
<
Bstatement
*>
stats
(
2
);
stats
[
0
]
=
s
;
stats
[
1
]
=
ldef
;
return
context
->
backend
()
->
statement_list
(
stats
);
}
gcc_assert
(
count
>
0
);
tree
pointer_chan_type_tree
=
(
channel_type_tree
==
NULL_TREE
?
ptr_type_node
:
build_pointer_type
(
channel_type_tree
));
tree
chans_arg
;
tree
pointer_boolean_type_tree
=
build_pointer_type
(
boolean_type_node
);
tree
is_sends_arg
;
std
::
vector
<
Bstatement
*>
statements
;
if
(
i
==
0
)
{
chans_arg
=
fold_convert_loc
(
location
,
pointer_chan_type_tree
,
null_pointer_node
);
is_sends_arg
=
fold_convert_loc
(
location
,
pointer_boolean_type_tree
,
null_pointer_node
);
}
else
{
tree
index_type_tree
=
build_index_type
(
size_int
(
count
-
1
));
tree
chan_array_type_tree
=
build_array_type
(
channel_type_tree
,
index_type_tree
);
tree
chan_constructor
=
build_constructor
(
chan_array_type_tree
,
chan_init
);
tree
chan_var
=
create_tmp_var
(
chan_array_type_tree
,
"CHAN"
);
DECL_IGNORED_P
(
chan_var
)
=
0
;
DECL_INITIAL
(
chan_var
)
=
chan_constructor
;
DECL_SOURCE_LOCATION
(
chan_var
)
=
location
;
TREE_ADDRESSABLE
(
chan_var
)
=
1
;
tree
decl_expr
=
build1
(
DECL_EXPR
,
void_type_node
,
chan_var
);
SET_EXPR_LOCATION
(
decl_expr
,
location
);
append_to_statement_list
(
decl_expr
,
&
final_stmt_list
);
tree
is_send_array_type_tree
=
build_array_type
(
boolean_type_node
,
index_type_tree
);
tree
is_send_constructor
=
build_constructor
(
is_send_array_type_tree
,
is_send_init
);
tree
is_send_var
=
create_tmp_var
(
is_send_array_type_tree
,
"ISSEND"
);
DECL_IGNORED_P
(
is_send_var
)
=
0
;
DECL_INITIAL
(
is_send_var
)
=
is_send_constructor
;
DECL_SOURCE_LOCATION
(
is_send_var
)
=
location
;
TREE_ADDRESSABLE
(
is_send_var
)
=
1
;
decl_expr
=
build1
(
DECL_EXPR
,
void_type_node
,
is_send_var
);
SET_EXPR_LOCATION
(
decl_expr
,
location
);
append_to_statement_list
(
decl_expr
,
&
final_stmt_list
);
chans_arg
=
fold_convert_loc
(
location
,
pointer_chan_type_tree
,
build_fold_addr_expr_loc
(
location
,
chan_var
));
is_sends_arg
=
fold_convert_loc
(
location
,
pointer_boolean_type_tree
,
build_fold_addr_expr_loc
(
location
,
is_send_var
));
}
mpz_t
ival
;
mpz_init_set_ui
(
ival
,
count
);
Expression
*
ecount
=
Expression
::
make_integer
(
&
ival
,
NULL
,
location
);
mpz_clear
(
ival
);
static
tree
select_fndecl
;
tree
call
=
Gogo
::
call_builtin
(
&
select_fndecl
,
location
,
"__go_select"
,
4
,
sizetype
,
sizetype
,
size_int
(
count
),
boolean_type_node
,
(
default_clause
==
NULL
?
boolean_false_node
:
boolean_true_node
),
pointer_chan_type_tree
,
chans_arg
,
pointer_boolean_type_tree
,
is_sends_arg
);
if
(
call
==
error_mark_node
)
return
error_mark_node
;
Type
*
chan_array_type
=
Type
::
make_array_type
(
runtime_chan_type
,
ecount
);
Expression
*
chans
=
Expression
::
make_composite_literal
(
chan_array_type
,
0
,
false
,
chan_init
,
location
);
context
->
gogo
()
->
lower_expression
(
context
->
function
(),
&
chans
);
Temporary_statement
*
chan_temp
=
Statement
::
make_temporary
(
chan_array_type
,
chans
,
location
);
statements
.
push_back
(
tree_to_stat
(
chan_temp
->
get_tree
(
context
)));
Type
*
is_send_array_type
=
Type
::
make_array_type
(
Type
::
lookup_bool_type
(),
ecount
->
copy
());
Expression
*
is_sends
=
Expression
::
make_composite_literal
(
is_send_array_type
,
0
,
false
,
is_send_init
,
location
);
context
->
gogo
()
->
lower_expression
(
context
->
function
(),
&
is_sends
);
Temporary_statement
*
is_send_temp
=
Statement
::
make_temporary
(
is_send_array_type
,
is_sends
,
location
);
statements
.
push_back
(
tree_to_stat
(
is_send_temp
->
get_tree
(
context
)));
mpz_init_set_ui
(
ival
,
0
);
Expression
*
zero
=
Expression
::
make_integer
(
&
ival
,
NULL
,
location
);
mpz_clear
(
ival
);
Expression
*
ref
=
Expression
::
make_temporary_reference
(
chan_temp
,
location
);
Expression
*
chan_arg
=
Expression
::
make_array_index
(
ref
,
zero
,
NULL
,
location
);
chan_arg
=
Expression
::
make_unary
(
OPERATOR_AND
,
chan_arg
,
location
);
chan_arg
=
Expression
::
make_unsafe_cast
(
runtime_chanptr_type
,
chan_arg
,
location
);
ref
=
Expression
::
make_temporary_reference
(
is_send_temp
,
location
);
Expression
*
is_send_arg
=
Expression
::
make_array_index
(
ref
,
zero
->
copy
(),
NULL
,
location
);
is_send_arg
=
Expression
::
make_unary
(
OPERATOR_AND
,
is_send_arg
,
location
);
Expression
*
default_arg
=
Expression
::
make_boolean
(
default_clause
!=
NULL
,
location
);
Expression
*
call
=
Runtime
::
make_call
(
Runtime
::
SELECT
,
location
,
4
,
ecount
->
copy
(),
default_arg
,
chan_arg
,
is_send_arg
);
context
->
gogo
()
->
lower_expression
(
context
->
function
(),
&
call
);
Bexpression
*
bcall
=
tree_to_expr
(
call
->
get_tree
(
context
));
tree
stmt_list
=
NULL_TREE
;
std
::
vector
<
std
::
vector
<
Bexpression
*>
>
cases
;
std
::
vector
<
Bstatement
*>
clauses
;
cases
.
resize
(
count
+
(
default_clause
!=
NULL
?
1
:
0
));
clauses
.
resize
(
count
+
(
default_clause
!=
NULL
?
1
:
0
));
int
index
=
0
;
if
(
default_clause
!=
NULL
)
this
->
add_clause_tree
(
context
,
0
,
default_clause
,
break_label
,
&
stmt_list
);
{
this
->
add_clause_backend
(
context
,
location
,
index
,
0
,
default_clause
,
break_label
,
&
cases
,
&
clauses
);
++
index
;
}
i
=
1
;
i
nt
i
=
1
;
for
(
Clauses
::
iterator
p
=
this
->
clauses_
.
begin
();
p
!=
this
->
clauses_
.
end
();
++
p
)
{
if
(
!
p
->
is_default
())
{
this
->
add_clause_tree
(
context
,
i
,
&*
p
,
break_label
,
&
stmt_list
);
this
->
add_clause_backend
(
context
,
location
,
index
,
i
,
&*
p
,
break_label
,
&
cases
,
&
clauses
);
++
i
;
++
index
;
}
}
Bstatement
*
ldef
=
break_label
->
get_definition
(
context
);
append_to_statement_list
(
stat_to_tree
(
ldef
),
&
stmt_list
);
Bstatement
*
switch_stmt
=
context
->
backend
()
->
switch_statement
(
bcall
,
cases
,
clauses
,
location
);
statements
.
push_back
(
switch_stmt
);
tree
switch_stmt
=
build3
(
SWITCH_EXPR
,
sizetype
,
call
,
stmt_list
,
NULL_TREE
);
SET_EXPR_LOCATION
(
switch_stmt
,
location
);
append_to_statement_list
(
switch_stmt
,
&
final_stmt_list
);
Bstatement
*
ldef
=
break_label
->
get_definition
(
context
);
statements
.
push_back
(
ldef
);
return
final_stmt_list
;
return
context
->
backend
()
->
statement_list
(
statements
)
;
}
// Add the tree for CLAUSE to STMT_LIST.
void
Select_clauses
::
add_clause_tree
(
Translate_context
*
context
,
int
case_index
,
Select_clause
*
clause
,
Unnamed_label
*
bottom_label
,
tree
*
stmt_list
)
{
tree
label
=
create_artificial_label
(
clause
->
location
());
append_to_statement_list
(
build3
(
CASE_LABEL_EXPR
,
void_type_node
,
build_int_cst
(
sizetype
,
case_index
),
NULL_TREE
,
label
),
stmt_list
);
append_to_statement_list
(
clause
->
get_statements_tree
(
context
),
stmt_list
);
Select_clauses
::
add_clause_backend
(
Translate_context
*
context
,
source_location
location
,
int
index
,
int
case_value
,
Select_clause
*
clause
,
Unnamed_label
*
bottom_label
,
std
::
vector
<
std
::
vector
<
Bexpression
*>
>
*
cases
,
std
::
vector
<
Bstatement
*>*
clauses
)
{
mpz_t
ival
;
mpz_init_set_ui
(
ival
,
case_value
);
Expression
*
e
=
Expression
::
make_integer
(
&
ival
,
NULL
,
location
);
mpz_clear
(
ival
);
(
*
cases
)[
index
].
push_back
(
tree_to_expr
(
e
->
get_tree
(
context
)));
Bstatement
*
s
=
clause
->
get_statements_backend
(
context
);
source_location
gloc
=
(
clause
->
statements
()
==
NULL
?
clause
->
location
()
:
clause
->
statements
()
->
end_location
());
Bstatement
*
g
=
bottom_label
->
get_goto
(
context
,
gloc
);
append_to_statement_list
(
stat_to_tree
(
g
),
stmt_list
);
if
(
s
==
NULL
)
(
*
clauses
)[
index
]
=
g
;
else
{
std
::
vector
<
Bstatement
*>
stats
(
2
);
stats
[
0
]
=
s
;
stats
[
1
]
=
g
;
(
*
clauses
)[
index
]
=
context
->
backend
()
->
statement_list
(
stats
);
}
}
// Class Select_statement.
...
...
@@ -4266,8 +4300,9 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
tree
Select_statement
::
do_get_tree
(
Translate_context
*
context
)
{
return
this
->
clauses_
->
get_tree
(
context
,
this
->
break_label
(),
this
->
location
());
Bstatement
*
ret
=
this
->
clauses_
->
get_backend
(
context
,
this
->
break_label
(),
this
->
location
());
return
stat_to_tree
(
ret
);
}
// Make a select statement.
...
...
gcc/go/gofrontend/statements.h
View file @
f54d331e
...
...
@@ -678,9 +678,9 @@ class Select_clauses
bool
may_fall_through
()
const
;
//
Return a tree implementing the select statement
.
tree
get_
tree
(
Translate_context
*
,
Unnamed_label
*
break_label
,
source_location
);
//
Convert to the backend representation
.
Bstatement
*
get_
backend
(
Translate_context
*
,
Unnamed_label
*
break_label
,
source_location
);
private
:
// A single clause.
...
...
@@ -749,8 +749,8 @@ class Select_clauses
may_fall_through
()
const
;
// Return a tree for the statements to execute.
tree
get_statements_
tree
(
Translate_context
*
);
Bstatement
*
get_statements_
backend
(
Translate_context
*
);
private
:
// The channel.
...
...
@@ -778,8 +778,10 @@ class Select_clauses
};
void
add_clause_tree
(
Translate_context
*
,
int
,
Select_clause
*
,
Unnamed_label
*
,
tree
*
);
add_clause_backend
(
Translate_context
*
,
source_location
,
int
index
,
int
case_value
,
Select_clause
*
,
Unnamed_label
*
,
std
::
vector
<
std
::
vector
<
Bexpression
*>
>*
cases
,
std
::
vector
<
Bstatement
*>*
clauses
);
typedef
std
::
vector
<
Select_clause
>
Clauses
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment