@@ -60,7 +60,6 @@
go/import-elf.o \
go/lex.o \
go/parse.o \
- go/refcount.o \
go/statements.o \
go/types.o \
go/unsafe.o
@@ -149,7 +148,7 @@
go/expressions.o: go/expressions.cc $(GO_SYSTEM_H) intl.h $(TREE_H) \
$(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) $(TM_P_H) \
$(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/export.h $(GO_IMPORT_H) \
- go/refcount.h $(GO_STATEMENTS_H) $(GO_LEX_H) $(GO_EXPRESSIONS_H)
+ $(GO_STATEMENTS_H) $(GO_LEX_H) $(GO_EXPRESSIONS_H)
go/go.o: go/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) $(GO_PARSE_H) \
$(GO_GOGO_H)
go/go-dump.o: go/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) go/go-dump.h
@@ -160,10 +159,10 @@
go/gogo-tree.o: go/gogo-tree.cc $(GO_SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
tree-iterator.h $(CGRAPH_H) langhooks.h convert.h output.h \
$(TM_P_H) $(DIAGNOSTIC_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) \
- $(GO_STATEMENTS_H) go/refcount.h $(GO_GOGO_H)
+ $(GO_STATEMENTS_H) $(GO_GOGO_H)
go/gogo.o: go/gogo.cc $(GO_SYSTEM_H) go/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) \
$(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) go/dataflow.h $(GO_IMPORT_H) \
- go/export.h go/refcount.h $(GO_GOGO_H)
+ go/export.h $(GO_GOGO_H)
go/import.o: go/import.cc $(GO_SYSTEM_H) $(srcdir)/../include/filenames.h \
$(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) go/export.h $(GO_IMPORT_H)
go/import-archive.o: go/import-archive.cc $(GO_SYSTEM_H) $(GO_IMPORT_H)
@@ -172,15 +171,11 @@
go/lex.o: go/lex.cc $(GO_LEX_H) $(GO_SYSTEM_H)
go/parse.o: go/parse.cc $(GO_SYSTEM_H) $(GO_LEX_H) $(GO_GOGO_H) $(GO_TYPES_H) \
$(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) $(GO_PARSE_H)
-go/refcount.o: go/refcount.cc $(GO_SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
- tree-iterator.h $(RTL_H) $(GO_C_H) go/go-dump.h $(GO_GOGO_H) \
- $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) go/refcount.h
go/statements.o: go/statements.cc $(GO_SYSTEM_H) intl.h $(TREE_H) \
$(GIMPLE_H) convert.h tree-iterator.h $(TREE_FLOW_H) $(REAL_H) \
- $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) go/refcount.h \
+ $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \
$(GO_STATEMENTS_H)
go/types.o: go/types.cc $(GO_SYSTEM_H) intl.h $(TREE_H) $(GIMPLE_H) \
$(REAL_H) $(GO_C_H) $(GO_GOGO_H) go/operator.h $(GO_EXPRESSIONS_H) \
- $(GO_STATEMENTS_H) go/export.h $(GO_IMPORT_H) go/refcount.h \
- $(GO_TYPES_H)
+ $(GO_STATEMENTS_H) go/export.h $(GO_IMPORT_H) $(GO_TYPES_H)
go/unsafe.o: go/unsafe.cc $(GO_SYSTEM_H) $(GO_TYPES_H) $(GO_GOGO_H)
@@ -24,7 +24,6 @@
#include "types.h"
#include "export.h"
#include "import.h"
-#include "refcount.h"
#include "statements.h"
#include "lex.h"
#include "expressions.h"
@@ -135,16 +134,6 @@
this->warn_unused_value();
}
-// This is the default implementation of the function to handle
-// decrementing the reference count of the old value of an lvalue.
-// Any expression which may be an l-value must implement this.
-
-Expression*
-Expression::do_being_set(Refcounts*)
-{
- gcc_unreachable();
-}
-
// This virtual function is called to export expressions. This will
// only be used by expressions which may be constant.
@@ -802,10 +791,6 @@
do_is_addressable() const
{ return true; }
- Expression*
- do_being_set(Refcounts*)
- { return this; }
-
tree
do_get_tree(Translate_context*)
{ return error_mark_node; }
@@ -925,38 +910,6 @@
gcc_unreachable();
}
-// This variable is being copied. We may need to increment the
-// reference count.
-
-Expression*
-Var_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
-
- // FIXME: If this is the last use of this variable, then instead of
- // introducing a copy we can avoid freeing this variable at the end
- // of the function.
-
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// This variable is being set. We may need to decrement the reference
-// count of the old value.
-
-Expression*
-Var_expression::do_being_set(Refcounts* refcounts)
-{
- if (this->variable_->is_variable()
- && this->variable_->var_value()->holds_only_args())
- return this;
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get the tree for a reference to a variable.
tree
@@ -999,31 +952,6 @@
this->statement_->set_is_address_taken();
}
-// The temporary variable is being copied. We may need to increment
-// the reference count.
-
-Expression*
-Temporary_reference_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// The variable is being set. We may need to decrement the reference
-// count of the old value.
-
-Expression*
-Temporary_reference_expression::do_being_set(Refcounts* refcounts)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree referring to the variable.
tree
@@ -1070,10 +998,6 @@
do_is_lvalue() const
{ return true; }
- Expression*
- do_being_set(Refcounts*)
- { return this; }
-
tree
do_get_tree(Translate_context*);
@@ -1141,9 +1065,7 @@
return this->function_->name();
}
-// Traversal. FIXME: Traversing the closure means that we make an
-// entry in the reference count queue for it, but we will never use
-// that entry in practice.
+// Traversal.
int
Func_expression::do_traverse(Traverse* traverse)
@@ -1166,24 +1088,6 @@
gcc_unreachable();
}
-// Copying a function expression requires copying the closure, if any.
-
-Expression*
-Func_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (this->closure_ != NULL)
- this->closure_ = this->closure_->being_copied(refcounts, for_local);
- return this;
-}
-
-// There is nothing to do if we discard a function expression.
-
-Expression*
-Func_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Get the tree for a function expression without evaluating the
// closure.
@@ -2345,12 +2249,6 @@
do_copy()
{ return this; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context* context);
@@ -2556,32 +2454,6 @@
}
}
-// Copying a constant will require incrementing a reference count if
-// the constant is a struct or an array with components that require
-// reference counts. If the type itself is reference counted then
-// copying it should not require any adustment.
-
-Expression*
-Const_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- Type* type = this->type();
- if (type->is_refcounted())
- return this;
- if (!type->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// Referring to a constant never increments a reference count.
-
-Expression*
-Const_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Return a tree for the const reference.
tree
@@ -2763,7 +2635,7 @@
Type_conversion_expression(Type* type, Expression* expr,
source_location location)
: Expression(EXPRESSION_CONVERSION, location),
- type_(type), expr_(expr), is_being_copied_(false)
+ type_(type), expr_(expr)
{ }
// Return the type to which we are converting.
@@ -2823,12 +2695,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context* context);
@@ -2840,8 +2706,6 @@
Type* type_;
// The expression to convert.
Expression* expr_;
- // Whether this expression is being copied.
- bool is_being_copied_;
};
// Traversal.
@@ -3223,66 +3087,6 @@
}
}
-// The type conversion is being copied elsewhere. If we do not call a
-// function which creates a new reference, then we need to pass this
-// on to the subsidiary expression.
-
-Expression*
-Type_conversion_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- this->is_being_copied_ = true;
- Type* type = this->type_;
- Type* expr_type = this->expr_->type();
- bool copy_base;
- if (type == expr_type)
- copy_base = true;
- else if (type->interface_type() != NULL
- || expr_type->interface_type() != NULL)
- copy_base = false;
- else if (type->is_string_type()
- && (expr_type->integer_type() != NULL
- || expr_type->deref()->array_type() != NULL))
- copy_base = false;
- else if (type->is_open_array_type() && expr_type->is_string_type())
- copy_base = false;
- else
- copy_base = true;
- if (copy_base && expr_type->has_refcounted_component())
- this->expr_ = this->expr_->being_copied(refcounts, for_local);
- return this;
-}
-
-// A type conversion may introduce a reference count.
-
-Expression*
-Type_conversion_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- Type* type = this->type_;
- Type* expr_type = this->expr_->type();
- bool need_decrement;
- if (type == expr_type)
- need_decrement = false;
- else if (type->interface_type() != NULL)
- need_decrement = true;
- else if (expr_type->interface_type() != NULL)
- need_decrement = type->has_refcounted_component();
- else if (type->is_string_type()
- && (expr_type->integer_type() != NULL
- || expr_type->deref()->array_type() != NULL))
- need_decrement = true;
- else if (type->is_open_array_type() && expr_type->is_string_type())
- need_decrement = true;
- else
- need_decrement = false;
- if (!need_decrement)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Get a tree for a type conversion.
tree
@@ -3572,15 +3376,6 @@
do_is_addressable() const
{ return this->op_ == OPERATOR_MULT; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -4030,52 +3825,6 @@
}
}
-// Copying a unary expression may require incrementing a reference
-// count.
-
-Expression*
-Unary_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- if (this->op_ == OPERATOR_PLUS)
- {
- this->expr_ = this->expr_->being_copied(refcounts, for_local);
- return this;
- }
- else if (this->op_ == OPERATOR_AND && this->is_constant())
- {
- // No need to increment the reference count when the address is
- // a constant.
- return this;
- }
- else
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// A unary expression does not increment any reference counts, so
-// there are no reference counts to decrement afterward.
-
-Expression*
-Unary_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// Assigning to *p requires decrementing the reference count of the
-// old value.
-
-Expression*
-Unary_expression::do_being_set(Refcounts* refcounts)
-{
- gcc_assert(this->op_ == OPERATOR_MULT);
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for a unary expression.
tree
@@ -5674,31 +5423,6 @@
}
}
-// Copying a binary expression never requires incrementing a reference
-// count, but we do have to disable incrementing the reference count.
-
-Expression*
-Binary_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// A binary expression increments a reference count when adding
-// strings.
-
-Expression*
-Binary_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->op_ != OPERATOR_PLUS
- || !this->left_->type()->is_string_type()
- || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Get a tree for a binary expression.
tree
@@ -8348,64 +8072,6 @@
return interface_method->get_function_tree(context, expr);
}
-// The call expression is being copied. There is nothing to do here
-// except to disable any decrements--the function should return with
-// an appropriate reference count.
-
-Expression*
-Call_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// Where needed, decrement the reference counts of any values returned
-// by this call.
-
-Expression*
-Call_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- Function_type* fntype = this->get_function_type();
- if (fntype == NULL)
- return this;
- const Typed_identifier_list* results = fntype->results();
- if (results == NULL)
- return this;
- if (results->size() == 1)
- {
- if (!results->begin()->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
- }
- else if (!this->is_value_discarded_)
- {
- // If the value is not discarded, each result will be handled
- // separately via Call_expression_result.
- return this;
- }
- else
- {
- for (Typed_identifier_list::const_iterator p = results->begin();
- p != results->end();
- p++)
- {
- if (p->type()->has_refcounted_component())
- {
- if (this->refcount_entries_ == NULL)
- this->refcount_entries_ = new std::vector<Refcount_entry>;
- Refcount_entry re = refcounts->add(REFCOUNT_DECREMENT_COMPUTED,
- p->type());
- this->refcount_entries_->push_back(re);
- }
- }
- return this;
- }
-}
-
// Build the call expression.
tree
@@ -8542,49 +8208,11 @@
if (fntype->results() != NULL && fntype->results()->size() > 1)
ret = save_expr(ret);
- if (this->refcount_entries_ != NULL)
- ret = this->set_refcount_queue_entries(context, ret);
-
this->tree_ = ret;
return ret;
}
-// Set entries in the decrement queue as needed.
-
-tree
-Call_expression::set_refcount_queue_entries(Translate_context* context,
- tree ret)
-{
- Gogo* gogo = context->gogo();
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- tree val = ret;
- Function_type* fntype = this->get_function_type();
- const Typed_identifier_list* results = fntype->results();
- gcc_assert(TREE_CODE(TREE_TYPE(val)) == RECORD_TYPE);
- std::vector<Refcount_entry>::const_iterator pre =
- this->refcount_entries_->begin();
- tree field = TYPE_FIELDS(TREE_TYPE(val));
- for (Typed_identifier_list::const_iterator pr = results->begin();
- pr != results->end();
- ++pr, field = TREE_CHAIN(field))
- {
- gcc_assert(field != NULL_TREE);
- if (pr->type()->has_refcounted_component())
- {
- gcc_assert(pre != this->refcount_entries_->end());
- Refcount_entry re = *pre;
- tree f = fold_build3(COMPONENT_REF, TREE_TYPE(field), val, field,
- NULL_TREE);
- pr->type()->set_refcount_queue_entry(gogo, refcounts, &re, f);
- ++pre;
- }
- }
- gcc_assert(pre == this->refcount_entries_->end());
- gcc_assert(field == NULL_TREE);
- return ret;
-}
-
// Make a call expression.
Call_expression*
@@ -8601,7 +8229,7 @@
public:
Call_result_expression(Call_expression* call, unsigned int index)
: Expression(EXPRESSION_CALL_RESULT, call->location()),
- call_(call), index_(index), is_being_copied_(false)
+ call_(call), index_(index)
{ }
protected:
@@ -8628,12 +8256,6 @@
do_must_eval_in_order() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -8642,8 +8264,6 @@
Expression* call_;
// Which result we want.
unsigned int index_;
- // Whether the result is being copied.
- bool is_being_copied_;
};
// Traverse a call result.
@@ -8718,28 +8338,6 @@
this->call_->determine_type_no_context();
}
-// The result will come back with a reference, so we don't need to do
-// anything to copy it.
-
-Expression*
-Call_result_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// Decrement the reference count if necessary.
-
-Expression*
-Call_result_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_ || !this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
-}
-
// Return the tree.
tree
@@ -8880,15 +8478,6 @@
do_address_taken(bool escapes)
{ this->array_->address_taken(escapes); }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -9011,44 +8600,6 @@
mpz_clear(lval);
}
-// Copying an element of an array may require incrementing a reference
-// count. Copying a slice requires incrementing the reference count
-// of the underlying array.
-
-Expression*
-Array_index_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (this->end_ == NULL && !this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// Referring to an element of an array does not require changing any
-// reference counts. If the array is changed before the value is
-// used, the program is ill-defined. We do not introduce a reference
-// count for a slice, so there is nothing to decrement. FIXME: Is
-// that safe?
-
-Expression*
-Array_index_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// Assigning to an element of an array may require decrementing a
-// reference count of the old value.
-
-Expression*
-Array_index_expression::do_being_set(Refcounts* refcounts)
-{
- gcc_assert(this->end_ == NULL);
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for an array index.
tree
@@ -9249,7 +8800,7 @@
String_index_expression(Expression* string, Expression* start,
Expression* end, source_location location)
: Expression(EXPRESSION_STRING_INDEX, location),
- string_(string), start_(start), end_(end), is_being_copied_(false)
+ string_(string), start_(start), end_(end)
{ }
protected:
@@ -9276,12 +8827,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -9293,8 +8838,6 @@
// The end index of a slice. This may be NULL for a single index,
// or it may be a nil expression for the length of the string.
Expression* end_;
- // Whether the slice is being copied.
- bool is_being_copied_;
};
// String index traversal.
@@ -9379,28 +8922,6 @@
mpz_clear(ival);
}
-// Copying a string index or a string slice does not require any
-// special action.
-
-Expression*
-String_index_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// A string slice introduces a new reference which must be decremented
-// if the value is discarded.
-
-Expression*
-String_index_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->end_ == NULL || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Get a tree for a string index.
tree
@@ -9561,43 +9082,6 @@
}
}
-// If we are copying the map index to a variable, we need to increment
-// the reference count.
-
-Expression*
-Map_index_expression::do_being_copied(Refcounts* refcounts, bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// We don't do anything with the reference count of a map index if we
-// aren't copying it, so there is nothing to do here. FIXME: Is this
-// safe?
-
-Expression*
-Map_index_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// If we are changing the map index, we need to decrement the
-// reference count for the old value, and we may need to increment the
-// reference count for the new index.
-
-Expression*
-Map_index_expression::do_being_set(Refcounts* refcounts)
-{
- if (this->get_map_type()->key_type()->has_refcounted_component())
- this->index_ = this->index_->being_copied(refcounts, false);
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for a map index.
tree
@@ -9726,41 +9210,6 @@
gcc_assert(struct_type->field(this->field_index_) != NULL);
}
-// If we are copying the field to a variable, we need to increment the
-// reference count.
-
-Expression*
-Field_reference_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_INCREMENT_COPIED,
- this, for_local);
-}
-
-// We do not need to bump the reference count; any change to the
-// structure before the value of the field is used would mean an
-// invalid program.
-
-Expression*
-Field_reference_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
-// If we are changing the field, we need to decrement the reference
-// count for the old value.
-
-Expression*
-Field_reference_expression::do_being_set(Refcounts* refcounts)
-{
- if (!this->type()->has_refcounted_component())
- return this;
- return Expression::make_refcount_decrement_lvalue(refcounts, this);
-}
-
// Get a tree for a field reference.
tree
@@ -10175,7 +9624,7 @@
public:
Allocation_expression(Type* type, source_location location)
: Expression(EXPRESSION_ALLOCATION, location),
- type_(type), is_being_copied_(false)
+ type_(type)
{ }
protected:
@@ -10198,20 +9647,12 @@
do_copy()
{ return new Allocation_expression(this->type_, this->location()); }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
private:
// The type we are allocating.
Type* type_;
- // Whether this value is being copied.
- bool is_being_copied_;
};
// Check the type of an allocation expression.
@@ -10223,28 +9664,6 @@
this->report_error(_("invalid new of function type"));
}
-// An allocation expression arrives with a reference count, so nothing
-// special is needed to copy it.
-
-Expression*
-Allocation_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// An allocation expression arrives with a reference count, so if we
-// don't copy the value we must free it.
-
-Expression*
-Allocation_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree for an allocation expression.
tree
@@ -10272,7 +9691,7 @@
public:
Make_expression(Type* type, Expression_list* args, source_location location)
: Expression(EXPRESSION_MAKE, location),
- type_(type), args_(args), is_being_copied_(false)
+ type_(type), args_(args)
{ }
protected:
@@ -10296,12 +9715,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -10310,8 +9723,6 @@
Type* type_;
// The arguments to pass to the make routine.
Expression_list* args_;
- // Whether the expression is being copied.
- bool is_being_copied_;
};
// Traversal.
@@ -10355,28 +9766,6 @@
this->set_is_error();
}
-// An newly created object arrives with a reference count, so nothing
-// special is needed to copy it.
-
-Expression*
-Make_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// A newly created object arrives with a reference count, so if we
-// don't copy the value we must free it.
-
-Expression*
-Make_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree for a make expression.
tree
@@ -10435,12 +9824,6 @@
do_is_addressable() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -10572,49 +9955,6 @@
gcc_assert(pv == this->vals_->end());
}
-// If we are copying the constructed struct, then we need to increment
-// the reference count of any elements as needed.
-
-Expression*
-Struct_construction_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (this->vals_ == NULL
- || !this->type()->has_refcounted_component()
- || this->is_constant_struct())
- return this;
- Expression_list* newvals = new Expression_list;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
- ++pv)
- {
- if (*pv == NULL)
- newvals->push_back(NULL);
- else if (!(*pv)->type()->has_refcounted_component())
- newvals->push_back(*pv);
- else
- {
- Expression* e = (*pv)->being_copied(refcounts, for_local);
- newvals->push_back(e);
- }
- }
- delete this->vals_;
- this->vals_ = newvals;
- return this;
-}
-
-// This is called if the constructed struct does not appear on the
-// right hand side of an assignment statement--in other words, the
-// value is built, used, and discarded. In this case we don't need to
-// do anything. If any of the values require a reference count
-// adjustment, that will be handled by the expression itself.
-
-Expression*
-Struct_construction_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Return a tree for constructing a struct.
tree
@@ -10746,12 +10086,6 @@
do_is_addressable() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts* refcounts);
-
void
do_export(Export*) const;
@@ -10867,49 +10201,6 @@
}
}
-// If we are copying the constructed array, then we need to increment
-// the reference count of any elements as needed.
-
-Expression*
-Array_construction_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- if (this->vals_ == NULL
- || !this->type()->has_refcounted_component()
- || this->is_constant_array())
- return this;
- Expression_list* newvals = new Expression_list;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
- ++pv)
- {
- if (*pv == NULL)
- newvals->push_back(NULL);
- else if (!(*pv)->type()->has_refcounted_component())
- newvals->push_back(*pv);
- else
- {
- Expression* e = (*pv)->being_copied(refcounts, for_local);
- newvals->push_back(e);
- }
- }
- delete this->vals_;
- this->vals_ = newvals;
- return this;
-}
-
-// This is called if the constructed array does not appear on the
-// right hand side of an assignment statement--in other words, the
-// value is built, used, and discarded. In this case we don't need to
-// do anything. If any of the values require a reference count
-// adjustment, that will be handled by the expression itself.
-
-Expression*
-Array_construction_expression::do_note_decrements(Refcounts*)
-{
- return this;
-}
-
// Get a constructor tree for the array values.
tree
@@ -11175,7 +10466,7 @@
Map_construction_expression(Type* type, Expression_list* vals,
source_location location)
: Expression(EXPRESSION_MAP_CONSTRUCTION, location),
- type_(type), vals_(vals), is_being_copied_(false)
+ type_(type), vals_(vals)
{ gcc_assert(vals == NULL || vals->size() % 2 == 0); }
protected:
@@ -11199,12 +10490,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts* refcounts);
-
tree
do_get_tree(Translate_context*);
@@ -11216,8 +10501,6 @@
Type* type_;
// The list of values.
Expression_list* vals_;
- // Whether the expression is being copied.
- bool is_being_copied_;
};
// Traversal.
@@ -11289,26 +10572,6 @@
}
}
-// Copying a map construction should not require any special action.
-
-Expression*
-Map_construction_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// Constructing a map always introduces a reference count.
-
-Expression*
-Map_construction_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree for constructing a map.
tree
@@ -11953,29 +11216,6 @@
this->report_error(_("type guard only valid for interface types"));
}
-// If we are copying the type guard to a variable, we don't need to do
-// anything; any reference count will already have been incremented.
-
-Expression*
-Type_guard_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// If we are converting to a reference counted type, then the
-// conversion process will increment the reference count.
-
-Expression*
-Type_guard_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (!this->type_->has_refcounted_component() || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
-}
-
// Return a tree for a type guard expression.
tree
@@ -12018,10 +11258,9 @@
class Heap_composite_expression : public Expression
{
public:
- Heap_composite_expression(Expression* expr, bool for_go_statement,
- source_location location)
+ Heap_composite_expression(Expression* expr, source_location location)
: Expression(EXPRESSION_HEAP_COMPOSITE, location),
- expr_(expr), for_go_statement_(for_go_statement), is_being_copied_(false)
+ expr_(expr)
{ }
protected:
@@ -12041,16 +11280,9 @@
do_copy()
{
return Expression::make_heap_composite(this->expr_->copy(),
- this->for_go_statement_,
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -12063,41 +11295,8 @@
private:
// The composite literal which is being put on the heap.
Expression* expr_;
- // True if this composite literal is being created for a go
- // statement. This is used to control reference count adjustments.
- bool for_go_statement_;
- // Whether this expression is being copied.
- bool is_being_copied_;
};
-// A heap composite is created with a new reference count, so nothing
-// special need be done to copy it. However, we do have to increment
-// the reference counts of the composite literal of which it is a
-// copy.
-
-Expression*
-Heap_composite_expression::do_being_copied(Refcounts* refcounts,
- bool for_local)
-{
- gcc_assert(!this->for_go_statement_);
- this->is_being_copied_ = true;
- this->expr_ = this->expr_->being_copied(refcounts, for_local);
- return this;
-}
-
-// Constructing a heap composite always introduces a reference count.
-// If we are creating this for a go statement, then the reference
-// count should be decremented in the thunk, not here.
-
-Expression*
-Heap_composite_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->for_go_statement_ || this->is_being_copied_)
- return this;
- return Expression::make_refcount_adjust(refcounts, REFCOUNT_DECREMENT_NEW,
- this, false);
-}
-
// Return a tree which allocates a composite literal on the heap.
tree
@@ -12124,10 +11323,9 @@
// Allocate a composite literal on the heap.
Expression*
-Expression::make_heap_composite(Expression* expr, bool for_go_statement,
- source_location location)
-{
- return new Heap_composite_expression(expr, for_go_statement, location);
+Expression::make_heap_composite(Expression* expr, source_location location)
+{
+ return new Heap_composite_expression(expr, location);
}
// Class Receive_expression.
@@ -12166,36 +11364,6 @@
}
}
-// If we are copying the received value to a variable, we don't need
-// to do anything; any reference count will already have been
-// incremented.
-
-Expression*
-Receive_expression::do_being_copied(Refcounts*, bool)
-{
- this->is_being_copied_ = true;
- return this;
-}
-
-// The receive will come with a reference count which we need to
-// decrement afterward.
-
-Expression*
-Receive_expression::do_note_decrements(Refcounts* refcounts)
-{
- if (this->is_being_copied_)
- return this;
- Channel_type* channel_type = this->channel_->type()->channel_type();
- if (channel_type == NULL)
- return this;
- Type* element_type = channel_type->element_type();
- if (!element_type->has_refcounted_component())
- return this;
- return Expression::make_refcount_adjust(refcounts,
- REFCOUNT_DECREMENT_COMPUTED,
- this, false);
-}
-
// Get a tree for a receive expression.
tree
@@ -12288,24 +11456,6 @@
}
}
-// Called if the value is being copied. There is nothing to do here.
-
-Expression*
-Send_expression::do_being_copied(Refcounts*, bool)
-{
- return this;
-}
-
-// Reference count adjustments for a send expression. The expression
-// that we are sending is being copied.
-
-Expression*
-Send_expression::do_note_decrements(Refcounts* refcounts)
-{
- this->val_ = this->val_->being_copied(refcounts, false);
- return this;
-}
-
// Get a tree for a send expression.
tree
@@ -12334,189 +11484,6 @@
return new Send_expression(channel, val, location);
}
-// Class Refcount_adjust_expression.
-
-// The type of adjustment.
-
-int
-Refcount_adjust_expression::classification() const
-{
- return this->refcount_entry_->classification();
-}
-
-// Types should already have been determined and checked.
-
-void
-Refcount_adjust_expression::do_determine_type(const Type_context*)
-{
- gcc_unreachable();
-}
-
-void
-Refcount_adjust_expression::do_check_types(Gogo*)
-{
- gcc_unreachable();
-}
-
-// Return a tree for the reference count adjustment.
-
-tree
-Refcount_adjust_expression::do_get_tree(Translate_context* context)
-{
- // If we are incrementing a decrement, then skip both adjustments.
- if (this->expr_->classification() == EXPRESSION_REFCOUNT_ADJUST
- && this->classification() == REFCOUNT_INCREMENT_COPIED)
- {
- Refcount_adjust_expression* rae =
- static_cast<Refcount_adjust_expression*>(this->expr_);
- int rae_cl = rae->classification();
- // We should never see an increment of an old value; that makes
- // no sense.
- if (rae_cl == REFCOUNT_DECREMENT_NEW
- || rae_cl == REFCOUNT_DECREMENT_COMPUTED)
- return rae->expr()->get_tree(context);
- }
-
- tree expr_tree = this->expr_->get_tree(context);
- if (expr_tree == error_mark_node)
- return error_mark_node;
- if (DECL_P(expr_tree)
- || (TREE_CODE(expr_tree) == ADDR_EXPR
- && DECL_P(TREE_OPERAND(expr_tree, 0))))
- {
- // Because of the limited context, we don't need to save V or
- // &V.
- }
- else if (this->expr_->type()->array_type() != NULL
- && !this->expr_->type()->is_open_array_type())
- {
- // We are just going to take the address of a fixed array, don't
- // try to save it. Saving it fails because it requires an array
- // copy to the temporary variable.
- }
- else
- expr_tree = save_expr(expr_tree);
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- Refcount_entry re = *this->refcount_entry_;
- tree set = this->expr_->type()->set_refcount_queue_entry(context->gogo(),
- refcounts,
- &re,
- expr_tree);
- return build2(COMPOUND_EXPR, TREE_TYPE(expr_tree), set, expr_tree);
-}
-
-// Make a reference count adjustment.
-
-Expression*
-Expression::make_refcount_adjust(Refcounts* refcounts, int classification,
- Expression* expr, bool for_local)
-{
- // Simplify adjusting the reference count of a reference count
- // adjustment.
- if (expr->classification() == EXPRESSION_REFCOUNT_ADJUST)
- {
- Refcount_adjust_expression* rae =
- static_cast<Refcount_adjust_expression*>(expr);
- int rae_cl = rae->classification();
-
- // If we are incrementing a decrement, then we can discard both
- // the increment and the decrement.
- if (classification == REFCOUNT_INCREMENT_COPIED)
- {
- // We should never see an increment of an old value; that
- // makes no sense.
- gcc_assert(rae_cl != REFCOUNT_DECREMENT_OLD);
- if (rae_cl == REFCOUNT_DECREMENT_NEW
- || rae_cl == REFCOUNT_DECREMENT_COMPUTED)
- {
- // FIXME: We don't reclaim the Refcount_entry.
- return rae->expr();
- }
- }
-
- // If we are decrementing an increment, then we can not in
- // general discard both adjustments. The count might be
- // incremented in order to pass the value to a function. If we
- // discard both adjustments, then the object may be freed during
- // the function call.
- }
-
- Refcount_entry entry = refcounts->add(classification, expr->type());
- return new Refcount_adjust_expression(new Refcount_entry(entry),
- expr, for_local);
-}
-
-// Class Refcount_decrement_lvalue_expression
-
-// Constructor.
-
-Refcount_decrement_lvalue_expression::Refcount_decrement_lvalue_expression(
- Refcount_entry* entry,
- Expression* expr)
- : Expression(EXPRESSION_REFCOUNT_DECREMENT_LVALUE, expr->location()),
- refcount_entry_(entry), expr_(expr)
-{
- gcc_assert(expr->is_lvalue());
-}
-
-
-// Traversal.
-
-int
-Refcount_decrement_lvalue_expression::do_traverse(Traverse* traverse)
-{
- return Expression::traverse(&this->expr_, traverse);
-}
-
-// Types should already have been determined and checked at this
-// point.
-
-void
-Refcount_decrement_lvalue_expression::do_determine_type(const Type_context*)
-{
- gcc_unreachable();
-}
-
-void
-Refcount_decrement_lvalue_expression::do_check_types(Gogo*)
-{
- gcc_unreachable();
-}
-
-// The normal tree expansion is simply the one for THIS->EXPR_. We
-// require that the user call the set function appropriately.
-
-tree
-Refcount_decrement_lvalue_expression::do_get_tree(Translate_context* context)
-{
- return this->expr_->get_tree(context);
-}
-
-// Set the expression to VAL.
-
-tree
-Refcount_decrement_lvalue_expression::set(Translate_context* context,
- tree lhs_tree, tree rhs_tree)
-{
- if (lhs_tree == error_mark_node || rhs_tree == error_mark_node)
- return error_mark_node;
- lhs_tree = stabilize_reference(lhs_tree);
-
- // FIXME: If we are changing a value which may be visible to
- // multiple goroutines--i.e., anything other than a local
- // variable--then we should use an atomic swap. Otherwise we can
- // get inconsistent reference counts.
-
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- Refcount_entry re = *this->refcount_entry_;
- tree save = this->expr_->type()->set_refcount_queue_entry(context->gogo(),
- refcounts,
- &re,
- lhs_tree);
- tree set = fold_build2(MODIFY_EXPR, void_type_node, lhs_tree, rhs_tree);
- return fold_build2(COMPOUND_EXPR, void_type_node, save, set);
-}
-
// An expression which evaluates to a pointer to the type descriptor
// of a type.
@@ -12598,17 +11565,6 @@
return new Label_addr_expression(label, location);
}
-// Make a reference count decrement of an lvalue.
-
-Expression*
-Expression::make_refcount_decrement_lvalue(Refcounts* refcounts,
- Expression* expr)
-{
- Refcount_entry entry = refcounts->add(REFCOUNT_DECREMENT_OLD, expr->type());
- return new Refcount_decrement_lvalue_expression(new Refcount_entry(entry),
- expr);
-}
-
// Import an expression. This comes at the end in order to see the
// various class definitions.
@@ -35,14 +35,10 @@
class Type_guard_expression;
class Receive_expression;
class Send_expression;
-class Refcount_adjust_expression;
-class Refcount_decrement_lvalue_expression;
class Named_object;
class Export;
class Import;
class Temporary_statement;
-class Refcounts;
-class Refcount_entry;
class Label;
// The base class for all expressions.
@@ -92,8 +88,6 @@
EXPRESSION_HEAP_COMPOSITE,
EXPRESSION_RECEIVE,
EXPRESSION_SEND,
- EXPRESSION_REFCOUNT_ADJUST,
- EXPRESSION_REFCOUNT_DECREMENT_LVALUE,
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_LABEL_ADDR
};
@@ -262,7 +256,7 @@
// Take a composite literal and allocate it on the heap.
static Expression*
- make_heap_composite(Expression*, bool for_go_statement, source_location);
+ make_heap_composite(Expression*, source_location);
// Make a receive expression. VAL is NULL for a unary receive.
static Receive_expression*
@@ -272,19 +266,6 @@
static Send_expression*
make_send(Expression* channel, Expression* val, source_location);
- // Make an expression which evaluates another expression and stores
- // the value into the reference queue. This expression then
- // evaluates to the same value. FOR_LOCAL is true if this is for a
- // local variable.
- static Expression*
- make_refcount_adjust(Refcounts*, int classification, Expression*,
- bool for_local);
-
- // Make an expression which decrements the reference count of the
- // old value of an lvalue.
- static Expression*
- make_refcount_decrement_lvalue(Refcounts*, Expression*);
-
// Make an expression which evaluates to the type descriptor of a
// type.
static Expression*
@@ -481,24 +462,6 @@
receive_expression()
{ return this->convert<Receive_expression, EXPRESSION_RECEIVE>(); }
- // If this is a reference count adjustment, return the
- // Refcount_adjust_expression. Otherwise, return NULL.
- Refcount_adjust_expression*
- refcount_adjust_expression()
- {
- return this->convert<Refcount_adjust_expression,
- EXPRESSION_REFCOUNT_ADJUST>();
- }
-
- // If this is a reference decrement expression, return it.
- // Otherwise, return NULL.
- Refcount_decrement_lvalue_expression*
- refcount_decrement_lvalue_expression()
- {
- return this->convert<Refcount_decrement_lvalue_expression,
- EXPRESSION_REFCOUNT_DECREMENT_LVALUE>();
- }
-
// Return true if this is a composite literal.
bool
is_composite_literal() const;
@@ -579,42 +542,6 @@
must_eval_in_order() const
{ return this->do_must_eval_in_order(); }
- // This is called when the value of an expression is being stored
- // somewhere. In some cases this requires that the reference count
- // be incremented. FOR_LOCAL is true if this is called when either
- // a local variable appears on the left hand of the assignment or
- // when this is in a return statement. This should return a new
- // Expression which does the appropriate reference count adjustment.
- // When no reference count needs to be increment, this should simply
- // return THIS. The note_decrements method will be called on this
- // expression later; in some cases all that being_copied has to do
- // is prevent note_decrements from doing anything.
- Expression*
- being_copied(Refcounts* refcounts, bool for_local)
- { return this->do_being_copied(refcounts, for_local); }
-
- // If this expression computes any values whose reference count must
- // be decremented when the statement is complete, store them in the
- // reference count decrement queue. This is not called for an
- // expression which is the complete left hand side of an assignment.
- // It will be called for subexpressions of LHS's, and for all RHS
- // expressions. This returns a new expression which should replace
- // the current expression. When no reference counts need to be
- // decremented, this should simply return THIS.
- Expression*
- note_decrements(Refcounts* refcounts)
- { return this->do_note_decrements(refcounts); }
-
- // This is called when the expression is being set. The expression
- // must be an lvalue. In some cases this requires that the
- // reference count of the old value of the expression be
- // decremented. This should return a new Expression which does the
- // appropriate adjustment. When no reference count needs to be
- // decremented, this should simply return THIS.
- Expression*
- being_set(Refcounts* refcounts)
- { return this->do_being_set(refcounts); }
-
// Return the tree for this expression.
tree
get_tree(Translate_context*);
@@ -736,21 +663,6 @@
do_must_eval_in_order() const
{ return false; }
- // Child class implements incrementing reference count.
- virtual Expression*
- do_being_copied(Refcounts*, bool)
- { return this; }
-
- // Child class implements noting reference count decrements.
- virtual Expression*
- do_note_decrements(Refcounts*)
- { return this; }
-
- // Child class implements whether the old value of an lvalue needs
- // to have its reference count decremented.
- virtual Expression*
- do_being_set(Refcounts*);
-
// Child class implements conversion to tree.
virtual tree
do_get_tree(Translate_context*) = 0;
@@ -969,12 +881,6 @@
void
do_address_taken(bool);
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1017,12 +923,6 @@
void
do_address_taken(bool);
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1090,7 +990,7 @@
Binary_expression(Operator op, Expression* left, Expression* right,
source_location location)
: Expression(EXPRESSION_BINARY, location),
- op_(op), left_(left), right_(right), is_being_copied_(false)
+ op_(op), left_(left), right_(right)
{ }
// Return the operator.
@@ -1192,12 +1092,6 @@
this->right_->copy(), this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1211,8 +1105,6 @@
Expression* left_;
// The right hand side operand.
Expression* right_;
- // Whether the expression is being copied.
- bool is_being_copied_;
};
// A call expression. The go statement needs to dig inside this.
@@ -1223,9 +1115,9 @@
Call_expression(Expression* fn, Expression_list* args,
source_location location)
: Expression(EXPRESSION_CALL, location),
- fn_(fn), args_(args), type_(NULL), tree_(NULL), refcount_entries_(NULL),
+ fn_(fn), args_(args), type_(NULL), tree_(NULL),
is_value_discarded_(false), varargs_are_lowered_(false),
- is_being_copied_(false), is_deferred_(false)
+ is_deferred_(false)
{ }
// The function to call.
@@ -1299,12 +1191,6 @@
bool
do_must_eval_in_order() const;
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
virtual tree
do_get_tree(Translate_context*);
@@ -1337,9 +1223,6 @@
Interface_field_reference_expression*,
tree*);
- tree
- set_refcount_queue_entries(Translate_context*, tree ret);
-
// The function to call.
Expression* fn_;
// The arguments to pass. This may be NULL if there are no
@@ -1349,16 +1232,10 @@
Type* type_;
// The tree for the call, used for a call which returns a tuple.
tree tree_;
- // If needed a list of entries in the reference count queue. These
- // are set to values returned by a tuple call if some of the values
- // need to have their reference counts decremented.
- std::vector<Refcount_entry>* refcount_entries_;
// True if the value is being discarded.
bool is_value_discarded_;
// True if varargs have already been lowered.
bool varargs_are_lowered_;
- // True if the value is being copied.
- bool is_being_copied_;
// True if the call is an argument to a defer statement.
bool is_deferred_;
};
@@ -1415,12 +1292,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1607,15 +1478,6 @@
// A map index expression is an lvalue but it is not addressable.
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1760,15 +1622,6 @@
do_is_addressable() const
{ return this->expr_->is_addressable(); }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
- Expression*
- do_being_set(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1852,7 +1705,7 @@
public:
Type_guard_expression(Expression* expr, Type* type, source_location location)
: Expression(EXPRESSION_TYPE_GUARD, location),
- expr_(expr), type_(type), is_being_copied_(false)
+ expr_(expr), type_(type)
{ }
// Return the expression to convert.
@@ -1887,12 +1740,6 @@
this->location());
}
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1901,8 +1748,6 @@
Expression* expr_;
// The type to which to convert.
Type* type_;
- // Whether this expression is being copied.
- bool is_being_copied_;
};
// A receive expression.
@@ -1912,8 +1757,7 @@
public:
Receive_expression(Expression* channel, source_location location)
: Expression(EXPRESSION_RECEIVE, location),
- channel_(channel), is_value_discarded_(false), for_select_(false),
- is_being_copied_(false)
+ channel_(channel), is_value_discarded_(false), for_select_(false)
{ }
// Return the channel.
@@ -1955,12 +1799,6 @@
do_must_eval_in_order() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -1971,8 +1809,6 @@
bool is_value_discarded_;
// Whether this is for a select statement.
bool for_select_;
- // Whether the value is being copied.
- bool is_being_copied_;
};
// A send expression.
@@ -2020,12 +1856,6 @@
do_must_eval_in_order() const
{ return true; }
- Expression*
- do_being_copied(Refcounts*, bool);
-
- Expression*
- do_note_decrements(Refcounts*);
-
tree
do_get_tree(Translate_context*);
@@ -2040,115 +1870,4 @@
bool for_select_;
};
-// Adjust the reference count of a value.
-
-class Refcount_adjust_expression : public Expression
-{
- public:
- Refcount_adjust_expression(Refcount_entry* entry, Expression* expr,
- bool for_local)
- : Expression(EXPRESSION_REFCOUNT_ADJUST, expr->location()),
- refcount_entry_(entry), expr_(expr), for_local_(for_local)
- { }
-
- // The type of adjustment.
- int
- classification() const;
-
- // The underlying expression.
- Expression*
- expr()
- { return this->expr_; }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return Expression::traverse(&this->expr_, traverse); }
-
- Type*
- do_type()
- { return this->expr_->type(); }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Refcount_adjust_expression(this->refcount_entry_,
- this->expr_,
- this->for_local_);
- }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The reference count entry.
- Refcount_entry* refcount_entry_;
- // The expression whose reference count we are incrementing.
- Expression* expr_;
- // Whether this is to be stored in a local variable, for debugging
- // purposes.
- bool for_local_;
-};
-
-// Decrement the reference count of the old value of an lvalue in an
-// assignment.
-
-class Refcount_decrement_lvalue_expression : public Expression
-{
- public:
- Refcount_decrement_lvalue_expression(Refcount_entry* entry,
- Expression* expr);
-
- // The underlying expression.
- Expression*
- expr()
- { return this->expr_; }
-
- // Set THIS->EXPR_ (an lvalue) to RHS_TREE. LHS_TREE is THIS
- // converted to tree form. This should be called instead of
- // get_tree.
- tree
- set(Translate_context*, tree lhs_tree, tree rhs_tree);
-
- protected:
- int
- do_traverse(Traverse*);
-
- Type*
- do_type()
- { return this->expr_->type(); }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Refcount_decrement_lvalue_expression(this->refcount_entry_,
- this->expr_);
- }
-
- bool
- do_is_lvalue() const
- { return true; }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The reference count entry.
- Refcount_entry* refcount_entry_;
- // The expression which is being set.
- Expression* expr_;
-};
-
#endif // !defined(GO_EXPRESSIONS_H)
@@ -135,12 +135,6 @@
// Convert complicated go and defer statements into simpler ones.
::gogo->simplify_thunk_statements();
-
- // Check which variables are only set to argument values.
- ::gogo->find_only_arg_vars();
-
- // Add reference counts for garbage collection.
- ::gogo->add_refcounts();
}
// Write out globals.
@@ -28,7 +28,6 @@
#include "types.h"
#include "expressions.h"
#include "statements.h"
-#include "refcount.h"
#include "gogo.h"
// Whether we have seen any errors.
@@ -1424,7 +1423,6 @@
tree init = NULL_TREE;
tree except = NULL_TREE;
tree fini = NULL_TREE;
- source_location end_loc = this->block_->end_location();
// Initialize variables if necessary.
for (tree v = declare_vars; v != NULL_TREE; v = TREE_CHAIN(v))
@@ -1434,21 +1432,6 @@
append_to_statement_list(dv, &init);
}
- // If there is a reference count queue, initialize it at the
- // start of the function.
- bool have_refcounts = (this->refcounts_ != NULL
- && !this->refcounts_->empty());
- if (have_refcounts)
- {
- tree iq = this->refcounts_->init_queue(gogo, this->location_);
- append_to_statement_list(iq, &init);
- }
-
- // Flush the reference count queue when we leave the function.
- tree flush = NULL_TREE;
- if (have_refcounts)
- flush = this->refcounts_->flush_queue(gogo, true, end_loc);
-
// If we have a defer stack, initialize it at the start of a
// function.
if (this->defer_stack_ != NULL_TREE)
@@ -1459,15 +1442,7 @@
append_to_statement_list(defer_init, &init);
// Clean up the defer stack when we leave the function.
- this->build_defer_wrapper(gogo, named_function, flush, &except,
- &fini);
- flush = NULL_TREE;
- }
-
- if (flush != NULL_TREE)
- {
- gcc_assert(fini == NULL_TREE);
- fini = flush;
+ this->build_defer_wrapper(gogo, named_function, &except, &fini);
}
if (code != NULL_TREE && code != error_mark_node)
@@ -1495,11 +1470,11 @@
// Build the wrappers around function code needed if the function has
// any defer statements. This sets *EXCEPT to an exception handler
-// and *FINI to a finally handler. FLUSH is run in *FINI if not NULL.
+// and *FINI to a finally handler.
void
Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
- tree flush, tree *except, tree *fini)
+ tree *except, tree *fini)
{
source_location end_loc = this->block_->end_location();
@@ -1571,9 +1546,6 @@
append_to_statement_list(try_catch, &stmt_list);
- if (flush != NULL_TREE)
- append_to_statement_list(flush, &stmt_list);
-
if (this->type_->results() != NULL
&& !this->type_->results()->empty()
&& !this->type_->results()->front().name().empty())
@@ -1760,31 +1732,6 @@
append_to_statement_list(statement, &statements);
}
- if (!this->final_statements_.empty())
- {
- tree final_statements = NULL_TREE;
- source_location loc = UNKNOWN_LOCATION;
- for (std::vector<Statement*>::const_iterator p =
- this->final_statements_.begin();
- p != this->final_statements_.end();
- ++p)
- {
- tree statement = (*p)->get_tree(&subcontext);
- if (statement != error_mark_node)
- {
- append_to_statement_list(statement, &final_statements);
- if (loc == UNKNOWN_LOCATION)
- loc = (*p)->location();
- }
- }
- if (final_statements != NULL_TREE)
- {
- statements = build2(TRY_FINALLY_EXPR, void_type_node,
- statements, final_statements);
- SET_EXPR_LOCATION(statements, loc);
- }
- }
-
TREE_USED(block) = 1;
tree bind = build3(BIND_EXPR, void_type_node, BLOCK_VARS(block), statements,
@@ -2961,7 +2908,7 @@
// which the length of an array calls the len function on another
// array with the same type descriptor, and that other array is
// initialized with values which require reference count
- // adjustments.
+ // adjustments. This may no longer be required.
go_preserve_from_gc(decl);
*pdecl = decl;
if (phash != NULL)
@@ -17,7 +17,6 @@
#include "dataflow.h"
#include "import.h"
#include "export.h"
-#include "refcount.h"
#include "gogo.h"
// Class Gogo.
@@ -2312,111 +2311,6 @@
return TRAVERSE_CONTINUE;
}
-// A dump for find_only_arg_vars.
-
-static Go_dump find_only_arg_vars_dump("argvars");
-
-// A traversal class to find all the local variables.
-
-class Traverse_find_vars : public Traverse
-{
- public:
- Traverse_find_vars(std::list<Named_object*>* vars)
- : Traverse(traverse_variables),
- vars_(vars)
- { }
-
- protected:
- int
- variable(Named_object* var)
- {
- if (var->is_variable() && !var->var_value()->is_global())
- this->vars_->push_back(var);
- return TRAVERSE_CONTINUE;
- }
-
- private:
- // We add variables to this list.
- std::list<Named_object*>* vars_;
-};
-
-// Find variables which are only set to argument values.
-
-void
-Gogo::find_only_arg_vars()
-{
- std::list<Named_object*> vars;
- Traverse_find_vars tfv(&vars);
- this->traverse(&tfv);
-
- Dataflow dataflow;
- dataflow.initialize(this);
-
- // We start with all the variables. As we find variables which are
- // set to values which are not arguments, we remove them from the
- // list. Note that this is flow-insensitive; we could in some cases
- // do slightly better by being flow-sensitive.
-
- bool changed = true;
- while (changed)
- {
- changed = false;
- std::list<Named_object*>::iterator pv = vars.begin();
- while (pv != vars.end())
- {
- const Dataflow::Defs* defs = dataflow.find_defs(*pv);
- if (defs == NULL)
- {
- // The variable is never set.
- gcc_assert((*pv)->var_value()->is_parameter());
- ++pv;
- }
- else
- {
- Dataflow::Defs::const_iterator pd;
- for (pd = defs->begin(); pd != defs->end(); ++pd)
- {
- if (pd->val == NULL)
- {
- if (!pd->is_init)
- break;
- }
- else if (pd->val->var_expression() == NULL)
- break;
- else
- {
- Var_expression* ve = pd->val->var_expression();
- Named_object* source = ve->named_object();
- if (std::find(vars.begin(), vars.end(), source)
- == vars.end())
- break;
- }
- }
- if (pd == defs->end())
- ++pv;
- else
- {
- // This variable is set to something which is not an
- // argument value.
- pv = vars.erase(pv);
- changed = true;
- }
- }
- }
- }
-
- for (std::list<Named_object*>::const_iterator pv = vars.begin();
- pv != vars.end();
- ++pv)
- {
- (*pv)->var_value()->set_holds_only_args();
-
- // FIXME: This should go to a file.
- if (find_only_arg_vars_dump.is_enabled())
- inform((*pv)->location(), "%qs: only args var", (*pv)->name().c_str());
- }
-}
-
// Traversal class used to check for return statements.
class Check_return_statements_traverse : public Traverse
@@ -2519,9 +2413,9 @@
Function::Function(Function_type* type, Function* enclosing, Block* block,
source_location location)
: type_(type), enclosing_(enclosing), named_results_(NULL),
- closure_var_(NULL), refcounts_(NULL), block_(block), location_(location),
- fndecl_(NULL), defer_stack_(NULL), calls_recover_(false),
- is_recover_thunk_(false), has_recover_thunk_(false)
+ closure_var_(NULL), block_(block), location_(location), fndecl_(NULL),
+ defer_stack_(NULL), calls_recover_(false), is_recover_thunk_(false),
+ has_recover_thunk_(false)
{
}
@@ -2601,16 +2495,6 @@
}
}
-// Allocate reference count information for the function.
-
-Refcounts*
-Function::refcounts()
-{
- if (this->refcounts_ == NULL)
- this->refcounts_ = new Refcounts;
- return this->refcounts_;
-}
-
// Return whether this function is a method.
bool
@@ -2687,7 +2571,6 @@
gcc_assert(this->enclosing_ == x->enclosing_);
gcc_assert(this->named_results_ == x->named_results_);
std::swap(this->closure_var_, x->closure_var_);
- gcc_assert(this->refcounts_ == NULL && x->refcounts_ == NULL);
std::swap(this->block_, x->block_);
gcc_assert(this->location_ == x->location_);
gcc_assert(this->fndecl_ == NULL && x->fndecl_ == NULL);
@@ -2908,7 +2791,6 @@
bindings_(new Bindings(enclosing == NULL
? NULL
: enclosing->bindings())),
- final_statements_(),
start_location_(location),
end_location_(UNKNOWN_LOCATION)
{
@@ -2931,14 +2813,6 @@
this->statements_.insert(this->statements_.begin(), statement);
}
-// Add a statement which runs when the block is complete.
-
-void
-Block::add_final_statement(Statement* statement)
-{
- this->final_statements_.push_back(statement);
-}
-
// Replace a statement in a block.
void
@@ -3089,9 +2963,6 @@
return TRAVERSE_EXIT;
}
- // We don't traverse the final statements, which are only used for
- // reference counting purposes.
-
return TRAVERSE_CONTINUE;
}
@@ -3135,7 +3006,7 @@
: type_(type), init_(init), preinit_(NULL), location_(location),
is_global_(is_global), is_parameter_(is_parameter),
is_receiver_(is_receiver), is_varargs_parameter_(false),
- is_address_taken_(false), holds_only_args_(false), init_is_lowered_(false),
+ is_address_taken_(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)
@@ -43,7 +43,6 @@
class Translate_context;
class Export;
class Import;
-class Refcounts;
// This file declares the basic classes used to hold the internal
// representation of Go which is built by the parser.
@@ -363,10 +362,6 @@
void
check_types_in_block(Block*);
- // Find variables which are only set to argument values.
- void
- find_only_arg_vars();
-
// Check for return statements.
void
check_return_statements();
@@ -402,10 +397,6 @@
void
simplify_thunk_statements();
- // Add reference counts for garbage collection.
- void
- add_refcounts();
-
// Write out the global values.
void
write_globals();
@@ -831,10 +822,6 @@
void
add_statement_at_front(Statement*);
- // Add a statement which runs when the block is done.
- void
- add_final_statement(Statement*);
-
// Replace a statement in a block.
void
replace_statement(size_t index, Statement*);
@@ -893,8 +880,6 @@
std::vector<Statement*> statements_;
// Binding contour.
Bindings* bindings_;
- // A list of statements which must be run when exiting the block.
- std::vector<Statement*> final_statements_;
// Location of start of block.
source_location start_location_;
// Location of end of block.
@@ -968,10 +953,6 @@
void
set_closure_type();
- // Get the reference count adjustments for this function.
- Refcounts*
- refcounts();
-
// Get the block of statements associated with the function.
Block*
block() const
@@ -1090,7 +1071,7 @@
copy_parm_to_heap(Gogo*, Named_object*, tree);
void
- build_defer_wrapper(Gogo*, Named_object*, tree, tree*, tree*);
+ build_defer_wrapper(Gogo*, Named_object*, tree*, tree*);
typedef std::vector<Named_object*> Named_results;
@@ -1111,9 +1092,6 @@
// The closure variable, passed as a parameter using the static
// chain parameter. Normally NULL.
Named_object* closure_var_;
- // The reference count adjustments which must be made in this
- // function.
- Refcounts* refcounts_;
// The outer block of statements in the function.
Block* block_;
// The source location of the start of the function.
@@ -1255,11 +1233,6 @@
is_address_taken() const
{ return this->is_address_taken_; }
- // Whether this variable only holds argument values.
- bool
- holds_only_args() const
- { return this->holds_only_args_; }
-
// Whether this variable should live in the heap.
bool
is_in_heap() const
@@ -1283,8 +1256,7 @@
clear_init()
{ this->init_ = NULL; }
- // Set the initial value; used for reference counts and converting
- // shortcuts.
+ // Set the initial value; used for converting shortcuts.
void
set_init(Expression* init)
{ this->init_ = init; }
@@ -1363,11 +1335,6 @@
set_address_taken()
{ this->is_address_taken_ = true; }
- // Note that this variable only holds argument values.
- void
- set_holds_only_args()
- { this->holds_only_args_ = true; }
-
// Get the initial value of the variable as a tree. This may only
// be called if has_pre_init() returns false.
tree
@@ -1420,10 +1387,6 @@
bool is_varargs_parameter_ : 1;
// Whether something takes the address of this variable.
bool is_address_taken_ : 1;
- // True if this variable is only set to argument values (e.g., it is
- // a parameter which is not changed, or a local variable set only to
- // parameters).
- bool holds_only_args_ : 1;
// True if we have lowered the initialization expression.
bool init_is_lowered_ : 1;
// True if init is a tuple used to set the type.
@@ -2446,7 +2446,7 @@
Struct_type* st = closure_var->var_value()->type()->deref()->struct_type();
Expression* cv = Expression::make_struct_composite_literal(st, initializer,
location);
- return Expression::make_heap_composite(cv, false, location);
+ return Expression::make_heap_composite(cv, location);
}
// PrimaryExpr = Operand { Selector | Index | Slice | TypeGuard | Call } .
@@ -2866,7 +2866,7 @@
expr = Expression::make_type(Type::make_pointer_type(expr->type()),
location);
else if (op == OPERATOR_AND && expr->is_composite_literal())
- expr = Expression::make_heap_composite(expr, false, location);
+ expr = Expression::make_heap_composite(expr, location);
else if (op != OPERATOR_CHANOP)
expr = Expression::make_unary(op, expr, location);
else
@@ -1,942 +0,0 @@
-// refcount.cc -- Go frontend reference counts.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <algorithm>
-
-#include "go-system.h"
-
-#include <gmp.h>
-
-extern "C"
-{
-#include "tree.h"
-#include "gimple.h"
-#include "tree-iterator.h"
-#include "rtl.h"
-}
-
-#include "go-c.h"
-#include "go-dump.h"
-#include "gogo.h"
-#include "types.h"
-#include "expressions.h"
-#include "statements.h"
-#include "refcount.h"
-
-// Class Refcounts.
-
-// Add a new reference count entry.
-
-Refcount_entry
-Refcounts::add(int classification, Type* type)
-{
- gcc_assert(!this->is_complete_);
- Entries* pentries = &this->entries_[classification];
- int index = pentries->size();
- Refcount_entry r(classification, index);
- type->add_refcount_queue_entries(this, &r);
- return Refcount_entry(classification, index);
-}
-
-// Add a new entry for a type which only requires a single entry.
-
-void
-Refcounts::add_one(Type* type, Refcount_entry *entry)
-{
- gcc_assert(!this->is_complete_);
- Entries* pentries = &this->entries_[entry->classification()];
- gcc_assert(pentries->size() == entry->index());
- pentries->push_back(type);
- entry->increment();
-}
-
-// The type of a reference count entry.
-
-Type*
-Refcounts::get_type(Refcount_entry entry)
-{
- int cl = entry.classification();
- gcc_assert(cl >= REFCOUNT_DECREMENT_NEW && cl < REFCOUNT_MAX);
- Entries* entries = &this->entries_[cl];
- gcc_assert(entry.index() < entries->size());
- return (*entries)[entry.index()];
-}
-
-// Return whether there are no reference count adjustments.
-
-bool
-Refcounts::empty() const
-{
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- if (!this->entries_[i].empty())
- return false;
- return true;
-}
-
-// Whether we can handle this reference count queue in a simple way,
-// without building a full queue structure. We want to use the queue
-// structure if there is a decrement of a newly allocated value,
-// because an increment in a called function will remove the
-// decrement. Otherwise, we use a simple approach if there is only
-// one entry in the queue.
-
-bool
-Refcounts::is_simple() const
-{
- gcc_assert(this->is_complete_);
- if (!this->entries_[REFCOUNT_DECREMENT_NEW].empty())
- return false;
- size_t count = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- count += this->entries_[i].size();
- return count <= 1;
-}
-
-// Get the descriptor for a simple queue. Return true if this is an
-// increment.
-
-bool
-Refcounts::simple_descriptor(Gogo* gogo, tree* pdescriptor) const
-{
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- {
- if (!this->entries_[i].empty())
- {
- gcc_assert(this->entries_[i].size() == 1);
- Type* type = this->entries_[i][0];
- *pdescriptor = type->type_descriptor(gogo);
- return i == REFCOUNT_INCREMENT_COPIED;
- }
- }
- gcc_unreachable();
-}
-
-// The type of an entry in the reference count array. This is the
-// structure declared in libgo/runtime/go-refcount.h.
-
-tree
-Refcounts::entry_type(Gogo* gogo)
-{
- static tree struct_type;
- if (struct_type == NULL_TREE)
- {
- struct_type = make_node(RECORD_TYPE);
-
- tree dtype = gogo->type_descriptor_type_tree();
- dtype = build_qualified_type(dtype, TYPE_QUAL_CONST);
- tree fields = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__descriptor"),
- build_pointer_type(dtype));
-
- tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__value"),
- ptr_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- finish_builtin_struct(struct_type, "__go_refcount_entry", fields,
- NULL_TREE);
-
- go_preserve_from_gc(struct_type);
- }
-
- return struct_type;
-}
-
-// The type of the reference count array for this structure.. This is
-// the structure declared in libgo/runtime/go-refcount.h.
-
-tree
-Refcounts::struct_type(Gogo* gogo)
-{
- gcc_assert(this->is_complete_);
-
- tree struct_type = make_node(RECORD_TYPE);
-
- tree fields = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__caller"),
- build_pointer_type(struct_type));
-
- tree field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__callers_were_scanned"),
- boolean_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__did_not_scan_decrements"),
- boolean_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__decrement_new_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__decrement_computed_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__decrement_old_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__increment_copy_count"),
- short_unsigned_type_node);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- size_t count = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- count += this->entries_[i].size();
- gcc_assert(count > 0);
-
- tree entry_type = Refcounts::entry_type(gogo);
- tree index_type = build_index_type(size_int(count - 1));
- tree array_type = build_array_type(entry_type, index_type);
- field = build_decl(BUILTINS_LOCATION, FIELD_DECL,
- get_identifier("__entries"), array_type);
- TREE_CHAIN(field) = fields;
- fields = field;
-
- finish_builtin_struct(struct_type, "__go_refcount", fields, NULL_TREE);
-
- return struct_type;
-}
-
-// Get the initializer for the reference count tree.
-
-tree
-Refcounts::get_initializer(Gogo* gogo)
-{
- gcc_assert(this->is_complete_);
- gcc_assert(!this->is_simple());
-
- size_t count = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- count += this->entries_[i].size();
- gcc_assert(count > 0);
-
- VEC(constructor_elt, gc)* init = VEC_alloc(constructor_elt, gc, 8);
-
- tree decl = this->get_tree(gogo);
- tree type = TREE_TYPE(decl);
-
- tree field = TYPE_FIELDS(type);
-
- constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__caller") == 0);
- elt->index = field;
- elt->value = this->queue_head_decl(gogo);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__callers_were_scanned") == 0);
- elt->index = field;
- elt->value = boolean_false_node;
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__did_not_scan_decrements") == 0);
- elt->index = field;
- elt->value = boolean_false_node;
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__decrement_new_count") == 0);
- elt->index = field;
- size_t c = this->entries_[REFCOUNT_DECREMENT_NEW].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__decrement_computed_count") == 0);
- elt->index = field;
- c = this->entries_[REFCOUNT_DECREMENT_COMPUTED].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__decrement_old_count") == 0);
- elt->index = field;
- c = this->entries_[REFCOUNT_DECREMENT_OLD].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__increment_copy_count") == 0);
- elt->index = field;
- c = this->entries_[REFCOUNT_INCREMENT_COPIED].size();
- gcc_assert(c <= 0xffff);
- elt->value = build_int_cst_type(TREE_TYPE(field), c);
-
- field = TREE_CHAIN(field);
- elt = VEC_quick_push(constructor_elt, init, NULL);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__entries") == 0);
- elt->index = field;
-
- tree desc_field = TYPE_FIELDS(TREE_TYPE(TREE_TYPE(field)));
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(desc_field)),
- "__descriptor") == 0);
- tree value_field = TREE_CHAIN(desc_field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(value_field)),
- "__value") == 0);
-
- VEC(constructor_elt, gc)* entries_init = VEC_alloc(constructor_elt,
- gc, count);
- size_t index = 0;
- for (int i = 0; i < REFCOUNT_MAX; ++i)
- {
- Entries* entries = &this->entries_[i];
- for (Entries::const_iterator p = entries->begin();
- p != entries->end();
- ++p, ++index)
- {
- VEC(constructor_elt, gc)* entry_init = VEC_alloc(constructor_elt,
- gc, 2);
- constructor_elt* eelt = VEC_quick_push(constructor_elt,
- entry_init, NULL);
- eelt->index = desc_field;
- Type* type = *p;
- eelt->value = type->type_descriptor(gogo);
-
- eelt = VEC_quick_push(constructor_elt, entry_init, NULL);
- eelt->index = value_field;
- eelt->value = fold_convert(TREE_TYPE(value_field),
- null_pointer_node);
-
- eelt = VEC_quick_push(constructor_elt, entries_init, NULL);
- eelt->index = size_int(index);
- eelt->value = build_constructor(TREE_TYPE(TREE_TYPE(field)),
- entry_init);
- }
- }
-
- elt->value = build_constructor(TREE_TYPE(field), entries_init);
-
- return build_constructor(TREE_TYPE(decl), init);
-}
-
-// Get the local variable which holds the reference count tree.
-
-tree
-Refcounts::get_tree(Gogo* gogo)
-{
- gcc_assert(!this->is_simple());
- if (this->decl_ == NULL_TREE)
- {
- tree type = this->struct_type(gogo);
- this->decl_ = create_tmp_var(type, NULL);
- }
- return this->decl_;
-}
-
-// Get the local variable which holds the only entry we need if the
-// queue is simple.
-
-tree
-Refcounts::get_simple_tree(Gogo*)
-{
- gcc_assert(this->is_simple());
- if (this->simple_decl_ == NULL_TREE)
- this->simple_decl_ = create_tmp_var(ptr_type_node, NULL);
- return this->simple_decl_;
-}
-
-// Return a tree which sets the queue entry for ENTRY to VAL.
-
-tree
-Refcounts::set_entry_tree(Gogo* gogo, Refcount_entry entry, tree val)
-{
- gcc_assert(this->is_complete_);
-
- gcc_assert(POINTER_TYPE_P(TREE_TYPE(val)));
-
- if (this->is_simple())
- return build2(MODIFY_EXPR, void_type_node, this->get_simple_tree(gogo),
- fold_convert(ptr_type_node, val));
-
- int cl = entry.classification();
- gcc_assert(cl >= REFCOUNT_DECREMENT_NEW && cl < REFCOUNT_MAX);
- Entries* entries = &this->entries_[cl];
- tree decl = this->get_tree(gogo);
- tree field = TYPE_FIELDS(TREE_TYPE(decl));
- field = TREE_CHAIN(TREE_CHAIN(field));
- field = TREE_CHAIN(TREE_CHAIN(field));
- field = TREE_CHAIN(TREE_CHAIN(field));
- field = TREE_CHAIN(field);
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__entries") == 0);
-
- // Set R to the __entries array.
- tree r = build3(COMPONENT_REF, TREE_TYPE(field), decl, field, NULL_TREE);
-
- unsigned int index = entry.index();
- gcc_assert(index < entries->size());
- for (int i = 0; i < cl; ++i)
- index += this->entries_[i].size();
-
- // Set R to the specific entry in the __entries array.
- r = build4(ARRAY_REF, TREE_TYPE(TREE_TYPE(r)), r, size_int(index),
- NULL_TREE, NULL_TREE);
-
- field = TREE_CHAIN(TYPE_FIELDS(TREE_TYPE(r)));
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__value") == 0);
-
- // Set R to the __value field in the specific entry in the __entries
- // array.
- r = build3(COMPONENT_REF, TREE_TYPE(field), r, field, NULL_TREE);
-
- // An assignment to the field.
- tree set = build2(MODIFY_EXPR, void_type_node, r,
- fold_convert(ptr_type_node, val));
-
- // Set the changed flag to true.
- tree set_flag = build2(MODIFY_EXPR, void_type_node,
- this->get_flag_tree(gogo), boolean_true_node);
-
- // Return the pair of assignments.
- return build2(COMPOUND_EXPR, void_type_node, set, set_flag);
-}
-
-// Return the tree for the flag which indicates whether anything
-// changed.
-
-tree
-Refcounts::get_flag_tree(Gogo*)
-{
- gcc_assert(!this->is_simple());
- if (this->flag_decl_ == NULL_TREE)
- {
- tree decl = create_tmp_var(boolean_type_node, NULL);
- DECL_INITIAL(decl) = boolean_false_node;
- this->flag_decl_ = decl;
- }
- return this->flag_decl_;
-}
-
-// Return a decl for the thread-local variable which holds the head of
-// the list of reference count queues.
-
-tree
-Refcounts::queue_head_decl(Gogo* gogo)
-{
- gcc_assert(!this->is_simple());
- if (this->queue_head_decl_ == NULL_TREE)
- {
- tree local_decl = this->get_tree(gogo);
- tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
- get_identifier("__go_refcount_head"),
- build_pointer_type(TREE_TYPE(local_decl)));
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
- DECL_TLS_MODEL(decl) = decl_default_tls_model(decl);
- go_preserve_from_gc(decl);
- this->queue_head_decl_ = decl;
- }
- return this->queue_head_decl_;
-}
-
-// Return the tree for initializating the reference count queue at the
-// start of a function. We use a thread-local variable to record the
-// current queue.
-
-tree
-Refcounts::init_queue(Gogo* gogo, source_location location)
-{
- tree statements = NULL_TREE;
-
- if (this->is_simple())
- {
- tree decl = this->get_simple_tree(gogo);
- tree set = build2(INIT_EXPR, void_type_node, decl, null_pointer_node);
- SET_EXPR_LOCATION(set, location);
- append_to_statement_list(set, &statements);
- }
- else
- {
- tree decl = this->get_tree(gogo);
- tree init = build2(INIT_EXPR, void_type_node, decl,
- this->get_initializer(gogo));
- SET_EXPR_LOCATION(init, location);
- append_to_statement_list(init, &statements);
-
- tree queue_head = this->queue_head_decl(gogo);
- tree set = build2(MODIFY_EXPR, void_type_node, queue_head,
- fold_convert(TREE_TYPE(queue_head),
- build_fold_addr_expr(decl)));
- SET_EXPR_LOCATION(set, location);
- append_to_statement_list(set, &statements);
-
- init = build1(DECL_EXPR, void_type_node, this->get_flag_tree(gogo));
- SET_EXPR_LOCATION(init, location);
- append_to_statement_list(init, &statements);
- }
-
- return statements;
-}
-
-// Return the tree for flushing the reference count queue.
-
-tree
-Refcounts::flush_queue(Gogo* gogo, bool at_end_of_function,
- source_location location)
-{
- if (this->is_simple())
- {
- tree decl = this->get_simple_tree(gogo);
- static tree increment_fndecl;
- static tree decrement_fndecl;
- static tree* pfndecl;
- const char* name;
- tree descriptor;
- if (this->simple_descriptor(gogo, &descriptor))
- {
- pfndecl = &increment_fndecl;
- name = "__go_increment_refcount";
- }
- else
- {
- pfndecl = &decrement_fndecl;
- name = "__go_decrement_refcount";
- }
- return Gogo::call_builtin(pfndecl,
- location,
- name,
- 2,
- void_type_node,
- ptr_type_node,
- decl,
- TREE_TYPE(descriptor),
- descriptor);
- }
-
- tree decl = this->get_tree(gogo);
- tree flag_decl = this->get_flag_tree(gogo);
- static tree flush_fndecl;
- tree call = Gogo::call_builtin(&flush_fndecl,
- location,
- "__go_refcount_flush_queue",
- 1,
- void_type_node,
- build_pointer_type(TREE_TYPE(decl)),
- build_fold_addr_expr(decl));
- tree set = build2(MODIFY_EXPR, void_type_node, flag_decl,
- boolean_false_node);
- tree ret = build3(COND_EXPR, void_type_node, flag_decl,
- build2(COMPOUND_EXPR, void_type_node, call, set),
- NULL_TREE);
- SET_EXPR_LOCATION(ret, location);
-
- if (at_end_of_function)
- {
- tree queue_head = this->queue_head_decl(gogo);
- tree decl = this->get_tree(gogo);
- tree field = TYPE_FIELDS(TREE_TYPE(decl));
- gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
- "__caller") == 0);
- tree field_ref = build3(COMPONENT_REF, TREE_TYPE(field), decl, field,
- NULL_TREE);
- tree set_head = build2(MODIFY_EXPR, void_type_node, queue_head,
- field_ref);
- SET_EXPR_LOCATION(set_head, location);
- ret = build2(COMPOUND_EXPR, void_type_node, ret, set_head);
- }
-
- return ret;
-}
-
-// Class Refcount_traverse_expressions.
-
-// Gather expressions which need to have their reference count
-// decremented after a statement is complete. This is called for
-// expressions which are not in themselves lvalues or rvalues.
-
-class Refcount_traverse_expressions : public Traverse
-{
- public:
- Refcount_traverse_expressions(Refcounts* refcounts,
- Expression* skip)
- : Traverse(traverse_blocks | traverse_expressions),
- refcounts_(refcounts), skip_(skip)
- { }
-
- void
- set_skip(Expression* skip)
- { this->skip_ = skip; }
-
- protected:
- // We only want to look at expressions which are the top level of a
- // statement. If a statement includes a block, we do not want to
- // look at the expressions in the statements in the block. For
- // example, we want to look at the condition of an If_statement, not
- // the expressions in the statements in the then and else blocks.
- int
- block(Block*)
- { return TRAVERSE_SKIP_COMPONENTS; }
-
- int
- expression(Expression**);
-
- private:
- // Temporary values which need decrementing.
- Refcounts* refcounts_;
- // An Expression to skip, because it occurs as the complete RHS.
- Expression* skip_;
-};
-
-int
-Refcount_traverse_expressions::expression(Expression** pexpr)
-{
- Expression* expr = *pexpr;
-
- if (expr == this->skip_)
- return TRAVERSE_CONTINUE;
-
- // If EXPR is a constant, we don't need to increment any reference
- // counts. We check here to catch cases like &global_variable,
- // where we can tell that is a constant when we take the address,
- // but not if we recurse down to look at the global variable.
- if (expr->is_constant())
- return TRAVERSE_SKIP_COMPONENTS;
-
- *pexpr = expr->note_decrements(this->refcounts_);
-
- return TRAVERSE_CONTINUE;
-}
-
-// Class Refcount_traverse_assignments.
-
-// For each assignment in a statement, gather values which need
-// reference count increments and decrements.
-
-class Refcount_traverse_assignments : public Traverse_assignments
-{
- public:
- Refcount_traverse_assignments(Refcounts* refcounts,
- Expression_list* do_not_increment)
- : refcounts_(refcounts), do_not_increment_(do_not_increment)
- { }
-
- protected:
- void
- initialize_variable(Named_object*);
-
- void
- assignment(Expression**, Expression**);
-
- void
- value(Expression**, bool, bool);
-
- private:
- static bool
- holds_only_arg_vars(Expression* expr);
-
- // Temporary values which need decrementing.
- Refcounts* refcounts_;
- // A list of expressions whose reference counts should not be
- // incremented. This may be NULL.
- Expression_list* do_not_increment_;
-};
-
-// Handle reference counts for a variable initialization.
-
-void
-Refcount_traverse_assignments::initialize_variable(Named_object* var)
-{
- Expression* init = var->var_value()->init();
- if (init != NULL)
- {
- Expression* init_hold = init;
- if (!var->var_value()->holds_only_args()
- || !Refcount_traverse_assignments::holds_only_arg_vars(init))
- init = init->being_copied(this->refcounts_,
- !var->var_value()->is_global());
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- Expression::traverse(&init, &rte);
- if (init != init_hold)
- var->var_value()->set_init(init);
- }
-}
-
-// Return whether EXPR is a variable which only holds argument values.
-
-bool
-Refcount_traverse_assignments::holds_only_arg_vars(Expression* expr)
-{
- if (expr == NULL)
- return false;
- Var_expression* ve = expr->var_expression();
- if (ve == NULL)
- return false;
- Named_object* no = ve->named_object();
- return no->is_variable() && no->var_value()->holds_only_args();
-}
-
-// Handle reference counts for an assignment in a statement.
-
-void
-Refcount_traverse_assignments::assignment(Expression** plhs, Expression** prhs)
-{
- if (!Refcount_traverse_assignments::holds_only_arg_vars(*plhs)
- || !Refcount_traverse_assignments::holds_only_arg_vars(*prhs))
- {
- bool is_local = (*plhs)->is_local_variable();
- if (plhs != NULL)
- *plhs = (*plhs)->being_set(this->refcounts_);
- if (prhs != NULL)
- *prhs = (*prhs)->being_copied(this->refcounts_,
- is_local);
- }
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- if (plhs != NULL)
- {
- rte.set_skip(*plhs);
- Expression::traverse(plhs, &rte);
- }
- if (prhs != NULL)
- {
- rte.set_skip(NULL);
- Expression::traverse(prhs, &rte);
- }
-}
-
-// Handle reference counts for a value used in an assignment.
-
-void
-Refcount_traverse_assignments::value(Expression** pval, bool is_stored,
- bool is_local)
-{
- if (is_stored)
- {
- bool increment = true;
- if (this->do_not_increment_ != NULL)
- {
- Expression_list::iterator p =
- std::find(this->do_not_increment_->begin(),
- this->do_not_increment_->end(),
- *pval);
- if (p != this->do_not_increment_->end())
- {
- this->do_not_increment_->erase(p);
- increment = false;
- }
- }
-
- if (increment)
- *pval = (*pval)->being_copied(this->refcounts_,
- is_local);
- }
-
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- Expression::traverse(pval, &rte);
-}
-
-// Class Refcount_traverse_statements.
-
-// Find statements which need reference count adjustments.
-
-class Refcount_traverse_statements : public Traverse
-{
- public:
- Refcount_traverse_statements(Refcounts* refcounts)
- : Traverse(traverse_functions | traverse_blocks | traverse_statements),
- refcounts_(refcounts)
- { }
-
- protected:
- int
- function(Named_object*)
- { return TRAVERSE_SKIP_COMPONENTS; }
-
- int
- block(Block*);
-
- int
- statement(Block*, size_t* pindex, Statement*);
-
- private:
- // Reference count entries for this function.
- Refcounts* refcounts_;
-};
-
-// Adjust reference counts for a block. This is where we decrement
-// the reference count for local variables.
-
-int
-Refcount_traverse_statements::block(Block* b)
-{
- // If the block ends with a return statement, build a list of
- // variables which are returned. Use the list to optimize returning
- // a reference counted local variable. FIXME: This is a very
- // simple-minded version of this optimization.
- std::vector<Named_object*> returned;
- Return_statement* r = NULL;
- const std::vector<Statement*>* statements = b->statements();
- if (!statements->empty())
- {
- r = statements->back()->return_statement();
- if (r != NULL)
- {
- const Expression_list* vals = r->vals();
- if (vals != NULL)
- {
- for (Expression_list::const_iterator pv = vals->begin();
- pv != vals->end();
- ++pv)
- {
- Var_expression* ve = (*pv)->var_expression();
- if (ve != NULL)
- {
- Named_object* no = ve->named_object();
- if (std::find(returned.begin(), returned.end(), no)
- == returned.end())
- returned.push_back(no);
- }
- }
- }
- }
- }
-
- Bindings* bindings = b->bindings();
- for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
- p != bindings->end_definitions();
- ++p)
- {
- // If we find a parameter which does not only hold parameter
- // values, we need to queue up a reference count increment at
- // the start of the function.
- if ((*p)->is_variable()
- && (*p)->var_value()->is_parameter()
- && !(*p)->var_value()->holds_only_args()
- && (*p)->var_value()->type()->has_refcounted_component())
- {
- source_location loc = (*p)->location();
- Refcounts* rc = this->refcounts_;
- Refcount_entry re = rc->add(REFCOUNT_INCREMENT_COPIED,
- (*p)->var_value()->type());
- Expression* rhs = Expression::make_var_reference(*p, loc);
- Statement* s =
- Statement::make_refcount_queue_assignment_statement(rc, &re, rhs,
- loc);
- b->add_statement_at_front(s);
- }
-
- // We need to queue up reference count decrements for all local
- // variables at the end of the block.
- if ((*p)->is_variable()
- && ((*p)->var_value()->is_in_heap()
- || (!(*p)->var_value()->holds_only_args()
- && (*p)->var_value()->type()->has_refcounted_component())))
- {
- std::vector<Named_object*>::iterator prv =
- std::find(returned.begin(), returned.end(), *p);
- if (prv == returned.end())
- {
- source_location loc = b->end_location();
- Refcounts* rc = this->refcounts_;
- Type* type = (*p)->var_value()->type();
- const bool is_in_heap = (*p)->var_value()->is_in_heap();
- if (is_in_heap)
- type = Type::make_pointer_type(type);
- Refcount_entry re = rc->add(REFCOUNT_DECREMENT_OLD, type);
- Expression* rhs = Expression::make_var_reference(*p, loc);
- if (is_in_heap)
- rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
- Statement* s =
- Statement::make_refcount_queue_assignment_statement(rc, &re,
- rhs, loc);
- b->add_final_statement(s);
- }
- else
- {
- r->add_do_not_increment(*p);
- returned.erase(prv);
- }
- }
- }
- return TRAVERSE_CONTINUE;
-}
-
-// Adjust reference counts for a statement.
-
-int
-Refcount_traverse_statements::statement(Block* block, size_t* pindex,
- Statement* s)
-{
- if (s->is_block_statement())
- return TRAVERSE_CONTINUE;
-
- // Simple avoidance of reference count adjustments when returning a
- // local variable.
- Expression_list* do_not_increment = NULL;
- Return_statement* r = s->return_statement();
- if (r != NULL)
- do_not_increment = r->do_not_increment();
-
- Refcount_traverse_assignments rta(this->refcounts_, do_not_increment);
- if (!s->traverse_assignments(&rta))
- {
- Refcount_traverse_expressions rte(this->refcounts_, NULL);
- s->traverse(block, pindex, &rte);
- }
-
- gcc_assert(do_not_increment == NULL || do_not_increment->empty());
-
- return TRAVERSE_CONTINUE;
-}
-
-// Class Refcount_traverse_functions.
-
-// Walk over the functions adding reference count adjustments.
-
-class Refcount_traverse_functions : public Traverse
-{
- public:
- Refcount_traverse_functions()
- : Traverse(traverse_functions)
- { }
-
- protected:
- int
- function(Named_object*);
-};
-
-int
-Refcount_traverse_functions::function(Named_object* no)
-{
- Refcounts* refcounts = no->func_value()->refcounts();
- Refcount_traverse_statements rts(refcounts);
- no->func_value()->block()->traverse(&rts);
- refcounts->set_is_complete();
- return TRAVERSE_CONTINUE;
-}
-
-// Walk the tree adding reference count adjustments.
-
-void
-Gogo::add_refcounts()
-{
- Refcount_traverse_functions rtf;
- this->traverse(&rtf);
-}
@@ -1,167 +0,0 @@
-// refcount.h -- Go fronetnd reference counts. -*- C++ -*-
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef GO_REFCOUNT_H
-#define GO_REFCOUNT_H
-
-// This file defines classes used to insert reference count
-// manipulation as needed in the generated program.
-
-class Gogo;
-class Type;
-class Block;
-class Expression;
-class Call_expression;
-
-// Each function maintains a local queue of values whose reference
-// count must be incremented or decremented when exiting the function.
-// These are the different sorts of values found on that queue. This
-// is not an enum because we want to declare values of this in other
-// header files without including this one.
-
-// Decrement reference count for newly allocated value created via a
-// call to new or some builtin function such as string addition.
-const int REFCOUNT_DECREMENT_NEW = 0;
-
-// Decrement reference count for value referenced during the course of
-// an expression, such as a value returned by a function call.
-const int REFCOUNT_DECREMENT_COMPUTED = 1;
-
-// Decrement reference count for old value stored in a variable or
-// memory location to which a new value was assigned.
-const int REFCOUNT_DECREMENT_OLD = 2;
-
-// Increment reference count for value copied into variable or memory
-// location.
-const int REFCOUNT_INCREMENT_COPIED = 3;
-
-// One more than the largest value.
-const int REFCOUNT_MAX = 4;
-
-// An entry in a reference count queue.
-
-class Refcount_entry
-{
- public:
- Refcount_entry(int classification, unsigned int index)
- : classification_(classification), index_(index)
- { }
-
- // The type of reference count adjustment.
- int
- classification() const
- { return this->classification_; }
-
- // The index in the specific reference count queue.
- unsigned int
- index() const
- { return this->index_; }
-
- // Update this entry to point to the next entry in the queue.
- void
- increment()
- { ++this->index_; }
-
- private:
- // Which sort of adjustment this is.
- int classification_;
- // The index in the specific reference count queue.
- unsigned int index_;
-};
-
-// The overall reference count queue. There will be one of these
-// objects for each function.
-
-class Refcounts
-{
- public:
- Refcounts()
- : entries_(), decl_(NULL), flag_decl_(NULL), queue_head_decl_(NULL),
- simple_decl_(NULL), is_complete_(false)
- { }
-
- // Add a new entry.
- Refcount_entry
- add(int classification, Type*);
-
- // Add a new entry for a type which only requires a single entry.
- // Increment *ENTRY.
- void
- add_one(Type*, Refcount_entry* entry);
-
- // Called after all entries have been added.
- void
- set_is_complete()
- { this->is_complete_ = true; }
-
- // Get the type of the variable stored in ENTRY.
- Type*
- get_type(Refcount_entry);
-
- // Return whether there are no reference count adjustments.
- bool
- empty() const;
-
- // Return a tree which sets the queue entry for ENTRY to VAL. VAL
- // must be a pointer type.
- tree
- set_entry_tree(Gogo*, Refcount_entry entry, tree val);
-
- // Initialize the reference count queue at the start of a function.
- tree
- init_queue(Gogo*, source_location);
-
- // Return the tree for flushing the reference count queue.
- tree
- flush_queue(Gogo*, bool at_end_of_function, source_location);
-
- private:
- bool
- is_simple() const;
-
- bool
- simple_descriptor(Gogo*, tree*) const;
-
- static tree
- entry_type(Gogo*);
-
- tree
- struct_type(Gogo*);
-
- tree
- get_tree(Gogo*);
-
- tree
- get_initializer(Gogo*);
-
- tree
- get_flag_tree(Gogo*);
-
- tree
- queue_head_decl(Gogo*);
-
- tree
- get_simple_tree(Gogo*);
-
- /* The type of a list of entries. */
- typedef std::vector<Type*> Entries;
-
- // Reference count adjustments, indexed by a REFCOUNT_xxx value.
- Entries entries_[REFCOUNT_MAX];
- // The local variable which holds the reference count queue.
- tree decl_;
- // The local variable which is a flag which is set when anything
- // changes.
- tree flag_decl_;
- // A decl for the head of the list of reference count queues.
- tree queue_head_decl_;
- // A decl used if the queue is simple (i.e., has only one entry).
- tree simple_decl_;
- // Set to true after we have added all reference counts.
- bool is_complete_;
-};
-
-#endif // !defined(GO_REFCOUNT_H)
@@ -24,7 +24,6 @@
#include "types.h"
#include "expressions.h"
#include "gogo.h"
-#include "refcount.h"
#include "statements.h"
// Class Statement.
@@ -407,49 +406,7 @@
Statement::make_temporary(Block* block, Type* type, Expression* init,
source_location location)
{
- Temporary_statement* ret = new Temporary_statement(type, init, location);
- if (ret->type()->has_refcounted_component())
- block->add_final_statement(Statement::destroy_temporary(ret));
- return ret;
-}
-
-// Destroy a temporary variable.
-
-class Destroy_temporary_statement : public Statement
-{
- public:
- Destroy_temporary_statement(Temporary_statement* statement)
- : Statement(STATEMENT_DESTROY_TEMPORARY, statement->location()),
- ref_(Expression::make_temporary_reference(statement,
- statement->location()))
- { }
-
- protected:
- int
- do_traverse(Traverse*)
- { gcc_unreachable(); }
-
- bool
- do_traverse_assignments(Traverse_assignments*)
- { gcc_unreachable(); }
-
- // FIXME.
- tree
- do_get_tree(Translate_context* context)
- { return this->ref_->get_tree(context); }
-
- private:
- // A reference to the temporary variable being destroyed.
- Expression* ref_;
-};
-
-// Make a statement which destroys a temporary variable.
-
-Statement*
-Statement::destroy_temporary(Temporary_statement* statement)
-{
- gcc_assert(statement->type()->has_refcounted_component());
- return new Destroy_temporary_statement(statement);
+ return new Temporary_statement(type, init, location);
}
// An assignment statement.
@@ -568,21 +525,11 @@
rhs_tree = Expression::convert_for_assignment(context, this->lhs_->type(),
this->rhs_->type(), rhs_tree,
this->location());
-
- Refcount_decrement_lvalue_expression *rdle =
- this->lhs_->refcount_decrement_lvalue_expression();
- tree ret;
- if (rdle == NULL)
- ret = fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
- lhs_tree, rhs_tree);
- else
- {
- ret = rdle->set(context, lhs_tree, rhs_tree);
- if (CAN_HAVE_LOCATION_P(ret))
- SET_EXPR_LOCATION(ret, this->location());
- }
-
- return ret;
+ if (rhs_tree == error_mark_node)
+ return error_mark_node;
+
+ return fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
+ lhs_tree, rhs_tree);
}
// Make an assignment statement.
@@ -1714,15 +1661,6 @@
&& parameters->begin()->type()->points_to() == NULL)))
return false;
- // If the single parameter is reference counted, then we need a
- // thunk in order to decrement the reference count when the function
- // is complete. FIXME: In practice this means that the only simple
- // go statements are the ones with no parameters.
- if (parameters != NULL
- && !parameters->empty()
- && parameters->begin()->type()->has_refcounted_component())
- return false;
-
// If the function returns multiple values, or returns a type other
// than integer, floating point, or pointer, then it may get a
// hidden first parameter, in which case we need the more
@@ -1736,13 +1674,6 @@
&& results->begin()->type()->points_to() == NULL)))
return false;
- // If the function returns a reference counted type, then we need a
- // thunk in order to discard the function's return value.
- if (results != NULL
- && !results->empty()
- && results->begin()->type()->has_refcounted_component())
- return false;
-
// If this calls something which is not a simple function, then we
// need a thunk.
Expression* fn = this->call_->call_expression()->fn();
@@ -1767,8 +1698,6 @@
bool
Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
{
- // FIXME: This doesn't work, because we might get a REFCOUNT_ADJUST
- // which we will never execute.
Expression* fn = this->call_->call_expression()->fn();
Expression* fn2 = fn;
tassign->value(&fn2, true, false);
@@ -1933,7 +1862,7 @@
location);
// Allocate the initialized struct on the heap.
- constructor = Expression::make_heap_composite(constructor, true, location);
+ constructor = Expression::make_heap_composite(constructor, location);
// Look up the thunk.
Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
@@ -2251,9 +2180,6 @@
location));
}
- // FIXME: Now we need to decrement the reference count of the
- // parameter.
-
// That is all the thunk has to do.
gogo->finish_function(location);
}
@@ -2282,19 +2208,6 @@
else
{
gcc_assert(args->size() == 1);
- Expression* arg = args->front();
-
- // The argument will typically include a reference count
- // decrement. We do not want that decrement: the thunk is
- // responsible for decrementing the reference count. FIXME: We
- // will have an entry on the queue which is never used.
- if (arg->refcount_adjust_expression() != NULL)
- {
- int cl = arg->refcount_adjust_expression()->classification();
- if (cl != REFCOUNT_INCREMENT_COPIED)
- arg = arg->refcount_adjust_expression()->expr();
- }
-
*parg = args->front()->get_tree(context);
}
}
@@ -2388,32 +2301,8 @@
// Class Return_statement.
-// Record that we should not increment the reference count of NO.
-
-void
-Return_statement::add_do_not_increment(Named_object* no)
-{
- gcc_assert(this->vals_ != NULL);
- for (Expression_list::const_iterator p = this->vals_->begin();
- p != this->vals_->end();
- ++p)
- {
- Var_expression* ve = (*p)->var_expression();
- if (ve != NULL && ve->named_object() == no)
- {
- if (this->do_not_increment_ == NULL)
- this->do_not_increment_ = new Expression_list;
- this->do_not_increment_->push_back(ve);
- return;
- }
- }
- gcc_unreachable();
-}
-
-// Traverse assignments. A return statement doesn't assign any
-// values, but it does require that we increment the reference count
-// of the values we are returning. So we treat each return value as a
-// top level RHS in an expression.
+// Traverse assignments. We treat each return value as a top level
+// RHS in an expression.
bool
Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
@@ -2880,23 +2769,7 @@
tree
Label_statement::do_get_tree(Translate_context* context)
{
- tree ret = this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
-
- // If this function has a reference count queue, we flush it at each
- // label. We need to do this in case the label is used to implement
- // a loop; otherwise some entries in the reference count queue may
- // get reused.
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- if (refcounts != NULL && !refcounts->empty())
- {
- tree flush = refcounts->flush_queue(context->gogo(), false,
- this->location());
- tree statements = NULL_TREE;
- append_to_statement_list(ret, &statements);
- append_to_statement_list(flush, &statements);
- ret = statements;
- }
- return ret;
+ return this->build_stmt_1(LABEL_EXPR, this->label_->get_decl());
}
// Make a label statement.
@@ -5232,73 +5105,3 @@
{
return new For_range_statement(index_var, value_var, range, location);
}
-
-// An assignment to an entry in the reference count queue.
-
-class Refcount_queue_assignment_statement : public Statement
-{
- public:
- Refcount_queue_assignment_statement(Refcount_entry entry,
- Expression* expr,
- source_location location)
- : Statement(STATEMENT_REFCOUNT_QUEUE_ASSIGNMENT, location),
- entry_(entry), expr_(expr)
- { }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return this->traverse_expression(traverse, &this->expr_); }
-
- // Types should have been determined and checked before any of these
- // statements are created.
-
- void
- do_determine_types()
- { gcc_unreachable(); }
-
- void
- do_check_types(Gogo*)
- { gcc_unreachable(); }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The entry in the reference count queue.
- Refcount_entry entry_;
- // The expression we are storing in the queue.
- Expression* expr_;
-};
-
-// Implement the actual assignment.
-
-tree
-Refcount_queue_assignment_statement::do_get_tree(Translate_context* context)
-{
- // We only need this statement for variables. It will only work for
- // expressions without side effects.
- tree expr_tree = this->expr_->get_tree(context);
- if (expr_tree == error_mark_node)
- return error_mark_node;
- gcc_assert(TREE_CODE(expr_tree) == VAR_DECL
- || TREE_CODE(expr_tree) == PARM_DECL
- || (TREE_CODE(expr_tree) == INDIRECT_REF
- && TREE_CODE(TREE_OPERAND(expr_tree, 0)) == VAR_DECL));
- Refcounts* refcounts = context->function()->func_value()->refcounts();
- return this->expr_->type()->set_refcount_queue_entry(context->gogo(),
- refcounts,
- &this->entry_,
- expr_tree);
-}
-
-// Make an assignment to an entry in the reference count queue.
-
-Statement*
-Statement::make_refcount_queue_assignment_statement(Refcounts*,
- Refcount_entry* entry,
- Expression* expr,
- source_location location)
-{
- return new Refcount_queue_assignment_statement(*entry, expr, location);
-}
@@ -40,8 +40,6 @@
class Type_case_clauses;
class Select_clauses;
class Typed_identifier_list;
-class Refcounts;
-class Refcount_entry;
// This class is used to traverse assignments made by a statement
// which makes assignments.
@@ -90,7 +88,6 @@
STATEMENT_ERROR,
STATEMENT_VARIABLE_DECLARATION,
STATEMENT_TEMPORARY,
- STATEMENT_DESTROY_TEMPORARY,
STATEMENT_ASSIGNMENT,
STATEMENT_EXPRESSION,
STATEMENT_BLOCK,
@@ -105,7 +102,6 @@
STATEMENT_IF,
STATEMENT_CONSTANT_SWITCH,
STATEMENT_SELECT,
- STATEMENT_REFCOUNT_QUEUE_ASSIGNMENT,
// These statements types are created by the parser, but they
// disappear during the lowering pass.
@@ -140,11 +136,6 @@
static Temporary_statement*
make_temporary(Block*, Type*, Expression*, source_location);
- // Make a statement which destroys a temporary variable. This may
- // return NULL if there is nothing to do.
- static Statement*
- destroy_temporary(Temporary_statement*);
-
// Make an assignment statement.
static Statement*
make_assignment(Expression*, Expression*, source_location);
@@ -261,12 +252,6 @@
make_for_range_statement(Expression* index_var, Expression* value_var,
Expression* range, source_location);
- // Make a statement which stores a value in the reference count
- // queue.
- static Statement*
- make_refcount_queue_assignment_statement(Refcounts*, Refcount_entry*,
- Expression*, source_location);
-
// Return the statement classification.
Statement_classification
classification() const
@@ -572,7 +557,7 @@
Return_statement(const Typed_identifier_list* results, Expression_list* vals,
source_location location)
: Statement(STATEMENT_RETURN, location),
- results_(results), vals_(vals), do_not_increment_(NULL)
+ results_(results), vals_(vals)
{ }
// The list of values being returned. This may be NULL.
@@ -580,17 +565,6 @@
vals() const
{ return this->vals_; }
- // Return list of expressions whose reference count should not be
- // incremented. This is modified by the caller.
- Expression_list*
- do_not_increment()
- { return this->do_not_increment_; }
-
- // Indicate that we should not increment the reference count of the
- // variable. The variable is being returned by this statement.
- void
- add_do_not_increment(Named_object*);
-
protected:
int
do_traverse(Traverse* traverse)
@@ -622,10 +596,6 @@
const Typed_identifier_list* results_;
// Return values. This may be NULL.
Expression_list* vals_;
- // List of variables whose reference count should not be
- // incremented. This may be NULL. This is only used during the
- // reference counting pass.
- Expression_list* do_not_increment_;
};
// Select_clauses holds the clauses of a select statement. This is
@@ -25,7 +25,6 @@
#include "statements.h"
#include "export.h"
#include "import.h"
-#include "refcount.h"
#include "types.h"
// Class Type.
@@ -197,17 +196,6 @@
}
}
-// Add entries to the reference count queue for this type. This is
-// the default version, which adds a single pointer.
-
-void
-Type::do_add_refcount_queue_entries(Refcounts* refcounts,
- Refcount_entry* entry)
-{
- gcc_assert(this->is_refcounted());
- refcounts->add_one(this, entry);
-}
-
// Return true if this is an error type. Don't give an error if we
// try to dereference an undefined forwarding type, as this is called
// in the parser when the type may legitimately be undefined.
@@ -731,30 +719,6 @@
gcc_unreachable();
}
-// Return a tree copying VAL, a value of this type, into the reference
-// count queue at ENTRY. This modifies ENTRY.
-
-tree
-Type::set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- return this->do_set_refcount_queue_entry(gogo, refcounts, entry, val);
-}
-
-// Default implementation of do_set_refcount_queue_entry. This works
-// for any reference count type which is represented as a pointer.
-
-tree
-Type::do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- gcc_assert(this->is_refcounted());
- gcc_assert(POINTER_TYPE_P(TREE_TYPE(val)));
- tree ret = refcounts->set_entry_tree(gogo, *entry, val);
- entry->increment();
- return ret;
-}
-
// Return a type descriptor for this type.
tree
@@ -1559,18 +1523,6 @@
return ret;
}
-// Copy a string into the reference count queue.
-
-tree
-String_type::do_set_refcount_queue_entry(Gogo *gogo, Refcounts* refcounts,
- Refcount_entry *entry, tree val) const
-{
- tree ret = refcounts->set_entry_tree(gogo, *entry,
- this->bytes_tree(gogo, val));
- entry->increment();
- return ret;
-}
-
// The type descriptor for the string type.
void
@@ -2671,41 +2623,6 @@
return false;
}
-// Whether this contains a reference counted component.
-
-bool
-Struct_type::do_has_refcounted_component() const
-{
- const Struct_field_list* fields = this->fields();
- if (fields == NULL)
- return false;
- for (Struct_field_list::const_iterator p = fields->begin();
- p != fields->end();
- ++p)
- {
- if (p->type()->has_refcounted_component())
- return true;
- }
- return false;
-}
-
-// Add entries to the refcount queue for this type.
-
-void
-Struct_type::do_add_refcount_queue_entries(Refcounts* refcounts,
- Refcount_entry* entry)
-{
- const Struct_field_list* fields = this->fields();
- gcc_assert(fields != NULL);
- for (Struct_field_list::const_iterator p = fields->begin();
- p != fields->end();
- ++p)
- {
- if (p->type()->has_refcounted_component())
- p->type()->add_refcount_queue_entries(refcounts, entry);
- }
-}
-
// Whether this type is compatible with T.
bool
@@ -3084,38 +3001,6 @@
return ret;
}
-// Copy a struct into the reference count queue.
-
-tree
-Struct_type::do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- const Struct_field_list* fields = this->fields();
- gcc_assert(fields != NULL);
- tree ret = NULL_TREE;
- tree field = TYPE_FIELDS(TREE_TYPE(val));
- for (Struct_field_list::const_iterator p = fields->begin();
- p != fields->end();
- ++p, field = TREE_CHAIN(field))
- {
- gcc_assert(field != NULL_TREE);
- if (p->type()->has_refcounted_component())
- {
- tree f = build3(COMPONENT_REF, TREE_TYPE(field), val, field,
- NULL_TREE);
- tree set = p->type()->set_refcount_queue_entry(gogo, refcounts,
- entry, f);
- if (ret == NULL_TREE)
- ret = set;
- else
- ret = build2(COMPOUND_EXPR, void_type_node, ret, set);
- }
- }
- gcc_assert(field == NULL_TREE);
- gcc_assert(ret != NULL_TREE);
- return ret;
-}
-
// Type descriptor.
void
@@ -3484,14 +3369,7 @@
length_tree,
size_one_node));
- tree ret = build_array_type(element_type_tree, index_type);
-
- // If the element type requires reference counting, then we need
- // this to be stored in memory.
- if (this->element_type_->has_refcounted_component())
- TREE_ADDRESSABLE(ret) = 1;
-
- return ret;
+ return build_array_type(element_type_tree, index_type);
}
else
{
@@ -3684,18 +3562,6 @@
constructor);
}
-// Copy an array into the reference count queue.
-
-tree
-Array_type::do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
-{
- tree ret = refcounts->set_entry_tree(gogo, *entry,
- this->value_pointer_tree(gogo, val));
- entry->increment();
- return ret;
-}
-
// Return a tree for a pointer to the values in ARRAY.
tree
@@ -5515,19 +5381,6 @@
return true;
}
-// The number of reference count queue entries required.
-
-void
-Named_type::do_add_refcount_queue_entries(Refcounts* refcounts,
- Refcount_entry* entry)
-{
- // If this is not a struct or an array, just use the type itself.
- if (this->struct_type() == NULL && this->array_type() == NULL)
- this->Type::do_add_refcount_queue_entries(refcounts, entry);
- else
- this->type_->add_refcount_queue_entries(refcounts, entry);
-}
-
// Return a hash code. This is used for method lookup. We simply
// hash on the name itself.
@@ -45,8 +45,6 @@
class Translate_context;
class Export;
class Import;
-class Refcounts;
-class Refcount_entry;
// Type codes used in type descriptors. These must match the values
// in libgo/runtime/go-type.h.
@@ -590,27 +588,6 @@
has_pointer() const
{ return this->do_has_pointer(); }
- // Return true if this type requires reference counting: if copying
- // or destroying a value of this type requires adjusting a reference
- // count.
- bool
- is_refcounted() const
- { return this->do_is_refcounted(); }
-
- // Return true if this type has some component which is reference
- // counted. If IS_REFCOUNTED returns true for this type, then this
- // returns true as well.
- bool
- has_refcounted_component() const
- { return this->do_has_refcounted_component(); }
-
- // Add entries to the reference count queue to hold an object of
- // this type. This normally adds a single entry but may add more
- // for structures.
- void
- add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry)
- { return this->do_add_refcount_queue_entries(refcounts, entry); }
-
// Return true if this is an error type. An error type indicates a
// parsing error.
bool
@@ -829,12 +806,6 @@
source_location location)
{ return this->do_make_expression_tree(context, args, location); }
- // Return a tree copying VAL, a value of this type, into the
- // reference count queue at ENTRY. This modifies ENTRY.
- tree
- set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
// Build a type descriptor entry for this type. Return a pointer to
// it.
tree
@@ -898,17 +869,6 @@
do_has_pointer() const
{ return false; }
- virtual bool
- do_is_refcounted() const
- { return false; }
-
- virtual bool
- do_has_refcounted_component() const
- { return this->do_is_refcounted(); }
-
- virtual void
- do_add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry);
-
virtual unsigned int
do_hash_for_method(Gogo*) const;
@@ -926,10 +886,6 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- virtual tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
virtual void
do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl) = 0;
@@ -1029,10 +985,6 @@
static tree
build_receive_return_type(tree type);
- tree
- inc_or_dec_refcount(Gogo* gogo, tree expr_tree, source_location,
- bool is_local, bool is_increment);
-
// A hash table we use to avoid infinite recursion.
typedef std::tr1::unordered_set<const Named_type*, Type_hash_identical,
Type_identical> Types_seen;
@@ -1502,20 +1454,12 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
tree
do_get_tree(Gogo*);
tree
do_init_tree(Gogo* gogo, bool);
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -1620,12 +1564,6 @@
do_has_pointer() const
{ return true; }
- // Function types are really pointers, and they are reference
- // counted in case that pointer points to a trampoline.
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -1693,10 +1631,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return !this->is_unsafe_pointer_type(); }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -1948,12 +1882,6 @@
bool
do_has_pointer() const;
- bool
- do_has_refcounted_component() const;
-
- void
- do_add_refcount_queue_entries(Refcounts*, Refcount_entry*);
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -1963,10 +1891,6 @@
tree
do_init_tree(Gogo*, bool);
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -2047,13 +1971,6 @@
return this->length_ == NULL || this->element_type_->has_pointer();
}
- bool
- do_is_refcounted() const
- {
- return (this->length_ == NULL
- || this->element_type_->has_refcounted_component());
- }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2070,10 +1987,6 @@
do_make_expression_tree(Translate_context*, Expression_list*,
source_location);
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const;
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -2144,10 +2057,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2229,10 +2138,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2337,10 +2242,6 @@
do_has_pointer() const
{ return true; }
- bool
- do_is_refcounted() const
- { return true; }
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2541,17 +2442,6 @@
do_has_pointer() const
{ return this->type_->has_pointer(); }
- bool
- do_is_refcounted() const
- { return this->type_->is_refcounted(); }
-
- bool
- do_has_refcounted_component() const
- { return this->type_->has_refcounted_component(); }
-
- void
- do_add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry);
-
unsigned int
do_hash_for_method(Gogo*) const;
@@ -2571,13 +2461,6 @@
source_location location)
{ return this->type_->make_expression_tree(context, args, location); }
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
- {
- return this->type_->set_refcount_queue_entry(gogo, refcounts, entry, val);
- }
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -2678,18 +2561,6 @@
do_has_pointer() const
{ return this->base()->has_pointer(); }
- bool
- do_is_refcounted() const
- { return this->base()->is_refcounted(); }
-
- bool
- do_has_refcounted_component() const
- { return this->base()->has_refcounted_component(); }
-
- void
- do_add_refcount_queue_entries(Refcounts* refcounts, Refcount_entry* entry)
- { return this->real_type()->add_refcount_queue_entries(refcounts, entry); }
-
unsigned int
do_hash_for_method(Gogo* gogo) const
{ return this->real_type()->hash_for_method(gogo); }
@@ -2710,13 +2581,6 @@
source_location location)
{ return this->base()->make_expression_tree(context, args, location); }
- tree
- do_set_refcount_queue_entry(Gogo* gogo, Refcounts* refcounts,
- Refcount_entry* entry, tree val) const
- {
- return this->base()->set_refcount_queue_entry(gogo, refcounts, entry, val);
- }
-
void
do_type_descriptor_decl(Gogo*, Named_type*, tree*);
@@ -315,10 +315,6 @@
runtime/go-rec-nb-small.c \
runtime/go-rec-small.c \
runtime/go-recover.c \
- runtime/go-refcount-decrement.c \
- runtime/go-refcount-flush.c \
- runtime/go-refcount-increment.c \
- runtime/go-refcount-msg.c \
runtime/go-reflect.c \
runtime/go-reflect-call.c \
runtime/go-reflect-chan.c \
@@ -9,7 +9,6 @@
#include "go-alloc.h"
#include "go-panic.h"
-#include "go-refcount.h"
#include "interface.h"
/* Convert one interface type into another interface type.
@@ -118,8 +117,6 @@
ret->__methods = methods;
ret->__object = rhs->__object;
- __go_increment_refcount (ret->__object, ret->__type_descriptor);
-
if (success != NULL)
*success = 1;
@@ -7,7 +7,6 @@
#include <assert.h>
#include "go-alloc.h"
-#include "go-refcount.h"
#include "interface.h"
/* Allocate a new interface for a type which is represented as a
@@ -25,7 +24,5 @@
ret->__methods = methods;
ret->__object = object;
- __go_increment_refcount (object, type_descriptor);
-
return ret;
}
@@ -1,34 +0,0 @@
-/* go-refcount-decrement.c -- decrement reference count.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "go-refcount.h"
-
-/* Decrement the reference count for a pointer. */
-
-void
-__go_decrement_refcount (void *value,
- const struct __go_type_descriptor *descriptor)
-{
- struct
- {
- struct __go_refcount q;
- struct __go_refcount_entry e;
- } s;
- struct __go_refcount *queue;
-
- queue = &s.q;
- __builtin_memset (queue, 0, sizeof (struct __go_refcount));
- queue->__caller = __go_refcount_head;
- __go_refcount_head = queue;
- queue->__decrement_computed_count = 1;
- queue->__entries[0].__descriptor = descriptor;
- queue->__entries[0].__value = value;
- __go_refcount_flush_queue (queue);
- __go_refcount_head = queue->__caller;
-}
@@ -1,224 +0,0 @@
-/* go-refcount-flush.c -- flush reference count queue.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "go-alloc.h"
-#include "go-refcount.h"
-#include "runtime.h"
-#include "malloc.h"
-
-/* The head of the list of reference count queues. This variable is
- maintained by the code generated by the compiler. It exists in
- order to initialize the __caller field of struct __go_refcount. */
-
-__thread struct __go_refcount *__go_refcount_head;
-
-void
-__go_refcount_flush_queue (struct __go_refcount *queue)
-{
- unsigned int allocated;
- struct __go_refcount_msg *msg;
- struct __go_refcount *prc;
- unsigned int increment_count;
- unsigned int count;
- unsigned int offset;
- unsigned int i;
- unsigned int decrement_count;
-
- /* Gather all the increments. We gather up all the increments in
- this function and in all the callers. */
- allocated = 0;
- msg = NULL;
- increment_count = 0;
- for (prc = queue; prc != NULL; prc = prc->__caller)
- {
- count = prc->__increment_copy_count;
- if (count > 0)
- {
- offset = (prc->__decrement_new_count
- + prc->__decrement_computed_count
- + prc->__decrement_old_count);
- for (i = offset; i < offset + count; ++i)
- {
- struct __go_refcount_entry *pre;
- void *value;
- struct __go_refcount *qrc;
- _Bool found;
- unsigned int up_count;
- const unsigned int up_count_limit = 20;
-
- pre = &prc->__entries[i];
- value = pre->__value;
- if (value == NULL)
- continue;
- pre->__value = NULL;
-
- /* If we find an increment for something which has a
- decrement queued up, we can discard both the
- increment and the decrement. Don't look up more than
- 20 stack frames, so that this doesn't take too
- long. */
- found = 0;
- for (qrc = queue, up_count = 0;
- qrc != NULL && up_count < up_count_limit && !found;
- qrc = qrc->__caller, ++up_count)
- {
- unsigned int c;
- unsigned int j;
-
- c = (qrc->__decrement_new_count
- + qrc->__decrement_computed_count
- + qrc->__decrement_old_count);
- for (j = 0; j < c; ++j)
- {
- struct __go_refcount_entry *qre;
-
- qre = &qrc->__entries[j];
- if (qre->__value == value)
- {
- qre->__value = NULL;
- found = 1;
- break;
- }
- }
- }
-
- if (!found)
- {
- if (qrc != NULL)
- qrc->__did_not_scan_decrements = 1;
- if (increment_count >= allocated)
- {
- unsigned int new_allocated;
- struct __go_refcount_msg *new_msg;
-
- new_allocated = allocated == 0 ? 32 : allocated * 2;
- new_msg = __go_alloc (sizeof (struct __go_refcount_msg)
- + new_allocated * sizeof (void *));
- if (allocated > 0)
- {
- __builtin_memcpy (new_msg, msg,
- (sizeof (struct __go_refcount_msg)
- + allocated * sizeof (void *)));
- __go_free (msg);
- }
- allocated = new_allocated;
- msg = new_msg;
- }
- msg->__pointers[increment_count] = value;
- ++increment_count;
- }
- }
- }
-
- /* If we've already scanned the callers for increments, we can
- stop now. */
- if (prc->__callers_were_scanned)
- break;
-
- /* We are going to scan all the callers of PRC for increments;
- mark it now to avoid future scanning. */
- prc->__callers_were_scanned = 1;
- }
-
- /* Gather up the decrements. We can only send the decrements from
- the current function. That is because callers may have queued up
- decrements for temporary objects they created in order to call
- this function. If we apply those decrements now, we will discard
- objects that we might still be using. */
- decrement_count = 0;
-
- if (queue->__did_not_scan_decrements)
- {
- if (queue->__caller != NULL)
- queue->__caller->__did_not_scan_decrements = 1;
- count = (queue->__decrement_new_count
- + queue->__decrement_computed_count
- + queue->__decrement_old_count);
- offset = 0;
- }
- else
- {
- /* Any decrements in __decrement_new_count can be freed
- immediately. We did not see any increments for these
- objects; if we did, the increment would have cleared the
- decrement in the loop above. */
- count = queue->__decrement_new_count;
- for (i = 0; i < count; ++i)
- {
- struct __go_refcount_entry *pre;
- void *value;
- size_t size;
-
- pre = &queue->__entries[i];
- value = pre->__value;
- if (value == NULL)
- continue;
- pre->__value = NULL;
-
- /* FIXME: For debugging. We can't just free a slice because
- it has an embedded pointer. */
- if (pre->__descriptor->__code != GO_SLICE
- && mlookup (value, NULL, NULL, NULL, NULL))
- {
- size = pre->__descriptor->__size;
-
-#if 0
- /* FIXME: This is wrong if the value has embedded pointers. */
- __builtin_memset (value, 0xa5, size);
- __go_free (value);
-#endif
- }
- }
-
- count = queue->__decrement_computed_count + queue->__decrement_old_count;
- offset = queue->__decrement_new_count;
- }
-
- for (i = offset; i < offset + count; ++i)
- {
- struct __go_refcount_entry *pre;
- void *value;
-
- pre = &queue->__entries[i];
- value = pre->__value;
- if (value == NULL)
- continue;
- pre->__value = NULL;
-
- if (increment_count + decrement_count >= allocated)
- {
- unsigned int new_allocated;
- struct __go_refcount_msg *new_msg;
-
- new_allocated = allocated == 0 ? 32 : allocated * 2;
- new_msg = __go_alloc (sizeof (struct __go_refcount_msg)
- + new_allocated * sizeof (void *));
- if (allocated > 0)
- {
- __builtin_memcpy (new_msg, msg,
- (sizeof (struct __go_refcount_msg)
- + allocated * sizeof (void *)));
- __go_free (msg);
- }
- allocated = new_allocated;
- msg = new_msg;
- }
- msg->__pointers[increment_count + decrement_count] = value;
- ++decrement_count;
- }
-
- if (increment_count == 0 && decrement_count == 0)
- assert (msg == NULL);
- else
- {
- msg->__increments = increment_count;
- msg->__decrements = decrement_count;
- __go_send_refcount_msg (msg);
- }
-}
@@ -1,34 +0,0 @@
-/* go-refcount-increment.c -- increment reference count.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "go-refcount.h"
-
-/* Increment the reference count for a pointer. */
-
-void
-__go_increment_refcount (void *value,
- const struct __go_type_descriptor *descriptor)
-{
- struct
- {
- struct __go_refcount q;
- struct __go_refcount_entry e;
- } s;
- struct __go_refcount *queue;
-
- queue = &s.q;
- __builtin_memset (queue, 0, sizeof (struct __go_refcount));
- queue->__caller = __go_refcount_head;
- __go_refcount_head = queue;
- queue->__increment_copy_count = 1;
- queue->__entries[0].__descriptor = descriptor;
- queue->__entries[0].__value = value;
- __go_refcount_flush_queue (queue);
- __go_refcount_head = queue->__caller;
-}
@@ -1,46 +0,0 @@
-/* go-refcount-msg.c -- send reference counts to GC thread.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "go-alloc.h"
-#include "go-refcount.h"
-
-/* Send a reference count message to the GC thread. */
-
-void
-__go_send_refcount_msg (struct __go_refcount_msg *msg)
-{
- static _Bool init;
- static _Bool debug;
-
- if (!init)
- {
- debug = getenv ("GO_DEBUG_REFCOUNT") != NULL;
- init = 1;
- }
-
- if (debug)
- {
- unsigned int count;
- unsigned int i;
- unsigned int offset;
-
- count = msg->__increments;
- for (i = 0; i < count; ++i)
- fprintf (stderr, "Increment refcount %p\n", msg->__pointers[i]);
- offset = count;
- count = msg->__decrements;
- for (i = 0; i < count; ++i)
- fprintf (stderr, "Decrement refcount %p\n",
- msg->__pointers[i + offset]);
- }
-
- /* FIXME: Not implemented. */
-
- __go_free (msg);
-}
@@ -1,92 +0,0 @@
-/* go-refcount.h -- reference count structure.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#ifndef LIBGO_GO_REFCOUNT_H
-#define LIBGO_GO_REFCOUNT_H
-
-#include "go-type.h"
-
-/* Each entry in the reference count table looks like this. */
-
-struct __go_refcount_entry
-{
- /* The type descriptor. */
- const struct __go_type_descriptor *__descriptor;
- /* If the value is a pointer, or in general if the size of the value
- is the size of a pointer, this holds the value itself. Otherwise
- it holds a pointer to the value. This will be NULL when there is
- no value whose reference count needs adjusting. */
- void *__value;
-};
-
-/* Each function which requires reference count adjustments has a
- local variable whose type is this structure. */
-
-struct __go_refcount
-{
- /* A pointer to the reference count structure for the calling
- function. This will be set to NULL if there is no caller with
- reference counts, or if all reference counts in the caller have
- been processed. */
- struct __go_refcount *__caller;
- /* This flag is initialized to false. It is set to true when we
- have scanned all the callers for increments. We only need to
- scan the callers once, since we zero out each increment as we
- find it. */
- _Bool __callers_were_scanned;
- /* This flag is initialized to false. It is set to true if we have
- stopped scanning for decrements because there were too many stack
- frames. When this flag is true we can not simply free newly
- allocated values. */
- _Bool __did_not_scan_decrements;
-
- /* The number of entries for newly allocated values. */
- unsigned short __decrement_new_count;
- /* The number of entries for computed values. */
- unsigned short __decrement_computed_count;
- /* The number of entries for old values which must be
- decremented. */
- unsigned short __decrement_old_count;
- /* The number of entries for copied values which must be
- incremented. */
- unsigned short __increment_copy_count;
-
- /* The actual entries. The number of elements in this array is the
- sum of the count variables. */
- struct __go_refcount_entry __entries[];
-};
-
-/* The struct used to send reference count adjustments to the GC
- thread. */
-
-struct __go_refcount_msg
-{
- /* The current epoch. */
- unsigned int __epoch;
- /* The number of pointers whose reference counts need to be
- incremented. */
- unsigned short __increments;
- /* The number of pointers whose reference counts need to be
- decremented. */
- unsigned short __decrements;
- /* The pointers whose reference counts need adjusting. The
- increment pointers come first, followed by the decrement
- pointers. */
- void *__pointers[];
-};
-
-/* The head of the list of reference count structures. */
-
-extern __thread struct __go_refcount *__go_refcount_head;
-
-extern void __go_increment_refcount (void *,
- const struct __go_type_descriptor *);
-
-extern void __go_refcount_flush_queue (struct __go_refcount *);
-
-extern void __go_send_refcount_msg (struct __go_refcount_msg *);
-
-#endif /* !defined (LIBGO_GO_REFCOUNT_H) */