Commit 036165d8 by Chris Manghane Committed by Ian Lance Taylor

compiler: Use backend interface for defining global declarations.

	* go-gcc.cc: Include "cgraph.h" and "gimplify.h".
	(Gcc_backend::return_statement): Push and pop function.
	(Gcc_backend::label): Likewise.
	(Gcc_backend::function_defer_statement): Likewise.
	(Gcc_backend::switch_statement): Add function parameter.
	(Gcc_backend::block): Don't permit function to be NULL.
	(Gcc_backend::temporary_variable): Change go_assert to
	gcc_assert.
	(Gcc_backend::gc_root_variable): New function.
	(Gcc_backend::write_global_definitions): New function.

From-SVN: r209819
parent 10695c6a
2014-04-25 Chris Manghane <cmang@google.com>
* go-gcc.cc: Include "cgraph.h" and "gimplify.h".
(Gcc_backend::return_statement): Push and pop function.
(Gcc_backend::label): Likewise.
(Gcc_backend::function_defer_statement): Likewise.
(Gcc_backend::switch_statement): Add function parameter.
(Gcc_backend::block): Don't permit function to be NULL.
(Gcc_backend::temporary_variable): Change go_assert to
gcc_assert.
(Gcc_backend::gc_root_variable): New function.
(Gcc_backend::write_global_definitions): New function.
2014-04-22 Chris Manghane <cmang@google.com>
* go-gcc.cc (Gcc_backend::temporary_variable): Push cfun around
......
......@@ -29,9 +29,11 @@
#include "stor-layout.h"
#include "varasm.h"
#include "tree-iterator.h"
#include "cgraph.h"
#include "convert.h"
#include "basic-block.h"
#include "gimple-expr.h"
#include "gimplify.h"
#include "toplev.h"
#include "output.h"
#include "real.h"
......@@ -317,7 +319,7 @@ class Gcc_backend : public Backend
Location);
Bstatement*
switch_statement(Bexpression* value,
switch_statement(Bfunction* function, Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
Location);
......@@ -376,6 +378,9 @@ class Gcc_backend : public Backend
Location, Bstatement**);
Bvariable*
gc_root_variable(Btype*, Bexpression*);
Bvariable*
immutable_struct(const std::string&, bool, bool, Btype*, Location);
void
......@@ -420,6 +425,12 @@ class Gcc_backend : public Backend
bool
function_set_body(Bfunction* function, Bstatement* code_stmt);
void
write_global_definitions(const std::vector<Btype*>&,
const std::vector<Bexpression*>&,
const std::vector<Bfunction*>&,
const std::vector<Bvariable*>&);
private:
// Make a Bexpression from a tree.
Bexpression*
......@@ -1709,6 +1720,7 @@ Gcc_backend::return_statement(Bfunction* bfunction,
tree result = DECL_RESULT(fntree);
if (result == error_mark_node)
return this->error_statement();
tree ret;
if (vals.empty())
ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node,
......@@ -1732,7 +1744,14 @@ Gcc_backend::return_statement(Bfunction* bfunction,
// statement.
tree stmt_list = NULL_TREE;
tree rettype = TREE_TYPE(result);
if (DECL_STRUCT_FUNCTION(fntree) == NULL)
push_struct_function(fntree);
else
push_cfun(DECL_STRUCT_FUNCTION(fntree));
tree rettmp = create_tmp_var(rettype, "RESULT");
pop_cfun();
tree field = TYPE_FIELDS(rettype);
for (std::vector<Bexpression*>::const_iterator p = vals.begin();
p != vals.end();
......@@ -1818,6 +1837,7 @@ Gcc_backend::if_statement(Bexpression* condition, Bblock* then_block,
Bstatement*
Gcc_backend::switch_statement(
Bfunction* function,
Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
......@@ -1825,6 +1845,12 @@ Gcc_backend::switch_statement(
{
gcc_assert(cases.size() == statements.size());
tree decl = function->get_tree();
if (DECL_STRUCT_FUNCTION(decl) == NULL)
push_struct_function(decl);
else
push_cfun(DECL_STRUCT_FUNCTION(decl));
tree stmt_list = NULL_TREE;
std::vector<std::vector<Bexpression*> >::const_iterator pc = cases.begin();
for (std::vector<Bstatement*>::const_iterator ps = statements.begin();
......@@ -1864,6 +1890,7 @@ Gcc_backend::switch_statement(
append_to_statement_list(t, &stmt_list);
}
}
pop_cfun();
tree tv = value->get_tree();
if (tv == error_mark_node)
......@@ -1922,13 +1949,7 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing,
tree block_tree = make_node(BLOCK);
if (enclosing == NULL)
{
// FIXME: Permitting FUNCTION to be NULL is a temporary measure
// until we have a proper representation of the init function.
tree fndecl;
if (function == NULL)
fndecl = current_function_decl;
else
fndecl = function->get_tree();
tree fndecl = function->get_tree();
gcc_assert(fndecl != NULL_TREE);
// We may have already created a block for local variables when
......@@ -1982,7 +2003,6 @@ Gcc_backend::block(Bfunction* function, Bblock* enclosing,
void_type_node, BLOCK_VARS(block_tree),
NULL_TREE, block_tree);
TREE_SIDE_EFFECTS(bind_tree) = 1;
return new Bblock(bind_tree);
}
......@@ -2214,7 +2234,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
return this->error_variable();
}
go_assert(function != NULL);
gcc_assert(function != NULL);
tree decl = function->get_tree();
tree var;
......@@ -2263,6 +2283,28 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
return new Bvariable(var);
}
// Make a GC root variable.
Bvariable*
Gcc_backend::gc_root_variable(Btype* type, Bexpression* init)
{
tree type_tree = type->get_tree();
tree init_tree = init->get_tree();
if (type_tree == error_mark_node || init_tree == error_mark_node)
return this->error_variable();
tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
create_tmp_var_name("gc"), type_tree);
DECL_EXTERNAL(decl) = 0;
TREE_PUBLIC(decl) = 0;
TREE_STATIC(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
DECL_INITIAL(decl) = init_tree;
rest_of_decl_compilation(decl, 1, 0);
return new Bvariable(decl);
}
// Create a named immutable initialized data structure.
Bvariable*
......@@ -2277,9 +2319,9 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
get_identifier_from_string(name),
build_qualified_type(type_tree, TYPE_QUAL_CONST));
TREE_STATIC(decl) = 1;
TREE_USED(decl) = 1;
TREE_READONLY(decl) = 1;
TREE_CONSTANT(decl) = 1;
TREE_USED(decl) = 1;
DECL_ARTIFICIAL(decl) = 1;
if (!is_hidden)
TREE_PUBLIC(decl) = 1;
......@@ -2369,7 +2411,17 @@ Gcc_backend::label(Bfunction* function, const std::string& name,
{
tree decl;
if (name.empty())
decl = create_artificial_label(location.gcc_location());
{
tree func_tree = function->get_tree();
if (DECL_STRUCT_FUNCTION(func_tree) == NULL)
push_struct_function(func_tree);
else
push_cfun(DECL_STRUCT_FUNCTION(func_tree));
decl = create_artificial_label(location.gcc_location());
pop_cfun();
}
else
{
tree id = get_identifier_from_string(name);
......@@ -2477,11 +2529,18 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
{
tree undefer_tree = undefer->get_tree();
tree defer_tree = defer->get_tree();
tree fntree = function->get_tree();
if (undefer_tree == error_mark_node
|| defer_tree == error_mark_node)
|| defer_tree == error_mark_node
|| fntree == error_mark_node)
return this->error_statement();
if (DECL_STRUCT_FUNCTION(fntree) == NULL)
push_struct_function(fntree);
else
push_cfun(DECL_STRUCT_FUNCTION(fntree));
tree stmt_list = NULL;
Blabel* blabel = this->label(function, "", location);
Bstatement* label_def = this->label_definition_statement(blabel);
......@@ -2494,6 +2553,7 @@ Gcc_backend::function_defer_statement(Bfunction* function, Bexpression* undefer,
tree try_catch =
build2(TRY_CATCH_EXPR, void_type_node, undefer_tree, catch_body);
append_to_statement_list(try_catch, &stmt_list);
pop_cfun();
return this->make_statement(stmt_list);
}
......@@ -2538,6 +2598,88 @@ Gcc_backend::function_set_body(Bfunction* function, Bstatement* code_stmt)
return true;
}
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
void
Gcc_backend::write_global_definitions(
const std::vector<Btype*>& type_decls,
const std::vector<Bexpression*>& constant_decls,
const std::vector<Bfunction*>& function_decls,
const std::vector<Bvariable*>& variable_decls)
{
size_t count_definitions = type_decls.size() + constant_decls.size()
+ function_decls.size() + variable_decls.size();
tree* defs = new tree[count_definitions];
// Convert all non-erroneous declarations into Gimple form.
size_t i = 0;
for (std::vector<Bvariable*>::const_iterator p = variable_decls.begin();
p != variable_decls.end();
++p)
{
if ((*p)->get_tree() != error_mark_node)
{
defs[i] = (*p)->get_tree();
go_preserve_from_gc(defs[i]);
++i;
}
}
for (std::vector<Btype*>::const_iterator p = type_decls.begin();
p != type_decls.end();
++p)
{
tree type_tree = (*p)->get_tree();
if (type_tree != error_mark_node
&& IS_TYPE_OR_DECL_P(type_tree))
{
defs[i] = TYPE_NAME(type_tree);
gcc_assert(defs[i] != NULL);
go_preserve_from_gc(defs[i]);
++i;
}
}
for (std::vector<Bexpression*>::const_iterator p = constant_decls.begin();
p != constant_decls.end();
++p)
{
if ((*p)->get_tree() != error_mark_node)
{
defs[i] = (*p)->get_tree();
go_preserve_from_gc(defs[i]);
++i;
}
}
for (std::vector<Bfunction*>::const_iterator p = function_decls.begin();
p != function_decls.end();
++p)
{
tree decl = (*p)->get_tree();
if (decl != error_mark_node)
{
go_preserve_from_gc(decl);
gimplify_function_tree(decl);
cgraph_finalize_function(decl, true);
defs[i] = decl;
++i;
}
}
// Pass everything back to the middle-end.
wrapup_global_declarations(defs, i);
finalize_compilation_unit();
check_global_declarations(defs, i);
emit_debug_global_declarations(defs, i);
delete[] defs;
}
// The single backend.
static Gcc_backend gcc_backend;
......
......@@ -406,9 +406,9 @@ class Backend
// integers, then STATEMENTS[i] is executed. STATEMENTS[i] will
// either end with a goto statement or will fall through into
// STATEMENTS[i + 1]. CASES[i] is empty for the default clause,
// which need not be last.
// which need not be last. FUNCTION is the current function.
virtual Bstatement*
switch_statement(Bexpression* value,
switch_statement(Bfunction* function, Bexpression* value,
const std::vector<std::vector<Bexpression*> >& cases,
const std::vector<Bstatement*>& statements,
Location) = 0;
......@@ -534,6 +534,12 @@ class Backend
bool address_is_taken, Location location,
Bstatement** pstatement) = 0;
// Create a GC root variable. TYPE is the __go_gc_root_list struct described
// in Gogo::register_gc_vars. INIT is the composite literal consisting of a
// pointer to the next GC root and the global variables registered.
virtual Bvariable*
gc_root_variable(Btype* type, Bexpression* init) = 0;
// Create a named immutable initialized data structure. This is
// used for type descriptors, map descriptors, and function
// descriptors. This returns a Bvariable because it corresponds to
......@@ -653,6 +659,16 @@ class Backend
// true on success, false on failure.
virtual bool
function_set_body(Bfunction* function, Bstatement* code_stmt) = 0;
// Utility.
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
virtual void
write_global_definitions(const std::vector<Btype*>& type_decls,
const std::vector<Bexpression*>& constant_decls,
const std::vector<Bfunction*>& function_decls,
const std::vector<Bvariable*>& variable_decls) = 0;
};
// The backend interface has to define this function.
......
......@@ -3578,127 +3578,7 @@ Expression::make_unsafe_cast(Type* type, Expression* expr,
return new Unsafe_type_conversion_expression(type, expr, location);
}
// Unary expressions.
class Unary_expression : public Expression
{
public:
Unary_expression(Operator op, Expression* expr, Location location)
: Expression(EXPRESSION_UNARY, location),
op_(op), escapes_(true), create_temp_(false), expr_(expr),
issue_nil_check_(false)
{ }
// Return the operator.
Operator
op() const
{ return this->op_; }
// Return the operand.
Expression*
operand() const
{ return this->expr_; }
// Record that an address expression does not escape.
void
set_does_not_escape()
{
go_assert(this->op_ == OPERATOR_AND);
this->escapes_ = false;
}
// Record that this is an address expression which should create a
// temporary variable if necessary. This is used for method calls.
void
set_create_temp()
{
go_assert(this->op_ == OPERATOR_AND);
this->create_temp_ = true;
}
// Apply unary opcode OP to UNC, setting NC. Return true if this
// could be done, false if not. Issue errors for overflow.
static bool
eval_constant(Operator op, const Numeric_constant* unc,
Location, Numeric_constant* nc);
static Expression*
do_import(Import*);
protected:
int
do_traverse(Traverse* traverse)
{ return Expression::traverse(&this->expr_, traverse); }
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
Expression*
do_flatten(Gogo*, Named_object*, Statement_inserter*);
bool
do_is_constant() const;
bool
do_is_immutable() const
{ return this->expr_->is_immutable()
|| (this->op_ == OPERATOR_AND && this->expr_->is_variable()); }
bool
do_numeric_constant_value(Numeric_constant*) const;
Type*
do_type();
void
do_determine_type(const Type_context*);
void
do_check_types(Gogo*);
Expression*
do_copy()
{
return Expression::make_unary(this->op_, this->expr_->copy(),
this->location());
}
bool
do_must_eval_subexpressions_in_order(int*) const
{ return this->op_ == OPERATOR_MULT; }
bool
do_is_addressable() const
{ return this->op_ == OPERATOR_MULT; }
tree
do_get_tree(Translate_context*);
void
do_export(Export*) const;
void
do_dump_expression(Ast_dump_context*) const;
void
do_issue_nil_check()
{ this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
private:
// The unary operator to apply.
Operator op_;
// Normally true. False if this is an address expression which does
// not escape the current function.
bool escapes_;
// True if this is an address expression which should create a
// temporary variable if necessary.
bool create_temp_;
// The operand.
Expression* expr_;
// Whether or not to issue a nil check for this expression if its address
// is being taken.
bool issue_nil_check_;
};
// Class Unary_expression.
// If we are taking the address of a composite literal, and the
// contents are not constant, then we want to make a heap expression
......@@ -4214,11 +4094,18 @@ Unary_expression::do_get_tree(Translate_context* context)
}
}
// Build a decl for a constant constructor.
if ((this->expr_->is_composite_literal()
if (this->is_gc_root_)
{
// Build a decl for a GC root variable. GC roots are mutable, so they
// cannot be represented as an immutable_struct in the backend.
Bvariable* gc_root = gogo->backend()->gc_root_variable(btype, bexpr);
bexpr = gogo->backend()->var_expression(gc_root, loc);
}
else if ((this->expr_->is_composite_literal()
|| this->expr_->string_expression() != NULL)
&& this->expr_->is_immutable())
{
// Build a decl for a constant constructor.
static unsigned int counter;
char buf[100];
snprintf(buf, sizeof buf, "C%u", counter);
......@@ -12508,6 +12395,14 @@ Fixed_array_construction_expression::do_get_tree(Translate_context* context)
return expr_to_tree(this->get_constructor(context, btype));
}
Expression*
Expression::make_array_composite_literal(Type* type, Expression_list* vals,
Location location)
{
go_assert(type->array_type() != NULL && !type->is_slice_type());
return new Fixed_array_construction_expression(type, NULL, vals, location);
}
// Construct a slice.
class Slice_construction_expression : public Array_construction_expression
......
......@@ -30,6 +30,7 @@ class Var_expression;
class Temporary_reference_expression;
class Set_and_use_temporary_expression;
class String_expression;
class Unary_expression;
class Binary_expression;
class Call_expression;
class Func_expression;
......@@ -327,6 +328,10 @@ class Expression
static Expression*
make_struct_composite_literal(Type*, Expression_list*, Location);
// Make an array composite literal.
static Expression*
make_array_composite_literal(Type*, Expression_list*, Location);
// Make a slice composite literal.
static Expression*
make_slice_composite_literal(Type*, Expression_list*, Location);
......@@ -533,6 +538,12 @@ class Expression
Expression*
deref();
// If this is a unary expression, return the Unary_expression
// structure. Otherwise return NULL.
Unary_expression*
unary_expression()
{ return this->convert<Unary_expression, EXPRESSION_UNARY>(); }
// If this is a binary expression, return the Binary_expression
// structure. Otherwise return NULL.
Binary_expression*
......@@ -1286,6 +1297,143 @@ class String_expression : public Expression
Type* type_;
};
// A Unary expression.
class Unary_expression : public Expression
{
public:
Unary_expression(Operator op, Expression* expr, Location location)
: Expression(EXPRESSION_UNARY, location),
op_(op), escapes_(true), create_temp_(false), is_gc_root_(false),
expr_(expr), issue_nil_check_(false)
{ }
// Return the operator.
Operator
op() const
{ return this->op_; }
// Return the operand.
Expression*
operand() const
{ return this->expr_; }
// Record that an address expression does not escape.
void
set_does_not_escape()
{
go_assert(this->op_ == OPERATOR_AND);
this->escapes_ = false;
}
// Record that this is an address expression which should create a
// temporary variable if necessary. This is used for method calls.
void
set_create_temp()
{
go_assert(this->op_ == OPERATOR_AND);
this->create_temp_ = true;
}
// Record that this is an address expression of a GC root, which is a
// mutable composite literal. This used for registering GC variables.
void
set_is_gc_root()
{
go_assert(this->op_ == OPERATOR_AND);
this->is_gc_root_ = true;
}
// Apply unary opcode OP to UNC, setting NC. Return true if this
// could be done, false if not. Issue errors for overflow.
static bool
eval_constant(Operator op, const Numeric_constant* unc,
Location, Numeric_constant* nc);
static Expression*
do_import(Import*);
protected:
int
do_traverse(Traverse* traverse)
{ return Expression::traverse(&this->expr_, traverse); }
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
Expression*
do_flatten(Gogo*, Named_object*, Statement_inserter*);
bool
do_is_constant() const;
bool
do_is_immutable() const
{
return (this->expr_->is_immutable()
|| (this->op_ == OPERATOR_AND && this->expr_->is_variable()));
}
bool
do_numeric_constant_value(Numeric_constant*) const;
Type*
do_type();
void
do_determine_type(const Type_context*);
void
do_check_types(Gogo*);
Expression*
do_copy()
{
return Expression::make_unary(this->op_, this->expr_->copy(),
this->location());
}
bool
do_must_eval_subexpressions_in_order(int*) const
{ return this->op_ == OPERATOR_MULT; }
bool
do_is_addressable() const
{ return this->op_ == OPERATOR_MULT; }
tree
do_get_tree(Translate_context*);
void
do_export(Export*) const;
void
do_dump_expression(Ast_dump_context*) const;
void
do_issue_nil_check()
{ this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
private:
// The unary operator to apply.
Operator op_;
// Normally true. False if this is an address expression which does
// not escape the current function.
bool escapes_;
// True if this is an address expression which should create a
// temporary variable if necessary.
bool create_temp_;
// True if this is an address expression for a GC root. A GC root is a
// special struct composite literal that is mutable when addressed, meaning
// it cannot be represented as an immutable_struct in the backend.
bool is_gc_root_;
// The operand.
Expression* expr_;
// Whether or not to issue a nil check for this expression if its address
// is being taken.
bool issue_nil_check_;
};
// A binary expression.
class Binary_expression : public Expression
......
......@@ -44,6 +44,7 @@ class Backend;
class Export;
class Import;
class Bexpression;
class Btype;
class Bstatement;
class Bblock;
class Bvariable;
......@@ -591,11 +592,6 @@ class Gogo
Expression*
runtime_error(int code, Location);
// Build a builtin struct with a list of fields.
static tree
builtin_struct(tree* ptype, const char* struct_name, tree struct_type,
int nfields, ...);
// Mark a function declaration as a builtin library function.
static void
mark_fndecl_as_builtin_library(tree fndecl);
......@@ -650,17 +646,18 @@ class Gogo
Named_object*
initialization_function_decl();
// Write the magic initialization function.
void
write_initialization_function(Named_object* fndecl, tree init_stmt_list);
// Create the magic initialization function.
Named_object*
create_initialization_function(Named_object* fndecl, Bstatement* code_stmt);
// Initialize imported packages.
void
init_imports(tree*);
init_imports(std::vector<Bstatement*>&);
// Register variables with the garbage collector.
void
register_gc_vars(const std::vector<Named_object*>&, tree*);
register_gc_vars(const std::vector<Named_object*>&,
std::vector<Bstatement*>&);
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
......@@ -1086,7 +1083,7 @@ class Function
get_or_make_decl(Gogo*, Named_object*);
// Return the function's decl after it has been built.
tree
Bfunction*
get_decl() const;
// Set the function decl to hold a backend representation of the function
......@@ -1675,7 +1672,7 @@ class Named_constant
Named_constant(Type* type, Expression* expr, int iota_value,
Location location)
: type_(type), expr_(expr), iota_value_(iota_value), location_(location),
lowering_(false), is_sink_(false)
lowering_(false), is_sink_(false), bconst_(NULL)
{ }
Type*
......@@ -1737,6 +1734,10 @@ class Named_constant
static void
import_const(Import*, std::string*, Type**, Expression**);
// Get the backend representation of the constant value.
Bexpression*
get_backend(Gogo*, Named_object*);
private:
// The type of the constant.
Type* type_;
......@@ -1754,6 +1755,8 @@ class Named_constant
bool lowering_;
// Whether this constant is blank named and needs only type checking.
bool is_sink_;
// The backend representation of the constant value.
Bexpression* bconst_;
};
// A type declaration.
......@@ -2176,9 +2179,10 @@ class Named_object
std::string
get_id(Gogo*);
// Return a tree representing this object.
tree
get_tree(Gogo*, Named_object* function);
// Get the backend representation of this object.
void
get_backend(Gogo*, std::vector<Bexpression*>&, std::vector<Btype*>&,
std::vector<Bfunction*>&);
// Define a type declaration.
void
......@@ -2219,8 +2223,6 @@ class Named_object
Function_declaration* func_declaration_value;
Package* package_value;
} u_;
// The DECL tree for this object if we have already converted it.
tree tree_;
};
// A binding contour. This binds names to objects.
......
......@@ -434,15 +434,9 @@ Temporary_statement::do_get_backend(Translate_context* context)
{
go_assert(this->bvariable_ == NULL);
// FIXME: Permitting FUNCTION to be NULL here is a temporary measure
// until we have a better representation of the init function.
Named_object* function = context->function();
Bfunction* bfunction;
if (function == NULL)
bfunction = NULL;
else
bfunction = tree_to_function(function->func_value()->get_decl());
go_assert(function != NULL);
Bfunction* bfunction = function->func_value()->get_decl();
Btype* btype = this->type()->get_backend(context->gogo());
Bexpression* binit;
......@@ -2781,8 +2775,6 @@ Return_statement::do_get_backend(Translate_context* context)
Location loc = this->location();
Function* function = context->function()->func_value();
tree fndecl = function->get_decl();
Function::Results* results = function->result_variables();
std::vector<Bexpression*> retvals;
if (results != NULL && !results->empty())
......@@ -2797,7 +2789,7 @@ Return_statement::do_get_backend(Translate_context* context)
}
}
return context->backend()->return_statement(tree_to_function(fndecl),
return context->backend()->return_statement(function->get_decl(),
retvals, loc);
}
......@@ -3803,8 +3795,10 @@ Constant_switch_statement::do_get_backend(Translate_context* context)
this->clauses_->get_backend(context, break_label, &all_cases,
&all_statements);
Bfunction* bfunction = context->function()->func_value()->get_decl();
Bstatement* switch_statement;
switch_statement = context->backend()->switch_statement(switch_val_expr,
switch_statement = context->backend()->switch_statement(bfunction,
switch_val_expr,
all_cases,
all_statements,
this->location());
......@@ -4980,7 +4974,9 @@ Select_clauses::get_backend(Translate_context* context,
std::vector<Bstatement*> statements;
statements.reserve(2);
Bstatement* switch_stmt = context->backend()->switch_statement(bcall,
Bfunction* bfunction = context->function()->func_value()->get_decl();
Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
bcall,
cases,
clauses,
location);
......
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