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
4bc44ceb
Commit
4bc44ceb
authored
Jan 09, 2014
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
compiler: Add flattening pass
From-SVN: r206502
parent
abd47137
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
267 additions
and
5 deletions
+267
-5
gcc/go/gofrontend/expressions.h
+18
-0
gcc/go/gofrontend/go.cc
+4
-1
gcc/go/gofrontend/gogo.cc
+202
-4
gcc/go/gofrontend/gogo.h
+14
-0
gcc/go/gofrontend/statements.cc
+10
-0
gcc/go/gofrontend/statements.h
+19
-0
No files found.
gcc/go/gofrontend/expressions.h
View file @
4bc44ceb
...
...
@@ -575,6 +575,18 @@ class Expression
int
iota_value
)
{
return
this
->
do_lower
(
gogo
,
function
,
inserter
,
iota_value
);
}
// Flatten an expression. This is called after order_evaluation.
// FUNCTION is the function we are in; it will be NULL for an
// expression initializing a global variable. INSERTER may be used
// to insert statements before the statement or initializer
// containing this expression; it is normally used to create
// temporary variables. This function must resolve expressions
// which could not be fully parsed into their final form. It
// returns the same Expression or a new one.
Expression
*
flatten
(
Gogo
*
gogo
,
Named_object
*
function
,
Statement_inserter
*
inserter
)
{
return
this
->
do_flatten
(
gogo
,
function
,
inserter
);
}
// Determine the real type of an expression with abstract integer,
// floating point, or complex type. TYPE_CONTEXT describes the
// expected type.
...
...
@@ -698,6 +710,12 @@ class Expression
do_lower
(
Gogo
*
,
Named_object
*
,
Statement_inserter
*
,
int
)
{
return
this
;
}
// Return a flattened expression.
virtual
Expression
*
do_flatten
(
Gogo
*
,
Named_object
*
,
Statement_inserter
*
)
{
return
this
;
}
// Return whether this is a constant expression.
virtual
bool
do_is_constant
()
const
...
...
gcc/go/gofrontend/go.cc
View file @
4bc44ceb
...
...
@@ -119,12 +119,15 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
// Use temporary variables to force order of evaluation.
::
gogo
->
order_evaluations
();
// Flatten the parse tree.
::
gogo
->
flatten
();
// Build thunks for functions which call recover.
::
gogo
->
build_recover_thunks
();
// Convert complicated go and defer statements into simpler ones.
::
gogo
->
simplify_thunk_statements
();
// Dump ast, use filename[0] as the base name
::
gogo
->
dump_ast
(
filenames
[
0
]);
}
...
...
gcc/go/gofrontend/gogo.cc
View file @
4bc44ceb
...
...
@@ -2703,6 +2703,169 @@ Gogo::order_evaluations()
this
->
traverse
(
&
order_eval
);
}
// Traversal to flatten parse tree after order of evaluation rules are applied.
class
Flatten
:
public
Traverse
{
public
:
Flatten
(
Gogo
*
gogo
,
Named_object
*
function
)
:
Traverse
(
traverse_variables
|
traverse_functions
|
traverse_statements
|
traverse_expressions
),
gogo_
(
gogo
),
function_
(
function
),
inserter_
()
{
}
void
set_inserter
(
const
Statement_inserter
*
inserter
)
{
this
->
inserter_
=
*
inserter
;
}
int
variable
(
Named_object
*
);
int
function
(
Named_object
*
);
int
statement
(
Block
*
,
size_t
*
pindex
,
Statement
*
);
int
expression
(
Expression
**
);
private
:
// General IR.
Gogo
*
gogo_
;
// The function we are traversing.
Named_object
*
function_
;
// Current statement inserter for use by expressions.
Statement_inserter
inserter_
;
};
// Flatten variables.
int
Flatten
::
variable
(
Named_object
*
no
)
{
if
(
!
no
->
is_variable
())
return
TRAVERSE_CONTINUE
;
if
(
no
->
is_variable
()
&&
no
->
var_value
()
->
is_global
())
{
// Global variables can have loops in their initialization
// expressions. This is handled in flatten_init_expression.
no
->
var_value
()
->
flatten_init_expression
(
this
->
gogo_
,
this
->
function_
,
&
this
->
inserter_
);
return
TRAVERSE_CONTINUE
;
}
go_assert
(
!
no
->
var_value
()
->
has_pre_init
());
return
TRAVERSE_SKIP_COMPONENTS
;
}
// Flatten the body of a function. Record the function while flattening it,
// so that we can pass it down when flattening an expression.
int
Flatten
::
function
(
Named_object
*
no
)
{
go_assert
(
this
->
function_
==
NULL
);
this
->
function_
=
no
;
int
t
=
no
->
func_value
()
->
traverse
(
this
);
this
->
function_
=
NULL
;
if
(
t
==
TRAVERSE_EXIT
)
return
t
;
return
TRAVERSE_SKIP_COMPONENTS
;
}
// Flatten statement parse trees.
int
Flatten
::
statement
(
Block
*
block
,
size_t
*
pindex
,
Statement
*
sorig
)
{
// Because we explicitly traverse the statement's contents
// ourselves, we want to skip block statements here. There is
// nothing to flatten in a block statement.
if
(
sorig
->
is_block_statement
())
return
TRAVERSE_CONTINUE
;
Statement_inserter
hold_inserter
(
this
->
inserter_
);
this
->
inserter_
=
Statement_inserter
(
block
,
pindex
);
// Flatten the expressions first.
int
t
=
sorig
->
traverse_contents
(
this
);
if
(
t
==
TRAVERSE_EXIT
)
{
this
->
inserter_
=
hold_inserter
;
return
t
;
}
// Keep flattening until nothing changes.
Statement
*
s
=
sorig
;
while
(
true
)
{
Statement
*
snew
=
s
->
flatten
(
this
->
gogo_
,
this
->
function_
,
block
,
&
this
->
inserter_
);
if
(
snew
==
s
)
break
;
s
=
snew
;
t
=
s
->
traverse_contents
(
this
);
if
(
t
==
TRAVERSE_EXIT
)
{
this
->
inserter_
=
hold_inserter
;
return
t
;
}
}
if
(
s
!=
sorig
)
block
->
replace_statement
(
*
pindex
,
s
);
this
->
inserter_
=
hold_inserter
;
return
TRAVERSE_SKIP_COMPONENTS
;
}
// Flatten expression parse trees.
int
Flatten
::
expression
(
Expression
**
pexpr
)
{
// Keep flattening until nothing changes.
while
(
true
)
{
Expression
*
e
=
*
pexpr
;
if
(
e
->
traverse_subexpressions
(
this
)
==
TRAVERSE_EXIT
)
return
TRAVERSE_EXIT
;
Expression
*
enew
=
e
->
flatten
(
this
->
gogo_
,
this
->
function_
,
&
this
->
inserter_
);
if
(
enew
==
e
)
break
;
*
pexpr
=
enew
;
}
return
TRAVERSE_SKIP_COMPONENTS
;
}
// Flatten an expression. INSERTER may be NULL, in which case the
// expression had better not need to create any temporaries.
void
Gogo
::
flatten_expression
(
Named_object
*
function
,
Statement_inserter
*
inserter
,
Expression
**
pexpr
)
{
Flatten
flatten
(
this
,
function
);
if
(
inserter
!=
NULL
)
flatten
.
set_inserter
(
inserter
);
flatten
.
expression
(
pexpr
);
}
void
Gogo
::
flatten
()
{
Flatten
flatten
(
this
,
NULL
);
this
->
traverse
(
&
flatten
);
}
// Traversal to convert calls to the predeclared recover function to
// pass in an argument indicating whether it can recover from a panic
// or not.
...
...
@@ -4286,10 +4449,11 @@ Variable::Variable(Type* type, Expression* init, bool is_global,
backend_
(
NULL
),
is_global_
(
is_global
),
is_parameter_
(
is_parameter
),
is_receiver_
(
is_receiver
),
is_varargs_parameter_
(
false
),
is_used_
(
false
),
is_address_taken_
(
false
),
is_non_escaping_address_taken_
(
false
),
seen_
(
false
),
init_is_lowered_
(
false
),
type_from_init_tuple_
(
false
),
type_from_range_index_
(
false
),
type_from_range_value_
(
false
),
type_from_chan_element_
(
false
),
is_type_switch_var_
(
false
),
determined_type_
(
false
),
in_unique_section_
(
false
)
seen_
(
false
),
init_is_lowered_
(
false
),
init_is_flattened_
(
false
),
type_from_init_tuple_
(
false
),
type_from_range_index_
(
false
),
type_from_range_value_
(
false
),
type_from_chan_element_
(
false
),
is_type_switch_var_
(
false
),
determined_type_
(
false
),
in_unique_section_
(
false
)
{
go_assert
(
type
!=
NULL
||
init
!=
NULL
);
go_assert
(
!
is_parameter
||
init
==
NULL
);
...
...
@@ -4351,6 +4515,40 @@ Variable::lower_init_expression(Gogo* gogo, Named_object* function,
}
}
// Flatten the initialization expression after ordering evaluations.
void
Variable
::
flatten_init_expression
(
Gogo
*
gogo
,
Named_object
*
function
,
Statement_inserter
*
inserter
)
{
Named_object
*
dep
=
gogo
->
var_depends_on
(
this
);
if
(
dep
!=
NULL
&&
dep
->
is_variable
())
dep
->
var_value
()
->
flatten_init_expression
(
gogo
,
function
,
inserter
);
if
(
this
->
init_
!=
NULL
&&
!
this
->
init_is_flattened_
)
{
if
(
this
->
seen_
)
{
// We will give an error elsewhere, this is just to prevent
// an infinite loop.
return
;
}
this
->
seen_
=
true
;
Statement_inserter
global_inserter
;
if
(
this
->
is_global_
)
{
global_inserter
=
Statement_inserter
(
gogo
,
this
);
inserter
=
&
global_inserter
;
}
gogo
->
flatten_expression
(
function
,
inserter
,
&
this
->
init_
);
this
->
seen_
=
false
;
this
->
init_is_flattened_
=
true
;
}
}
// Get the preinit block.
Block
*
...
...
gcc/go/gofrontend/gogo.h
View file @
4bc44ceb
...
...
@@ -487,6 +487,10 @@ class Gogo
void
lower_constant
(
Named_object
*
);
// Flatten an expression.
void
flatten_expression
(
Named_object
*
function
,
Statement_inserter
*
,
Expression
**
);
// Create all necessary function descriptors.
void
create_function_descriptors
();
...
...
@@ -531,6 +535,10 @@ class Gogo
void
order_evaluations
();
// Flatten parse tree.
void
flatten
();
// Build thunks for functions which call recover.
void
build_recover_thunks
();
...
...
@@ -1447,6 +1455,10 @@ class Variable
void
lower_init_expression
(
Gogo
*
,
Named_object
*
,
Statement_inserter
*
);
// Flatten the initialization expression after ordering evaluations.
void
flatten_init_expression
(
Gogo
*
,
Named_object
*
,
Statement_inserter
*
);
// A special case: the init value is used only to determine the
// type. This is used if the variable is defined using := with the
// comma-ok form of a map index or a receive expression. The init
...
...
@@ -1580,6 +1592,8 @@ class Variable
bool
seen_
:
1
;
// True if we have lowered the initialization expression.
bool
init_is_lowered_
:
1
;
// True if we have flattened the initialization expression.
bool
init_is_flattened_
:
1
;
// True if init is a tuple used to set the type.
bool
type_from_init_tuple_
:
1
;
// True if init is a range clause and the type is the index type.
...
...
gcc/go/gofrontend/statements.cc
View file @
4bc44ceb
...
...
@@ -246,6 +246,16 @@ Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
return
this
;
}
// Flatten the variable's initialization expression.
Statement
*
Variable_declaration_statement
::
do_flatten
(
Gogo
*
gogo
,
Named_object
*
function
,
Block
*
,
Statement_inserter
*
inserter
)
{
this
->
var_
->
var_value
()
->
flatten_init_expression
(
gogo
,
function
,
inserter
);
return
this
;
}
// Convert a variable declaration to the backend representation.
Bstatement
*
...
...
gcc/go/gofrontend/statements.h
View file @
4bc44ceb
...
...
@@ -306,6 +306,16 @@ class Statement
Statement_inserter
*
inserter
)
{
return
this
->
do_lower
(
gogo
,
function
,
block
,
inserter
);
}
// Flatten a statement. This is called immediately after the order of
// evaluation rules are applied to statements. It returns the same
// Statement or a new one. FUNCTION is the function containing this
// statement. BLOCK is the block containing this statement.
// INSERTER can be used to insert new statements before this one.
Statement
*
flatten
(
Gogo
*
gogo
,
Named_object
*
function
,
Block
*
block
,
Statement_inserter
*
inserter
)
{
return
this
->
do_flatten
(
gogo
,
function
,
block
,
inserter
);
}
// Set type information for unnamed constants.
void
determine_types
();
...
...
@@ -412,6 +422,12 @@ class Statement
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
,
Statement_inserter
*
)
{
return
this
;
}
// Implemented by the child class: lower this statement to a simpler
// one.
virtual
Statement
*
do_flatten
(
Gogo
*
,
Named_object
*
,
Block
*
,
Statement_inserter
*
)
{
return
this
;
}
// Implemented by child class: set type information for unnamed
// constants. Any statement which includes an expression needs to
// implement this.
...
...
@@ -583,6 +599,9 @@ class Variable_declaration_statement : public Statement
Statement
*
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
,
Statement_inserter
*
);
Statement
*
do_flatten
(
Gogo
*
,
Named_object
*
,
Block
*
,
Statement_inserter
*
);
Bstatement
*
do_get_backend
(
Translate_context
*
);
...
...
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