From patchwork Wed Jan 11 04:48:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 135350 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 21F8AB6EEE for ; Wed, 11 Jan 2012 15:49:05 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1326862146; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:From:To:Subject:Date:Message-ID:User-Agent: MIME-Version:Content-Type:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=pRdETcv6wOGz432cMQmwplVBOys=; b=M0/f/fuKc9PmX0c gh1E8ImvWlp6H78p5AiIWRNRNgQnSM2UvLD7FCH3qSRAJv1Q+WGGRNUssXGMK9z+ 4JV5PHAiAx3qrPE6Cg48WJDGr2TLDdX84F0rE//HoUfKOn4DfHHjg0uPrOSyD0tq gheqnMmCnk93RbrCKN0eI117DcYk= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:From:To:Subject:Date:Message-ID:User-Agent:MIME-Version:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=MsBx96Ew6qLEouVCh1S0yI8XOG99QQ1WRJfenGHjKvF1+H14MHMotu5d64e2iB TuJLk7w05vkAErXqVGDHNFS2fulMuGrbdL82yB153Yf7FM82m0y001hbbaF2gavK RZjzaUL6h9agh+LfwOocuQ100te/dCZo7LCV6RjsJBBto=; Received: (qmail 7762 invoked by alias); 11 Jan 2012 04:48:58 -0000 Received: (qmail 7746 invoked by uid 22791); 11 Jan 2012 04:48:53 -0000 X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_LOW, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from mail-iy0-f175.google.com (HELO mail-iy0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 11 Jan 2012 04:48:36 +0000 Received: by iafi7 with SMTP id i7so555035iaf.20 for ; Tue, 10 Jan 2012 20:48:35 -0800 (PST) Received: by 10.43.47.135 with SMTP id us7mr24455372icb.31.1326257315145; Tue, 10 Jan 2012 20:48:35 -0800 (PST) Received: by 10.43.47.135 with SMTP id us7mr24455360icb.31.1326257315050; Tue, 10 Jan 2012 20:48:35 -0800 (PST) Received: from coign.google.com (adsl-71-133-8-30.dsl.pltn13.pacbell.net. [71.133.8.30]) by mx.google.com with ESMTPS id l35sm965258ibj.0.2012.01.10.20.48.33 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 10 Jan 2012 20:48:34 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Use backend interface for type size and align Date: Tue, 10 Jan 2012 20:48:32 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch to the Go frontend changes it to use the backend interface to determine type size and alignment information. This is a preliminary to a patch adjusting the handling of struct comparison, which will follow. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian 2012-01-10 Ian Lance Taylor * go-gcc.cc (Gcc_backend::type_size): New function. (Gcc_backend::type_alignment): New function. (Gcc_backend::type_field_alignment): New function. (Gcc_backend::type_field_offset): New function. * go-backend.c (go_type_alignment): Remove. * go-c.h (go_type_alignment): Don't declare. Index: gcc/go/go-gcc.cc =================================================================== --- gcc/go/go-gcc.cc (revision 182698) +++ gcc/go/go-gcc.cc (working copy) @@ -1,5 +1,5 @@ // go-gcc.cc -- Go frontend to gcc IR. -// Copyright (C) 2011 Free Software Foundation, Inc. +// Copyright (C) 2011, 2012 Free Software Foundation, Inc. // Contributed by Ian Lance Taylor, Google. // This file is part of GCC. @@ -195,6 +195,18 @@ class Gcc_backend : public Backend bool is_circular_pointer_type(Btype*); + size_t + type_size(Btype*); + + size_t + type_alignment(Btype*); + + size_t + type_field_alignment(Btype*); + + size_t + type_field_offset(Btype*, size_t index); + // Expressions. Bexpression* @@ -755,6 +767,56 @@ Gcc_backend::is_circular_pointer_type(Bt return btype->get_tree() == ptr_type_node; } +// Return the size of a type. + +size_t +Gcc_backend::type_size(Btype* btype) +{ + tree t = TYPE_SIZE_UNIT(btype->get_tree()); + gcc_assert(TREE_CODE(t) == INTEGER_CST); + gcc_assert(TREE_INT_CST_HIGH(t) == 0); + unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t); + size_t ret = static_cast(val_wide); + gcc_assert(ret == val_wide); + return ret; +} + +// Return the alignment of a type. + +size_t +Gcc_backend::type_alignment(Btype* btype) +{ + return TYPE_ALIGN_UNIT(btype->get_tree()); +} + +// Return the alignment of a struct field of type BTYPE. + +size_t +Gcc_backend::type_field_alignment(Btype* btype) +{ + return go_field_alignment(btype->get_tree()); +} + +// Return the offset of a field in a struct. + +size_t +Gcc_backend::type_field_offset(Btype* btype, size_t index) +{ + tree struct_tree = btype->get_tree(); + gcc_assert(TREE_CODE(struct_tree) == RECORD_TYPE); + tree field = TYPE_FIELDS(struct_tree); + for (; index > 0; --index) + { + field = DECL_CHAIN(field); + gcc_assert(field != NULL_TREE); + } + HOST_WIDE_INT offset_wide = int_byte_position(field); + gcc_assert(offset_wide >= 0); + size_t ret = static_cast(offset_wide); + gcc_assert(ret == static_cast(offset_wide)); + return ret; +} + // Return the zero value for a type. Bexpression* Index: gcc/go/gofrontend/types.h =================================================================== --- gcc/go/gofrontend/types.h (revision 182971) +++ gcc/go/gofrontend/types.h (working copy) @@ -861,6 +861,27 @@ class Type std::string mangled_name(Gogo*) const; + // If the size of the type can be determined, set *PSIZE to the size + // in bytes and return true. Otherwise, return false. This queries + // the backend. + bool + backend_type_size(Gogo*, unsigned int* psize); + + // If the alignment of the type can be determined, set *PALIGN to + // the alignment in bytes and return true. Otherwise, return false. + bool + backend_type_align(Gogo*, unsigned int* palign); + + // If the alignment of a struct field of this type can be + // determined, set *PALIGN to the alignment in bytes and return + // true. Otherwise, return false. + bool + backend_type_field_align(Gogo*, unsigned int* palign); + + // Whether the backend size is known. + bool + is_backend_type_size_known(Gogo*) const; + // Get the hash and equality functions for a type. void type_functions(Gogo*, Named_type* name, Function_type* hash_fntype, @@ -2013,6 +2034,12 @@ class Struct_type : public Type traverse_field_types(Traverse* traverse) { return this->do_traverse(traverse); } + // If the offset of field INDEX in the backend implementation can be + // determined, set *POFFSET to the offset in bytes and return true. + // Otherwise, return false. + bool + backend_field_offset(Gogo*, unsigned int index, unsigned int* poffset); + // Import a struct type. static Struct_type* do_import(Import*); @@ -2507,8 +2534,9 @@ class Named_type : public Type local_methods_(NULL), all_methods_(NULL), interface_method_tables_(NULL), pointer_interface_method_tables_(NULL), location_(location), named_btype_(NULL), dependencies_(), - is_visible_(true), is_error_(false), is_converted_(false), - is_circular_(false), seen_(false), seen_in_get_backend_(false) + is_visible_(true), is_error_(false), is_placeholder_(false), + is_converted_(false), is_circular_(false), seen_(false), + seen_in_get_backend_(false) { } // Return the associated Named_object. This holds the actual name. @@ -2672,6 +2700,13 @@ class Named_type : public Type add_dependency(Named_type* nt) { this->dependencies_.push_back(nt); } + // Return true if the size and alignment of the backend + // representation of this type is known. This is always true after + // types have been converted, but may be false beforehand. + bool + is_named_backend_type_size_known() const + { return this->named_btype_ != NULL && !this->is_placeholder_; } + // Export the type. void export_named_type(Export*, const std::string& name) const; @@ -2766,8 +2801,11 @@ class Named_type : public Type bool is_visible_; // Whether this type is erroneous. bool is_error_; + // Whether the current value of named_btype_ is a placeholder for + // which the final size of the type is not known. + bool is_placeholder_; // Whether this type has been converted to the backend - // representation. + // representation. Implies that is_placeholder_ is false. bool is_converted_; // Whether this is a pointer or function type which refers to the // type itself. Index: gcc/go/gofrontend/backend.h =================================================================== --- gcc/go/gofrontend/backend.h (revision 182971) +++ gcc/go/gofrontend/backend.h (working copy) @@ -198,6 +198,25 @@ class Backend virtual bool is_circular_pointer_type(Btype*) = 0; + // Return the size of a type. + virtual size_t + type_size(Btype*) = 0; + + // Return the alignment of a type. + virtual size_t + type_alignment(Btype*) = 0; + + // Return the alignment of a struct field of this type. This is + // normally the same as type_alignment, but not always. + virtual size_t + type_field_alignment(Btype*) = 0; + + // Return the offset of field INDEX in a struct type. INDEX is the + // entry in the FIELDS std::vector parameter of struct_type or + // set_placeholder_struct_type. + virtual size_t + type_field_offset(Btype*, size_t index) = 0; + // Expressions. // Return an expression for a zero value of the given type. This is Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 182971) +++ gcc/go/gofrontend/types.cc (working copy) @@ -1950,6 +1950,126 @@ Type::mangled_name(Gogo* gogo) const return ret; } +// Return whether the backend size of the type is known. + +bool +Type::is_backend_type_size_known(Gogo* gogo) const +{ + switch (this->classification_) + { + case TYPE_ERROR: + case TYPE_VOID: + case TYPE_BOOLEAN: + case TYPE_INTEGER: + case TYPE_FLOAT: + case TYPE_COMPLEX: + case TYPE_STRING: + case TYPE_FUNCTION: + case TYPE_POINTER: + case TYPE_NIL: + case TYPE_MAP: + case TYPE_CHANNEL: + case TYPE_INTERFACE: + return true; + + case TYPE_STRUCT: + { + const Struct_field_list* fields = this->struct_type()->fields(); + for (Struct_field_list::const_iterator pf = fields->begin(); + pf != fields->end(); + ++pf) + if (!pf->type()->is_backend_type_size_known(gogo)) + return false; + return true; + } + + case TYPE_ARRAY: + { + const Array_type* at = this->array_type(); + if (at->length() == NULL) + return true; + else + { + mpz_t ival; + mpz_init(ival); + Type* dummy; + bool length_known = at->length()->integer_constant_value(true, + ival, + &dummy); + mpz_clear(ival); + if (!length_known) + return false; + return at->element_type()->is_backend_type_size_known(gogo); + } + } + + case TYPE_NAMED: + return this->named_type()->is_named_backend_type_size_known(); + + case TYPE_FORWARD: + { + const Forward_declaration_type* fdt = this->forward_declaration_type(); + return fdt->real_type()->is_backend_type_size_known(gogo); + } + + case TYPE_SINK: + case TYPE_CALL_MULTIPLE_RESULT: + go_unreachable(); + + default: + go_unreachable(); + } +} + +// If the size of the type can be determined, set *PSIZE to the size +// in bytes and return true. Otherwise, return false. This queries +// the backend. + +bool +Type::backend_type_size(Gogo* gogo, unsigned int *psize) +{ + Btype* btype = this->get_backend(gogo); + if (!this->is_backend_type_size_known(gogo)) + return false; + size_t size = gogo->backend()->type_size(btype); + *psize = static_cast(size); + if (*psize != size) + return false; + return true; +} + +// If the alignment of the type can be determined, set *PALIGN to +// the alignment in bytes and return true. Otherwise, return false. + +bool +Type::backend_type_align(Gogo* gogo, unsigned int *palign) +{ + Btype* btype = this->get_backend(gogo); + if (!this->is_backend_type_size_known(gogo)) + return false; + size_t align = gogo->backend()->type_alignment(btype); + *palign = static_cast(align); + if (*palign != align) + return false; + return true; +} + +// Like backend_type_align, but return the alignment when used as a +// field. + +bool +Type::backend_type_field_align(Gogo* gogo, unsigned int *palign) +{ + Btype* btype = this->get_backend(gogo); + if (!this->is_backend_type_size_known(gogo)) + return false; + size_t a = gogo->backend()->type_field_alignment(btype); + *palign = static_cast(a); + if (*palign != a) + return false; + return true; +} + // Default function to export a type. void @@ -4589,6 +4709,24 @@ Struct_type::do_mangled_name(Gogo* gogo, ret->push_back('e'); } +// If the offset of field INDEX in the backend implementation can be +// determined, set *POFFSET to the offset in bytes and return true. +// Otherwise, return false. + +bool +Struct_type::backend_field_offset(Gogo* gogo, unsigned int index, + unsigned int* poffset) +{ + Btype* btype = this->get_backend(gogo); + if (!this->is_backend_type_size_known(gogo)) + return false; + size_t offset = gogo->backend()->type_field_offset(btype, index); + *poffset = static_cast(offset); + if (*poffset != offset) + return false; + return true; +} + // Export. void @@ -7518,6 +7656,7 @@ Named_type::convert(Gogo* gogo) this->named_btype_ = bt; this->is_converted_ = true; + this->is_placeholder_ = false; } // Create the placeholder for a named type. This is the first step in @@ -7578,6 +7717,7 @@ Named_type::create_placeholder(Gogo* gog case TYPE_STRUCT: bt = gogo->backend()->placeholder_struct_type(this->name(), this->location_); + this->is_placeholder_ = true; set_name = false; break; @@ -7586,8 +7726,11 @@ Named_type::create_placeholder(Gogo* gog bt = gogo->backend()->placeholder_struct_type(this->name(), this->location_); else - bt = gogo->backend()->placeholder_array_type(this->name(), - this->location_); + { + bt = gogo->backend()->placeholder_array_type(this->name(), + this->location_); + this->is_placeholder_ = true; + } set_name = false; break; Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 182971) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -7979,35 +7979,32 @@ Builtin_call_expression::do_integer_cons return false; if (arg_type->named_type() != NULL) arg_type->named_type()->convert(this->gogo_); - tree arg_type_tree = type_to_tree(arg_type->get_backend(this->gogo_)); - if (arg_type_tree == error_mark_node) - return false; - unsigned long val_long; + + unsigned int ret; if (this->code_ == BUILTIN_SIZEOF) { - tree type_size = TYPE_SIZE_UNIT(arg_type_tree); - go_assert(TREE_CODE(type_size) == INTEGER_CST); - if (TREE_INT_CST_HIGH(type_size) != 0) - return false; - unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(type_size); - val_long = static_cast(val_wide); - if (val_long != val_wide) + if (!arg_type->backend_type_size(this->gogo_, &ret)) return false; } else if (this->code_ == BUILTIN_ALIGNOF) { if (arg->field_reference_expression() == NULL) - val_long = go_type_alignment(arg_type_tree); + { + if (!arg_type->backend_type_align(this->gogo_, &ret)) + return false; + } else { // Calling unsafe.Alignof(s.f) returns the alignment of // the type of f when it is used as a field in a struct. - val_long = go_field_alignment(arg_type_tree); + if (!arg_type->backend_type_field_align(this->gogo_, &ret)) + return false; } } else go_unreachable(); - mpz_set_ui(val, val_long); + + mpz_set_ui(val, ret); *ptype = NULL; return true; } @@ -8025,21 +8022,12 @@ Builtin_call_expression::do_integer_cons return false; if (st->named_type() != NULL) st->named_type()->convert(this->gogo_); - tree struct_tree = type_to_tree(st->get_backend(this->gogo_)); - go_assert(TREE_CODE(struct_tree) == RECORD_TYPE); - tree field = TYPE_FIELDS(struct_tree); - for (unsigned int index = farg->field_index(); index > 0; --index) - { - field = DECL_CHAIN(field); - go_assert(field != NULL_TREE); - } - HOST_WIDE_INT offset_wide = int_byte_position (field); - if (offset_wide < 0) + unsigned int offset; + if (!st->struct_type()->backend_field_offset(this->gogo_, + farg->field_index(), + &offset)) return false; - unsigned long offset_long = static_cast(offset_wide); - if (offset_long != static_cast(offset_wide)) - return false; - mpz_set_ui(val, offset_long); + mpz_set_ui(val, offset); return true; } return false; @@ -13939,25 +13927,26 @@ Type_info_expression::do_type() tree Type_info_expression::do_get_tree(Translate_context* context) { - tree type_tree = type_to_tree(this->type_->get_backend(context->gogo())); - if (type_tree == error_mark_node) - return error_mark_node; - - tree val_type_tree = type_to_tree(this->type()->get_backend(context->gogo())); - go_assert(val_type_tree != error_mark_node); - - if (this->type_info_ == TYPE_INFO_SIZE) - return fold_convert_loc(BUILTINS_LOCATION, val_type_tree, - TYPE_SIZE_UNIT(type_tree)); - else + Btype* btype = this->type_->get_backend(context->gogo()); + Gogo* gogo = context->gogo(); + size_t val; + switch (this->type_info_) { - unsigned int val; - if (this->type_info_ == TYPE_INFO_ALIGNMENT) - val = go_type_alignment(type_tree); - else - val = go_field_alignment(type_tree); - return build_int_cstu(val_type_tree, val); + case TYPE_INFO_SIZE: + val = gogo->backend()->type_size(btype); + break; + case TYPE_INFO_ALIGNMENT: + val = gogo->backend()->type_alignment(btype); + break; + case TYPE_INFO_FIELD_ALIGNMENT: + val = gogo->backend()->type_field_alignment(btype); + break; + default: + go_unreachable(); } + tree val_type_tree = type_to_tree(this->type()->get_backend(gogo)); + go_assert(val_type_tree != error_mark_node); + return build_int_cstu(val_type_tree, val); } // Dump ast representation for a type info expression. Index: gcc/go/go-backend.c =================================================================== --- gcc/go/go-backend.c (revision 182696) +++ gcc/go/go-backend.c (working copy) @@ -1,5 +1,5 @@ /* go-backend.c -- Go frontend interface to gcc backend. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -48,14 +48,6 @@ along with GCC; see the file COPYING3. /* This file holds all the cases where the Go frontend needs information from gcc's backend. */ -/* Return the alignment in bytes of a value of type T. */ - -unsigned int -go_type_alignment (tree t) -{ - return TYPE_ALIGN_UNIT (t); -} - /* Return the alignment in bytes of a struct field of type T. */ unsigned int Index: gcc/go/go-c.h =================================================================== --- gcc/go/go-c.h (revision 182696) +++ gcc/go/go-c.h (working copy) @@ -1,5 +1,5 @@ /* go-c.h -- Header file for go frontend gcc C interface. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -59,8 +59,6 @@ extern void go_preserve_from_gc (tree); extern const char *go_localize_identifier (const char*); -extern unsigned int go_type_alignment (tree); - extern unsigned int go_field_alignment (tree); extern void go_trampoline_info (unsigned int *size, unsigned int *alignment);