From patchwork Thu Jun 26 05:54:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Machado X-Patchwork-Id: 1755 Received: (qmail 30104 invoked by alias); 26 Jun 2014 05:55:09 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 30089 invoked by uid 89); 26 Jun 2014 05:55:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 26 Jun 2014 05:55:05 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1X02eE-0002dp-EB from Luis_Gustavo@mentor.com for gdb-patches@sourceware.org; Wed, 25 Jun 2014 22:55:02 -0700 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Wed, 25 Jun 2014 22:55:02 -0700 Received: from [172.30.72.126] (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.2.247.3; Wed, 25 Jun 2014 22:54:22 -0700 Message-ID: <53ABB5B3.1070803@codesourcery.com> Date: Thu, 26 Jun 2014 06:54:59 +0100 From: Luis Machado Reply-To: User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: "'gdb-patches@sourceware.org'" Subject: [PATCH] Fix passing/returning of complex data for PowerPC 32-bit X-IsSubscribed: yes The PowerPC 32-bit unified ABI states that there are two ways of passing and returning complex type data: - Pointer, in a register, to a memory area. - Data in registers. The problem is that it is not clear how to detect which variation a program is using. GDB currently does a bit of both. It uses the first mechanism for passing parameters and uses both to return data, depending on the size of the data type. It is a bit messy because GDB is not handling complex types explicitly. Checking the gdb.base/callfuncs.exp testcase for a PowerPC 32-bit target, with code built with GCC, showed a few failures related to complex types. This patch steers GDB towards what GCC seems to generate for PowerPC 32-bit and handles complex type passing/return via general registers (the second option). All failures are gone. The problem here is if some other target/compiler is using the other variation. So, for those that have a PowerPC 32-bit handy, can you confirm it works reliably? I'm thinking AIX, Darwin or some other eabi target. Otherwise, does this look reasonable? Regards, Luis 2014-06-26 Luis Machado * ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Explicitly handle passing of complex arguments. (do_ppc_sysv_return_value): Explicitly handle return of complex types. diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 1a880a6..2ea7796 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -269,6 +269,57 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, greg += 4; } } + else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + { + int lgpr = 11; + int type_size = TYPE_LENGTH (type); + int ngpr = type_size / tdep->wordsize; + + /* The PowerPC Unified 32-bit ABI states that complex types should + be handled in two different ways. Either they are passed via + general registers or they are returned as a pointer, in a + general register, to an area that contains the data. + + Unfortunately there is no straightforward way to decide what + variation a program is using. Therefore we assume the GCC + mechanism of passing the complex data in general registers. + + Float complex uses 2 consecutive GPR's. + + Double complex uses 4 consecutive GPR's. + + Long Double complex uses 4 or 8 consecutive GPR's, depending on + whether the long double is represented as a double or as a + 128-bit entity. + + Scalar-based complex types are passed in the same way as their + floating point counterparts. */ + + /* Check if we should pass this parameter in registers or + stack. */ + if (ngpr + greg > lgpr) + { + /* Pass parameter in the stack. */ + argoffset = align_up (argoffset, 8); + if (write_pass) + write_memory (sp + argoffset, val, len); + argoffset += len; + } + else + { + /* Pass the parameter in registers. */ + if (write_pass) + { + int i; + + for (i = 0; i < ngpr; i++) + regcache_cooked_write (regcache, + tdep->ppc_gp0_regnum + greg + i, + val + i * 4); + } + greg += ngpr; + } + } else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8 && !tdep->soft_float) { @@ -724,6 +775,45 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, } return RETURN_VALUE_REGISTER_CONVENTION; } + + /* The PowerPC Unified 32-bit ABI handles return of complex types in two + different ways. Either they are returned via general registers or they are + returned as a pointer, in a general register, to an area that contains the + data. + + Unfortunately there is no straightforward way to decide what variation a + program is using. Therefore we assume the GCC mechanism of returning the + complex data in general registers. + + Float complex uses 2 consecutive GPR's. + + Double complex uses 4 consecutive GPR's. + + Long Double complex uses 4 or 8 consecutive GPR's, depending on whether the + long double is represented as a double or as a 128-bit entity. + + Scalar-based complex types are returned in the same way as their floating + point counterparts. */ + if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + { + int i, nregs; + int return_reg = tdep->ppc_gp0_regnum + 3; + + nregs = TYPE_LENGTH (type) / tdep->wordsize; + + for (i = 0; i < nregs; i++) + { + if (readbuf) + regcache_cooked_read (regcache, return_reg + i, + readbuf + i * tdep->wordsize); + if (writebuf) + regcache_cooked_write (regcache, return_reg + i, + writebuf + i * tdep->wordsize); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } + if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 16 && !tdep->soft_float