compiler: add Ptrmask_symbol_expression
Add an expression to evaluate to the ptrmask for a type. This will be
used for global variables, which always use a ptrmask no matter how
large they are.
Change-Id: I0b79a31f4280d44f9ffbaf9fda1b265b384028c3
Reviewed-on: https://go-review.googlesource.com/40981
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/expressions.cc b/go/expressions.cc
index af7b49c..2953b3d 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -14617,6 +14617,91 @@
return new GC_symbol_expression(type);
}
+// An expression that evaluates to a pointer to a symbol holding the
+// ptrmask data of a type.
+
+class Ptrmask_symbol_expression : public Expression
+{
+ public:
+ Ptrmask_symbol_expression(Type* type)
+ : Expression(EXPRESSION_PTRMASK_SYMBOL, Linemap::predeclared_location()),
+ type_(type)
+ {}
+
+ protected:
+ Type*
+ do_type()
+ { return Type::make_pointer_type(Type::lookup_integer_type("uint8")); }
+
+ bool
+ do_is_static_initializer() const
+ { return true; }
+
+ void
+ do_determine_type(const Type_context*)
+ { }
+
+ Expression*
+ do_copy()
+ { return this; }
+
+ Bexpression*
+ do_get_backend(Translate_context*);
+
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
+ private:
+ // The type that this ptrmask symbol describes.
+ Type* type_;
+};
+
+// Return the ptrmask variable.
+
+Bexpression*
+Ptrmask_symbol_expression::do_get_backend(Translate_context* context)
+{
+ Gogo* gogo = context->gogo();
+
+ // If this type does not need a gcprog, then we can use the standard
+ // GC symbol.
+ int64_t ptrsize, ptrdata;
+ if (!this->type_->needs_gcprog(gogo, &ptrsize, &ptrdata))
+ return this->type_->gc_symbol_pointer(gogo);
+
+ // Otherwise we have to build a ptrmask variable, and return a
+ // pointer to it.
+
+ Bvariable* bvar = this->type_->gc_ptrmask_var(gogo, ptrsize, ptrdata);
+ Location bloc = Linemap::predeclared_location();
+ Bexpression* bref = gogo->backend()->var_expression(bvar, VE_rvalue, bloc);
+ Bexpression* baddr = gogo->backend()->address_expression(bref, bloc);
+
+ Type* uint8_type = Type::lookup_integer_type("uint8");
+ Type* pointer_uint8_type = Type::make_pointer_type(uint8_type);
+ Btype* ubtype = pointer_uint8_type->get_backend(gogo);
+ return gogo->backend()->convert_expression(ubtype, baddr, bloc);
+}
+
+// Dump AST for a ptrmask symbol expression.
+
+void
+Ptrmask_symbol_expression::do_dump_expression(
+ Ast_dump_context* ast_dump_context) const
+{
+ ast_dump_context->ostream() << "ptrmask(";
+ ast_dump_context->dump_type(this->type_);
+ ast_dump_context->ostream() << ")";
+}
+
+// Make a ptrmask symbol expression.
+
+Expression*
+Expression::make_ptrmask_symbol(Type* type)
+{
+ return new Ptrmask_symbol_expression(type);
+}
+
// An expression which evaluates to some characteristic of a type.
// This is only used to initialize fields of a type descriptor. Using
// a new expression class is slightly inefficient but gives us a good
diff --git a/go/expressions.h b/go/expressions.h
index 5750396..03bb085 100644
--- a/go/expressions.h
+++ b/go/expressions.h
@@ -128,6 +128,7 @@
EXPRESSION_RECEIVE,
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_GC_SYMBOL,
+ EXPRESSION_PTRMASK_SYMBOL,
EXPRESSION_TYPE_INFO,
EXPRESSION_SLICE_INFO,
EXPRESSION_SLICE_VALUE,
@@ -402,6 +403,13 @@
static Expression*
make_gc_symbol(Type* type);
+ // Make an expression that evaluates to the address of a ptrmask
+ // symbol for TYPE. For most types this will be the same as
+ // make_gc_symbol, but for larger types make_gc_symbol will return a
+ // gcprog while this will return a ptrmask.
+ static Expression*
+ make_ptrmask_symbol(Type* type);
+
// Make an expression which evaluates to some characteristic of a
// type. These are only used for type descriptors, so there is no
// location parameter.